...
2. Tekninen toteutus
Demo löytyy osoitteesta:
http://195.148.97.131/~noora_savolainen/index.php?new=5&y=0
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ä.
...
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++;
}
|
2.3 HTML ja CSS
Ensimmäinen vaihe html- koodauksessa oli luoda käyttöliittymäsuunnitelman (rautalangan) pohjalta elementit html- sivulle.
...
Code Block |
---|
<?php if(isset($_GET['new'])) { echo '<script type="text/javascript">roughScroll("new-comment");</script>'; } ?> |
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>
|
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);
}
|