SPA-portletti on toteutettavissa käyttäen pelkästään jQuery-kirjastoa, tässä käydään läpi ydinkohdat.
Sivujen dynaamiseen esittämiseen on ainakin kaksi käyttökelpoista, vaihtoehtoista tapaa:
1. Ladataan sivun kaikki sisältövaihtoehdot kerralla, sivua alunperin ladattessa:
Vaihtoehtoinen sisältö sijoitetaan peräkkäisten div-elementtien sisällöksi. Toiminnan aikana hallitaan, mikä div-elementti sisältöineen näytetään, tai voidaan näyttää useitakin div-lohkoja kerralla. Latautumisvaiheessa voidaan säädellä sivujen latautumista esim. käyttäjän oikeuksien perusteella, jotka luetaan aloitussivun scriptletissa.
Koodiesimerkki div-lohkojen latautumisesta käyttäen yksinkertaista jsp-include tagia:
<% if (bPermOne) { %> <jsp:include page="/html/jqpure/contentOne.jsp" /> <% } %> <% if (bPermTwo) { %> <jsp:include page="/html/jqpure/contentTwo.jsp" /> <% } %>
Ladattavat sivut ovat normaaleja JSP-sivuja, joissa elementien id:iden yksilöinnissä on käytetty tagia. Sivuun liittyvä alustusdata voidaan hakea Ajaxilla sivun latautumisen jälkeen, mutta mahdollista on myös tuoda data sivulle perinteisen portlet-sivun tapaan. Yksinkertaisempaa on käyttää Ajaxia tässäkin, jos sitä käytetään muualla portletin sivuilla.
Div-lohkojen näkyminen voidaan hallita HTML-elementin style.display -määrityksellä. Visibility-määritys ei käy, koska se jättää näytölle kohdalleen tyhjän tilan, vaikka sisältö häviääkin.
Koodiesimerkki div-elementin näkyvyyden hallinnasta:
var divElem = document.getElementById(gsNamespace + sActiveId); divElem.style.display = "inline"; // piilottava on "none"
Tämä tapa on helppo ja selkeä, ja suositeltava niissä tapauksissa, missä käyttöoikeudet eivät rajoita koodin näkymistä selaimen sivukoodissa. Tämä ratkaisu mahdollistaa myös piilossa olevan sivun käytön Javascript-koodissa, piilosivulle voidaan esimerkiksi ladata dataa taustalla jo ennen sivun näyttämistä.
2. Ladataan sivu dynaamisesti käytön aikana:
Dynaaminen sivu ladataan suoravaisesti Javascriptissa jQuerylla pääsivun div-lohkon sisällöksi. Tähän jQuery käyttää omaa load-metodiaan, joka hakee sivun sisällön Ajaxilla palvelimelta, eikä sitä tarvitse koodata itse:
.... // esittele globaalit muuttujat JSP-sivulla ja tallenna ne js-muuttujiin: var gsNamespace = "<portlet:namespace />"; // jsp-pääsivulta var gsContextPath = "<%=request.getContextPath()%>"; // pääsivulta jsp:n request-muuttujasta .... var sViewPage = "/html/sovellus/jspsivu.jsp"; // jsp-sivu ladattavaksi var sPage = gsContextPath + sViewPage; var sDivId = gsNamespace + sDivSomeId; // lataa sPage-sivun sDivId:n osoittaman div-elementin sisällöksi: jQuery("#" + sDivId).load(sPage);
Sivua voi vaihtaa toiseen yksinkertaisesti, kirjoittaa vain uuden sivun vanhan päälle. Vanha sivu sisältöineen häviää. jQueryn load-metodi ei rajoitu div-elementteihin, mutta div-elementti on yleinen tapa merkitä yhtenäinen lohko HTML-sivulla.
Ongelmana tässä on, että vaikka dynaamisesti ladattava JSP-sivu prosessoidaan normaalisti JSP-sivuna, Liferay tagitusta ei prosessoida, kuten tapahtuu sivua perinteiseen tapaan portleteissa ladatessa tai vaihtoehdossa 1 edellä. Niinpä sivulla olevat elementtien id:t, jotka sisältävät <portlet:namespace /> -tagin, on esitettävä toisin: doView-metodissa kirjoitetaan portletin namespace-tieto talteen (esim. johonkin Java-luokkaan staattiseksi tiedoksi). Namespace on luettavissa vaikkapa doView-metodissa kutsulla
renderResponse.getNamespace().
Ladattavassa JSP-sivuissa portletin namespace-tieto haetaan scripletissa (tässä String tyyppiseen ns-muuttujaan). JSP-sivulla sitä käytetään normaalisti, esim.
...
Tähän JSP-sivuun liittyvässä Javascriptissa kyseiseen HTML-elementtiin viitataan normaalisti:
var elem = document.getElementById(gsNamespace + sDivSomeId).
Javascriptin gsNamespace- ja Javan ns-muuttuja sisältävät siis saman tiedon.
jQuerya käytetään myös Ajax-pohjaisten palvelinkutsujen välittämiseen. Nämä kutsut portletin Java-koodin serveResource-metodiin ovat ainoat tavat hakea dataa serverilta. JSP-sivun alkulatauksen jälkeen tarvittavat toiminnot koodataan normaalisti window.onload -eventin käsittelymeteodiin, josta sieltäkin kutsutaan Ajax-toimintoja.
Pelkästään jQuerya käytettäessä ei kannata yrittää tehdä SPA-instanceable-portlettia, joka tarkoittaa SPA-portlettia, joka esitetään useaan kertaan samalla portaalisivulla. Ratkaisu menee liian vaikeaksi. Kaksi tai useampia jQuery-SPA -portlettia voidaan kyllä laittaa samalle portaalisivulle, kunhan portlettien nimiavaruudet ovat käyttöliittymässä uniikkeja.
History-toiminto ei toimi automaattisesti siten, että se muistaisi jQuerylla dynaamisesti avatut sivut. Jos tätä tarkkuutta tarvitaan, on history-toiminto koodattava itse. Tähän tarkoitukseen voi käyttää Javascriptissa olevia window.history.pushState- ja popState-toimintoja.