Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Javascript: pikkukuvien suurennus

Sivun loppuun

pistemies [16.03.2009 17:16:37]

#

Tämä liittyy tuohon edelliseen. Kullakin rivillä näytetään yksi 160 px levyinen kuva (tästä klikataan se suurin kuva,josta edellisessä ketjussa kysyin) ja kaksi ihan pientä kuvaa. Noita pienimpiä kuvia pitäisi pystyä vaihtamaan vuorollaan niin, että näytetään tuossa 160px levyisenä , kun taas kuva, joka sinä on, siirtyisi ihan pikkukuvaksi.
Php:lla olen tämän saanut tehtyä, mutta tuo sama pitäisi saada javascriptillä, jotta sivu ei klikatessa "hypähdä" ylös.

Ps. Kyselyyn: Miksi näin monen kokoisia kuvia ? :)
V: Jotta kuvat ei vie turhaa tilaa sivulla.

Metabolix [16.03.2009 17:51:10]

#

Tässä on tyypillistä JS-kikkailua kuvien osoitteiden kanssa:

<!-- XHTML -->
<div id="kuvat">
  <img src="kuva1.pieni.jpg" alt="" />
  <img src="kuva2.pieni.jpg" alt="" />
  <img src="kuva3.pieni.jpg" alt="" />
</div>
// JS
var img_suuri = null;
function suurenna(img) {
  if (img_suuri) {
    img_suuri.src = img_suuri.src.replace(".suuri.", ".pieni.");
  }
  img.src = img.src.replace(".pieni.", ".suuri.");
  img_suuri = img;
}
window.onload = function () {
  var kuvat = document.getElementById("kuvat").getElementsByTagName("img");
  for (var i in kuvat) {
    kuvat[i].onclick = function() { suurenna(this); };
  }
}

Tässä taas kaikki kuvat on laitettu suoraan sivulle, tyylittely hoidetaan CSS:llä ja vain suurennetun valinta JS:llä.

<!-- XHTML -->
<div id="kuvat">
  <img src="kuva1p.jpg" class="pieni" alt="" /><img src="kuva1.jpg" class="suuri" alt="" />
  <img src="kuva2p.jpg" class="pieni" alt="" /><img src="kuva2.jpg" class="suuri" alt="" />
  <img src="kuva3p.jpg" class="pieni" alt="" /><img src="kuva3.jpg" class="suuri" alt="" />
</div>
/* CSS */
/* suuret ja valittu pieni piiloon */
.suuri, #pieni {
  display: none;
}
/* sen sijaan valittu suuri saa näkyä */
#suuri {
  display: inline;
}
// JS
function pienenna(img_suuri) {
  if (!img_suuri) return;
  img_suuri.id = null;
  img_suuri.previousSibling.id = null;
}
function suurenna(img_pieni) {
  pienenna(document.getElementById("suuri"));
  img_pieni.id = "pieni";
  img_pieni.nextSibling.id = "suuri";
}
window.onload = function () {
  var kuvat = document.getElementById("kuvat").getElementsByTagName("img");
  for (var i in kuvat) {
    var img = kuvat[i];
    if (img.className == "pieni") {
      img.onclick = function() { suurenna(this); };
    } else if (img.className == "suuri") {
      img.onclick = function() { pienenna(this); };
    }
  }
}

Kumpaakaan koodia en testannut.

pistemies [16.03.2009 18:02:59]

#

Kiitoksia.

Php:lla olen tehnyt siten, että kaikkien pienten kuvien nimet on arrayssa. Ensimmäisenä arrayssa oleva kuva tulostetaan 160px levyisenä, muut pienempinä. Kun klikataan noita ihan pikkukuvia, arrayn järjestys muuttuu.

Voiko tuota samaa tekniikkaa soveltaa javascriptiin ja jos voi, onko se hyvä vai huono konsti?

Metabolix [16.03.2009 19:53:48]

#

Kannattaa lähteä liikkeelle siitä, millä tavalla tarkalleen haluat sivun toimivan.

