Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: JavaScript: XML-haun täydentäminen jQueryllä

tsuriga [10.01.2011 08:36:31]

#

Vinkin pääasiallisena tarkoituksena on demota yksinkertaista XML-datasta hakemista ja automaattista täydennystä jQueryllä sekä jQuery UI:llä. Selostan ohessa sekä kuvauksessa että itse koodissa myös muutamia vinkissä käytettyjä hyviä kaista- ja nopeusoptimoinnin käytänteitä sivun merkkaukseen, ulkoisiin resursseihin ja JavaScriptiin liittyen. Itse koodivinkissä näytetään hakulaatikko, johon kirjoittamalla käyttäjälle näytetään syöte-ehdotuksia haettujen XML-tietojen pohjalta. Käyttäjän selatessa ehdotuksia näytetään myös esikatselu valittaviin tietoihin. Vinkki pohjautuu jQuery UI:n sivuilta löytyvään XML-demoon, jonka päivitin ja purin auki helppolukuisammaksi kommenttien avulla.

Rakenteen merkkauksesta (HTML5)

DOCTYPE on nykyään karsitun yksinkertainen ja type-attribuutit voidaan jättää CSS- ja JavaScript-tiedostojen tapauksessa merkitsemättä, kunhan palvelin tarjoilee ne oikeilla MIME-tyypeillä. Esimerkissä käytin script-tagin boolean-ominaisuutta defer, joka määrittää skriptin taustalla ladattavaksi, mutta vasta sivun parsimisen päätyttyä suoritettavaksi. Taustalla lataaminen nopeuttaa on hyötyä varsinkin suuremmilla sivuistoilla, joilla käytössä olevia skriptejä saattaa olla kymmeniä. Attribuuttien async ja defer määritelmät ja selaintuki on vasta työn alla.

Sivuston merkistön määritteleminen mahdollisimman aikaisessa vaiheessa dokumenttia on suositeltavaa nopeuden ja turvallisuuden kannalta. Jos et voi vaikuttaa palvelimen lähettämiin otsikkotietoihin kuten esimerkissä, HTML5 tarjoaa myös yksinkertaistetun <meta charset="utf-8"/>-tagin.

Ulkoiset resurssit

Tekstimuotoiset ulkoiset resurssit (CSS, JavaScript) kannattaa minimoida, yhdistää, pakata ja kakuttaa.

Minimointi ja yhdistäminen
Minimoinnilla tarkoitetaan koodin toiminnan kannalta ylimääräisten merkkien poistamista. CSS- ja JavaScript-tiedostot voidaan minimoida YUI Compressorilla. Muista säilyttää projektistasi myös alkuperäiset tiedostot. Yhdistämisellä tarkoitetaan samantyyppisten ulkoisten resurssien yhdistämistä suuremmiksi kokonaisuuksiksi, jolloin käyttäjän ja palvelimen väliset yhteydenotot vähenevät. Demossa pakkasin haetut tiedostot palvelinpään PHP-skriptillä, koska pakkaus HTTP-palvelinohjelmalla ei luonnistunut.

Pakkaus ja kakuttaminen
Pakkaamisella tarkoitetaan resurssien tiivistämistä esimerkiksi gzip-algoritmilla selaimen sitä tukiessa. Kakuttaminen taasen on huono suomennos englanninkieliselle termille caching, joka tarkoittaa resurssien lataamista välimuistiin. Perusperiaatteena on, että harvemmin muuttuville resursseille ohjeistetaan pidempää elinaikaa selaimen välimuistissa. Tässä vinkissä en asioita sen tarkemmin esittele, mutta näihin löytyy erinomaisia neuvoja muun muassa tästä Merrin viestistä ja tästä Viral Patelin artikkelista.

Kuvien optimointi
Kuvat, varsinkin PNG-kuvat, voidaan optimoida. Demossa käyttämäni Sunny-teeman kuvat pienenivät koosta 45kB kokoon 33kB (~27 % säästö) pngrewrite- ja pngout-ohjelmien avulla. Ainakaan Googlen sisältöpalvelimilta ladattavat kuvat eivät vielä kirjoitushetkellä olleet optimoituja, joten demossa kuvat tarjoillaan esimerkin vuoksi omalta palvelimelta. Tosielämässä hyödyt staattisen sisällön hakujen keskittämisestä sisältöpalvelimille ohittavat käyttäjän mahdollisen kaistansäästön hyödyn. Kuvienpienennyskripti PNG-kuville löytyy kuvauksen lopussa olevan linkin takaa.

