2.0_beta sync to rsa
[framework/web/web-ui-fw.git] / libs / js / jquery-geo-1.0a4 / docs / examples / twheat / index.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta charset="utf-8">
5   <title>Twheat</title>
6   <meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1">
7   <meta name="description" content="Search Twitter based on location and draw the results as a heat map">
8   <meta name="author" content="Ryan Westphal">
9   <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/blitzer/jquery-ui.css" />
10   <style type="text/css">
11     html
12     {
13       font:13px/1.231 Calibri,Arial,sans-serif; *font-size:small;
14     }
15
16     .links
17     {
18       float: right;
19     }
20
21     .docLink 
22     {
23       background: url(img/$.geo-logo-small.png) left no-repeat;
24       color: #7f0000;
25       display: block;
26       font-size: 24px;
27       font-weight: bold;
28       padding: 0 24px;
29       text-decoration: none;
30     }
31   
32     .info 
33     {
34       background: #fff;
35       border-radius: 8px;
36       box-shadow: -4px 4px #444;
37       opacity: .8;
38       padding: 8px;
39       position: absolute !important;
40       right: 16px;
41       top: 16px;
42     }
43
44     .not-mobile
45     {
46       display: none;
47     }
48
49 @media only screen and (min-width: 800px) 
50 {  
51   .not-mobile
52   {
53     display: block;
54   }
55 }
56     h1
57     {
58       margin-right: 256px;
59     }
60
61     h2
62     {
63       font-style: italic;
64       margin-left: 1rem;
65     }
66
67     #map
68     {
69       position: fixed;
70       bottom: 0;
71       left: 0;
72       right: 0;
73       top: 0;
74     }
75     #popup
76     {
77       background: #fff;
78       border: solid 1px #444;
79       border-radius: 8px;
80       display: none;
81       max-height: 80%;
82       padding: 4px;
83       position: absolute;
84       opacity: .6;
85       overflow: hidden;
86       width: 30%;
87     }
88     #popup p
89     {
90       border-top: 2px solid #444;
91       margin: 0;
92       padding: 0;
93     }
94     #popup p:first-child
95     {
96       border-top: none;
97     }
98     #content
99     {
100       background: #fefefe;
101       border: 2px solid #444;
102       border-radius: 8px;
103       padding: 4px;
104       position: relative;
105       display: inline-block;
106     }
107     #content label span
108     {
109       display: inline-block;
110       text-align: right;
111       width: 10rem;
112     }
113     #content button
114     {
115       width: 6rem;
116     }
117
118     #tweetButton
119     {
120       display: inline-block;
121     }
122
123     #appendedCount
124     {
125       float: right;
126       margin-top: 1rem;
127     }
128
129   </style>
130 </head>
131 <body>
132   <div>
133     <div id="map">
134       <div id="popup">
135       </div>
136     </div>
137     <div id="content">
138       <form id="loc">
139         <label>
140           <span>Zoom to</span>
141           <input type="text" name="l" autofocus />
142         </label>
143         <button type="submit">Zoom</button>
144       </form>
145       <form id="twit">
146         <label>
147           <span>Search Twitter for</span>
148           <input type="text" name="q" />
149         </label>
150         <button type="submit">Search</button>
151       </form>
152       <div id="appendedCount">no tweets mapped yet :(</div>
153       <div id="tweetButton"></div>
154     </div>
155     <div class="info not-mobile">
156       <div class="links">
157         <a href="http://jquerygeo.com/" class="docLink">jQuery Geo &gt;</a>
158       </div>
159       <h1>Twheat!</h1>
160       <h2>A Twitter Heat Map</h2>
161     </div>
162   </div>
163   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
164   <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
165   <script src="http://code.jquerygeo.com/jquery.geo-1.0a4.min.js"></script>
166   <script>
167     $(function () {
168       var map = null,
169           checkedIds = [], //< list of tweet ids we've checked
170           appendedCount = 0, //< number of tweets we successfully appended
171           searchTerm = "", //< last search term
172           searching = false,
173           currentXhr = null, //< an ajax request reference if we need to cancel
174           
175           twitterButtonHtml = '<a href="https://twitter.com/share" class="twitter-share-button" data-count="vertical" data-via="ryanttb">Tweet</a><script src="//platform.twitter.com/widgets.js">\x3C/script>';
176
177       function initMap(center, zoom) {
178         // create a map using an optional center and zoom
179         map = $("#map").geomap({
180           center: center || [-71.0597732, 42.3584308],
181           zoom: zoom || 10,
182
183           // set the shapeStyle to a largish solid but translucent circle
184           // to give the tweets a heat map effect
185           shapeStyle: {
186             strokeOpacity: 0,
187             fillOpacity: .2,
188             width: "16px",
189             height: "16px",
190             borderRadius: "16px",
191             color: "#e44"
192           },
193
194           move: function (e, geo) {
195             // when the user moves, search for appended tweets
196             // and show a popup
197
198             // clear the popup
199             $("#popup").hide().html("");
200
201             if (searchTerm) {
202               // spatial query, geo has the cursor location as a map point
203               // this will find appended tweets within 3 pixels
204               var features = map.geomap("find", geo, 3),
205                   popupHtml = "",
206                   i = 0;
207
208               // for each tweet found, add some html to the popup
209               for (; i < features.length; i++) {
210                 popupHtml += "<p>" + features[i].properties.tweet + "</p>";
211               }
212
213               if (popupHtml) {
214                 // if any tweets found, show the popup
215                 var $popup = $("#popup").append(popupHtml).css({
216                   left: e.pageX,
217                   top: e.pageY
218                 });
219                 
220                 var widthOver = $(window).width() - ( $popup.width() + e.pageX ),
221                     heightOver = ($(window).height() - 32) - ( $popup.height() + e.pageY ),
222                     left = e.pageX,
223                     top = e.pageY;
224
225                 if ( widthOver < 0 ) {
226                   left += widthOver;
227                 }
228
229                 if ( heightOver < 0 ) {
230                   top += heightOver;
231                 }
232
233                 $popup.css({
234                   left: left,
235                   top: top
236                 }).show();
237               }
238             }
239           }
240         });
241
242         if ( searchTerm && !searching ) {
243           autoSearch();
244         }
245       }
246
247       $("#loc").submit(function (e) {
248         e.preventDefault();
249
250         // when the user clicks the location search button,
251         // send a request to nominatim for an OpenStreatMap data search
252         $.ajax({
253           url: "http://open.mapquestapi.com/nominatim/v1/search",
254           data: {
255             format: "json",
256             q: $("#loc input").val()
257           },
258           dataType: "jsonp",
259           jsonp: "json_callback",
260           success: function (results) {            
261             if (results && results.length > 0) {
262               // if we get a result, relaunch the app to the new location with the old search
263               // this will allow users to tweet their map
264               window.location.search = 
265                 "q=" + encodeURIComponent($("#twit input").val()) +
266                 "&l=" + encodeURIComponent($("#loc input").val()) +
267                 "&center=" + results[0].lon + "," + results[0].lat +
268                 "&zoom=" + map.geomap("option", "zoom");
269             }
270           }
271         });
272         return false;
273       });
274
275       $("#twit").submit(function (e) {
276         e.preventDefault();
277
278         // when the user clicks the tweet search button,
279         // send a request to twitter
280
281         if (currentXhr) {
282           // if there's a search pending, cancel it
283           currentXhr.abort();
284           currentXhr = null;
285         }
286
287         $("#popup").hide().html("");
288
289         // save our search term
290         searchTerm = $("#twit input").val();
291
292         if ( searchTerm ) {
293           // if we have a new search term, relaunch the app to the same location with the new search
294           // this will allow users to tweet their map
295           window.location.search = 
296             "q=" + encodeURIComponent(searchTerm) +
297             "&l=" + encodeURIComponent($("#loc input").val()) +
298             "&center=" + map.geomap("option", "center").toString() +
299             "&zoom=" + map.geomap("option", "zoom");
300         }
301
302         return false;
303       });
304
305       // jQueryUI for pretty buttons
306       $( "button" ).button();
307
308       function search() {
309         // called by autoSearch, this function actually searches Twitter for geo-enabled tweets
310
311         if ( map !== null ) {
312           var center = map.geomap("option", "center"), //< the center of the map in lon, lat
313               // the geocode argument to Twitter search,
314               // it's an array with [ lat, lon, radius in km ]
315               // geomap's center is lon, lat so we have to switch
316               // for radius we'll use document width * pixelSize converted to km (from meters)
317               // Twitter search has a max of 2500km
318               geocode = [ 
319                 center[1],
320                 center[0],
321                 Math.min(2500, map.geomap("option", "pixelSize") * $(document).width() / 2 / 1000) + "km"
322               ],
323               lastSearchTerm = searchTerm;
324
325           // actually send the request to Twitter
326           currentXhr = $.ajax({
327             url: "http://search.twitter.com/search.json",
328             data: {
329               rpp: 100,
330               q: lastSearchTerm,
331               geocode: geocode.join(",")
332             },
333             dataType: "jsonp",
334             complete: function () {
335               currentXhr = null;
336             },
337             success: function (tweets) {
338               if (searchTerm == lastSearchTerm && tweets.results) {
339                 // if we have results, search each of them for the geo or location property
340                 $.each(tweets.results, function () {
341                   appendTweet( this );
342
343                 });
344
345                 $("#appendedCount").text(appendedCount + " tweets mapped!");
346               }
347             }
348           });
349         }
350       }
351
352       function appendTweet( tweet ) {
353         // attempt to append a tweet if we haven't already
354         if ( $.inArray( tweet.id_str, checkedIds ) >= 0 ) {
355           return;
356         }
357
358         // we don't want to attempt more than once for a given tweet
359         checkedIds.push( tweet.id_str );
360
361         // store some tweet html as a property on the feature
362         var feature = {
363           type: "Feature",
364           geometry: {
365             type: "Point",
366             coordinates: [ 0, 0 ]
367           },
368           properties: {
369             tweet: "<b>" + tweet.from_user + "</b>: " + tweet.text
370           }
371         };
372
373         if (tweet.geo) {
374           // if we have a geo property, flip the coordinates because Twitter search isn't
375           // in proper GeoJSON spec order
376           // Twitter uses [lat, lon] instead of [lon, lat]
377           feature.geometry.coordinates = [
378             tweet.geo.coordinates[1],
379             tweet.geo.coordinates[0]
380           ];
381
382           map.geomap("append", feature);
383           appendedCount++;
384         } else if ( tweet.location ) {
385           // otherwise, attempt to geocode the location property
386           $.ajax({
387             url: "http://open.mapquestapi.com/nominatim/v1/search",
388             data: {
389               format: "json",
390               q: tweet.location
391             },
392             dataType: "jsonp",
393             jsonp: "json_callback",
394             success: function (results) {            
395               if (results && results.length > 0) {
396                 // if found, grab the location's lon & lat
397                 if (results[0].lon && results[0].lat) {
398                   feature.geometry.coordinates = [
399                     results[0].lon,
400                     results[0].lat
401                   ];
402
403                   // finally append the tweet
404                   map.geomap( "append", feature );
405                   appendedCount++;
406                   $("#appendedCount").text(appendedCount + " tweets mapped!");
407                 }
408               }
409             }
410           });
411         }
412       }
413
414       function autoSearch() {
415         searching = true;
416         if ( searchTerm ) {
417           search();
418           setTimeout(autoSearch, 5000);
419         }
420       }
421
422       // for fun, we support sending center, zoom and a tweet query in the query string
423       var queryString = window.location.search.substring(1),
424           params = queryString.split("&"),
425           options = {};
426
427       $.each(params, function() {
428         var idx = this.indexOf("=");
429         if (idx > 0) {
430           options[this.substring(0, idx)] = this.substring(idx + 1);
431         }
432       });
433
434       if (options.center) {
435         if (options.zoom) {          
436           initMap($.parseJSON("[" + options.center + "]"), parseInt(options.zoom));
437         } else {
438           initMap($.parseJSON("[" + options.center + "]"));
439         }
440       } else {
441         // if there's no center in the query string, try to use geolocation
442         if (navigator.geolocation) {
443           navigator.geolocation.getCurrentPosition(function (p) {
444             initMap([p.coords.longitude, p.coords.latitude]);
445           }, function (error) {
446             initMap();
447           });
448         } else {
449           // if all else fails, use defaults
450           initMap();
451         }
452       }
453
454       var title = "Twheat !";
455
456       if (options.q) {
457         searchTerm = decodeURIComponent(options.q);
458         $("#twit input").val(searchTerm);
459         title += " " + searchTerm;
460
461         if ( map !== null && !searching ) {
462           autoSearch();
463         }
464       }
465
466       if (options.l) {
467         var loc = decodeURIComponent(options.l);
468         $("#loc input").val(loc);
469         title += " " + loc;
470       }
471
472       $("title").html(title);
473       $("#tweetButton").append(twitterButtonHtml);
474     });  
475   </script>
476
477   <script>
478     var _gaq = [['_setAccount', 'UA-26084853-1'], ['_trackPageview']];
479     (function (d, t) {
480       var g = d.createElement(t), s = d.getElementsByTagName(t)[0]; g.async = 1;
481       g.src = ('https:' == location.protocol ? '//ssl' : '//www') + '.google-analytics.com/ga.js';
482       s.parentNode.insertBefore(g, s);
483     } (document, 'script'));
484   </script>
485 </body>
486 </html>