A) "Kuvat ovat sivulla muuttuvassa järjestyksessä ja ensimmäinen tulostetaan isompana." Loogisesti data on tällöin tuo mainitsemasi taulukko, jossa kuvat ovat halutussa järjestyksessä ja jota siis muutetaan tarpeen mukaan.

B) "Kuvat ovat aina samassa järjestyksessä, mutta yksi pitää piirtää isompana." Tässä tapauksessa on järkevää pitää kuvat siinä oikeassa järjestyksessä ja muulla keinolla ilmaista, että tämä yksi on nyt suurempi. Tämän tilanteen käsittelin koodeissani, koska alkuperäinen viestisi ei antanut erityisesti aihetta olettaa muuta.

C) "Pienet kuvat ovat tässä ja iso(t) tuossa keskemmällä."
C1) "Kuvien järjestys pysyy kuitenkin aina samana." Tilanne on siis käytännössä sama kuin B, eli kannattaa ilmaista suuruus muulla tavalla.
C2) "Suuri kuva menee aina listan alkuun/loppuun, kun se pienennetään." Nyt taas olisi loogista käyttää kahta taulukkoa, joista toisessa pidetään suuret ja toisessa pienet kuvat. Klikatessa siirretään kuva taulukosta toiseen.

Säilytä aina sellaista tietoa, joka parhaiten kertoo, mistä on kyse. Toki asiat onnistuvat muutenkin, kun hieman vääntää, mutta logiikka on tehokkaan ohjelmoinnin perusta.

pistemies [16.03.2009 22:21:11]

#

Kiitoksia. Nyt vasta ehdin noita testaamaan ... :9

Ps. Testasin tuota ylempää. En saanut tuota kunnolla toimimaan.

Metabolix [17.03.2009 00:28:08]

#

Korjasin koodeissa olleet minimaaliset virheet ja testasin kumpaakin. Nyt ne toimivat ainakin Firefoxilla.

pistemies [17.03.2009 18:31:36]

#

Toimii aika hyvin. Tein testissä tällaiset muutokset, eli muutetaan skriptissä hakemiston nimeä.

<div id="kuvat">
<img src="photos160/237_1.jpg" />
<img src="thumb/237_2.jpg" />
<img src="thumb/237_3.jpg" />
</div>

Yksi asia pitäisi jotenkin saada...
Tuossa windwo.onload funktiossa tai jossakin, pitäisi tehdä niin, että kuva, joka on suurin, tulostuu aina tuossa ekana. Pitäisikö kuville laittaa vaikka "sarjanumero": name="237_1" ja muutetaan replacessa suurennetun kuvan name ykköseksi ja tulostetaan noiden numeron järjestyksessä?

....

pistemies [17.03.2009 22:55:44]

#

Tähän on tultu:

var nro = null;
function thumbs237(nro){
var arr = new Array(3);

arr[0] = "237_1.jpg";
arr[1] = "237_2.jpg";
arr[2] = "237_3.jpg";
var nr = nro-1;
arr.splice(0,0,arr[nr]);
arr.splice(nr,2,arr[nr]);

return(arr);

}

Tuon funktion tiedot luodaan php:lla, mutta lähdekoodissa se tulostuu noin.
Tuo vaihtaa arrayn arvot keskenään, mutta on tulostusongelma. Miten saan arrayn silmukan tulostamaan muutoin kuin arrayn avaimen mukaan ?
Pitäisi löytää javascriptistä array_keys kaltainen toiminto. Onnistuuko sellainen tulostus?

Metabolix [17.03.2009 23:15:56]

#

