...
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ÄINENYKSITTÄ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);
}
|