Deep Linking — част 1

В последните два урока представихме как можем да добавим AJAX презареждане на страници. Показахме и как да кешираме информацията. Естественият ход на развитие на един сайт, а и коментари към уроците, предполагат да добавим и deep linking.

Какво е deep linking?

Отворете страниците от предния път: https://magadanski.com/demo/ajax-requests/. Разцъкайте навигацията. Нещо прави ли ви впечатление? Макар и съдържанието да се променя, адресът на страницата остава все един и същ. Това е проблем когато искаме да дадем link за точно определена страница.

Deep linking е възможността да представяме различни състояния на един и същ URL. Използва се когато дадена страница променя съдържанието си посредством JavaScript. Използвайки JS можем (и дори трябва) да обработим допълнително подадена информация в URL-а на страницата. Така показваме същото това състояние, до което човек е достигнал, кликвайки на бутон или нещо друго.

Deep linking може да се наложи при lightbox-ове, табове, акордеони, цели страници заредени с AJAX (както е в нашия случай) и др. Тъй като за момента при нас е налице единствено зареждане на ново съдържание с AJAX ще се погрижим за този случай. В последствие ще добавим и останалите елементи, за да видим как най-добре можем да ги съчетаем.

Техники за deep linking

Съществуват различни методи за подаване на допълнителна информация към script-овете на страницата през URL. Най-често се срещат стандартни GET аргументи. Те могат лесно да се използват и от сървъра, в случай че страницата ни се генерира от някакъв server-side script. Друг метод е чрез URL hash-ове.

URL GET аргументи

Това са незадължителни двойки ключ-стойност, които се изреждат след основната част на URL-а. След ключа се изписва знак за равенство, а след това е самата стойност. Преди да се подадат към URL-а се добавя “?” за да ги отдели. Двойките ключ-стойност се отделят с амперсанд (&). Пример:

http://example.com/?arg1=val1&arg2=val2

URL hash