Minulle ainakin jäi kovasti epäselväksi, mitä nyt haluat saada aikaan. Jos tarkoituksena on saada rivi pikkukuvia ja yksi iso, voit soveltaa vaihtoehtoa C, jossa valittu pikkukuva piilotetaan ja vastaava osoite laitetaan isolle kuvalle (aina sama elementti, #suuri):

<!-- XHTML -->
<img id="suuri" src="tyhja.png" alt="" />
<div id="kuvat">
  <img src="kuva1.pieni.png" alt="" />
  <img src="kuva2.pieni.png" alt="" />
  <img src="kuva3.pieni.png" alt="" />
</div>
// JS
var img_suurennettu = null;
function suurenna(img) {
  if (img_suurennettu) {
    img_suurennettu.id = null;
  }
  var img_suuri = document.getElementById("suuri");
  img_suuri.src = img.src.replace(".pieni.", ".suuri.");
  img_suuri.alt = img.alt;
  img_suurennettu = img;
  img_suurennettu.id = "suurennettu";
}
window.onload = function () {
  var kuvat = document.getElementById("kuvat").getElementsByTagName("img");
  for (var i in kuvat) {
    kuvat[i].onclick = function() { suurenna(this); };
  }
  if (kuvat.length) {
    suurenna(kuvat[0]);
  }
}
/* CSS */
/* piilotetaan suurennetun kuvan pieni versio */
#suurennettu {
  display: none;
}

Jos välttämättä haluat tuohon taulukkokikkailuun ruveta, on ehkä selkeämpää unohtaa splice ja käyttää sen sijaan deleteä ja pushia (tai unshiftia):

function ensimmaiseksi(t, i) {
  var tmp = t[i];
  delete t[i];
  t.unshift(tmp);
}

Taulukkoja voi käydä läpi, kuten koodeistani näkyy:

for (var i in taulu) {
  alert(i + ": " + taulu[i]);
}

pistemies [18.03.2009 00:43:34]

#

Moi.
Tuo funktio toimii aivan okein. Sitä lienee turha muutella. On peljästään funktion / arrayn tulostusongelma.

Tämän hetkinen yhden rivin kuvien koodi kokonaisuudessaan:

<script type="text/javascript">
var nro = null;
function thumbs237(nro){
var arr = new Array(3);

arr[0] = "237_1.jpg";
arr[1] = "237_2.jpg";
arr[2] = "237_3.jpg";
var nr = nro-1;
arr.splice(0,0,arr[nr]);
arr.splice(nr,2,arr[nr]);

return(arr);

}


var arr2 = new Array();
arr2 = thumbs237(1);

var pituus = arr2.length;
for(i=0;i<pituus;i++){

if(i == 0){
document.write('<div class="iso"><a href="photos/' + arr2[0] + '"  rel="lightbox[roadtrip]"><img src="photos160/' + arr2[0] + '" alt="1"></a></div></td></tr>');
}

if(arr2[1] !='' && i == 1){
arr21 = arr2[1].split("_");
arr211 = arr21[1].split(".");
num = arr211[0];
document.write('<tr><td class="kuvat-ala-rivi"><table><tr><td class="thumb"><div class="small"><a href="test.php?r=237&im=' + num + '" onclick="thumbs237(2);return false"><img src="thumb/' + arr2[1] + '"  alt="2"/></a></div></td>');
}
if(arr2[1] == '' && i == pituus){
document.write('</tr></table>');
}

if(arr2[2] !='' && i == 2){
arr22 = arr2[2].split("_");
arr221 = arr22[1].split(".");
num2 = arr221[0];
document.write('</td><td class="thumb"><div class="small"><a href="test.php?r=237&im=' + num2 + '" onclick="thumbs237(3);return false"><img src="thumb/' + arr2[2] + '" alt="3"/></a></div></td></tr></table>');
}
}
</script>

Nyt tuo tulostus toimii oikein. Ongelma on muuttunut siten, että tuo return false linkissä vaikuttaa siten, ettei tee mitään. Sen puuttuminen muuttaa siten, että sivu hypähtää ylös.

Muuttujista linkkeissä :
r = kyseisen rivin kuvat (ei huomioida muilla riveillä olevia kuvia, joissa on sama im-muuttuja)
im = kuvan järjestysnumero (loppuosa 1, 2, tai 3). Tämä vaikuttaa riviin arr2=thumbs237(1)
Onclickin thumbs(2) hakee taas saman kuvan arrayn järjestysnumeron mukaan.

Metabolix [18.03.2009 01:22:38]

#

