首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 HTML 5 构建 Web 应用程序(3)构建未来的应用程序

用 HTML 5 构建 Web 应用程序(3)构建未来的应用程序

构建未来的应用程序这个例子的重点是如何在移动设备上使用地理定位,但请记住 Firefox 3.5+ 也支持地理定位。这个应用程序首先查找用户当前位置附近的称为场所 的 Foursquare。场所可以是任何东西,但通常是指饭馆、酒吧、商店等。作为一个 Web 应用程序,我们的示例也受限于目前所有浏览器均执行的同源策略。它不能直接调用 Foursquare 的 API。而是使用一个 Java servlet 来实际代理这些调用。之所以采用 Java 并没有任何特别之处;您也可以用  PHP、Python、Ruby 等轻松编写一个类似的代理。清单 5 显示了一个代理 servlet。
清单 5. Foursquare 代理 servlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class FutureWebServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        String operation = request.getParameter("operation");
        if (operation != null && operation.equalsIgnoreCase("getDetails")){

            getDetails(request,response);
        }
        String geoLat = request.getParameter("geoLat");
        String geoLong = request.getParameter("geoLong");
        String baseUrl = "http://api.foursquare.com/v1/venues.json?";
        String urlStr = baseUrl + "geolat=" + geoLat + "&geolong=" + geoLong;
        PrintWriter out = response.getWriter();
        proxyRequest(urlStr, out);        
    }

    private void proxyRequest(String urlStr, PrintWriter out) throws IOException{
        try {
            URL url = new URL(urlStr);
            InputStream stream = url.openStream();
            BufferedReader reader = new BufferedReader( new InputStreamReader(stream));
            String line = "";
            while (line != null){
                line = reader.readLine();
                if (line != null){
                    out.append(line);
                }
            }
            out.flush();
            stream.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
     
    private void getDetails(HttpServletRequest request, HttpServletResponse response)
throws IOException{
        String venueId = request.getParameter("venueId");
        String urlStr = "http://api.foursquare.com/v1/venue.json?vid="+venueId;
        proxyRequest(urlStr, response.getWriter());
    }
}




这里需要注意的重要一点是代理了两个 Foursquare                API。一个用来搜索,另一个用来获得这个场所的细节。要辨别这二者,细节 API 添加了一个操作参数。此外,将返回类型指定为 JSON,这会使解析来自 JavaScript 的数据变得十分简单。知道了应用程序代码所能进行哪种类型的调用之后,接下来让我们看看它如何进行这些调用以及如何使用来自 Foursquare 的数据。
使用地理定位第一个调用是一个搜索。 显示了对于纬度和经度需要两个参数:geoLat 和 geoLong。如下的清单 6 显示了如何获得应用程序内的这两个参数以及如何调用这个 servlet。
清单 6. 用位置进行搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (!!navigator.geolocation){
    navigator.geolocation.getCurrentPosition(function(location) {
        venueSearch(location.coords.latitude, location.coords.longitude);
    });
}
var allVenues = [];
function venueSearch(geoLat, geoLong){
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if (this.readyState == 4 && this.status == 200){
            var responseObj = eval('(' + this.responseText + ')');
            var venues = responseObj.groups[0].venues;
            allVenues = venues;
            buildVenuesTable(venues);
        }
    }
    xhr.open("GET", "api?geoLat=" + geoLat + "&geoLong="+geoLong);
    xhr.send(null);
}




上述代码会查找浏览器的地理定位功能。如果浏览器有此功能,就会获得这个位置并用纬度和经度调用 venueSearch 函数。此函数使用了 Ajax(一个                XMLHttpRequest 对象调用  内的 servlet)。它为 callback 函数使用一个闭包、解析来自 Foursquare 的 JSON 数据并将一个由场所对象组成的数组传递给一个名为                buildVenuesTable 的函数,如下所示。
清单 7. 使用场所构建 UI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function buildVenuesTable(venues){
    var rows = venues.map(function (venue) {
        var row = document.createElement("tr");
        var nameTd = document.createElement("td");
        nameTd.appendChild(document.createTextNode(venue.name));
        row.appendChild(nameTd);
        var addrTd = document.createElement("td");
        var addrStr = venue.address + " " + venue.city + "," + venue.state;
        addrTd.appendChild(document.createTextNode(addrStr));
        row.appendChild(addrTd);
        var distTd = document.createElement("td");
        distTd.appendChild(document.createTextNode("" + venue.distance));
        row.appendChild(distTd);
        return row;
    });
    var vTable = document.createElement("table");
    vTable.border = 1;
    var header = document.createElement("thead");
    var nameLabel = document.createElement("td");
    nameLabel.appendChild(document.createTextNode("Venue Name"));
    header.appendChild(nameLabel);
    var addrLabel = document.createElement("td");
    addrLabel.appendChild(document.createTextNode("Address"));
    header.appendChild(addrLabel);
    var distLabel = document.createElement("td");
    distLabel.appendChild(document.createTextNode("Distance (m)"));
    header.appendChild(distLabel);
    vTable.appendChild(header);
    var body = document.createElement("tbody");
    rows.forEach(function(row) {
        body.appendChild(row);
    });
    vTable.appendChild(body);
    $("searchResults").appendChild(vTable);
    if (!!window.openDatabase){
        $("saveBtn").style.display = "block";
    }
}




内的代码主要是用来创建内含场所信息的数据表的 DOM 代码。但其中也不乏一些亮点。请注意高级 JavaScript                特性(比如数组对象的映射以及 forEach 函数)的使用。这里还有在支持地理定位的所有浏览器上均可用的一些特性。最后的两行代码也很有趣。对数据库支持的检测在此执行。如果支持,那么就启用一个 Save 按钮,用户单击此按钮就可将所有该场所的数据保存到一个本地数据库。下一节将讨论这一点是如何实现的。
返回列表