三、推特应用:我爱火腿

现在我们已经有了一个移动 web 应用,我想让我们探索使用 Twitter API 来做一些与老一套经典的“显示 Twitter 消息应用”有所不同的事情。正如我们在第二章中讨论的,使用 Twitter API 可以让你接触到总是充足的数据“消防水管”,这些数据可以用于所有类型的应用和游戏——基本上是你能想象到的任何东西。

我一直喜欢使用 Twitter 的一个想法来自几年前的一系列旧网络节目。虽然这个游戏的名字随着节目的变化而变化,但游戏背后的主要原则始终是一样的。用户会看到两个不同的押韵的搜索词,他们必须猜测哪个词会产生更多的推文。虽然规则很简单,但这个我们将构建并命名为“我爱火腿”的小游戏可以带来数小时的乐趣。所以事不宜迟,让我们启动本地开发环境,开始编写一些代码吧!

HTML

下面的清单 3–1建立了基本的 HTML 文档,它将成为我们应用的基础。

清单 3–1。 HTML 为我爱火腿

`<!DOCTYPE HTML>

I Love Ham

Which one of these fabulous tweets has more search results?!

`

我们在这个应用中使用的 HTML 标记将比“那条推文是谁?”中的要少一些,我们以前构建的应用,它看起来也非常相似!为了简单起见,我保留了几乎相同的文件夹树布局的命名约定(参见图 3–1):

  • /index.html
  • /css/styles.css
  • /js/main.js

images

图 3–1。 一个清晰易读的文件结构,就像 Adobe Dreamweaver CS 5.5 中看到的那样,将为您节省大量的时间,并减少后续的挫折!

在创建文件和组织项目的文件夹结构时,我发现坚持人类可读、一目了然且在整个项目中保持一致的命名方案通常很有用。如果您最终将文件命名为 " supercooldocument12-667.html",您会使最终用户更难找到这些文档,如果您将来回到应用进行更新和编辑,这可能会导致问题。(相信我们:你会完全忘记那些文件是做什么的。)另一个技巧是用当前日期命名文件,或者使用版本控制系统来保持事物的完整性。所以请记住,在命名文件时,要保持简单和/或有意义!

CSS

我们的 CSS 也将看起来类似于我们之前构建的应用。这里和那里有一些关键的区别,我们在这个应用中展示了一些简洁的 CSS 属性,例如text-shadow CSS 属性,它允许您在客户端浏览器中对文本应用一些非常奇妙的阴影效果。这并不依赖于让一个设计者用新的花哨的文本来制作一些过度压缩的图像,就像我们在过去所做的那样(过去,我指的是几年前!).

清单 3–2涵盖了在我们的应用中使用的常用元素的间距和字体大小的基本重置。

清单 3–2。 CSS 为我爱火腿——第一部

`/ RESET / html, body, header, section, div, p, ul, li, h2 { margin:0; padding:0; }

ul, li { list-style:none; }

/ GLOBAL CSS / html, body { width:100%; height:600px; overflow-x:hidden; }

body { font-size:14px; font-family: 'Droid Sans', Arial, Helvetica, sans-serif; background:#993366; }

h2 { font-size:18px; color:#fff; text-shadow:1px 1px 5px rgba(0,0,0,0.9); }`

我们的h2标签将成为我们text-shadow的幸运接收者。如果您查看这个应用的 HTML 标记,您可以看到这个h2标签包含了一个将呈现给用户的文本简介。根据游戏的当前状态,文本将改变多达四次,并将由应用的 JavaScript 更新。如前所述,如果我们用老方法做这件事,我们将不得不创建四个包含我们想要的文本的单独的图像,或者在需要时手动将这些图像插入页面,或者根据需要将它们作为背景图像分配给要分配给我们的 blurb 容器的 CSS 类。虽然这并不难做到,但这需要编写更多的代码,并在设备上加载更多的图形资源,如果用户在一个数据连接缓慢的区域,可能会导致明显的延迟或导致用户在情感上与你的应用断开连接!

清单 3–3中,我们将设置列表项:

清单 3–3。 我爱火腿的 CSS 第二部

`/ SECTION / section { margin:20px 10px; padding:10px; }

sectionul { width:100%; margin:25px 0; }

section li { margin:10px 0; padding:10px 5px 10px; min-height:22px; line-height:32px; border-radius:7px; background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#a1a1a1), to(#A1A1A1), color- stop(.6,#8A8A8A)); -webkit- box-shadow:0 0 20px rgba(0,0,0,0.5); box-shadow:2px 2px 10px rgba(0,0,0,0.8); }`