Minkä ihmeen takia haluat tulostaa sivun JS:llä? Siinä ei ole kerrassaan mitään järkeä, ja document.write on suuri paha, jota pitää välttää kuin ruttoa. Erityisen älytöntä on JS:llä printata turhia a-tageja, kun olennaiset kohdat ovat img-tagi ja onclick-tapahtuma.

Unohda erikoiset kikkailut ja laita data sellaiseksi, että se vastaa tarkoitusta, kuten jo aiemmin yritin selittää. Juuri tuohon koodiin tarkennuksena sanon, että laita yhdelle asialle (kuten kuvan järjestysnumero) aina yksi muuttuja (tai objektin jäsen tms.) äläkä sorru split-kikkailuihin. Muuten kiroat itseäsi, kun palaat tuon koodin pariin parin kuukauden tauon jälkeen.

Kirjoitat niin käsittämätöntä puuroa, etten jaksa tuohon vakavissani paneutua. Koodista on hankala käsittää mitään, kun muuttujat ovat "arr", "arr2", "arr21" jne. eikä kyseessä ole kuin satunnainen pätkä JS:ää, jonka kontekstista ei ole (vieläkään) tarkempaa tietoa.

Jos nyt malttaisit vähitellen selittää täsmällisesti, millaisen sivun haluat, olisi helpompi kertoa, miten se kannattaa toteuttaa. Kysymyksesi on valitettavasti edelleen tasolla "tein tällaisen koodin eikä se ihan toimi oikein" ilman tarkempia taustatietoja.

pistemies [18.03.2009 16:14:41]

#

Lyhyt selonteko sivusta:

Yhdellä sivulla näkyy n. 30-40 eri ilmoitusta. Jokaisessa voi olla 1-3 kuvaa ilmoituksen jättäjän valinnan mukaan. Yhdellä sivulla voi olla siis jopa 100 kuvaa.

Jokaisen ilmoituksen pienoiskuvat tulostuu tuon yllä olevan html-koodin mukaisesti:

<table>
<tr><td> .... 1: kuva 160 px  .......  </td> </tr>
<tr><td> 2: kuva 60 px </td> <td> 3: kuva 60 px </td> </tr>
</table>

Kunkin ilmoituksen pikkukuvia pitää pystyä vaihtamaan keskenään siten, että esim. kuva 3 siirtyy kohtaan 1 näkymään 160 px levyisenä. Tuolloin kuva 1 siirtyy kohtaan 2 ja kuva 2 kohtaan 3. Jos ollaan esim. katsomssa sivun alalaidassa olevan ilmoituksen kuvia, sivu täytyy pysyä auki sillä kohtaa, kun kuvaa vaihdetaan. Tämä on ainoa syy miksi olen ryhtynyt käyttämään tässä asiassa javascriptiä.

Miksi sitten käytän tuollaista arrayta. Koska en ole kovinkaan paljon opetellut javascriptiä. Tuollainen, jossa asia tehdään hiukan samoin kuin php:lla, on minulle kaikkein helpoin tapa käyttää javascriptiä.

Ps. En tulosta sivua javascriptillä, pelkästään tuon pien osan sivua, joka sisältää nuo pikkukuvat. Mutta tuokin osa, missä on javascriptiä, muotoillaan ensin php-funktiolla (kuten js-funktion yksilöllinen nimi) ja tulostetaan php:lla sivulle lopuksi näin: echo $kuvat; , Tuo javascript-koodi ei toimi tuollaisenaan ilman php:ta, joka vaihtaa im-numeron.

Ps 2: Kuvatiedostojen nimet on tosiaan myös tuon esimerkin mukaan. Pienet, suuremmat ja suurimman kuvan erottaa toisistaan vain kuvahakemiston nimi, ei tiedostonimi.

Ps 3: Muotoilusyistä kunkin kuvan ympärillä on oma div, niillä ei ole yhteistä div-elementtiä.

pistemies [18.03.2009 17:33:37]

#

Tuolta voi katsoa, millä tavoin kuvat tulostuu sivulle:
http://www.aijaa.com/v.php?i=3830008.jpg

Tuota tulostustyyliä ei ole tarkoitus muuttaa mitenkään javascriptin käytön takia.

