Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

1.

...

Kuvaus

...

Palvelun

...

lähtökohtana

...

on

...

palautteen

...

antaminen

...

ja

...

vastaanottaminen

...

avoimen

...

keskustelun

...

hengessä.

...

Palautteen

...

antaminen

...

tapahtuu

...

nimettömänä.

...

Käyttäjä

...

voi

...

rekisteröitymällä

...

luoda

...

itselleen

...

seinän.

...

Muut

...

käyttäjät

...

voivat

...

jättää

...

seinälle

...

viestejä

...

(palautetta).

...

Jos

...

viestin

...

lähettäjän

...

yksilöiminen

...

ei

...

muuten

...

ole

...

mahdollista,

...

voidaan

...

siihen

...

liittää

...

Facebook-kirjautuminen.

...

Lähettäjän

...

henkilöllisyys

...

jää

...

silloin

...

ainoastaan

...

ylläpidon

...

tietoon,

...

eikä

...

sitä

...

näytetä

...

sivulla.

...

Viestejä

...

voi

...

kommentoida

...

tai

...

äänestää

...

joko

...

ylös

...

tai

...

alas.

...

Äänestettäessä

...

ylös

...

viestin

...

arvo

...

nousee

...

yhdellä.

...

Äänestettäessä

...

alas

...

viestin

...

arvo

...

laskee

...

yhdellä.

...

Arvo

...

esitetään

...

kokonaislukuna

...

viestin

...

yhteydessä

...

ja

...

ne

...

järjestetään

...

sen

...

mukaan.

...

Käyttäjä

...

voi

...

äänestää

...

vain

...

kerran

...

yksittäistä

...

viestiä.

...

2.

...

Tekninen

...

toteutus

...

Demo

...

löytyy

...

osoitteesta:

...

http://195.148.97.131/~noora_savolainen/index.php

...

2.1

...

MySQL

...

Palvelun

...

tietokanta

...

on

...

jaettu

...

kahteen

...

tauluun:

...

Käyttäjiin

...

ja

...

viesteihin.

...

Viestit-taulu

...

sisältää

...

kaikki

...

palveluun

...

lähetetyt

...

viestit.

...

Käyttäjät-taulu

...

tallentaa

...

tiedot

...

rekisteröityneistä

...

käyttäjistä

...

ja

...

luoduista

...

seinistä.

...

2.1.1

...

Käyttäjät

...

Ei

...

vielä

...

toteutettu.

...

2.1.2

...

Viestit

...

Taulun

...

tietueet:

{
Code Block
}
+-------------+--------------+------+-----+-------------------+----------------+

| Field | Type | Null | Key | Default | Extra |

+-------------+--------------+------+-----+-------------------+----------------+

| id | int(11) | NO | PRI | NULL | auto_increment |

| message | varchar(500) | YES | | NULL | |

| parent | int(11) | YES | | -1 | |

| rating | int(11) | YES | | 0 | |

| user_id | int(11) | YES | | NULL | |

| submit_time | timestamp | NO | | CURRENT_TIMESTAMP | |

+-------------+--------------+------+-----+-------------------+----------------+
{code}
* 
  • id:

...

  • Tietueen

...

  • yksilöllinen

...

  • tunnus.

...

  • Luodaan

...

  • automaattisesti.

...

  • message:

...

  • Käyttäjän

...

  • kirjoittama

...

  • viesti.

...

  • parent:

...

  • Määrittää

...

  • onko

...

  • viestin

...

  • aseman

...

  • hierarkiassa.

...

  • Jos

...

  • arvo

...

  • on

...

  • muu

...

  • kuin

...

  • -1

...

  • se

...

  • on

...

  • kommentti,

...

  • jolloin

...

  • arvo

...

  • on

...

  • kommentoidun

...

  • viestin

...

  • id.

...

  • Oletusarvona

...

  • on

...

  • -1,

...

  • joka

...

  • tarkoittaa

...

  • kyseessä

...

  • olevan

...

  • ensimmäisen

...

  • tason

...

  • viestin.

...

  • Rating:

...

  • Ylös

...

  • -

...

  • ja

...

  • alas-äänien

...

  • kokonaisarvo.

...

  • user_id:

...

  • Sen

...

  • seinän

...

  • id,

...

  • johon

...

  • viesti

...

  • kuuluu