你也会注意到我们对 CSS 中的列表项做了一些不同的处理。这里,我们给按钮添加了一个漂亮的渐变背景,让它们看起来更有魅力。不同于之前我们在第一个应用中创建的渐变背景,这一个使用了三色渐变系统来给它更多的斜面效果。此外,就像我们的text-shadows一样,使用 CSS 有助于减少浪费我们客户的资源,例如加载我们不使用的图像。我知道我确实在反复强调这一点,但那是因为这是一条必须遵守的真正重要的规则!永远不要不小心浪费你客户的资源,尤其是当你生活在一个古怪的数据上限或缓慢的数据连接的世界里。最后但同样重要的是,在我们的 CSS 文件中(参见清单 3–4,我将向您介绍两个非常方便的 CSS 选择器来让您熟悉一下:beforeand :afterselectors

清单 3–4。 我爱火腿的 CSS 第三部

`sectionli.fail { background:#990000; color:#fff; }

sectionli.win { background:#009900; color:#fff; }

sectionli.fail, section li.win { border-bottom:1px solid #fff; }

sectionblockquote { margin:0; padding:0; } sectionblockquote:before { content: "\201c\ "; font-size:26px; float:left; margin-right:5px; padding-left:5px; }

sectionblockquote:after { content: "\201e\ "; font-size:26px; margin-left:5px; padding-left:5px; }`

现在,这些选择器很简洁,因为它们允许您在它们所附加的元素之前或之后添加内容。在这里,我将它们附加到 blockquote 元素,这是一个较老的 HTML 元素,用于在语义上将该内容标记为应该在页面上脱颖而出的引用。

现在,如果您查看content属性,您可能会有点困惑。在大多数情况下,人们通常会在这个字段中添加一些有意义的东西,比如一个“>”来代替无序列表中的项目符号,或者在链接到一篇文章的内容简介后添加一个省略号。然而,没有多少人知道,您还可以在这个属性中包含十六进制代码,以显示键盘上不常见的字符,例如我想在我的blockquote内容的开头和结尾添加的引号!

JavaScript

既然我们已经很好地理解了所有东西是如何布置的,那么是时候开始研究如何将所有的齿轮、滑轮和链轮放在一起,并让这个应用正常工作了!首先,就像在我们之前的应用中一样,我们首先在这里声明将在整个应用中使用的全局变量。在 JavaScript 中,理解使用全局变量和局部变量的区别是非常重要的。

简而言之,我想花点时间强调这是最基本的解释,局部变量是一个可以在函数中使用,但不能在不同的函数中使用或作为脚本的一部分的变量。功能基本上是可以重用的“捷径”。例如,我可能会创建一个函数,对给定的输入(称为“函数参数”,即在函数调用后放入()中的信息)进行一些数学运算,并在整个代码中重用该函数。局部变量在功能块内部使用,但在外部不可访问。就这些变量而言,把函数内部想象成一个与代码其余部分分离的小世界!

另一方面,正如您现在可能已经猜到的,全局变量是全局可访问的,因此您可以在 JavaScript 文件中的任何函数或对象中调用它。虽然有些人会嘲笑全局变量的使用,因为它们会引起问题。例如,一个全局变量可以从各种函数中更新,这就造成了在调试过程中变量如何变化的混乱。但是,为了学习,由于这是一本针对初学者的书,我们将在我们的示例中使用它们。

清单 3–5设置了一个在整个 JavaScript 文件中使用的全局变量列表,以及一个充满押韵演示选项的数组,让我们的用户开心几个小时...或者分钟。

清单 3–5。Javascript for I Love Ham-Part 1

`/   * I Love Ham   * @author: Rocco Augusto   * @file: js/main.js /

var correct = ''; var choice = ''; varresultLength = 0; var tweets =  [ ['I love ham','Earthquake in Japan'], ['Android is awesome', 'I just hit an opossum'], ['Ice cream sandwich','I fell out of my hammock'], ];`

与我们之前的游戏不同,我们将有更少的选择呈现给我们的用户。虽然我很想添加 50 到 100 个不同的押韵例子,但不幸的是,我只能机智地不假思索地创造三个例子。就目前而言,我认为三个是好的,但是如果你在家跟着做,试着尽可能多的放进去!我敢肯定,你们中的很多人比我更机智!

清单 3–6遍历我们应用的init()函数,从 API 获取我们的 Twitter JSON 提要。

清单 3–6。 我爱火腿的 Javascript 第二部分

`functioninit() { window.scrollTo(0, 1);

//reset the correct answer and currentRound array correct = ''; choice = getRandom(); $('ul, section').removeClass(); $('ul').empty();

//find out which item has more search results for(i=0;i<choice.length;i++){ var position = i; $.getJSON('http://search.twitter.com/search.json?rpp=100&q=' + choice[i].replace(/\s/g,'%20') + '&callback=?', function(data) { //check the length of results for each search //then set them to the "correct" variable correct.push(data.results.length); }); }

// generate the buttons for this round buildQuiz(); }`

这里有我们的init()函数,它将在 DOM(文档对象模型)加载后在应用中被调用和运行。当使用 Twitter API 时,你可以通过搜索发送几个参数。让我们快速浏览一遍!

  • 告诉 API 我们希望每页返回多少结果。在这种情况下,我们每次搜索最多获得 100 个结果。
  • Q是容纳我们的搜索查询的参数。
  • Callback被触发以确保 API 以 JSONP 格式发回数据,这样我们就不会遇到任何跨域安全问题!

你会注意到上面的另一件事是搜索查询中的 I,我们在那个时候调用这个术语进行搜索。在那一部分,我使用了replace()方法在我们的字符串中搜索所有空格,并用%20替换它们,这是一个空格的 URL 编码版本。这使得搜索可以通过普通的 HTTP 请求发送,而不会弄乱网页真正指向的位置。为了更好地理解为什么这是必要的,想象一下——有人给你发了一个[http://someawesomesite.com/some](http://someawesomesite.com/some)的链接。由于 URL 是不完整的,如果你发送链接的人点击了它,那么他们很可能会被导航到一个 URL 为[http://someawesomesite.com/some](http://someawesomesite.com/some),的页面,而 URL 的其他部分会被忽略,但是点击一个看起来像[http://someawesomesite.com/some%20awesome%20page](http://someawesomesite.com/some%20awesome%20page)的 URL 会把用户带到他们想要去的地方。始终确保您创建的 URL 中没有中断(参见图 3–2)!

images

图 3–2。 注意前面来自 Android Thoughts 的 URL 使用连字符而不是空格来呈现给用户一个更加友好和人类可读的 URL

从 Twitter 获取 JSONP 数据后,我们将解析data.resultsfield的数据,然后获取该数组的长度、其中的记录数,然后将它们推送到我们之前创建的正确数组中,如清单 3–7所示。

清单 3–7。Javascript for I Love Ham-Part 3

`// this function will grab a random user from // the tweets array. functiongetRandom() { var l = tweets.length;      // grab length of tweet array var ran = Math.floor(Math.random()*l);      // grab random user

return tweets[ran]; }

functionbuildQuiz() { var h = '';

for(i=0;i<choice.length;i++){ h += '

  • '; h += '  
    ' + choice[i] + '
    '; h += '
  • '; }

    // write buttons to the page $('ul').html(h); }

    $(function(){ // run the init() function and start the application init();

    // check for correct user on user selection $('ul li').live('click', function() { var id = $(this).index();var not = (id == 0) ? 1 : 0; var result = '';

    // restart the game if game over if($('ul').hasClass('gameover')) { init(); $('h2').text('Which one of these fabulous tweets has more search results?!'); } else { if(correct[id] > correct[not]) { //congratulate the player result = 'Congratulations! you are a total rock star!'; $('sectionli:eq('+ id + ')').addClass('win'); } else if(correct[id] == correct[not]) { //if it is a tie result = 'It is a tie! You\'re a winner by default!'; } else { //shame the player into playing again result = 'Boo! You failure!'; $('sectionli:eq('+ id + ')').addClass('fail'); }

    // addgameover class to page $('ul').addClass('gameover'); $('h2').text(result + 'Tap a button to play again!'); } }); });`

    在我们继续之前,值得一提的是,我们在“你是赢家”一行中加了一个反斜杠。这是因为我们使用了撇号,JavaScript 通常将其解释为字符串的结束。通过在它前面放置反斜杠,我们已经“转义”了它,告诉 JavaScript 对后面的撇号使用“替代”含义(在这种情况下,替代含义就是简单地将其视为字符串的一部分)。

    其余的函数与我们已经创建的非常相似,所以我们将跳过它们,直接跳到控制按钮被按下时会发生什么的代码。在这段代码中,我们获取被按下按钮的索引,或者无序列表中的位置。然后,我们将这个搜索的值与另一个搜索的值进行比较。如果你的选择是数字较大的那一个,那么你就赢了,页面顶部的广告会变成一条祝贺你成功的好消息,或者如果你选择得不好,会变成一条失败的消息。在我们的逻辑语句中,我们也有在平局和两次搜索得到相同票数的情况下该怎么做的说明。

    现在继续保存您的工作,启动您的浏览器,运行您新设计的应用(参见图 3–3)!虽然这很简单,但我相信您已经开始了解如何使用 HTML5、CSS3 和 JavaScript,实时创建一个非常有趣且响应迅速的 web 应用了!

    images

    图 3–3。 我喜欢在安卓 2.3 设备上运行的火腿

    总结

    不算太寒酸,如果我自己这么说的话!我们设法用一点代码和一个古怪的想法,很快就把它变成了一个好看的概念验证。我们已经展示了另一个通过 JavaScript 利用 Twitter API 的例子,并且我们已经建立了将它扩展到其他方面的平台——不仅仅是搜索 Tweets,还可以使用趋势主题和提及。只要再多花一点时间和精力,我们就可以在这个非常基础的 Twitter 应用的基础上,把它变成一个成熟的游戏,从我们用户的生活中吸取时间!