カテゴリー
XOOPS

XOOPSモジュール版WordPressのAjaxを使った投票システムをグラフ表示に

投票グラフ

ちょっと前に作成してこのブログの人気記事にもなっているXOOPSモジュール版WordPressの投票システムをパワーアップさせて、投票結果をグラフで表示するようにしてみました。
常連さんはブラウザの更新ボタンを押さないとキャッシュが残っててうまく動かないかもしれません。

選挙速報とか楽しいじゃないですか

テレビの選挙速報とかグラフがぐんぐん動いていって、果たして自分が投票した候補者は他の人も選んでいるのか、自分の選択がレアだったのか、そういうのを確認するのってなんか楽しいというか、安心するというか・・・。

つまり、自分が投票した記事を他の人がどう評価しているのかが、すぐに出てくると親切かもしれない。しかも、どうせならかっこよく。

そんなわけで、投票結果を動きのあるグラフで表示してみようと思ったわけです。

結果はJSONで

今回、投票するだけではなくサーバーからの投票数を受け取ってグラフ表示するために、いろいろと前準備が必要です。

まずは、サーバーから結果を返すためにPHP-JSONモジュールをインストールします。
PEARを使えば簡単です。

pear install json

でインストールできます。

あと、/etc/php.iniに

extension=json.so

の記述を追加した上で、Apacheを再起動しないといけません。
自分は最初、extentionと間違って書いてうまく動きませんでした(笑)

一応、これでphpinfo();するとJSONの項目が出るようになりました。
ちなみに、うちのOSはFedora Coreです(いまいちPEARやPHPは詳しくないのでOSが関係するかわかりませんが)。

テーブルは変わらず

以前の投票システムと同じテーブルを使います。

CREATE TABLE `xoops_wp_popularity` (
? `postnumber` int(11) NOT NULL default ‘0′,
? `good` int(11) NOT NULL default ‘0′,
? `bad` int(11) NOT NULL default ‘0′,
? PRIMARY KEY? (`postnumber`)
) TYPE=MyISAM;

サーバー側のvote.php

前からだいぶ変更。

<?php
//美乳
//WordPress人気投票

$fail = "fail";

$id = intval($_GET['id']);
if (!is_numeric($id)){
print $fail;
return;
}

$conn = mysql_connect("server","user","password");
mysql_select_db("xoops");

//投票データ取得
$post = GetPopularityData($id);

//
if (empty($post->good) && empty($post->bad))
{
//行追加
$sql = sprintf("insert into xoops_wp_popularity(postnumber, good, bad) values(%d, 0, 0);",$id);
@mysql_query($sql);

$post->good = 0;
$post->bad = 0;
}

switch ($_GET["vote"]){
case "good" :
$post->good = $post->good + 1;
$resultmsg = "良い評価をもらったよ!";
break;
case "bad" :
$post->bad = $post->bad + 1;
$resultmsg = "残念ながら、いまいちだという評価をもらったよ";
break;
default :
print($fail);
return;
}

//投票
vote($post);

//結果
ShowVoteResult($post);

//メール送信
mb_language("Japanese");
$mail_subject = "やったね!記事に投票がありました";
$mail_body.= $resultmsg."n";
$mail_body.= "良いと評価されたのが".$post->good."票、悪いと評価されたのが".$post->bad."票ですn";
$mail_body.= "投票された記事はこれn";
$mail_body.= "「".$post->title."」n";
$mail_body.= "http://XOOPSサイトのアドレス/modules/wordpress/index.php?p=".$id."&more=1&c=1";

mb_send_mail("通知先のアドレス",$mail_subject,$mail_body,"From: 差出人のアドレス");

//投票結果表示
function ShowVoteResult($post){
$val = array("good" => $post->good,
"bad" => $post->bad
);
$output = json_encode($val);
print $output;
}

//投票
function vote($post){
$sql = sprintf("update xoops_wp_popularity set good = %d, bad = %d where postnumber = %d;", $post->good, $post->bad, $post->post_id);
@mysql_query($sql);
}

//投票データを取得
function GetPopularitydata($p_number){
$data = NULL;

$sql = sprintf("select m.postnumber, m.good, m.bad, p.post_title from xoops_wp_popularity m RIGHT JOIN xoops_wp_posts p ON m.postnumber = p.ID where p.ID = %d;",$p_number);
$result = @mysql_query($sql);
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$data = new PopularityData;
$data->good = $row[1];
$data->bad = $row[2];
$data->title = $row[3];
$data->post_id = $p_number;
}

return $data;
}

//レコードデータ用クラス
class PopularityData {
var $good;
var $bad;
var $title;
var $post_id;
}
?>

投票されたらメールで通知するようにしています。
結果はさっきインストールしたPHP-JSONを使って、JSON形式で返しています。
ちなみに、

{"good":0,"bad":1}

こんな感じの文字列が返ってきます。

XOOPSテンプレートにライブラリ追加

今回、prototype.js以外にダイナミックなUIを実現するscript.aculo.usも使用しました。
XOOPSのディレクトリのthemeディレクトリの中を探っていくとtheme.htmlがあるので、これのheadタグの間に

<script language="javascript" src="/ajax/prototype.js"></script>
<script language="javascript" src="/ajax/scriptaculous.js"></script>
<script language="javascript" src="/ajax/votescript.js"></script>

を追加します。
votescript.jsは次項を。

クライアント側のJavaScript(votescript.js)