...

  • submit_time:

...

  • Aika,

...

  • jolloin

...

  • viesti

...

  • on

...

  • tallennettu

...

  • tietokantaan.

...

2.2

...

PHP

...

Palveluun

...

liittyvä

...

php

...

voidaan

...

jakaa

...

kolmeen

...

kategoriaan:

...

Järjestelmän

...

ominaisuuksien

...

alustaminen,

...

sivulle

...

lähetetyn

...

tiedon

...

käsittely

...

ja

...

tietokannasta

...

haetun

...

tiedon

...

perusteella

...

sivun

...

sisällön

...

muodostava

...

osa.

...

2.2.1

...

Ominaisuuksien

...

alustaminen

...

Yhdistäminen

...

tietokantaan

...

ja

...

sen

...

onnistuessa

...

asetusten

...

määrittely:

{
Code Block
}
//connect to database
try
{
	$mysql_conn = new PDO ("mysql:host=localhost;dbname=koala", "vompatti", "opossumi");
}catch (PDOException $e){
	die("Virhe: " . $e->getMessage());
}

// error handling
$mysql_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// encoding
$mysql_conn->exec("SET NAMES utf8");
{code}

Jos

...

sovelluksen

...

vaatimaa

...

taulua

...

ei

...

ole

...

tietokannassa

...

se

...

luodaan

...

(IF

...

NOT

...

EXISTS):

