ウェブ学のすすめ

Study of Web Design & Programing

GPSで指定した場所周辺のTwitterのツイートを表示する

プレビュー


↓別ウィンドウを開いて見る
GPS機能とTwitterの連携 - js do it

QRコード

※おすすめQRコード読み取りアプリ

お父さんQR
カテゴリ: ユーティリティ
サイズ: 2.3 MB
価格: 無料

ポイント

JSON(ジェイソン、JavaScript Object Notation)は、JavaScriptにおけるオブジェクトの表記法をベースとした軽量なデータ記述言語である。

引用:JavaScript Object Notation - Wikipedia

コード

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>GPS機能とTwitterの連携</title>
<link rel="stylesheet" href="css/style.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body>
<div id="container">
<header>
<h1>Twitter x Geocode</h1>
</header>
<div id="wrapper">
<div id="twitterModule">
<p class="title">Twitter Module</p>
<div id="area-tweets"></div>
    <form class="area-input"><input type="text" value="池袋駅"></form>
</div>
</div>
<footer></footer>
</div>
</body>
</html>
CSS
article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary { display: block; }
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; font-style: normal; font-weight: normal; vertical-align: baseline; background: transparent; }
li { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
ins { text-decoration: none; }
del { text-decoration: line-through; }
table { border-collapse: collapse; border-spacing: 0; }
img { vertical-align: bottom; }
:focus { outline: 0; }

body {
    font: 16px/1.5em;
    background: #F7F7F9;
    font-family:
	  "ヒラギノ角ゴ Pro W3",
	   "Hiragino Kaku Gothic Pro", 
	   "メイリオ", 
	   Meiryo, 
	   Osaka, 
	   "MS Pゴシック", 
	   "MS PGothic", 
	   sans-serif;
}
header {
    height: 40px;
    background:#333;
    display: block;
}
h1 {
     color: #fff;
     font-size: 1.2em;
     font-family:Verdana, Geneva, sans-serif;
     font-weight: bold;
     text-align: center;
     padding: 6px 0 0 10px;
}

/* ツイッターモジュール */
#twitterModule {
    width: 90%;
    height: 350px;
    margin:10px auto;
    overflow: hidden;
    background: #fff;
    box-shadow: 1px 1px 3px #333;
    border-radius: 8px 8px 0 0;
    -moz-border-radius: 8px 8px 0 0;
    -webkit-border-radius: 8px 8px 0 0;
}
#twitterModule .title {
    position: relative;
    padding: 6px;
    background: #0088CC;
    color: #F2F2F2;
    font-weight:bold;
    font-size: 18px;
    border-radius: 8px 8px 0 0;
    -moz-border-radius: 8px 8px 0 0;
    -webkit-border-radius: 8px 8px 0 0;
}

/* ツイートブロック */
#area-tweets p {
    padding: 1em;
    font-size: 14px;
    line-height: 1.2em;
    border-bottom:1px solid #ccc;
}
#area-tweets p a {
    color: #93A644;
    text-decoration: none;
    font-weight:bold;
}
#area-tweets p a.reply {
     color: #93A644;
}
#area-tweets p a:hover {
    text-decoration: underline;
}

#area-tweets .user {
    font-style: normal;
    color: #333;
    font-weight:bold;
    text-decoration: none;
}
#area-tweets .date {
    float:right;
    font-style: normal;
    font-weight: normal;
    color: #999;
    text-decoration: none;
}

/* 住所入力エリア */
#twitterModule .area-input {
    position: absolute;
    top: 420px;
    left:0;
    width: 100%;
    height: 40px;
    padding-top: 4px;
    background: #333;
    text-align:center;
}
#twitterModule .area-input input {
    width: 180px;
    height: 30px;
    font-size: 12px;
    border: 0;
    margin-top:3px;
    padding:0 0 0 10px;
    background:#CCC;
    color:#666;
    border-radius: 12px;
    -moz-border-radius: 12px;
    -webkit-border-radius: 12x;
    box-shadow: -1px -1px 3px #eee;
}

