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

...

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);
}