{
Code Block
}
//create table if doesn't exist
try
{
$mysql_conn->exec("CREATE TABLE IF NOT EXISTS peukku_viestit (
	id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	message VARCHAR(500),
	parent INT DEFAULT -1,
	rating INT DEFAULT 0,
	user_id INT,
	submit_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
}catch (PDOException $e){
	die("Virhe: " . $e->getMessage());
}
{code}

Luodaan

...

käyttäjälle

...

istunto,

...

jonka

...

perusteella

...

hänet

...

voidaan

...

myöhemmin

...

yksilöidä.

{
Code Block
}
// create session cookie
session_start();

if (!isset($_SESSION['session']) || !isset($_SESSION['token']))
{
	// this variable is to make sure we get post from correct form
	// we will add it to every form as a hidden field
	$_SESSION['token'] = uniqid(md5(microtime()), true);
	// this is for making it harder to hijack one's session cookie
	// save ip and user agent which created the session
	$_SESSION['session'] = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']);
}
{code}

h3. 

2.2.2

...

Lähetetyn

...

tiedon

...

käsittely

...

Jokaisessa

...

palvelun

...

lomakkeessa

...

on

...

kaksi

...

piilotettua

...

kenttää,

...

joka

...

liitetään

...

käyttäjän

...

lähettämiin

...

tietoihin.

...

"action"

...

määrittää

...

minkä

...

toiminnon

...

lomake

...

suorittaa.

{
Code Block
}
<input name="action" type="hidden" value="new_message" />
{code}

"token"

...

mahdollistaa

...

sen

...

lomakkeen

...

yksilöinnin,

...

josta

...

käyttäjä

...

on

...

lähettänyt

...

tiedot.

{
Code Block
}
<input name="token" type="hidden" value="new_message" />
{code}

Ensimmäiseksi

...

tarkistamme

...

onko

...

käyttäjän

...

lähettämää

...

dataa

...

olemassa.

...

Se

...

tehdään

...

selvittämällä

...

onko

...

tietoihin

...

liitetty

...

aikaisemmin

...

mainitsemani

...

action-kenttä.

...

Jos

...

sitä

...

ei

...

tarkisteta,

...

tapahtuu

...

virhe

...

lähetetyn

...

datan

...

puuttuessa.

{
Code Block
}
// Check if there's post data
if (isset($_POST['action'])){

   ...

}{code}

Tämän

...

jälkeen

...

varmistamme,

...

että

...

tiedot

...

on

...

lähetetty

...

lomakkeesta,

...

joka

...

oikeasti

...

sijaitsee

...

sivullamme

...

(vrt.

...

istunnon

...

luominen).

{
Code Block
}
// our security check from session cookie
if($_SESSION['token'] == $_POST['token'] && $_SESSION['session'] == md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']))
{

   ...

}
{code}

Edellisen

...

ehtolausekkeen

...

sisältä

...

löytyy

...

varsinainen

...

käyttäjän

...

lähettämän

...

tiedon

...

käsittely.

...


Toiminto

...

valitaan

...

selvittämällä

...

action-kentän

...

arvo,

...

jonka

...

PHP

...

on

...

tallentanut

...

post-datan

...

sisältävään

...

$_POST-muuttujaan.

...

Ensimmäiseksi

...

käsittelemme

...

tapauksen,

...

jossa

...

käyttäjä

...

haluaa

...

lisätä

...

uuden

...

viestin

...

tietokantaan.

...

Viestin

...

erikoismerkit

...

muunnetaan

...

HTML-muotoon

...

htmlspecialchars-funktiolla,

...

jotta

...

käyttäjän

...

ei

...

olisi

...

mahdollista

...

liittää

...

omaa

...

koodia

...

sivuille

...

viestien

...

välityksellä.

...


PHP:n

...

PDO-kirjaston

...

prepare-metodi

...

huolehtii

...

siitä,

...

ettei

...

käyttäjän

...

ole

...

mahdollista

...

syöttää

...

palveluun

...

omia

...

SQL-kyselyjä.

...

Käsiteltyämme

...

tiedot

...

varmistamme,

...

että

...

käyttäjä

...

ei

...

voi

...

lähettää

...

tietoja

...

uudestaan

...

käyttämällä

...

selaimen

...

edellinen-toimintoa.

...

Käytämme

...

header-funktiota:

...

header(

...

'Location:

...

index.php')

...

.

...

Koska

...

muokkaamme

...

suoraan

...

sivun

...

HTTP-otsaketta

...

(HTTP

...

header),

...

tulee

...

tämä

...

tehdä

...

ennen

...

kuin

...

yhtään

...

HTML-koodia

...

on

...

tulostettu

...

tiedostoon

...

tai

...

siitä

...

seuraa

...

virhe.

...

Huomaa,

...

että

...

syötämme

...

osoitteeseen

...

muuttujan,

...

joka

...

määrittää

...

uuden

...

tai

...

muuttunen

...

viestin

...

yksilöllisen

...

tunnuksen

...

(ID).

...

Tällä

...

tavalla

...

voimme

...

myöhemmin

...

korostaa

...

sen

...

erottumaan

...

muista

...

viesteistä

...

Javascriptin

...

ja

...

CSS:n

...

avulla.

{
Code Block
}
	// Choose the correct action based on the value of the $_POST['action']
	if ($_POST['action'] == 'new_message')
	{
		// Add a message to the database
		// prepare query
		// save it with htmlspecialchars in order to stop clever javascripting and HTML-tags ;)
		$query = $mysql_conn->prepare("INSERT INTO peukku_viestit (message) VALUES ('" . htmlspecialchars($_POST['message']) . "')");
		// run query
		$query->execute();

		//remove post data by redirecting to ourselves
		header( 'Location: index.php?new=' . $rivi['LAST_INSERT_ID()'] ) ;

	}
{code}

Peukku

...

ylös:

{
Code Block
}
else if ($_POST['action'] == 'peukuta')
	{
		// Update +rating to the database
		// prepare query
		$query = $mysql_conn->prepare("UPDATE peukku_viestit SET rating = rating + 1 WHERE id = '" . $_POST['id'] . "'");
		// run query
		$query->execute();

		//remove post data by redirecting to ourselves
		header( 'Location: index.php?new=' . $_POST['id'] );

	}
{code}

Peukku

...

alas:

{
Code Block
}
else if ($_POST['action'] == 'peukuta_nega')
	{
		// Update -rating to the database
		// prepare query
		$query = $mysql_conn->prepare("UPDATE peukku_viestit SET rating = rating - 1 WHERE id = '" . $_POST['id'] . "'");
		// run query
		$query->execute();

		//remove post data by redirecting to ourselves
		header( 'Location: index.php?new=' . $_POST['id'] );

	}

}
{code}

h3. 

2.2.3

...

Sisällön

...

muodostaminen

...

Aloitamme

...

suorittamalla

...

kyselyn

...

tietokannasta.

...

ORDER

...

BY-lause

...

järjestää

...

tiedon

...

haluamallamme

...

tavalla.

{
Code Block
}
// prepare the query
$kysely = $mysql_conn->prepare("SELECT * FROM peukku_viestit ORDER BY rating DESC, submit_time DESC");
// run it
$kysely->execute();
{code}

Wiki Markup
While-silmukka käy yksitellen jokaisen kyselyn sisältämän rivin läpi. Käytimme PDO::FETCH_ASSOC-ominaisuutta, jotta pääsisimme käsiksi tietueen arvoon tekstiavaimella indeksin numeron sijaan. {{$rivi\["rating"\]}} vastaan {{$rivi\[0\]}}.

{
Code Block
}
// process results from query one row at a time
$i=1;
while ($rivi = $kysely->fetch(PDO::FETCH_ASSOC)) {
	echo "<hr/>" . $i .
	". <br />Rating: " . $rivi["rating"]
    . " <br />Time: " . $rivi["submit_time"]
    . " <p>Message:<br />" . $rivi["message"]
    ."</p>";

    $i++;
}
{code}
h2. 

2.3

...

HTML

...

ja

...

CSS

...

Ensimmäinen

...

vaihe

...

html

...

-

...

koodauksessa

...

oli

...

luoda

...

käyttöliittymäsuunnitelman

...

(rautalangan)

...

pohjalta

...

elementit

...

html

...

-

...

sivulle.

...

Tämän

...

jälkeen

...

luotiin

...

css

...

-

...

tiedosto,

...

jolla

...

saatiin

...

elementit

...

suunnitelman

...

mukaisesti

...

paikoilleen

...

ja

...

selkeytettiin

...

käyttöliittymää

...

väreillä

...

ja

...

reunaviivoilla. 

Html- pohjan ollessa valmis lisättiin php- toiminnallisuudet; uuden toiveen lisääminen, toiveiden plus / negatiivinen peukutus sekä toiveiden järjestäminen pisteytyksen mukaan.

Toiminnallisuuksien lisäämisen jälkeen niitä testattiin ja hienosäädettiin, jonka jälkeen voitiin aloittaa käyttöliittymän ja ulkoasun hiominen.

2.4 Javascript

Sivuun on lisätty javascript-toiminnallisuus, joka automaattisesti siirtää sivun uuden tai muokatun elementin kohdalle.

Ensimmäiseksi selvitetään, missä elementti sijaitsee suhteessa dokumenttiin.

Code Block
&nbsp;

Html\- pohjan ollessa valmis lisättiin php\- toiminnallisuudet; uuden toiveen lisääminen, toiveiden plus / negatiivinen peukutus sekä toiveiden järjestäminen pisteytyksen mukaan.

Toiminnallisuuksien lisäämisen jälkeen niitä testattiin ja hienosäädettiin, jonka jälkeen voitiin aloittaa käyttöliittymän ja ulkoasun hiominen.

h2. 2.4 Javascript

Sivuun on lisätty javascript-toiminnallisuus, joka automaattisesti siirtää sivun uuden tai muokatun elementin kohdalle.


Ensimmäiseksi selvitetään, missä elementti sijaitsee suhteessa dokumenttiin.

{code}
// Determine the destination coordinate
// elmYPosition( string elementID )
// Returns target element Y position
function elmYPosition(eID) {
    var elm = document.getElementById(eID);
    var y = elm.offsetTop;
    var node = elm;
    while (node.offsetParent && node.offsetParent != document.body) {
        node = node.offsetParent;
        y += node.offsetTop;
    } return y;
}
{code}

Siirtyminen

...

oikealle

...

kohdalle

...

dokumentissa.

{
Code Block
}
// Scrolls straight from current page Y coordinate to specified element Y coordinate. 
// Dependencies: elemYPosition()
// roughScroll( string elementID )
function roughScroll(eID) {
    var stopY = parseInt(elmYPosition(eID));
	stopY = stopY - parseInt(window.innerHeight / 2);
	window.scrollTo(0, stopY);
}
{code}

Sijoitamme

...

viestin

...

HTML-koodiin

...

sen

...

yksilöllisen

...

tunnuksen

...

(ID),

...

jos

...

se

...

on

...

uusi

...

tai

...

sitä

...

on

...

muutettu.

...

Muutoksen

...

olemassaolo

...

tarkistetaan

...

isset-funktiolla.

{
Code Block
}

$i=1;
while ($rivi = $kysely->fetch(PDO::FETCH_ASSOC)) {

...

?>
<div class="single-comment" <?php 

// check if this item has been updated
if(isset($_GET['new']))
{
	if($rivi["id"] == $_GET['new'])
	{
		echo 'id="new-comment"';
	}
}

...

i++;
}
		
?>>
{code}

Lopuksi

...

tarvitsemme

...

vielä

...

tavan

...

selvittää,

...

onko

...

luotu

...

uutta

...

viestiä

...

tai

...

muutettu

...

vanhaa.

...

Toteutamme

...

sen

...

tarkistamalla

...

new-muuttujan

...

olemassaolon

...

isset-funktiolla.

...

Uuden

...

tai

...

muutetun

...

viestin

...

tapauksessa

...

printtaamme

...

Javascript-komennon,

...

joka

...

suorittaa

...

sivun

...

vierityksen.

{
Code Block
}
<?php
	if(isset($_GET['new']))
	{
		echo '<script type="text/javascript">roughScroll("new-comment");</script>';	
	}
	
 ?>
{code}

h2. 

2.5

...

Lähdekoodi

...

2.5.1

...

PHP

{
Code Block
}
<?php

/*if (!ini_get('display_errors')) {
    ini_set('display_errors', 1);
}*/

//connect
try
{
	$mysql_conn = new PDO ("mysql:host=localhost;dbname=koala", "vompatti", "opossumi");	
}catch (PDOException $e){
	die("Virhe: " . $e->getMessage());
}

// virheenkäsittely: virheet aiheuttavat poikkeuksen
$mysql_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// merkistä
$mysql_conn->exec("SET NAMES utf8");

//create table if doesn't exist
try
{
$mysql_conn->exec("CREATE TABLE IF NOT EXISTS peukku_viestit (
	id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
	message VARCHAR(500), 
	parent INT DEFAULT -1, 
	rating INT DEFAULT 0, 
	user_id INT, 
	submit_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
}catch (PDOException $e){
	die("Virhe: " . $e->getMessage());
}

// create session cookie
session_start();

if (!isset($_SESSION['session']) || !isset($_SESSION['token']))
{
	// this variable is to make sure we get post from correct form
	// we will add it to every form as a hidden field
	$_SESSION['token'] = uniqid(md5(microtime()), true); 
	// this is for making it harder to hijack one's session cookie 
	// save ip and user agent which created the session
	$_SESSION['session'] = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']); 
}


// Check if there's post data
if (isset($_POST['action']) && isset($_POST['token'])){
	// our security check from session cookie
	if($_SESSION['token'] == $_POST['token'] && $_SESSION['session'] == md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']))
	{
		// Choose the correct action based on the value of the $_POST['action']
		if ($_POST['action'] == 'new_message')
		{
			// Add a message to the database
			// valmistetaan kysely
			// save it with htmlspecialchars in order to stop clever javascripting ;)
			$query = $mysql_conn->prepare("INSERT INTO peukku_viestit (message) VALUES ('" . htmlspecialchars($_POST['message']) . "')");
			// suoritetaan kysely
			$query->execute();
			
			// save latest updated item
			$query = $mysql_conn->prepare("SELECT LAST_INSERT_ID()");
			$query->execute();
			$rivi = $query->fetch(PDO::FETCH_ASSOC);
			
			// this will regenerate users session every time something is posted
			// harder to hijack session cookie
			session_regenerate_id();
			
			//reomve post data by redirecting to ourselves
			
			header( 'Location: index.php?new=' . $rivi['LAST_INSERT_ID()'] ) ;
			//if(isset($rivi['LAST_INSERT_ID()']))
				//header( 'Location: index.php?new=' . $rivi['LAST_INSERT_ID()'] . '#new-comment');
			//else
				//header( 'Location: index.php' ) ;
			
		}
		
		else if ($_POST['action'] == 'peukuta')
		{
			// Add a Peukku to the database
			// valmistetaan kysely
			
			$query = $mysql_conn->prepare("UPDATE peukku_viestit SET rating = rating + 1 WHERE id = '" . $_POST['id'] . "'");
			// suoritetaan kysely
			$query->execute();
			
			// this will regenerate users session every time something is posted
			// harder to hijack session cookie
			session_regenerate_id();
			
			//reomve post data by redirecting to ourselves
			//THIS IS NEW
			header( 'Location: index.php?new=' . $_POST['id'] . '&y=' . $_POST['current_y'] ) ;
			//header( 'Location: index.php?new=' . $_POST['id'] ) ;
		
		}
	
		else if ($_POST['action'] == 'peukuta_nega')
		{
			// Add a Peukku to the database
			// valmistetaan kysely
			
			$query = $mysql_conn->prepare("UPDATE peukku_viestit SET rating = rating - 1 WHERE id = '" . $_POST['id'] . "'");
			// suoritetaan kysely
			$query->execute();
			
			// this will regenerate users session every time something is posted
			// harder to hijack session cookie
			session_regenerate_id();
			
			//reomve post data by redirecting to ourselves
			//THIS IS NEW
			header( 'Location: index.php?new=' . $_POST['id'] . '&y=' . $_POST['current_y'] ) ;
			//header( 'Location: index.php?new=' . $_POST['id'] ) ;
		
		}
		
	}
}

?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="script.js"></script>
<title>Profiili- Peukkupalvelu</title>
<link href="tyyli.css" rel="stylesheet" type="text/css">
</head>

<body>

<div id="wrapper">
	<div id="content">
        <h1>PEUKKUPALVELU</h1>
        <div id="profilewrapper">
			<div id="profilebox">
               	  	<img id="profileimg" src="images/profiilikuva.jpg" width="180" height="180" alt="Profiilikuva">
                        <ul class="profiletext">
                        	<h2>KD11S1VDV</h2>	
                                    <li>Kevättä odotellessa!</li>
                                    <li>Digilabra</li>
                                    <li>Hämeentie 161, Helsinki</li>
                        </ul>
                    
                </div>
              <div id="commentbox">
                    	<?php 

//YKSITTÄINEN VIESTI ALKAA
// valmistetaan kysely
$kysely = $mysql_conn->prepare("SELECT * FROM peukku_viestit ORDER BY rating DESC, submit_time DESC");
// suoritetaan kysely
$kysely->execute();

// käsitellään tulostaulun rivit yksi kerrallaan
$i=1;
while ($rivi = $kysely->fetch(PDO::FETCH_ASSOC)) {
    
    // peukutus, plussa
    ?>
<div class="single-comment" <?php 

// check if this item has been updated
	if(isset($_GET['new']))
	{
		if($rivi["id"] == $_GET['new'])
		{
			echo 'id="new-comment"';
		}
	}
		

?>>
<div id="date"><?php echo htmlspecialchars($rivi["submit_time"]); ?></div> 
<!--span><?php echo $i; $i++; ?></span-->  
<div id="message-text"><?php echo htmlspecialchars($rivi["message"]); ?></div>
  
  <div id="rating">
    
<form name="vote_message_plus<?php 
    	echo htmlspecialchars($rivi["id"]); 
    	?>" action="index.php" method="post" onsubmit="this.elements['current_y'].value=currentYPosition()">
    
		<input name="current_y" type="hidden" value="0" />
        <input name="token" type="hidden" value="<?php echo $_SESSION['token']?>" />
		<input name="action" type="hidden" value="peukuta" />
		<input name="id" type="hidden" value="<?php 
			echo htmlspecialchars($rivi["id"]); 
			?>" />
       
		<img onClick="document.vote_message_plus<?php 
    	echo htmlspecialchars($rivi["id"]); 
    	?>.submit();" src="images/thumb-up.png" width="25" height="32" alt="Tykkään"/>
        			<?php
				echo htmlspecialchars($rivi["rating"]);
				
		 	?>
                    
	</form>
<?php
	// peukutus, nega
?>
    <form name="vote_message_nega<?php 
    	echo htmlspecialchars($rivi["id"]); 
    	?>" action="index.php" method="post" onsubmit="this.elements['current_y'].value=currentYPosition()">
    
		<input name="current_y" type="hidden" value="0" />
        <input name="token" type="hidden" value="<?php echo $_SESSION['token']?>" />
		<input name="action" type="hidden" value="peukuta_nega" />
		<input name="id" type="hidden" value="<?php 
			echo htmlspecialchars($rivi["id"]); 
			?>" />
		<img onClick="document.vote_message_nega<?php 
    	echo htmlspecialchars($rivi["id"]); 
    	?>.submit();" src="images/thumb-down.png" width="25" height="32" alt="En tykkää"/>

	</form>
    	</div> <!--RATING LOPPUU-->	
  
  
        <br>
        <div class="float-clear"></div>
    </div>	<!--SINGLE COMMENT LOPPUU-->
    


<?php
}
//YKSITTÄINEN VIESTI LOPPUU
?>
                    
  				</div> <!--COMMENTBOX LOPPUU-->              
     		</div> <!--PROFILEBOX LOPPUU-->
          </div> <!--PROFILEWRAPPER LOPPUU-->
         
	<div id="messagewrapper">
        <div id="messagebox">

            <form name="statusupdate" action="index.php" method="post">
               <input name="token" type="hidden" value="<?php echo $_SESSION['token']?>" />
                <input name="action" type="hidden" value="new_message" />
                <p>
                    <label for="message">Kirjoita uusi toive: </label><br/>
                    <textarea name="message" id="message" rows="20" cols="50"></textarea>
                </p>
                <span class="float-right">
                	<input type="submit" value="Lähetä" />
                	<input type="reset" value="Tyhjennä" />
                </span>
            </form>
		</div>
    </div>
	<div class="float-clear"></div>
    </div>
</div>

<?php
	// THIS IS NEW
// check if the message is shown on-screen
if(isset($_GET['y']))
{

	echo '<script type="text/javascript">window.scrollTo(0,' . $_GET['y'] . ');</script>';
	
	?>
	
		<script type="text/javascript">
		
		var elemY = elmYPosition("new-comment");
		var curY = currentYPosition();
		var winHeight = window.innerHeight;
		var winHalf = winHeight / 2;
		
		curY += winHalf;
		
		var test = 0;
		
		if(elemY < curY)
		{
			test = curY + winHalf;
			
			if(test > elemY)
			{		
				smoothScroll("new-comment");
			}
		}
		else
		{
			test = curY - winHalf; 
		
			if(test < elemY)
			{		
				smoothScroll("new-comment");
			}
		}
		
		</script>
		
	<?php
}
else
{
	echo '<script type="text/javascript">smoothScroll("new-comment");</script>';
}

	
 ?>
</body>
</html>
{code}

h3. 

2.5.2

...

Javascript

{
Code Block
}
// Determine the point on the Y Axis at which the scrolling has to start
// Returns current page Y position
function currentYPosition() {
    // Firefox, Chrome, Opera, Safari
    if (self.pageYOffset) 
		return self.pageYOffset;
    // Internet Explorer 6 - standards mode
    if (document.documentElement && document.documentElement.scrollTop)
        return document.documentElement.scrollTop;
    // Internet Explorer 6, 7 and 8
    if (document.body.scrollTop) 
		return document.body.scrollTop;
    return 0;
}

// Determine the destination coordinate
// elmYPosition( string elementID )
// Returns target element Y position
function elmYPosition(eID) {
    var elm = document.getElementById(eID);
    var y = elm.offsetTop;
    var node = elm;
    while (node.offsetParent && node.offsetParent != document.body) {
        node = node.offsetParent;
        y += node.offsetTop;
    } return (y - elm.scrollTop) - (window.innerHeight / 2);
}

// Scrolls smoothly from current page Y coordinate to specified element Y coordinate. 
// Dependencies: currentYPosition(), elemYPosition()
// smoothScroll( string elementID )
function smoothScroll(eID) {
    var startY = currentYPosition();
    var stopY = elmYPosition(eID);
    var distance = stopY > startY ? stopY - startY : startY - stopY;
    if (distance < 100) {
        scrollTo(0, stopY); 
		return;
    }
    var speed = Math.round(distance / 100);
    if (speed >= 20) speed = 20;
    var step = Math.round(distance / 25);
    var leapY = stopY > startY ? startY + step : startY - step;
    var timer = 0;
    if (stopY > startY) {
        for ( var i=startY; i<stopY; i+=step ) {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY += step; if (leapY > stopY) leapY = stopY; timer++;
        } 
		return;
    }
    for ( var i=startY; i>stopY; i-=step ) {
        setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
        leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
    }
}

// Scrolls straight from current page Y coordinate to specified element Y coordinate. 
// Dependencies: elemYPosition()
// roughScroll( string elementID )
function roughScroll(eID) {
    var stopY = parseInt(elmYPosition(eID));
	stopY = stopY - parseInt(window.innerHeight / 2);
	window.scrollTo(0, stopY);
	//alert(stopY);
}
{code}