pistemies [18.03.2009 19:07:17]

#

Minulle ei aukea yhtään, miten tätä pitäisi muuttaa, jotta soveltuisi tuohon taulukkoon.

// JS
var img_suurennettu = null;
function suurenna(img) {
  if (img_suurennettu) {
    img_suurennettu.id = null;
  }
  var img_suuri = document.getElementById("suuri");
  img_suuri.src = img.src.replace(".pieni.", ".suuri.");
  img_suuri.alt = img.alt;
  img_suurennettu = img;
  img_suurennettu.id = "suurennettu";
}
window.onload = function () {
  var kuvat = document.getElementById("kuvat").getElementsByTagName("img");
  for (var i in kuvat) {
    kuvat[i].onclick = function() { suurenna(this); };
  }
  if (kuvat.length) {
    suurenna(kuvat[0]);
  }
}

Olen yrittänyt hommaa muuttamalla/lisäämällä pikkukuvien yhteiselle taulukolle id:n "pikkukuvat237" (kunkin ilmoituksen mukaan). Lisäksi lisäsin suurimmalle kuvalle id:n "iso237". Kunkin kuvan alt on 1,2, ja 3.
Replaceen muutin hakemiston nimen. Pitäisikö replacessa muuttaa myös tiedostonimi ja suorittaa se myös pikkukuville?

Metabolix [18.03.2009 20:42:04]

#

Heti helpotti ratkaisua, kun kerroit täsmällisemmin sisällöstä. Kyllähän nuo edelliset tosiaan olivat vähän hakoteillä siihen nähden.

