Joomla-projekti käynnissä ja yksi osa-alue on Ajax-pulikan tekeminen. Tähän mennessä olen jo näin pitkällä:
Ladattava pulikka on komponentti joka alunperin ladataan sivustolle wrapperimoduulin avulla ja sen jälkeen parilla linkillä klikkaillaan Ajax-toiminnallisuutta. Helppo nakki (no joo, oli siinä silti opettelemista). Ajaxilla ladattava urli näyttäisi about tältä: http://saitti.fi/?option=com_komponentti&task=teeJaTouhua
Konffasin kontrolleria jo siten, että muut tarvittavat parametrit (view, tmpl) oivalletaan siitä, että task on määritelty. Netistä löytyi kikka, joka selvitti, että jos tmpl == component, Joomla lataa periaatteessa vain komponentin tuottaman HTML:n. Mutta siinä on yksi mutta. Se silti wrappaa siihen ympärille doctype, html, head, body, lataa stylesheetit yms mums. Voiko sen välttää?
Seuraava asia koskeekin sitten Mootoolsia. Jquery-logiikallahan homma menee tietenkin näin:
var html = $(ajaxinPalauttamaMerkkijonoksiMuutettuVastaus); var theElementti = $('#elementinSelektori', html); $('#jokuToinenElementti').replaceWith(theElementti);
Eli suomeksi vielä poimia ajaxilla palautetusta merkkijonosta jokin elementti sisäkkäine elementteineen ja korvata sillä jokin muu. Olen ihan sopivasti ulalla siitä miten tämä toteutetaan MooToolsilla. MooToolsin dokumentaatio on tosi hankalaa luettavaa.
Jos tuo eka pulmani ratkeaa, niin tästä MooTools-onklemastahan tipahtaa sitten tuo elementin kalastaminen pois, koska onhan aina parempi siirtää niin vähän markupia kuin mahdollista.
Kiitos etukäteen avusta.
En nyt Joomlan sielunelämää juurikaan tunne, mutta ensimmäisen hakutuloksen ohjeessa sanotaan seuraavaa: Jos syötät Ajax-queryn mukana parametrin format: "raw"
niin Joomlan pitäis ymmärtää jättää wrappaukset pois.
http://www.wrox.com/WileyCDA/Section/id-306544.html:
By setting the format to raw (the second query parameter), Joomla executes the specified component and returns only the output that it has generated.
Samaa ehdottaa joomlatools-blogi Joomla!:n versiosta 1.5 etiäpäin.
Kokeilin, mutta mahdoinko tajuta?
http://saitti.fi/?option=com_komponentti&task=teeJaTouhua&format=raw tuottaa error 500, johtuen serverin konffauksista. Antaisin mielelläni oikean live-esimerkin, mutta en usko sen valitettavasti käyvän päinsä. Yritin tuota joka tapauksessa eri järjestyksessä, speksasin view, tmpl, kaikki turhat parametrit pois ja ei silti toimi.
:/
Tää ei nyt oikein rohkaise.
EDIT: Paitsi että sittenkin. Sain raw output pelaamaan, mutta kikka on siinä, että sille pitää jostain syystä olla oma view.
Seuraava vaihe mootoolsin kanssa: Linkin klikkaukseen bindattu klik-event toimii vain kerran. Johtuu siitä, että ajax palauttaa uuden linkin, johon ei eventti enää pädekään. Joskus oli jQuerynkin kanssa tällainen. Miten tästä eteenpäin?
Vaihtoehto 1: jQuerystä tutut live-eventit: Jay Carlson - Live Events in Mootools.
Element.implement({ addLiveEvent: function(event, selector, fn){ this.addEvent(event, function(e){ var t = $(e.target); if (!t.match(selector)) return false; fn.apply(t, [e]); }.bindWithEvent(this, selector, fn)); } }); // kutsuminen $(parentElement).addLiveEvent('click', 'selector', function(e){ alert('This is a live event'); });
Vaihtoehto 2: Bindaa eventti uuteen anchoriin samalla kun haet sen.
Jos linkkejä tulee useampia niin vaihtoehto 1 on luultavasti nopeampi jos vaan linkeillä on yhteinen parent
.
Tässä olisi nyt asiaan liittyvä JavaScript. Kokeilin tuota esimerkkiä, mutta ei futaa. Errori:
Uncaught TypeError: Object [object HTMLDivElement] has no method 'addLiveEvent'
Onko tuo Element-luokan laajennus väärässä paikassa (ja missä sen pitää olla jos on) vai onko minulla liian vanha MooTools (1.12), vai mikä mahtaa mättää?
window.addEvent('domready', function(){ Element.implement({ addLiveEvent: function(event, selector, fn){ this.addEvent(event, function(e){ var t = $(e.target); if (!t.match(selector)) return false; fn.apply(t, [e]); }.bindWithEvent(this, selector, fn)); } }); $$('.pelit').addLiveEvent('click', 'a.match-control', function(event){ event.preventDefault(); var url = this.href; var a = new Ajax(url, { method: 'get', onComplete: function(response){ $$('.pelit').setHTML(response); } }).request(); }); });
EDIT: Surkuhupaisaa. Tuo Jay Carlsonin ei näin -esimerkki, josta hän sanoo, että yäk, toimii täydellisesti.
Kyl tuo oikealta näyttää. Ei mitään hajua, että mille MooToolsin versiolle tuo vinkki on tehty. Carlsonin "yuck"-kommentti viittaa siihen, että rebindaus teettää selaimella ylimääräistä työtä. Kokeilitko, josko document.bodyyn
sitominen toimii (ei sillä, että sitä välttämättä suosittelisin, tässä ehkä mieluummin seuraava)? Voit jättää koodissasi removeEventsin
pois, koska ylikirjoitat setHTML:llä
kaikki ne elementit, joihin on sidottu poistettava eventti.
tsuriga kirjoitti:
Ei mitään hajua, että mille MooToolsin versiolle tuo vinkki on tehty.
Ei merkitystä enää, koska päivitin MooToolsin uusimpaan versioon compatibilityllä, eikä mitään muutosta.
tsuriga kirjoitti:
Kokeilitko, josko
document.bodyyn
sitominen toimii (ei sillä, että sitä välttämättä suosittelisin, lue etiäpäin)?
Kokeilin. Not work. Mutta ei se mitään. Tietysti olisi kiva selvittää täsmälleen mistä tämäkin kiikastaa ja tehdä asiat mieluummin kunnolla kuin sinne päin, mutta pääsin silti eteenpäin näinkin. Eli suurkiitos avusta.
On tuo silti mystinen juttu. Tuo Element.implement -kohta käytännössä kirjoittaa Element-luokalle uuden metodin, mutta jotain siinä menee vinoon, koska kun Elementistä luodaan instanssi ja kutsutaan metodia, sitä ei ole. :/
Ei tuo eventtien sitominen onCompletessa
miusta niin huono vaihtoehto tässä tapauksessa ole (ellei se nyt oikeasti ala olemaan hidas), kun voidaan jättää edellisten eventtien poistaminen pois. Semantiikka on tietysti hieno asia :). Selvensin vielä omaa viestiäni viestisi jälkeen.
Jos live eventit toimisivat niin voisit korvata tuon koko Ajax.requestin
tällä: $$('.pelit').load(this.href);
.
EDIT: Tutkinpa tuota implementtiä...
Function.bindWithEvent
on näköjään deprekoitu. Jätin sen pois ja toimii hyvin (testattu Fx5, Opera 11, Chrome 11, IE 9). Vaihdoin myös e.preventDefaultin
tilalle MooToolsin Event.stopin
, joka toimii varmemmin cross-browser tukea haettaessa. Jätin Element.implementin
ulos domreadystä
, koska skripti ladataan aina vasta MooToolsin latauduttua. Demo täällä, toimii myös kun JavaScript on pois päältä.
Element.implement({ addLiveEvent: function(event, selector, fn) { this.addEvent(event, function(e) { var t = $(e.target); if (!t.match(selector)) return false; fn.apply(t, [e]); }); } }); window.addEvent('domready', function() { $$('.pelit').addLiveEvent('click', 'a.match-control', function(event) { event.stop(); $$('.pelit').load(this.href); }); });
Jos haluat rajata painallukset kattamaan vain hiiren ykkösnapin painallukset JA jokin selain käyttäytyy tällaisessa tilanteessa virheellisesti, voit kokeilla lisätä ennen event.stoppia
ehdon if (event.which === 1 && !event.metaKey)
. Bongasin tämän Ajaxify snippetistä, mutta mieltäisin modifiereiden käsittelyn kyllä selaimen tehtäväksi. Pikatesti Fx:llä näyttäisi tukevan tätä ideaa.
EDIT: Päivitin hieman tekstejä, hajoo naama tällä hetkellä MooToolsin Request.HTML:ään
et pieni breikki ja uutta yritystä.
EDIT2: Alkuperäinen tarkoitus oli lisätä demoon mukaan skriptattu kakutus sekä URLin päivitys History.js:ää apuna käyttäen. Jos sen nyt jussin jälkeen toteutetan niin mainostanen sitä Ajax URL -keskustelussa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.