无论你是互联网世界的一个高手或是一个从来没有接触过互联网的新手,这篇文章将给你带来完整的在Ubuntu平台上开发HTML 5的应用。我们将慢慢地通过这个练习让你很自然地进入并熟悉整个的HTML 5应用的开发流程。在这个练习中,我们将设计一个最简单的RSS阅读器。当我们的应用设计完整后,应用的显示如下:
如果你是一个固执的HTM 5黑客,你可以选择任何你所喜欢的工具及工具包来开发你的HTML 5应用。它们将会很好地工作于Ubuntu手机上。我们将只专注于Ubuntu SDK提供的工具及工具包。更多关于HTML 5开发的信息可以在Ubuntu的官方网站或中文网站得到。
如果你还没有安装好自己的Ubuntu SDK,请参照文章“Ubuntu SDK 安装”来安装好自己的SDK。
特别提醒:在模拟器中参阅文章”怎么在Ubuntu手机中打开开发者模式“打开开发者模式,这样才可以把应用部署到模拟器中。
1)创建一个新的项目
在这一步,我们将使用Ubuntu SDK来生产一个项目:
请按照上面的步骤来创建一个新的项目“html5-rssreader”。我们首先在Desktop上运行该应用(使用热键
Ctrl +
R):
可以看出是以非常简单的HTML 5应用。我们可以点击应用的按钮在浏览器中打开上面显示的链接。
2)如何调试我们的应用
我们知道调试应用是非常重要的。我们怎么调试我们的HTML 5应用呢?我们开发的步骤是一般现在自己的电脑上开发好我们直接的应用,然后再打包并部署到自己的手机上或模拟器中。当我们在SDK中运行我们自己的HTML 5应用时,我们可以看到:
在Application Output输出窗口,我们可以看到一个地址:
http://192.168.1.106:9221
这个就是我们用来调试的地址。我们把这个地址拷到我们的Chrome或Chromium地址栏中,并进入:
在我们调试时,我们只能运行一个应用的实例,否则,我们将看不到任何的输出。
3)删除默认项目中不需要的代码
在这一节中,我们将删除项目中不需要的部分代码。
在项目的
www/目录中,你可以看到如下的内容:
- HTML 文件
- images (在www/img目录下)
- javascript文件 (在www/js目录下)
- CSS文件 (在www/css目录下)
首先我们来对index.html进行修改:
1)首先,我们来查看如下的代码:
<div data-role="content">
2)就像你看到的那样,有一个<div>在那里。它定义了一个叫做hello-page的tab。<div>包含了最直接的HTML组成部分。我们删除所有包含在
<div data-role="content">
<body>
<div data-role="mainview">
<header data-role="header">
<ul data-role="tabs">
<li data-role="tabitem" data-page="hello-page">Hello World</li>
</ul>
</header>
<div data-role="content">
</div>
</div>
<script src="js/app.js"></script>
</body>
重新运行我们的应用,我们可以看到:
我们可以看到应用中没有显示任何的东西。这也并不奇怪,因为我们本来就没有放任何的东西在里面。我们接下来也需要修改应用的标题。
4)删除不必要的代码
在上面的一节中,我们主要对index.html进行了修改。在这个章节里,我们将对css及javascript文件进行修改。
1)我们把css/app.css中的所有内容删除掉。这里的内容是针对helloworld模版的。我们不需要它们
2)在js/app.js文件中,我们删除如下的代码:
function addClass(elem, className) {
elem.className += ' ' + className;
};
function removeClass(elem, className) {
elem.className = elem.className.replace(className, '');
};
同时,我们删除从如下的行:
// Detect if Cordova script is uncommented or not and show the appropriate status.
到最后的一行的前面:
};
等我们完成所有的操作之后,最后js/app.js文件的内容如下:
/**
* Wait before the DOM has been loaded before initializing the
Ubuntu UI layer
*/
window.onload = function () {
var UI = new UbuntuUI();
UI.init();
};
UbuntuUI是Ubuntu HTML 5应用的一个关键的架构类。我们需要构造它并初始化它以生产我们需要的Ubuntu HTML 5应用。我们可以通过这个对象来方位Ubuntu HTML 5的对象(对应于Ubuntu DOM元)及方法。到目前位置,这是我们最基本的一个最小的一个HTML 5应用虽然没有任何的东西。运行我们的应用,我们可以看到:
5)设计我们自己的应用
在这个章节中,我们将专注于设计我们自己的应用,所以我们我们将删除所有和helloworld相关的东西。
1)把如下的行
<title>An Ubuntu HTML5 application</title>
<meta name="description" content="An Ubuntu HTML5 application">
<title>RSS Mobile Reader</title>
<meta name="description" content="RSS Mobile Reader">
2)删除如下的代码:
<ul data-role="tabs">
<li data-role="tabitem" data-page="hello-page">Hello World</li>
</ul>
取而代之的是,我们将使用pagestack。关于应用的两种布局,我们可以参考 网址以了解更多的信息。
我们在如下行
<div data-role="content">
的下面,加入如下的代码:
<div data-role="pagestack">
<div data-role="page" id="main" data-title="RSS Mobile Reader">
</div>
</div>
3)在js/app.js文件中,我们加入如下的一行代码在UbuntuUI初始化之后:
UI.pagestack.push("main");
这里,"pagestack"以一种stack的形式管理所有的pages。最初始,没有任何的page,push()方法通常是在应用启动时,把第一个page推进stack并显示出来。
如果我们现在再运行我们的应用,我们可以看到如下的内容。我们可以看到我们的应用的page标题已经发生变化。我们同时也可以注意到在页面的最下面,我们可以看到“back”字样。这是和上面的显示是不同的地方。
6)把我们的内容放到应用中去
在这个一节中,我们将把我们想要显示的内容放到我们的应用中。我们回顾一下我们的在该文章中一开始显示设计,在第一页中,实际上是一个列表的显示。它显示了我们需要的展示的RSS feed的列表。在接下来的第二页中,我们显示的是所选中的RSS feed所包含的所有每个entry的列表。最后一个页面显示的是每个entry的具体的内容。
现在我们开始在index.html中加入我们先前已经定义好的“main”的页面:
1)在index.html中加入如下的行到javascript的插入列表中:
<script src="/usr/share/ubuntu-html5-ui-toolkit/0.1/ambiance/js/list.js"></script>
这个对于我们使用列表来说是必须的。在“main”页面中,我们也加入称作为“ yourfeeds”的 list。
<section data-role="list" id="yourfeeds"></section>
2)在完成好我们上面的代码后,我们接下来主要的代码将在js/app.js文件中。我们可以是使用外部的库来帮我们完成我们的工作。在js/app.js文件中,我们在推入“main”页面过后,即如下的行:
UI.pagestack.push("main");
if (typeof localStorage["feeds"] == "undefined") {
restoreDefault();
}
//load local storage feeds
var feeds = eval(localStorage["feeds"]);
if (feeds !== null) {
var feeds_list = UI.list('#yourfeeds');
feeds_list.removeAllItems();
feeds_list.setHeader('My feeds');
for (var i = 0; i < feeds.length; i++) {
feeds_list.append(feeds[i],
null,
null,
function (target, thisfeed) { loadFeed(thisfeed); },
feeds[i]);
}
}
我们使用 localStorage来存储我们所需要的feeds。如果最早没有被定义,就是“underdefined”,我们将调用restoreDefault()(在下面的部分来实现)来初始化我们所需要的feeds。如果在localStorage中已经有我们所需要的feeds,我们先清除“yourfeeds”列表中的内容,并把list的header设为“My feeds”。每当列表中的某一项被点击,我们就调用loadFeed()(在下面的代码中来实现)来下载这个feed。
3)在js/app.js文件的最后部分加入如下的代码:
function restoreDefault() {
localStorage.clear();
var feeds = [];
feeds.push("http://daker.me/feed.xml");
feeds.push("http://www.omgubuntu.co.uk/feed");
feeds.push("http://hespress.com/feed/index.rss");
feeds.push("http://rss.slashdot.org/Slashdot/slashdot");
feeds.push("http://www.reddit.com/.rss");
feeds.push("http://www.guokr.com/rss/");
try {
localStorage.setItem("feeds", JSON.stringify(feeds));
window.location.reload();
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
console.log("Error: Local Storage limit exceeds.");
} else {
console.log("Error: Saving to local storage.");
}
}
}
在这里,我们定义了restoreDefault()函数。它首先清除localStorage的数据,并加入一个JSON格式的RSS feed到localStorage中。代码中也同时加入了一些exception处理。
我再次运行我们的应用,当我们点击我们的列表中的每一项时,没有任何的反应。这是因为我们根本就没有实现loadFeed函数。
到目前为止的素有代码在如下的地址可以下载:
7)从Internet下载内容
到目前为止,我们的代码并不复杂。互联网上有很多东西是值得我们借鉴和利用的。事实上,你可以从互联网上借鉴使用任何你所想要的库来完成你所需要的工作。在今天的练习中,我们借鉴
jquery来完成我们的一部分工作。
1)打开一个Teminal, 并进入到js/app.js所在的目录中,在它里面打入如下的命令:
cp /usr/share/javascript/jquery/jquery.min.js .
我们需要一个RSS的parser。虽然google也有一个自己的
API,但是由于一些原因这个API在中国并不能被使用。我们在Terminal中打入如下的命令:
git clone https://github.com/jfhovinne/jFeed.git
等我们下载完所有的源码后,我们进入目录:jFeed/build/dist,并把文件“jquery.jfeed.pack.js”拷入到我们的js/app.js目录中。
3)在index.html文件中,在<head>加入如下的语句:
<!-- External javascript imports -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.jfeed.pack.js"></script>
在“main”页面下,加入另外一个叫做“ results”的页面:
<div data-role="content">
<div data-role="pagestack">
<div data-role="page" id="main" data-title="RSS Mobile Reader">
<section data-role="list" id="yourfeeds"></section>
</div>
<div data-role="page" id="results" data-title="Articles >">
<section data-role="list" id="resultscontent"></section>
</div>
</div>
<div data-role="dialog" id="loading"><section><progress></progress></section></div>
</div>
这里,我们也加入了一个等待的“loading”对话框。在下载数据时,显示“loading”字样。
4)现在,我们更进一步在js/app.js文件中做一些修改,我们首先把UbuntuUI变成一个全球的变量,把如下的代码:
window.onload = function () {
var UI = new UbuntuUI();
改为:
var UI = new UbuntuUI();
$(document).ready(function () {
我们同时也需要在函数的最后把 };修改为});。这样整个代码为:
$(document).ready(function () {
UI.init();
UI.pagestack.push("main");
if (typeof localStorage["feeds"] == "undefined") {
restoreDefault();
}
//load local storage feeds
var feeds = eval(localStorage["feeds"]);
if (feeds !== null) {
var feeds_list = UI.list('#yourfeeds');
feeds_list.removeAllItems();
feeds_list.setHeader('My feeds');
for (var i = 0; i < feeds.length; i++) {
feeds_list.append(feeds[i],
null,
null,
function (target, thisfeed) { loadFeed(thisfeed); },
feeds[i]);
}
}
});
5)现在我们来完成loadFeed方法的实现。在js/app.js的末尾,我们加入如下的代码:
function loadFeed(url) {
UI.pagestack.push("results");
UI.dialog("loading").show()
console.log("url is: " + url );
$.getFeed( {
url: url,
success: function(feed) {
UI.dialog("loading").hide();
var results_list = UI.list('#resultscontent');
results_list.removeAllItems();
results_list.setHeader(feed.title);
console.log("title: " + feed.title);
// walk through the feeds
for( var i = 0; i < feed.items.length; i++ ) {
var item = feed.items[ i ];
// console.log("title: " + item.title);
// console.log("link: " + item.link);
// console.log("content: " + item.description);
results_list.append(
item.title.replace(/"/g, "'"),
null,
null,
function (target, result_infos) {
showArticle.apply(null, result_infos); },
[ escape(item.title),
escape(item.link),
escape(item.description) ] );
}
}
});
}
重新运行我们的应用,我们可以点击我们的每个rss feed,并看到每个rss feed的标题列表:
所有的源码在如下的地址找到:
8)显示实际的文章
如果细心的开发者仔细看了我们上一节的代码后,你可能会发现,我们已经提到了“showArticle”,但是我们还是没有实现它。当我们点击RSS feed的标题后,没有任何的东西显示。它的实现如下:
1)在index.html中,加入“article”页面:
<div data-role="content">
<div data-role="pagestack">
<div data-role="page" id="main" data-title="RSS Mobile Reader">
<section data-role="list" id="yourfeeds"></section>
</div>
<div data-role="page" id="results" data-title="Articles >">
<section data-role="list" id="resultscontent"></section>
</div>
<div data-role="page" id="article" data-title="Article >">
<section id="articleinfo"></section>
</div>
</div>
<div data-role="dialog" id="loading"><section><progress></progress></section></div>
</div>
2)在js/app.js文件的最后面,加入如下的方法:
function showArticle(title, url, desc) {
UI.pagestack.push("article");
if (typeof desc == "undefined")
desc = "(No description provided)";
$("#articleinfo").html("<p>" + unescape(title) + "</p><p>" + unescape(desc) + "</p><p><a target=\"_blank\" href=\"" + unescape(url) + "\">" + unescape(url) + "</a></p>");
}
这样我们就可以得到文章的标题及其内容。为了展示文章的内容,我们显示文章的title,内容及一个url。为了展示文章的内容及title,我们使用“
unescaped”。
重新运行我们的应用,我们可以看到如下的画面:
整个项目的源码在:
9)添加RSS feed
现在我们的RSS feed都是固定,预先设定好的。如果一个用户需要添加一个新的RSS feed该怎么办呢?
1)在index.html文件中,在javascript的import区域,加入如下的代码:
<script src="/usr/share/ubuntu-html5-ui-toolkit/0.1/ambiance/js/toolbars.js"></script>
<div data-role="page" id="main" data-title="RSS Mobile Reader">
<section data-role="list" id="yourfeeds"></section>
<footer id="footer1" data-role="footer" class="revealed">
<nav>
<ul>
<li>
<a href="#" id="addfeed">
<img src="/usr/share/ubuntu-html5-ui-toolkit/0.1//ambiance/img/actions/add.svg" alt="Add feed" />
<span>Add feed</span>
</a>
</li>
</ul>
</nav>
</footer>
</div>
我们在footer中加入了一个 toolbar以添加一个RSS feed。
3)我们添加一个
对话框来输入所需要的RSS feed的详细信息:
在“loading”对话框的前面或后面,添加对话框:
<div data-role="dialog" id="loading"><section><progress></progress></section></div>
<div data-role="dialog" id="addfeeddialog">
<section>
<h1>Add a new feed</h1>
<p>Type the url feed you want to add</p>
<input type="url" id="rssFeed" placeholder="http://">
<menu>
<button data-role="button" id="no">Cancel</button>
<button data-role="button" class="success" id="yes">Add</button>
</menu>
</section>
这里我们定义了一个叫做“addfeeddialog”的对话框。它让用户来输入一个RSS feed的url。
4)在如下函数:
$(document).ready(function () {
UI.button('yes').click(function (e) {
var url = $("#rssFeed").val();
if (url !== "") {
var feeds = eval(localStorage["feeds"]);
feeds.push(url);
localStorage.setItem("feeds", JSON.stringify(feeds));
window.location.reload();
}
});
UI.button('addfeed').click(function () {
$('#addfeeddialog').show();
});
重新运行我们的应用,并点击“Add feed”按钮
添加一个RSS feed是不是在弹指之间呢?所有的源码在:
10)你的挑战
我们现在对话框的“Cancel”还不能工作,你可以帮我完成它的代码吗?
11)美化我们的应用
在这个章节里,我们将通过使用css来达到美化我们的应用的目的。
在css/app.css文件中,我们加入如下的代码:
#articleinfo {
padding: 10px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#articleinfo iframe {
max-width: 100%;
}
#articleinfo p {
margin: 7px 0;
}
#articleinfo a{
text-decoration: none;
color: #787878;
font-weight: bold;
}
重新运行我们的应用,我们可以看到Article显示得更加漂亮。到目前为止,所有的源码在如下的地址可以找到:
我们也可以参阅文章“
为HTML5应用创建独立于平台的Theme”来创建一个独立于平台的theme。
如果大家有任何的问题,欢迎在文章的评论中提出来。