Het gebruik van JavaScript voor het ontwikkelen van dynamische en interactieve websites en webapplicaties is in de afgelopen jaren enorm toegenomen. Met de komst van JavaScript Libraries worden veel van de vroegere obstakels tijdens ontwikkeling weggenomen. Dit artikel gaat over de helderste ster aan het JavaScript-library firmament, jQuery.
jQuery is een lichtgewicht, open-source JavaScript-bibliotheek die het schrijven van toegankelijke, cross-browser client-side code vereenvoudigt. Microsoft heeft jQuery onlangs aan Visual Studio toegevoegd als aanvulling op het reeds bestaande ASP.NET Ajax Framework. In dit artikel gaan we kort in op de mogelijkheden van jQuery en geven we een paar voorbeelden van vaak voorkomende toepassingen. Tot slot zullen we enkele best-practices geven en het gebruik van jQuery in combinatie met ASP.NET toelichten.
INLEIDING
JavaScript is een client-side scripting taal die relatief eenvoudig is te gebruiken, maar daarom ook eenvoudig te misbruiken (vaak uit gebrek aan kennis). De manier waarop verschillende webbrowsers JavaScript en het Document Object Model (DOM) interpreteren is erg uiteenlopend. Dit maakt het schrijven van complexere, cross-browser JavaScript tot een omslachtige en lastige klus waarbij veel browser-specifieke kennis vereist is. De betere JavaScript libraries nemen deze zorg uit handen en maken het schrijven van JavaScipt weer leuk.
AFBEELDING 1, jQuery Logo
In januari 2006 werd jQuery geïntroduceerd door John Resig en groeide in korte tijd uit tot een van de meest gebruikte JavaScript libraries in zijn soort. Sinds September 2008 levert Microsoft de jQuery library mee met Visual Studio, inclusief intellisense, voorbeelden en documentatie. Microsoft heeft aangegeven zelf geen wijzigingen aan te brengen in de jQuery broncode, maar wel suggesties te doen in de richting van het jQuery ontwikkelteam. De meegeleverde jQuery bestanden blijven onder de originele open source MIT-Licentie vallen.
John Resig’s idee achter jQuery is het vergemakkelijken van JavaScript ontwikkeling door het overbruggen van browser verschillen en het aanbieden van verkorte functies. Resig heeft deze denkwijze samengevat in de jQuery slogan “write less, do more”. De jQuery library onderscheid zich van veel andere (plug-and-play) JavaScript libraries door zijn bottom-up benadering, geen kant-en-klare brokken functionaliteit maar een solide JavaScript fundatie waarop eigen toepassingen ontwikkeld kunnen worden. jQuery kent een enthousiaste en actieve open-source community en is uitgebreid gedocumenteerd op de officiële jQuery website (www.jquery.com). De library heeft een verassend kleine bestandsgrootte van 19kb . Een groot aantal eigen geschreven toepassingen die gebouwd zijn op de jQuery library zijn gratis verkrijgbaar in plug-in vorm.
De basisprincipes van jQuery
De basis van jQuery berust op het principe van “selectie en bewerking”. Er worden één of meerdere elementen uit de DOM structuur (HTML pagina) geselecteerd waar vervolgens een bewerking op uitgevoerd kan worden. Bij het selecteren maakt men gebruik van jQuery selectors die gebaseerd zijn op de syntax en semantiek van CSS en Xpath standaarden.
Selectie in jQuery
In jQuery kan men op verschillende manieren elementen op een pagina selecteren. Globaal bestaan er 3 soorten selectors:
• de basis CSS selectors (op type element, klassenaam of id)
• positionele selectors (op positie t.o.v. overige elementen)
• zelfgeschreven jQuery selectors
De basis selectors worden ook wel find selectors genoemd en worden gebruikt om elementen binnen de html structuur direct aan te spreken. Bijvoorbeeld:
$("a") om alle hyperlinks binnen de pagina te selecteren.
$("a#mylink") om de hyperlink met id-attribuut “mylink” te selecteren
$("a.mylinks") om alle hyperlinks met class-attribuut “mylinks” te selecteren
De positionele en zelfgeschreven selectoren worden ook wel filter selectors genoemd en worden gebruikt om een deelverzameling van elementen selecteren. Hier volgen enkele voorbeelden van een positionele selector:
$("a:first")
om de eerste hyperlink binnen een pagina te selecteren.
$("ul#mylist>li:odd")
Om alle “oneven” <LI> elementen binnen de <UL> met id-attribuut “mylist” te selecteren
(nb. Visueel geeft deze selectie de “even” elementen uit de lijst terug aangezien er op array-index geteld wordt, beginnende bij 0)
$("ul#mylist>li:not(:first-child):not(:last-child)")
Om alle lijst-elementen <LI> binnen de <UL> met id-attribuut “mylist” te selecteren met uizondering van de eerste en de laatste
Wanneer de standaard selectors niet voldoen, is het ook nog mogelijk om jQuery uit te breiden met een zelfgeschreven selector. De syntax hiervoor is als volgt:
$.extend($.expr[':'], {
EXPRESSION_NAME: "EXPRESSION_RULE"
});
Zoals hierboven te zien is, wordt elke jQuery selectie uitgevoerd binnen de zogenaamde jQuery wrapper. Deze wordt standaard aangeroepen met de afgekorte functie $() en geeft een speciaal JavaScript (jQuery) object terug. Hierin bevindt zich een array van elementen die aan de uitgevoerde selectie voldoen. Ook wanneer maar 1 element aan de selectie voldoet, geeft jQuery een array object terug. Dit laatste is even wennen wanneer men met jQuery aan de slag gaat. De jQuery wrapper dient tevens als een namespace prefix voor de aanroep van een aantal generieke jQuery functies uit de library. Om conflicten bij het gebruik van meerdere libraries te voorkomen kan de jQuery wrapper uitgeschakeld of aangepast worden.
Bewerking in jQuery
Op een uitgevoerde jQuery selectie kan men vervolgens een bewerking loslaten. Meestal bestaan deze bewerkingen uit het genereren en invoegen, veranderen, verbergen of verwijderen van HTML elementen (DOM manipulatie) maar denk ook aan het koppelen van effecten (zoals animaties) aan de acties (bijvoorbeeld muisklik) van een gebruiker, ook wel event registratie genoemd. Zie bijvoorbeeld listing 1, daar worden alle hyperlinks met class-attribuut “mylinks” rood gekleurd en animeren naar een breedte van 130 pixels zodra er op geklikt wordt.
$("a.mylinks").bind("click", function() {
$(this).css('color', 'red').animate({ width: 130 })
});
LISTING 1, binding aan een click event
De kracht van jQuery zit hem vooral in de compacte syntax die het mogelijk maakt om in enkele regels code een selectie en een bewerking uit te voeren. Bovendien is het met behulp van het zogenaamde “chaining”mogelijkheid om meerdere bewerkingen sequentieel te laten uitvoeren op één enkele selectie, zoals in bovenstaand voorbeeld waar zowel de kleur aangepast wordt als de breedte geanimeerd wordt in één query .