Ajaxの肝。クライアント側のJavaScriptはこんな感じ。
Ajaxディレクトリにvote.phpがあると想定しています。

// JavaScript Document
// 美乳
function voteGood(id)
{
displayProgress();

new Ajax.Request("/ajax/vote.php?id=" + id + "&vote=good", { method: 'get', onSuccess: displayResult, onFailure : displayFail });
}

function voteBad(id)
{
displayProgress();

new Ajax.Request("/ajax/vote.php?id=" + id + "&vote=bad", { method: 'get', onSuccess : displayResult ,onFailure : displayFail});
}

function displayProgress()
{
//いったん隠しておく
new Effect.Fade("good-count", { from:0, to:0, duration:0});
new Effect.Fade("bad-count", { from:0, to:0, duration:0});

$("vote-result").innerHTML = '投票処理中・・・'
}

function displayResult(responseHttpObj, json)
{
eval("var ret = " + responseHttpObj.responseText);

if (responseHttpObj.responseText == 'fail')
{
$("vote-result").innerHTML = 'ごめんなさい、サーバーに問題が発生していてうまく投票できませんでした';
}else{
$("vote-result").innerHTML = '投票ありがとうございます! ';

//グラフ描画
var totalVote = new Number(ret.good) + new Number(ret.bad);
var goodPercent = ret.good / totalVote * 100;
var badPercent = ret.bad / totalVote * 100;

var graph = new Effect.Transform([
{ "#good-graph" : 'width:' + goodPercent + 'px'},
{ "#bad-graph" : 'width:' + badPercent + 'px'}
], { duration: 1 });
graph.play();

$("good-count").innerHTML = 'よい  ' + ret.good + '票';
$("bad-count").innerHTML = 'わるい ' + ret.bad + '票';

new Effect.Appear("good-count", { from:0, to:1, duration:2});
new Effect.Appear("bad-count", { from:0, to:1, duration:2});

}
}

function displayFail()
{
$("vote-result").innerHTML = 'サーバーエラー!';
}

コメントで「いったん隠しておく」としてあるのは、票数を透明にして、いきなり数値が見えないようにするためにやってます。
グラフが伸びる前に数値が出たらワクワク感がないですから(笑)
もっとうまい方法があるのかもしれませんが、一応目的は達せたので、このままにしています。

グラフは、script.aculo.usのTransformを使って、うにょーんとグラフが伸びていく効果を使っています。
なかなかいい感じ(笑)

script.aculo.usの使い方はこちらを参考にさせていただきました。ありがとうございます。

はまったのはJSONデータの受け取りで、あちこちサイト見たけど、なぜかevalしないとデータが取り出せない。
evalはあぶないらしいからあまり使いたくないのだけど。
引数のjsonは結局使わず。

コメントテンプレートもだいぶ変えた

comments-template.phpに以下のような行を追加します。このファイルはwordpressのthemesフォルダにあります。

<div class="vote-box">
<div id="vote-result">
この記事は良かったですか?(探していた情報、面白い)
<input type="submit" name="Submit" value="&hearts;" onClick="voteGood(<?php print($post->ID); ?>);" style="font-size: 130%; color: #DDAADD;">
<input type="submit" name="Submit" value="×" onClick="voteBad(<?php print($post->ID); ?>);" style="font-size: 130%; color: #777777;">
投票すると結果がここに表示されます
</div>
<div id="vote-graph">
<div id="good-count"></div><div id="good-graph"></div>
<div style="clear:both;"></div>
<div id="bad-count"></div><div id="bad-graph"></div>
</div>
<div style="clear:both;"></div>
</div>
<div style="clear:both;"></div>

これで、Ajaxな投票ボタンとダイナミックなグラフ表示ができます。

ついでにCSSも

CSSはこんな感じです。

.vote-box {
background-color: #6699CC;
padding: 3px;
}

#vote-result {
float:left;
}

#vote-graph {
float:left;
padding-left: 20px;
}

#good-count {
float:left;
width:100px;
}

#bad-count {
float:left;
width:100px;
}

#good-graph {
float:left;
width:0px;
height:20px;
background-image: url(blue-bar.png);
}

#bad-graph {
float:left;
width:0px;
height:20px;
background-image: url(red-bar.png);
}

floatを駆使して一応思うとおりにレイアウトしてみましたが、果たしてこのやり方が正しいのかは不明です。
グラフの所はscript.aculo.usのTransFormで横に引き延ばすので、最初は0ピクセルにしています。
グラフは幅1ドットのグラフィックをGIMPで作成して、背景イメージとして設定しました。

こんな感じですね。

なかなかよい出来に

グラフを書くのはライブラリ使っても面倒だったけど(そもそもグラフを書くためのライブラリじゃないだろうし)、動きのあるいい感じのグラフになった。
他にもグラフを書く専用のライブラリもあったのですが、動くやつは見つけきれなかったので、script.aculo.usでがんばってみました。

前のと比べて今度はちゃんと結果を返すようになったので、これで晴れて Asynchronous Javascript?+ JSON で、Ajaj?
あれ、まだAJaxじゃないや(笑)

この記事を書いた人: A-tak

A-tak.com(えいたっく どっとこむ)の管理人。
Apple野郎なおっさんでしたが、ちょっと最近のAppleには飽き気味。
A-tak.comは2002年2月から運営(前身のサイトは1999年3月から)。今年で18年目!

Youtube / Twitter / Mastodon / Facebook

コメントは受け付けていません。