След GET аргументите в един URL идва ред на (отново незадължителен) URL hash. Отделя се чрез диез (#). Стойността на hash-а се третира като една цяла стойност. Може да се достъпи в JavaScript използвайки window.location.hash. Най-често се очаква, че това е просто една единствена стойност, която трябва да се обработи по определен начин. Можем да добавим знаци, по които да отделим параметри от hash-а. Така когато ги обработим по правилен начин можем да представим по-богата информация.

Трябва да се отбележи, че в IE 7/8 съществува бъг, който в някои случаи би довел до презареждане на страницата при задаване на нова стойност за hash-а на URL-а.

history.pushState

HTML5 hostory API-то на JavaScript дава възможност изцяло да променим адреса, който браузъра показва без да презареждаме страницата. Още по-хубавата част е, че новият адрес просто се добавя в историята на браузъра. Така лесно можем да цъкнем на back (а после и на forward) бутона на браузъра и ще идем до правилния URL. В нашия случай това е най-доброто решение, защото можем просто да зададем новия адрес.

Най-големият минус тук е, че по този начин губим поддръжка за стари браузъри (IE 7/8/9).

jQuery Address

За наш огромен късмет, не сме първите, които биха искали да добавят deep linking в сайта си. Даже мнозинстото искат тази функционалност. Благодарение на това съществуват различни JS библиотеки, които да ни улеснят като се грижат за проблеми в различните браузъри. jQuery Adress ни дава и възможност да използваме history.pushState като основен метод за работа. С минимални усилия можем да добавим и поддръжка за IE 7/8 чрез hash-ове.

Защо точно jQuery Address

Поради няколко причини:

  1. Защото това е jQuery plugin, а ние работим с jQuery
  2. Защото е разработен от същия човек, който на времето е направил SWF Address.

Какво е SWF Address?

Това е най-старата (известна на мене) JavaScript библиотека, която се използваше за подобна функционалност. Датира доста преди HTML5 и HTML web приложенията. Името може би ви подсказва, че тази библиотека даваше възможност за комуникация със SWF файлове (flash). Така че SWF Address беше единственият начин Flash web приложенията да дават връзки към различните си състояния.

Да отдадем почит на човека разработил SWF Address и jQuery Address — Ростислав Христов (да — българин е)!

Добавяне на deep linking функционалност

Ще работим с файловете от урока AJAX заявки (без кеширането). Защо без кеширане? Защото кеширането не е задължителен елемент. Макар и да е опростено допринася някаква слъжност към кода. В случая се опитваме да поддържаме всичко максимално просто. Така ще имате възможност да се упражните и самички и да добавите deep linking към версията с кеширане.

Ето и архив на файловете, с които ще започнем работа.

Като за начало, нека изтеглим jQuery Address JS plugin-а. Можете да направите това от официалната страница: http://www.asual.com/jquery/address/.

Можете да работите и с dev версията. Това е най-новата версия. Толкова нова, че е още в процес на разработка и е възможно да се окаже, че има bug-ове. Даже докато писах урока опитах и с нея, но резултатът не беше толкова добър, колкото със стабилната версия 1.5.

Dev версията може да се вземе от GitHub (папка src).

След като вече сме изтеглили jQuery Address (аз го записах в js/jquery-address) трябва да го добавим в страниците си:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>AJAX Requests</title>
	<link href="http://fonts.googleapis.com/css?family=Open+Sans:300&subset=latin,cyrillic-ext,cyrillic" rel="stylesheet" type="text/css" />
	<link rel="stylesheet" type="text/css" href="style.css" />
	<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
	<script type="text/javascript" src="js/jquery-address/jquery.address-1.5.js"></script>
	<script type="text/javascript" src="js/func.js"></script>
</head>

Не забравяйте, че това трябва да е налице във всички страници (index.html, slider.html, accordion.html, tabs.html).

Интегриране на jQuery Address

Сега вече можем да започнем работа и по същинската интеграция на jQuery Address.

Като за начало нека инициализираме jQuery Address за линковете от основната навигация. Нека закоментираме останалия ни код, тъй като ще трябва да бъде модифициран леко.

jQuery(function ($) {
	$.address.init(function () {
		$('nav a').address();
	})
	
	// $(document).on('click', 'nav a', function (e) {
	// 	e.preventDefault();
	// 	
	// 	$.get($(this).attr('href'), function (data, status, XHR) {
	// 		if (status == 'success') {
	// 			$('section[role="e;main"e;]').html($(data).find('section[role="e;main"e;]').html());
	// 			$('title').html($(data).filter('title').html());
	// 			$('header').html($(data).find('header').html());
	// 		} else {
	// 			// tell the user we could not connect to the server
	// 		}
	// 	});
	// });
});

Ако тестваме резултата сега, ще видим, че jQuery Address използва hash-ове, за да обозначи на коя страница сме. За момента съдържанието от новите страници, обаче не се зарежда. Ще стигнем и до там.

$.address.change

jQuery(function ($) {
	$.address.init(function () {
		$('nav a').address();
	});
	
	$.address.change(function (e) {
	});
});

Добавяме address.change event handler, който ще зарежда информацията, когато адресът на браузъра се промени.

jQuery(function ($) {
	var root = '/tutorials/deep-linking';
	
	$.address.init(function () {
		$('nav a').address();
	});
	
	$.address.change(function (e) {
		$.get(root + $.address.value(), function (data, status) {
			if (status == 'success') {
				// handle loaded data
			} else {
				// tell the user we could not connect to the server
			}
		});
	});
});

Добавили сме променливата root, в която ще съхраняваме root URL-а на сайта. В случай, че сайтът ни се намира в основата на домейна — тогава няма да имаме нужда от тази променлива. Но тъй като аз работя в папка “tutorials/deep-linking” е нужно да използвам такава променлива. Тя ми помага при правилното построяване на адресите, от които да зареждам съдържание.

Остава само да обработим по правилен начин заредената информация:

$.address.change(function (e) {
	$.get(root + $.address.value(), function (data, status, XHR) {
		if (status == 'success') {
			$('section[role="main"]').html($(data).find('section[role="main"]').html());
			
			$('title').html($(data).filter('title').html());
			$('header').html($(data).find('header').html());
		} else {
			// tell the user we could not connect to the server
		}
	});
});

До тук всичко върви на Chrome, Firefox, Safari, Opera, Internet Explorer 10, 9 и 8. Ами IE7? Оказа се, че начина, по който jQuery Address добавя hash за IE7 е като включва пълен адрес, а не само на компонента от връзката, която сме добавили. Този проблем има 4 решения:

  1. Да променим връзките, така че да са абсолютни, а не релативни
  2. Да променим връзките, така че да са релативни, но според site root
  3. Да добавим няколко реда JS, в който да правим проверка за IE7 и в такъв случай да прескочим конкатенирането с променливата root
  4. Да drop-им support за IE7

Аз лично предпочитам последния вариант. Пазарният дял на IE7 е под 2%. Освен това IE7 е четвъртата версия на IE от най-новата назад. Google официално поддържат само последните 2 major версии на всички браузъри. Значи официално не поддържат дори IE8.

Какво стана с history.pushState()?

Този урок стана вече твърде дълъг, така че това ще го оставим за следващия път. Тогава ще добавя и demo на целия урок.

Ако съм в добро настроение даже може да оправим и IE7.

5 Отговори на “Deep Linking — част 1”

  1. Урокът започва добре. За back бутона е важно да се обяснят нещата, особено в IE. Ще пиша повече, когато целият урок е завършен. Харесва ми това, че си разгледал deep linking, определено важен topic. Модерно е да се правят Full AJAX сайтове, но в много случаи deep linking не се включва, което е сериозен пропуск.

    PS Защо линковете в коментарите са nofollow :)?

    • Личи си колко правиш уроците и колко пишеш for the pass the time :P. Deep Linking е налице, както и поддръжка за Back бутона на браузърите. Когато напиша и втора част от урока ще кача и demo, където ще можеш сам да провериш, че всичко работи.

      Единственият проблем в момента е с IE7, но за него съм писал в урока.

      P.S. nofollow в коментарите е заради спамъри като тебе 😛 (по default е така в WordPress — би трябвало да знаеш тези SEO особености на един от най-използваните CMS-и).

  2. Ще се радвам да видя демото. Аз не “правя” уроците, защото знам как се правят повечето неща, макар и по друг начин (без jQuery Address). Въпреки това, чета уроците. Така се уча да гледам нещата от друг ъгъл, забелязвам интересни подробности. Ето нещо, което може да ти бъде интересно: https://developers.google.com/webmasters/ajax-crawling/docs/getting-started?hl=bg . Според мен IE много объркват нещата с тяхната назадничавост. history.pushState() е пътят, не #! и после сървърни обработки на _escaped_fragment_ .

    P.S. Хехе, знам :D… въпросът ми по-скоро се превежда: “Хайде pls да не са nofollow вече линковете”.

    • Не “правиш” уроците, ама затова после пишеш глупости, че нямало Deep Linking, при положение, че има.

      Не че е задължително да се ползва jQuery Address, но в практиката съм стигнал до извода, че е много по-добре (за някои неща) да използваш plugin, който не е от вчера и е тестван много повече от нещо, което ще скалъпиш за 10-15 минути.

      Това за #! и _escaped_fragment_ честно казано за първи път го виждам. От една страна — има логика, но от друга — съществува ли изобщо някой, който да си даде толкова много зор? По-скоро ще направя цял нов сайт, отколкото да добавя поддръжка за подобно нещо.

      Относно history.pushState() — определено е по-доброто решение, когато става въпрок за зареждане на съдържание на нова страница, но в някои случаи може просто да искаш да покажеш състояние на текущата страница, което ако покажеш с отделен URL ще има отрицателно влияние, тъй като такава страница или няма да съществува или ще представя нещо друго, а не състоянието, в което си бил по-рано.

      P.S. Мечтай 😛 (http://www.youtube.com/watch?v=txlXcJDtDwM)

  3. Прав си, че е играчка. На теория трябва в един AJAX сайт, който използва # , заради google crawler-ите винаги да е #! и после проверки в сървърната част за _escaped_fragment_ и да се върне HTML snapshot. Много сайтове го ползват. Twitter примерно. Аз лично харесвам как си направил нещата в този tutorial. Имаме реални html страници, които могат да се отворят директно, hash-а може да се наложи да се използва само в IE, тъй като history.pushState() ще свърши необходимото за смяна на адреса на истинската страница. Реалният шанс в сайт като твоя crawler-ите да се докопат до link с # в него е само ако някой IE user реши да постне url-а си от address bar-a в някой външен сайт (backlink към твоя). Тази вероятност не е никак голяма, пък и не трябва да те бърка, след като си има директни линкове към истинските страници. Така че нещата са добре откъм SEO.

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

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

Този сайт използва Akismet за намаляване на спама. Научете как се обработват данните ви за коментари.