AFBEELDING 2, jQuery syntax uitgelegd
Unobtrusive JavaScript
jQuery legt sterke focus op de ondersteuning van “Unobtrusive JavaScript”. Dit is een ontwikkelconcept waarbij gedrag (JavaScript) gescheiden wordt van structuur (HTML) op dezelfde manier waarop opmaak (CSS) van structuur wordt gescheiden. Unobtrusive JavaScript is een belangrijke voorwaarde bij de ontwikkeling van toegankelijke en vindbare websites.

AFBEELDING 3, progressive enhancement of layered semantic markup
Bij een scheiding van gedrag en structuur wacht men tot alle DOM elementen op de pagina volledig ingeladen zijn, alvorens er een JavaScript bewerking op losgelaten kan worden. Meestal wordt hier de onload handler van de window instantie voor gebruikt. jQuery biedt hier een verbeterde functie voor, die uitgevoerd wordt wanneer de DOM structuur ingeladen is en niet wacht op het inladen van externe bronnen (wat de window.onload functie wel doet). Deze jQuery functie staat in listing 2.
$(document).ready(function() {
// mijn code
});
LISTING 2, jQuery alternatief voor window.onload()
jQuery in actie
Om te demonstreren hoe snel jQuery geïmplementeerd kan worden, geven we hier een praktijkvoorbeeld van een eenvoudig accordion. De HTML bestaat uit een Unordered List element <UL> met daarin vragen en antwoorden, onderscheiden door een klassenaam. Zie listing 3.
<ul id="faq">
<li class="question">question1</li>
<li class="answer">answer1</li>
<li class="question">question2</li>
<li class="answer">answer2</li>
<li class="question">question3</li>
<li class="answer">answer3</li>
<li class="question">question4</li>
<li class="answer">answer4</li>
</ul>
<script type="text/javascript">
$("#faq li.answer").not(":first").hide();
$("#faq li.question:first").addClass("open");
$("#faq li.question").bind("click",function(){
$("#faq.open")
.next().slideUp()
.removeClass("open");
$(this).addClass("open").next().slideDown();
})
</script>
LISTING 3, accordion control
De JavaScript code voor het accordion doet het volgende:
• Regel 1: verberg alle antwoorden behalve het antwoord bij vraag 1
• Regel 2: Voeg een klassenaam “open” toe aan het LI element die de eerste vraag bevat
• Regel 4: definieer een functie die uitgevoerd wordt wanneer men op een van de vragen klikt.
• Regel 5: sluit de vraag die open staat en verwijder de klassenaam “open”.
• Regel 6: open de vraag waarop geklikt is en voeg de klassenaam “open” toe.
Zien is geloven en daarom hebben we deze en andere voorbeelden van jQuery toepassingen online gezet, je kunt ze bekijken op http://jqueryshowcase.evident.nl
AFBEELDING 4, accordion uit Evident jQuery showcase
Best Practices
De basis van jQuery is behoorlijk snel onder de knie te krijgen vanwege de logische en compacte syntax, maar het daadwerkelijk ontwikkelen van eigen toepassingen in jQuery, zal ongetwijfeld nog wat vraagtekens oproepen. Onderstaande tips kunnen hier wellicht bij helpen.
• Debug Tip: Vergeet “view source” voorgoed en bekijk het resultaat aan de voorkant met behulp van een developer tool in je webbrowser.
Voor Internet Explorer gebruikers is er de Web Developer Toolbar (standaard aanwezig in versie 8 en te downloaden voor versie 7). Voor FireFox gebruikers is er Firebug. Naast handige HTML en CSS hulpjes, beschikken beide Developer tools over de mogelijkheid van JavaScript debugging, onder andere door het bieden van console logging (een goed alternatief voor de bekende alert() functie). Met de console.log() functie kan het resultaat van een JavaScript statement direct weergegeven (gelogd) worden in de toolbar (onder het tabblad “Console”).
• Performance Tip: geef een context mee aan je jQuery selectoren.
Selecteren op een id is in JavaScript een stuk sneller dan het selecteren op een klassenaam. Geef daarom (indien bekend) een gebied (context) aan waarin je de selectie wilt laten uitvoeren. De syntax daarvoor is jQuery( expression, context ). Bijvoorbeeld:
$("a.mylinks","#wrapper");
• Safety Tip: check of elementen bestaan.
Wanneer één JavaScript bestand over meerdere pagina’s ingeladen wordt, kan het handig zijn om te checken of een bepaalde JavaScript functie van toepassing is op de actieve pagina. Zie listing 4.
if ($("ul#mylist").length) {
// mijn code
}
LISTING 4, check of elementen bestaan
• Styling Tip: Voeg een JavaScript afhankelijke klassenaam toe aan de body-tag om een afwijkende style te definiëren voor situaties zonder JavaScript ondersteuning. Zie listing 5.
<script type="text/javascript">
$(document).ready(function() {
$("body").addClass("activeJs").removeClass("noJs");
});
</script>
<body class="noJs">
LISTING 5, geef de body een class name als er javascript is
• Practical tip: Probeer het wiel niet opnieuw uit te vinden.
Veel voorkomende toepassingen zijn meestal al door iemand gemaakt, zoek daarom eerst even naar plugins die wellicht al aan je wensen voldoet. jQuery is open-source en er staan duizenden jQuery plugins online die je vrij kunt gebruiken en/of aanpassen.
jQuery en ASP.NET
jQuery kent veel toepassingsgebieden. In zijn kern is jQuery vooral een client-side library die door (front-end) developers ingezet wordt voor DOM-manipulatie en het toevoegen van animatie (voor eenvoudige animaties biedt jQuery steeds vaker een alternatief voor Flash). Maar ook op server-side gebied biedt jQuery interessante mogelijkheden.
jQuery past uitstekend bij ASP.NET. Wanneer je gebruik maakt van zowel jQuery als ASP.NET AJAX let dan even op het volgende: De afgekorte $() functie wordt door beide libraries als namespace gebruikt. De meest eenvoudig oplossing is het overschrijven van de standaard jQuery namespace, dit doe je met het aanroepen van de functie jQuery.noConflict(). In je code vervang je “$ “vervolgens door “jQuery”. Zie listing 6.
jQuery.noConflict();
jQuery(document).ready(function() {
// mijn code
});
LISTING 6, conflict tussen frameworks oplossen
Wanneer er plugins gebruikt worden die voor de $ namespace geschreven zijn, zullen deze niet meer werken totdat deze vervangen is, gelukkig komt dit zelden voor.
Bij veel .NET ontwikkelaars is JavaScript niet echt populair. JavaScript vereist een andere manier van werken en denken als ASP.NET. Wanneer je alleen plugins gebruikt, zul je nauwelijks merken dat het JavaScript is. Het toevoegen van een CSS class aan een HTML element is vaak al voldoende om functionaliteit toe te voegen. Je kunt dan haast declaratief programmeren, eenvoudiger kan bijna niet.
Belangrijk om te realiseren is dat jQuery uitsluitend client-side (in de browser) uitgevoerd wordt. Bij een postback gaat de state van een pagina verloren. Zijn de componenten in de AjaxControlToolkit (zie www.codeplex.com/AjaxControlToolkit) redelijk postback-bestendig, jQuery plugins zijn dat per definitie niet, jQuery is stateless. Een tab-control zal na iedere postback de eerste tab openen en dat is niet zo handig. Je kunt een hidden field toevoegen met het huidige tab nummer, daarmee kun je server-side de actieve tab controleren.
In combinatie met een UpdatePanel kunnen er verrassingen optreden omdat de jQuery plugin niet weet dat de html veranderd is. Er zijn twee manieren om dat te ondervangen. De eerste is een event handler op het ASP.NET AJAX framework, zie listing 7.
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
function EndRequestHandler(sender, args) {
if (args.get_error() == undefined) {
initJQ();
}
}
$(document).ready(function() {
initJQ();
});
function initJQ() {
// mijn code
}
</script>
LISTING 7, ASP.NET AJAX event handler initialiseert jQuery
De tweede manier is gebruik maken van jQuery "live events”, sinds versie 1.3 een onderdeel van jQuery. Dit is het koppelen van events aan bestaande, maar ook aan toekomstige (dynamisch gegenereerde) elementen. Zie listing 8.
$("a.mylinks").live("click", function(){
$(this).after(
$(document.createElement('a'))
.attr('href', 'javascript:void(0)')
.append($(document.createTextNode('generated link')))
.addClass('mylinks')
);
});
LISTING 8, jQuery “live event” binding
Overigens heeft jQuery uitstekende ajax functionaliteit in de core library. Daarmee kun je onder andere .NET page methods aanroepen. Op die manier kun je een lichtgewicht website maken, veel lichter dan wanneer je gebruik maakt van een UpdatePanel, maar ook minder makkelijk.
Conclusie
Het schrijven van toegankelijke, cross-browser JavaScript code wordt een stuk eenvoudiger gemaakt door een JavaScript library. Met behulp van de jQuery library schrijf je in korte tijd je eigen JavaScript toepassingen of voeg je eenvoudig bestaande plugins tot aan je project. jQuery is uitstekend te combineren met .NET. jQuery maakt het schrijven van JavaScript weer leuk!
Links
• Evident jQuery Showcase http://jqueryshowcase.evident.nl
• jQuery User Interface http://jqueryui.com/
• jQuery Intellisense in Visual Studio 2008 http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx
• Overzicht van jQuery plugins http://www.jqueryplugins.com/
• Overzicht van verschillende jQuery tutorials http://thethemeblog.com/tutorials/ultimate-collection-of-40-jquery-tutorials-and-resources