Droptiles是一套Metro风格的类似Win8的Web2.0控制面板。它采用图块(tiles)建立用户体验。图块(tiles)是一些可以从外部资源中获取数据的迷你应用。点击图块(tile)就能够启动全部应用。应用可以是任意已存在的网站,抑或专门为面板式体验而设计的自定义网站。Droptiles几乎全部是用HTML, Javascript 和CSS创建的,因此它具有很高的平台可移植性。示例工程采用ASP.NET创建,展示了一些服务端功能:如注册、登录以及从服务器获取动态数据。你也可以很容易地把它转变到PHP, Ruby, JSP或者其它平台。Droptiles是我之前编写的Dropthings的续篇,它是第一个开源的Web2.0控制面板。
访问 Droptiles.com 获得即时体验!
从https://github.com/oazabir/Droptiles获取代码。
Metro风格的UI。它是一个受metroui.org.ua启发的CSS框架,用来创建Metro风格的网站。
拖拽图块(tiles)定制个性化体验。
客户端对象模型及数据绑定,简化了MVVM模式的实现。
服务端实现具有平台无关性,采用PHP, JSP皆很轻松。
实时图块(Live Tiles),图块(Tiles)即是迷你应用,可以从多种源中加载数据。
它甚至有自己的应用商店!
如何使用Droptiles
企业Dashboard整合来自不同系统的数据,并提供为内联网/互联网应用一个快速启动板。
Web 2.0的门户网站,提供tile形式的portlets。整合来自各种服务的数据,并作为不同服务的快速启动板。
触摸启用Kiosk前端。最适用于酒店,餐厅,银行前台自助服务。
新闻的内容整合器和研究目的。
主要部分
Droptiles有三个主要部分:
Dashboard
应用程序商店
登录,注册,设置。
Dashboard是展示tiles的主页面。
App商店陈列了一系列可让用户添加到Dashboard上的应用程序。
登录,注册,设定区都是用ASP.NET设计的且它们还使用了ASP.NET的Membership provider。
Dashboard
Dashboard由各个部分构成。每部分包含一系列tiles。你看到到每个框都是一个Tile。tiles是迷你型应用程序。一个tile可以是以下几种类型:
简单的html页面
一个动态JavaScript迷你App
动态网页
让我们来看看 Flickr 的瓦片组件. 首先,所有的瓦片组件外观都在 Tiles.js 文件中定义, 它包含了所有瓦片组件的元数据. 例如, Flickr 瓦片组件元数据定义如下:
01 |
flickr: function (uniqueId) { |
02 |
return { |
03 |
uniqueId: uniqueId, |
04 |
name: "flickr" , |
05 |
iconSrc: "img/Flickr alt 1.png" , |
06 |
label: "Flickr" , |
07 |
size: "tile-double tile-double-vertical" , |
08 |
color: "bg-color-darken" , |
09 |
appUrl: "http://www.flickr.com/" , |
10 |
cssSrc: [ "tiles/flickr/flickr.css" ], |
11 |
scriptSrc: [ "tiles/flickr/flickr.js" ], |
12 |
initFunc: "flickr_load" |
13 |
}; |
14 |
} |
icon 表示 javascript, css, html 被载入时将在瓦片组件上显示的默认图标. 瓦片组件水平和垂直的尺寸在size属性中定义. 然后当点击瓦片时,将会在全屏视图中打开的URL定义在appUrl中. 附带需要加载的 CSS, Javascripts 在cssSrc和 scriptSrc中定义. 最后 initFunc 告知了js在被加载时都会运行一次的函数.
元数据定义了瓦片组件如何在面板上显示. 从Flickr加载数据的行为来自Flickr.js 文件, 定义如下:
01 |
function flickr_load(tile, div) { |
02 |
|
03 |
var url = "http://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=json&tags=nature&jsoncallback=?" ; |
04 |
|
05 |
$.getJSON(url, function (data) { |
06 |
var ctr = 0 ; |
07 |
$.each(data.items.reverse(), function (i, item) { |
08 |
if (item.tags.length < 150 ) { |
09 |
var sourceSquare = item.media.m; |
10 |
var sourceOrig = (item.media.m).replace( "_m.jpg" , ".jpg" ); |
11 |
|
12 |
var htmlString = '' ; |
13 |
htmlString += '' ; |
14 |
htmlString += '' + item.title + '' + |
15 |
'' ; |
16 |
|
17 |
tile.slides.push(htmlString); |
18 |
|
19 |
ctr = ctr + 1 ; |
20 |
} |
21 |
}); |
22 |
|
23 |
tile.counter(ctr); |
24 |
}); |
25 |
|
26 |
} |
这就是了.
瓦片组件可以是直接在瓦片盒里面直接加载的动态aspx页面. 例如:
仪表面板的运行方式是:
首先获取区域的列表,还有每个区域中瓦片组件的列表.
按照Tiles.js文件中的定义创建瓦片盒子.
对于每一个瓦片, 看看瓦片组件是否有任何外部的JS, CSS 和 html 文件需要加载. 如果有,就加载它们.
执行在initFunc定义的函数. 向其传入瓦片对象, 瓦片组件的div引用还有initParams .
Dashboard上默认的tile的显示方法同样在Tiles.js文件中定义:
01 |
window.DefaultTiles = [ |
02 |
{ |
03 |
name : "Section1" , |
04 |
tiles: [ |
05 |
{ id: "flickr1" , name: "flickr" }, |
06 |
{ id: "amazon1" , name: "amazon" }, |
07 |
{ id: "news1" , name: "news" }, |
08 |
{ id: "weather1" , name: "weather" }, |
09 |
{ id: "calendar1" , name: "calendar" }, |
10 |
{ id: "feature1" , name: "feature" }, |
11 |
{ id: "facebook1" , name: "facebook" } |
12 |
] |
13 |
}, |
14 |
{ |
15 |
name: "Section2" , |
16 |
tiles: [ |
17 |
{ id: "wikipedia1" , name: "wikipedia" }, |
18 |
{ id: "email1" , name: "email" }, |
19 |
{ id: "maps1" , name: "maps" }, |
20 |
{ id: "angrybirds1" , name: "angrybirds" }, |
21 |
{ id: "cuttherope1" , name: "cutTheRope" }, |
22 |
{ id: "dynamicTile1" , name: "dynamicTile" }, |
23 |
{ id: "buy1" , name: "buy" }] |
24 |
}, |
25 |
{ |
26 |
name: "Section3" , tiles: [ |
27 |
{ id: "youtube1" , name: "youtube" }, |
28 |
{ id: "ie1" , name: "ie" }, |
29 |
|
30 |
] |
31 |
} |
32 |
]; |
Tile按照他们被定义的顺序显示。他们的名字不用和Tile metadata中定义的名字相一致。
在一个tile上有不同的部分:
下面的html定义了这种tile设计:
01 |
< div class = "metro-sections" data-bind = "foreach: sections" > |
02 |
< div class = "metro-section" data-bind = "attr: {id : uniqueId}, foreach: sortedTiles" > |
03 |
< div data-bind = "attr: { id: uniqueId, 'class': tileClasses }" > |
04 |
<!-- ko if: tileImage --> |
05 |
< div class = "tile-image" > |
06 |
< img data-bind = "attr: { src: tileImage }" src = "img/Internet%20Explorer.png" /> |
07 |
</ div > |
08 |
<!-- /ko --> |
09 |
<!-- ko if: iconSrc --> |
10 |
<!-- ko if: slides().length == 0 --> |
11 |
< div data-bind = "attr: { 'class': iconClasses }" > |
12 |
< img data-bind = "attr: { src: iconSrc }" src = "img/Internet%20Explorer.png" /> |
13 |
</ div > |
14 |
<!-- /ko --> |
15 |
<!-- /ko --> |
16 |
< div data-bind = "foreach: slides" > |
17 |
< div class = "tile-content-main" > |
18 |
< div data-bind = "html: $data" > |
19 |
</ div > |
20 |
</ div > |
21 |
</ div > |
22 |
<!-- ko if: label --> |
23 |
< span class = "tile-label" data-bind = "html: label" >Label</ span > |
24 |
<!-- /ko --> |
25 |
<!-- ko if: counter --> |
26 |
< span class = "tile-counter" data-bind = "html: counter" >10</ span > |
27 |
<!-- /ko --> |
28 |
<!-- ko if: subContent --> |
29 |
< div data-bind = "attr: { 'class': subContentClasses }, html: subContent" > |
30 |
subContent |
31 |
</ div > |
32 |
<!-- /ko --> |
33 |
</ div > |
34 |
</ div > |
35 |
</ div > |
标记中到处都是KnockoutJS标记,它们被用于绑定Tile对象模型到html对象。
这里的流程图显示了Dashboard是如何被加载的:
Dashboard.js中的代码直截了当,并且魔法般地实现了功能!
01 |
var viewModel = new DashboardModel( "Start" , [], window.currentUser, ui, TileBuilders); |
02 |
|
03 |
$(document).ready(function () { |
04 |
|
05 |
// Hide the body area until it is fully loaded in order to prevent flickrs |
06 |
$( '#content' ).css( 'visibility' , 'visible' ); |
07 |
|
08 |
// Initiate KnockoutJS binding which creates all the tiles and binds the whole |
09 |
// UI to viewModel. |
10 |
ko.applyBindings(viewModel); |
11 |
|
12 |