Puhtaasti HTML:n avulla ongelmasi ratkeaa tietenkin niin, että asetat suuren kuvan a-tagille id:n ja laitat sen myös suurennuslinkin osoitteen perään (#kuva237), jolloin lukija päätyy suurennuksen jälkeen takaisin tuon kuvan kohdalle.

Jos kuvien määrä on varmasti tiedossa (max. 3) ja nimet ovat tosiaan id_1, id_2 ja id_3, voit tietysti tehdä funktion sen mukaan. Yksi mahdollisuus on tietenkin asettaa kuville id:t niin, että elementit on helppo löytää ja tunnistaa, ja kirjoittaa molemmille pikkukuville asiaankuuluva onclick-funktio.

<!-- XTHML -->
<div>
<a href="kuva_1_1.hieno.png">
  <img class="suuri" id="ilmoitus_1_suuri" src="kuva_1_1.suuri.png" alt="" />
</a>
<img class="vasen" id="ilmoitus_1_vasen" src="kuva_1_2.pieni.png" alt="" />
<img class="oikea" id="ilmoitus_1_oikea" src="kuva_1_3.pieni.png" alt="" />
</div>

<div>
<a href="kuva_2_1.hieno.png">
  <img class="suuri" id="ilmoitus_2_suuri" src="kuva_2_1.suuri.png" alt="" />
</a>
<img class="vasen" id="ilmoitus_2_vasen" src="kuva_2_2.pieni.png" alt="" />
<img class="oikea" id="ilmoitus_2_oikea" src="kuva_2_3.pieni.png" alt="" />
</div>

<div>
<a href="kuva_3_1.hieno.png">
  <img class="suuri" id="ilmoitus_3_suuri" src="kuva_3_1.suuri.png" alt="" />
</a>
<img class="vasen" id="ilmoitus_3_vasen" src="kuva_3_2.pieni.png" alt="" />
<img class="oikea" id="ilmoitus_3_oikea" src="kuva_3_3.pieni.png" alt="" />
</div>
/* CSS */
.suuri {
  display: block;
}
.vasen, .oikea {
  display: inline;
}
// JS
function src_pieneksi(src_suuri) {
  return src_suuri.replace(".suuri.", ".pieni.");
}
function src_suureksi(src_pieni) {
  return src_pieni.replace(".pieni.", ".suuri.");
}
function src_linkiksi(src_suuri) {
  return src_suuri.replace(".suuri.", ".hieno.");
}
function aseta_kuvat(k1, k1_src, k2, k2_src, k3, k3_src) {
  if (k1) k1.src = k1_src;
  if (k2) k2.src = k2_src;
  if (k3) k3.src = k3_src;
  if (k1) {
    var a = k1.parentNode; // linkki suuren kuvan ympärillä
    a.href = src_linkiksi(k1_src);
  }
}
function kierrata(p1, s, p2) {
  if (p2) { // p1 => s; s => p2; p2 => p1;
    aseta_kuvat(
      s, src_suureksi(p1.src),
      p2, src_pieneksi(s.src),
      p1, p2.src
    );
  } else { // p1 <=> s;
    aseta_kuvat(
      s, src_suureksi(p1.src),
      p1, src_pieneksi(s.src)
    );
  }
}
function suurenna_vasen() {
  var vasen_id = this.id;
  var oikea_id = vasen_id.replace(/_vasen$/, "_oikea");
  var suuri_id = vasen_id.replace(/_vasen$/, "_suuri");
  var vasen = this, oikea = document.getElementById(oikea_id);
  var suuri = document.getElementById(suuri_id);
  kierrata(vasen, suuri, oikea);
}
function suurenna_oikea() {
  var oikea_id = this.id;
  var vasen_id = oikea_id.replace(/_oikea$/, "_vasen");
  var suuri_id = vasen_id.replace(/_vasen$/, "_suuri");
  var oikea = this, vasen = document.getElementById(vasen_id);
  var suuri = document.getElementById(suuri_id);
  kierrata(oikea, suuri, vasen);
}
window.onload = function () {
  var kuvat = document.body.getElementsByTagName("img");
  for (var i in kuvat) {
    var match = ("" + kuvat[i].id).match(/^ilmoitus_[0-9]+_([a-z]+)$/);
    if (!match) continue;
    if (match[1] == "vasen") kuvat[i].onclick = suurenna_vasen;
    if (match[1] == "oikea") kuvat[i].onclick = suurenna_oikea;
  }
}

(Tämä ei vastaa aivan idealistista toteutustapaani, mutta jos kerran JS on hieman hakusessa, en rupea turhia hienostelemaan.)

pistemies [19.03.2009 23:32:23]

#

Kiitos. Skripti toimi yksittäisellä koesivulla, mutta ei ole toiminut tuossa varsinaisella sivulla, jossa nuo ilmoitukset tulostetaan.
Kuvat tulostuvat nyt tähän tyyliin.
Kuva-rakennelma:

<div>
<a href="photos/237_1.jpg"  rel="lightbox" title="Kittilä"><img  class="suuri" id="ilmoitus_237_suuri" src="photos160/237_1.jpg"  alt=""/>
</a>
<img  class="vasen" id="ilmoitus_237_vasen" src="thumb/237_2.jpg" alt=""/>
<img  class="oikea" id="ilmoitus_237_oikea" src="thumb/237_3.jpg" alt=""/>
</div>

Varinaisessa js-skriptissä on muutettu replacessa hakemiston nimi. Se toimi testi-tiedostossa, jossa oli pelkästään sinun skriptisi.
Noissa thumb-kuvissahan ei ole varsinaista linkkiä.Ei tosin toiminut linkkien kerakaan. Toisaalta tuo #kuva237 systeemi ei ole hyvä, mikäli tuossa on kyse a name toiminnosta.

Johtuuko toimimattomuus siitä, että tuon suuren kuvan linkki on ohjattu lightboxin javascript-koodille. Tässä on toiminto "linkki suuren kuvan ympärillä" eli sama linkki.

pistemies [20.03.2009 14:33:02]

#

Olen lisännyt tähän kuville samat muotoilut, mitä aiemmin oli kuvien ympärillä olevilla olevilla div-elementeillä. Se asia toimii hyvin.
Pitäisi vaan saada tuo kuvien vaihto pelaamaan sekä sivun pysyminen auki niin, ettei se liikahda ylös eikä alaspäin kuvaa klikatessa. Toisin sanoen ei ladata koko sivua, vaan ladataan uudestaan vain tämä osa sivusta.


Sivun alkuun

Vastaus

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

Tietoa sivustosta