#area-tweets .address {
     padding: 1em;
     color: #279572;
     font-weight: bold;
}
JavaScript
(function($) {
	
/* 設定 */
  var geo = {
    twitter: "http://search.twitter.com/search.json",
    lat: 35.724442, 	// 緯度
    lng: 139.715447,	// 経度
    rad: 3, 			// 半径(km)
    addr: "池袋駅", 	// 表示されている住所・施設名
    timerGetTweet: 0,	// getTweet関数のループを止めるためのタイマーID格納用
    google: new google.maps.Geocoder()	// このgeo.googleを通じてMaps APIを利用します。
  };
	
/* 実行 */
  $(function() {

    getTweet();
    slideTweet();

    $("#area-tweets").hover(function() {
        $(this).find("p").first().stop();
    }, function() {
        slideTweet();
    });

// form要素のsubmit時
  $("#twitterModule .area-input").submit(function() {
        getAddress();
			
// sumitiイベントのデフォルト動作(action属性への遷移。この場合は同じページの再読込)をキャンセルし、リロードしないようにします。
      return false;
    });

// input要素のblur時
  $("#twitterModule input").blur(function() {
        getAddress();
    });
  });

/* 入力 */
  function getAddress() {

// var value = $("#twitterModule input").attr("value");
    var value = $("#twitterModule input").val();
		
// 表示内容と入力内容の間に変更がなかった場合は何もしません。
    if (geo.addr === value) { return false; }

// 入力内容を表示内容として保存します。
    geo.addr = value;

// getGeocode関数を実行します。
    getGeocode();
  }

/* 取得(位置情報 */
  function getGeocode() {
    if (!geo.google) {
        return false;
    }
		
  geo.google.geocode({ "address": geo.addr }, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
          geo.lat = results[0].geometry.location.lat();
          geo.lng = results[0].geometry.location.lng();
      }

// すでに登録されたツイートを削除するためresetTweetを実行します。
    resetTweet();

// getTweetは30秒ごとに実行するようになっていますので、タイマーIDを使って、いったんそのタイマーを中断します。
    clearTimeout(geo.timerGetTweet);

// 新たにgetTweetを実行します。
    getTweet();
        });
  }

/* 消去 */
  function resetTweet() {
      var mod = $("#twitterModule"),

// ツイートエリアの高さを取得します。
// モジュールの高さ - タイトルエリアの高さ - インプットエリアの高さ

  areaHeight = mod.height() - mod.children(".title").height() - mod.children(".area-input").height();
    h = 0,		// ツイートブロックの高さ集計用
    index = 0;	// 削除基点となるツイートブロックのインデックス番号用

// eachメソッドでツイートブロック(p)の高さを順に加算して、ツイートエリアの高さを越えた時点で、そのインデックス番号を取得して終了する。
  $("#area-tweets p").each(function(i) {
      h += $(this).height();
      if (areaHeight < h) {
            index = i;
            return false;
      }
  });

// nextAllメソッドとremoveメソッドでインデックス番号以降のツイートブロックを削除する。
      $("#area-tweets p").eq(index).nextAll().remove();
   }

/* 取得(ツイート) */
  function getTweet() {
        var area = $("#area-tweets"),

// Twitter Search APIのURLにパラメータを付加する。
        url = geo.twitter + "?geocode=" + geo.lat + "," + geo.lng + "," + geo.rad + "km";

        $.getJSON(url + "&callback=?", function(data) {
            var results = data.results,
            p = $("<p>", { "class": "address" });	// 住所表示用

// 住所を表示するブロックを追加する。
    p.text(geo.addr + " 周辺").appendTo(area);

    for (var i = results.length; i--; ) {
        var p = $("<p>"),
            user = $("<a>", { "class": "user", target: "_blank" }),
            date = $("<span>", { "class": "date" }),
            datetime = new Date(results[i].created_at); 

    user.text(results[i].from_user).attr("href", "http://twitter.com/" + results[i].from_user);
        date.text(
            datetime.getFullYear() + "/" + 
            (datetime.getMonth() + 1) + "/" + 
            datetime.getDate() + " " + 
            datetime.toLocaleTimeString()
        );
    results[i].text = results[i].text.replace(/(https?:\/\/[\-\/a-z0-9_~.#?&=%]+)/ig, "<a target='_blank' href='$1'>$1</a>");
    results[i].text = results[i].text.replace(/@([a-z0-9_]+)/ig, "<a class='reply' target='_blank' href='http://twitter.com/$1'>@$1</a>");

    p.append(user, date, "<br>", results[i].text).appendTo(area);
  }

// 30秒後に再実行させます。
// ループ中断用にタイマーIDを格納します。
            geo.timerGetTweet = setTimeout(getTweet, 30000);
      });
  }

/* 表示 */
  function slideTweet() {
    var p = $("#area-tweets > p"), h = 0;

    if (!p.length) {
	setTimeout(slideTweet, 500);
	return false;
    }
		
	h = p.first().innerHeight();

	p.first().animate({
	  marginTop: -h
     }, {
     duration: (h + Math.round(p.first().css("marginTop").slice(0, -2))) * 50,
        easing: "linear",
	complete: function() {
	$(this).remove();
	slideTweet();
                }
      });
  }

  })(jQuery);