Mikäli kaistan kulutusta haluaa optimoida vielä enemmän, CSS-merkkauksesta voi poistaa merkinnät, jotka eivät ole käytössä omalla sivustolla. Lisäsäästöä kaistan ja toimintojen nopeuteen tuo myös osoitteiden pitäminen lyhyenä ja rakennemerkkauksen pitäminen mahdollisimman yksinkertaisena, jolloin selaimen ei tarvitse muodostaa monimutkaista dokumenttipuuta. Resurssien karsimisessa kannattaa kuitenkin olla tarkkana ja tutkia palvelimen lokitiedostoja puuttuvien tiedostojen varalta. Asiassa voi auttaa esimerkiksi YSlow-lisäosa.

JavaScript
Jos kaikki skriptit merkitään ladattavaksi otsikkotiedoissa, skriptit ladataan ennen sisältöä ja täten itse sivun näyttäminen hidastuu. Skriptien latauksessa tulee pitää mielessä niiden kriittisyys sivun toiminnan kannalta – sivun toiminnan mahdollistavat skriptit haluttaneen suorittaa mahdollisimman nopeasti tarvittavan sisällön latauduttua, mutta toimintaa täydentävät voidaan jättää myöhemmäksi. Kannattaa myös huomata CSS- ja JavaScript-tiedostojen latausjärjestys: JavaScript-skriptit ovat usein riippuvaisia toisista skripteistä, ja CSS:ssä toistuvat ulkoasusäännöt korvaavat toisensa. Jos haluat näyttää sivun rakenteen, halunnet näyttää sen myös tyyliteltynä heti alusta alkaen. Useat ulkoiset resurssit, kuten JavaScript-kirjastot ja jopa ulkoasuresurssit, voidaan merkitä ladattaviksi suurilta sisältöpalvelimilta. Esimerkissä jQuery ladataan Googlen tarjoamasta CDN:stä. jQuery UI on kokonaisuudessaan erittäin suuri kirjasto, joten se kannattaakin useasti tarjoilla käyttäjälle vain tarvittavat toiminnallisuudet sisältävänä.

Demo, lyhentämätön toteutus sekä PNG-kuvien optimointipaketti löytyvät osoitteesta http://theunnamedclan.org/tsuri/showcase/xmljquery/. Lisätietoa web-sivustojen optimoinnista löytyy Googlen Web Performance Best Practices -sivustolta.

Listaukset

xmljquery.js

/**
 * Detailed example of searching through
 * XML data and autocompleting with jQuery
 * and jQuery UI.
 *
 * @author tsuriga
 */

$(document).ready(function() {
    // Do an HTTP GET query to XML data
    $.get(

        // Path here is relative to the document's base URL
        'data/bookshelf.xml',

        /*
         * The success function that is run if
         * the HTTP GET query succeeded
         */
        function(xml) {

            // Fetch all book-tags in the XML data
            var bookTags = $('book', xml);

            // Map book nodes into autocomplete's selection options
            var bookMap = bookTags.map(function() {

                return {
                    // Text to display for this option
                    value: $('title', this).text(),

                    // Attach also book's author and year
                    author: $('author', this).text(),
                    year: $('year', this).text()
                };
            });

            // Fetch the mapped values as an array
            var books = bookMap.get();

            /*
             * Memorize the node and content object here so that there
             * is no need to always do a new DOM tree search or create
             * a new object whenever user focuses an item.
             */
            var preview = $('#preview');
            var content = '';

            // Assign autocomplete function to search input
            $('#search').autocomplete({

                // Use the book array as source for completion
                source: books,

                // Peek into data on each focus event
                focus: function(event, ui) {

                    /*
                     * Accumulate HTML for preview
                     *
                     * Notice how our previously set variables
                     * from the mapping procedure can now be
                     * read here in the ui.item property.
                     */
                    content = '<h3>' + ui.item.value +
                        ' (' + ui.item.year + ')</h3>' +
                        '<h4>' + ui.item.author + '</h4>';

                    // Show the HTML in the preview box
                    preview.html(content);
                },

                // Clear preview on select event
                select: function(event, ui) {
                    preview.html('');
                }
            });
        }
    );
});

index.php

<?php
header('Content-type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
 <head>
  <title>Example: Autocomplete an XML search with jQuery</title>
  <link rel="stylesheet" href="css/xmljquery.min.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" defer></script>
  <script src="js/xmljquery.min.js" defer></script>
  </head>
 <body>
  <input id="search" size="60" />
  <div id="preview">
  </div>
 </body>
</html>

villev [10.01.2011 14:23:15]

#

Hyvä vinkki! Suuret kiitokset, tämä antoi paljon ideoita ja parannuskeinoja!

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta