当前位置:3016.com-金沙城中心官网 > 前端 > 基于 HTML5 构建 Web 操作系统

基于 HTML5 构建 Web 操作系统

文章作者:前端 上传时间:2019-12-12

依附 HTML5 营造 Web 操作系统

2012/09/29 · HTML5, JavaScript · 1 评论 · HTML5, Javascript

来源:IBM Developerworks

简介: Web 操作系统有着古板操作系统不能比拟的优势,如能够随地随时使用其它极端进行拜谒,数据保存在劳动器端,空间越来越大,数据安全性更加好,能够选取服务器端的 CPU、内存等能源拓宽特别复杂的运算。但是当下的 Web 操作系统前端相当多基于 Flex、Silverlight、ActiveX 插件等本事开采,存在着对运动设备的支撑性差,终端安全性差,开采难度大等老毛病。

HTML5 是下一代 web 语言的正统,具备包容性好,安全性高,功用丰裕,开拓方便人民群众等优点,特别符合如 Web 操作系统风度翩翩类的富顾客端互连网选拔的前端开拓。本文将体现什么接收 HTML5 提供的有余新本领如:当地数据库、八线程开采、录像扶助、离线编制程序等营造一个骨干的 Web 操作系统。

简介

历史观的操作系统有着一些难以克制的弱项,如仅能在地头终端访谈,或仅帮忙有限的长途访谈,限于本地终端的财富,总结工夫虚亏,存款和储蓄空间有限,缺少有力的防火墙等生机勃勃体系安全部制,安全性非常糟糕。鉴于以上劣点,Web 操作系统应际而生 – Web 操作系统是意气风发种基于浏览器的设想的操作系统,客商通过浏览器能够在内部开展应用程序的操作,甚至有关数据的累积。Web 操作系统提供的中央服务有文本文书档案的开创与仓库储存,音频摄像文件的播音与仓库储存,提供对时间音信的援救等,更加尖端的劳动则含有即时通讯,邮件乃至游戏等服务。Web 操作系统制伏了金钱观操作系统的后天不良,在网络的支撑下,它能够在任什么时候间,任哪个地方点经由任何帮忙Web 的巅峰举行拜会,能够采用服务器端Infiniti的考虑及存款和储蓄财富,顾客数量保存在劳动器端,安全性较高。

图片 1

有关本事

当前营造 Web 操作系统的前端技术首要有 Flex、Silverlight、ActiveX 插件等等,它们各有部分优短处。

Flex

Flex 是叁个完美的富客商端应用框架,专心于页面突显,Adobe 专门的工作维护,统大器晚成稳固,并且其脚本语言 ActionScript3 是面向对象的,特别符合技士使用。缺点则是功耗高,占用带宽多,对移动使用的支撑性差。

Silverlight

Silverlight 是由微软临蓐的用于跟 Flash 抗衡的 QashqaiIA(富网络应用)解决方案,优点是颇负硬件级的增长速度成效,但它如今仍不成熟,对非 Windows 系统的扶持性并远远不足好,且学习难度超大。

ActiveX 插件

ActiveX 插件相仿是微软临蓐的 TiguanIA 解决方案,它是三个开花的缓和方案,能够相配两种语言,可是它的欠缺也是举世知名的,顾客要求调节浏览器的平安品级并下载插件工夫运行途锐IA 应用,十分的大地回退了安全性。

HTML5

为推动 web 标准化运动的上进,W3C 推出了下一代 HTML 的标准 – HTML5,为无数的商号所支撑,因而有着非凡的前景。它有以下特征:首先,为增加顾客体验,加强了 web 网页的表现品质;其次,为适应 GL450IA 应用的演化,追加了本地数据库等 web 应用的效应;再一次,由于中度标准化以致比比较多浏览器厂家的用力支持,它的包容性和安全性超级高;最终它是大器晚成种轻便的语言,轻易为广大开采者通晓。更为谈何轻便的是,由于节省和功耗低,在移动设备上 HTML5 将具有更加大的优势。由此更相符如 Web 操作系统意气风发类的 EvoqueIA 应用的前端开荒。

系统简要介绍

本系统基于 HTML5 开采,利用 HTML5 引进的有余新本事如拖拽 API、摄像标签、本地数据库、draw API、三十三十二线程开荒、离线编制程序等提供了壹个为主的 Web 操作系统景况,包罗了对桌面包车型大巴扶持、应用程序的支撑,提供了三个轻松易行的视频播放器和记事本以致一个石英钟,并对系统日志进行了笔录,别的还提供了对离线状态的支撑。

桌面完成

系统对桌面包车型大巴支持尤为重要不外乎应用程序Logo的展开与拖拽,以至桌面的上下文菜单等。

桌面拖拽

桌面包车型大巴布局由自然数量的 div 组成,它们依据程序依次排列在矩形的桌面上,为应用程序Logo的开采与拖拽提供了核心的支持。

清单 1. 创建 div

XHTML

var iconHolder = document.createElement("div"); iconHolder.id = 'iconHolder' + i; iconHolder.className = "iconHolder"; mainDiv.appendChild(iconHolder);

1
2
3
4
var iconHolder = document.createElement("div");
iconHolder.id = 'iconHolder' + i;
iconHolder.className = "iconHolder";
mainDiv.appendChild(iconHolder);

HTML5 提供了对 drag 事件的支撑,大大简化了贯彻拖拽的难度。通过对 dragstart 事件的监听,将被拖拽的应用程序Logo所在的 div 记录下来,作为拖拽的源。

项目清单 2. 拖拽匡助

XHTML

iconHolder.add伊夫ntListener("dragstart", function(ev卡塔尔(英语:State of Qatar) { var dt = ev.dataTransfer; dt.setData("text/plain", ev.currentTarget.id卡塔尔;// 记录被拖拽Logo的 id }, false卡塔尔国; iconHolder.add伊芙ntListener("drop", function(ev卡塔尔(قطر‎ { var dt = ev.dataTransfer; var srcIconHolderId = dt.getData("text/plain"卡塔尔(قطر‎; var srcIconHolder = document.getElementById(srcIconHolderId卡塔尔国; // 假使拖拽至回笼站,则删掉被拖拽图标,不然交流两Logo位置if(ev.currentTarget.firstChild && ev.currentTarget.firstChild.id == "recycleBin" && srcIconHolder.firstChild.id != "recycleBin"){ srcIconHolder.innerHTML = ""; }else if(ev.currentTarget.firstChild){ var temp = ev.currentTarget.firstChild; ev.currentTarget.appendChild(srcIconHolder.firstChild); srcIconHolder.appendChild(temp); }else{ ev.currentTarget.appendChild(srcIconHolder.firstChild); } }, false);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
iconHolder.addEventListener("dragstart", function(ev) {
var dt = ev.dataTransfer;
dt.setData("text/plain", ev.currentTarget.id);// 记录被拖拽图标的 id
}, false);
 
iconHolder.addEventListener("drop", function(ev) {
var dt = ev.dataTransfer;
var srcIconHolderId = dt.getData("text/plain");
var srcIconHolder = document.getElementById(srcIconHolderId);
 
// 如果拖拽至回收站,则删掉被拖拽图标,否则互换两图标位置
if(ev.currentTarget.firstChild && ev.currentTarget.firstChild.id == "recycleBin" &&
srcIconHolder.firstChild.id != "recycleBin"){
                srcIconHolder.innerHTML = "";
}else if(ev.currentTarget.firstChild){
        var temp =  ev.currentTarget.firstChild;
        ev.currentTarget.appendChild(srcIconHolder.firstChild);
        srcIconHolder.appendChild(temp);
}else{
       ev.currentTarget.appendChild(srcIconHolder.firstChild);
}
}, false);

透过对 drop 事件的监听,能够博得拖拽的源,甚至拖拽的靶子 div。若指标 div 为空,则将源 div 中的应用程序Logo转移至目标 div 中。若目的 div 中已盈盈应用程序Logo,则将七个Logo的岗位沟通。若回笼站图标处于目的 div 中,回笼站将发挥效能并将源 div 中的应用程序Logo删除。图 1 体现了桌面拖拽的效果。

图 1. 桌面拖拽效果

图片 2程序展开

次第能够以三种办法张开,左键点击或通过上下文菜单打开。

经过监听 div 的 onclick 事件,获取要展开的应用程序 id,并选择 openApp 方法张开相应的应用程序可完结对左键点击的援助。

项目清单 3. 左键点击

XHTML

iconHolder.onclick = function(ev){ if(ev.currentTarget.firstChild){ openApp(ev.currentTarget.firstChild.id); ev.stopPropagation(); } };

1
2
3
4
5
6
iconHolder.onclick =  function(ev){
if(ev.currentTarget.firstChild){
        openApp(ev.currentTarget.firstChild.id);
        ev.stopPropagation();
}
};

经过监听 div 的 oncontextmenu 事件,获取要开采的应用程序 id,并采纳openAppContextMenu 方法显示相应应用程序的上下文菜单,可完毕对右键上下文菜单的扶持。

清单 4. 上下文菜单

XHTML

iconHolder.oncontextmenu = function(ev){ if(ev.currentTarget.firstChild){ openAppContextMenu(ev.currentTarget.firstChild.id, ev); ev.stopPropagation(); } return false; };

1
2
3
4
5
6
7
iconHolder.oncontextmenu =  function(ev){
if(ev.currentTarget.firstChild){
        openAppContextMenu(ev.currentTarget.firstChild.id, ev);
        ev.stopPropagation();
}
return false;
};

动用相应应用程序的 id,可以拿走相应应用程序的本子,并施行,同一时间在系统日志中记录下相应的操作。

项目清单 5. 主次张开

XHTML

function openApp(appId卡塔尔国{ var time = new Date(卡塔尔(قطر‎.getTime(卡塔尔; var action = "open app"; var details = "open: " + appId; addHistory(time, action, details卡塔尔;// 记录系统日志 var appScript = getAppScript(appId卡塔尔国;// 获取应用程序脚本 eval(appScript卡塔尔;// 试行应用程序 }

1
2
3
4
5
6
7
8
function openApp(appId){
    var time = new Date().getTime();
    var action = "open app";
    var details = "open: " + appId;
    addHistory(time, action, details);// 记录系统日志
    var appScript = getAppScript(appId);// 获取应用程序脚本
    eval(appScript);// 执行应用程序
}

清单 6. 开辟程序上下文菜单

XHTML

function openAppContextMenu(appId, ev卡塔尔(قطر‎{ var appContextMenu = document.getElementById("appContextMenu"卡塔尔国; appContextMenu.style.display="block";// 令上下文菜单可以见到appContextMenu.style.pixelTop=ev.clientY;// 设置内外文菜单位置appContextMenu.style.pixelLeft=ev.clientX; appContextMenu.style.background = "#eee"; appContextMenu.style.color = "black"; appContextMenu.style.fontSize = "30"; appContextMenu.style.width = "200px"; appContextMenu.style.height = "220px"; appContextMenu.style.opacity = 0.5;// 令上下文菜单反射率为 50%appContextMenu.innerHTML = ""; // 获取应用程序相应上下文菜单的从头到尾的经过 var apps = getApps(卡塔尔国; for(var i=0; i<apps.length; i++卡塔尔国{ if(apps[i].appId == appId){ for(var j=0; j<apps[i].contextMenu.length; j++){ appContextMenu.innerHTML += "<div class='appContextMenuItem' onclick="appContextMenu.style.display='none';" + apps[i].contextMenu[j].action + "" onmouseover='this.style.background="darkblue"' onmouseout='this.style.background="#eee"'>" +apps[i].contextMenu[j].name+"</div>"; } break; } } }

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
function openAppContextMenu(appId, ev){
var appContextMenu = document.getElementById("appContextMenu");
appContextMenu.style.display="block";// 令上下文菜单可见
appContextMenu.style.pixelTop=ev.clientY;// 设置上下文菜单位置
appContextMenu.style.pixelLeft=ev.clientX;
appContextMenu.style.background = "#eee";
appContextMenu.style.color = "black";
appContextMenu.style.fontSize = "30";
appContextMenu.style.width = "200px";
appContextMenu.style.height = "220px";
appContextMenu.style.opacity = 0.5;// 令上下文菜单透明度为 50%
appContextMenu.innerHTML = "";
 
// 获取应用程序相应上下文菜单的内容
var apps = getApps();
for(var i=0; i<apps.length; i++){
                if(apps[i].appId == appId){
                        for(var j=0; j<apps[i].contextMenu.length; j++){
                        appContextMenu.innerHTML += "<div class='appContextMenuItem'
                        onclick="appContextMenu.style.display='none';" +
                        apps[i].contextMenu[j].action + ""
                        onmouseover='this.style.background="darkblue"'
                        onmouseout='this.style.background="#eee"'>"
                        +apps[i].contextMenu[j].name+"</div>";
                        }
                        break;
                 }  
}
}

应用程序的上下文菜单由名称叫 appContextMenu 的 div 达成,将 oncontextmenu 事件中的 clientX 及 clientY 作为上下文菜单现身的职位,并将其折射率设置为 0.5。利用相应应用程序的 id 获取上下文菜单对应的剧情,并将其填写至上下文菜单。

图 2 显示了应用程序上下文菜单展开时的功力。

图 2. 应用程序上下文菜单

图片 3上下文菜单

桌面上下文菜单的落实方式与应用程序上下文菜单的落到实处方式为主临近,图 3 和图 4 分别是桌面以至职务栏的上下文菜单。

图 3. 桌面上下文菜单

图片 4

 图 4. 任务栏上下文菜单

图片 5视频播放器

系统提供了二个轻巧的录制播放器,它帮忙从系统外界拖拽录制文件举行广播。

顺应互联网媒体的演化,HTML5 提供了录像标签 video 以便于加强对录像的支撑,大大简化了 web 播放器开垦的难度,开辟职员仅凭几行代码,就能够支付出四个基本作用康健的录制播放器。

事项清单 7. 录像标签的创始

XHTML

var video = document.createElement('video'); video.id ='video'; video.src =''; video.width = 370; video.height = 260; video.controls = 'controls'; video.className = 'video'; appHolder.appendChild(video); addDragSupport(appHolder);

1
2
3
4
5
6
7
8
9
var video = document.createElement('video');
video.id ='video';
video.src ='';
video.width  = 370;
video.height = 260;
video.controls = 'controls';
video.className = 'video';
appHolder.appendChild(video);
addDragSupport(appHolder);

项目清单 7 中构造了三个 video 标签并将其增添到贰个名叫 appHolder 的 div 中。代码的尾声风流倜傥行为其加多了拖拽的帮助。

HTML5 不但帮忙浏览器内的拖拽,也支撑浏览器与地点系统里头的拖拽。项目清单 8 展现了为三个 div 增添拖拽协助的长河。

清单 8. 增添拖拽协助

JavaScript

function addDragSupport(dropbox){ document.addEventListener("dragenter", function(e){ }, false); document.addEventListener("dragleave", function(e){ }, false); dropbox.addEventListener("dragenter", function(e){ }, false); dropbox.addEventListener("dragleave", function(e){ }, false); dropbox.addEventListener("dragenter", function(e){ e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("dragover", function(e){ e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("drop", function(e){ handleFiles(e.dataTransfer.files, e.currentTarget, e); e.stopPropagation(); e.preventDefault(); }, false); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function addDragSupport(dropbox){
document.addEventListener("dragenter", function(e){
}, false);
document.addEventListener("dragleave", function(e){
}, false);
dropbox.addEventListener("dragenter", function(e){
}, false);
dropbox.addEventListener("dragleave", function(e){
}, false);
dropbox.addEventListener("dragenter", function(e){
e.stopPropagation();
e.preventDefault();
}, false);
dropbox.addEventListener("dragover", function(e){
e.stopPropagation();
e.preventDefault();
}, false);
dropbox.addEventListener("drop", function(e){
handleFiles(e.dataTransfer.files, e.currentTarget, e);
e.stopPropagation();
e.preventDefault();              
}, false);  
}

内部,handleFiles 函数表明了什么样对拖拽的文件进行管理。

事项清单 9. 拖拽管理

JavaScript

function handleFiles(files, dropbox, e卡塔尔国 { if(files.length == 0卡塔尔(قطر‎{// 若文件空中楼阁,则用相应文本取代 var dt = e.dataTransfer; var text = dt.getData("text/plain"卡塔尔(英语:State of Qatar); var p = document.createElement("p"卡塔尔(英语:State of Qatar); p.innerHTML += text; dropbox.appendChild(p卡塔尔国; return; } for (var i = 0; i < files.length; i++卡塔尔(قطر‎ { var file = files[i]; var fileProcessor = dropbox.firstChild; fileProcessor.classList.add("obj"卡塔尔(英语:State of Qatar); fileProcessor.file = file; // 添Gavin件 var reader = new FileReader(卡塔尔(英语:State of Qatar); reader.onload = (// 读取文件内容 function(aFileProcessor卡塔尔国 { return function(e卡塔尔国 { aFileProcessor.src = e.target.result; }; } 卡塔尔(英语:State of Qatar)(fileProcessor卡塔尔; reader.readAsDataU途胜L(file卡塔尔(قطر‎; } }

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
function handleFiles(files, dropbox, e) {
    if(files.length == 0){// 若文件不存在,则用相应文本代替
         var dt = e.dataTransfer;
         var text = dt.getData("text/plain");
         var p = document.createElement("p");
         p.innerHTML += text;
         dropbox.appendChild(p);
         return;
}
 
for (var i = 0; i < files.length; i++) {
         var file = files[i];
         var fileProcessor = dropbox.firstChild;
         fileProcessor.classList.add("obj");
         fileProcessor.file = file; // 添加文件
 
         var reader = new FileReader();
         reader.onload = (// 读取文件内容
         function(aFileProcessor) {
                 return function(e) {
                 aFileProcessor.src = e.target.result;
};
}
)(fileProcessor);
  reader.readAsDataURL(file);
}
}

handleFiles 函数首先剖断文件是或不是留存,若不设有,则以相应文字替代,若存在,则对

持有文件相继实行拍卖。向 fileprocessor( 这里是摄像标签 )添Gavin书,然后使用 FileReader 读取文件内容至 fileprocessor 举行拍卖。

图 5 展现了拖拽三个录像文件 movie.ogg 到播放器的效果与利益。

图 5. 摄像播放

图片 6

本地存款和储蓄

Web 操作系统平常将多数数量存款和储蓄于服务器端,那样做的补益一句话来说,数据存款和储蓄空间越来越大,安全性更加好。但是那样做也可以有白璧微瑕,由于网络的稳定性如故较本地球磁性盘差,所以在抽离互联网的场景下,Web 操作系统无法得到相应的数码能源,因而 Web 操作系统须求明确的会见本地存款和储蓄空间的能力,当然本地存款和储蓄空间仅是当作劳动器端存款和储蓄的叁个增加补充,它的空间有限,访谈也惨被断定的限量。

直接以来,HTML 以 Cookie 作为拜望本地空间的章程,不过,这种办法有着大多劣势和不足,如存款和储蓄的数额格式过于轻易,平日仅为键值对;存款和储蓄的半空中山大学小有限。为此,HTML5 提供了本地数据库以加强地点存款和储蓄空间的拜谒本事,它是一个简化版的数据库,能够支持模拟的 SQL 以至轻易的事务管理等功效。

系统为永葆地点存款和储蓄,创设了三个名叫 MyData 的数据库。清单 10 显示了数据库创造的进程。

清单 10. 创建数据库

XHTML

var db; var openDatabase; if(openDatabase != undefined) db = openDatabase('MyData', '', 'My Database', 102400);

1
2
3
4
var db;
var openDatabase;
if(openDatabase != undefined)
     db = openDatabase('MyData', '', 'My Database', 102400);

中间 MyData 为数据库的称呼,省略的参数为数据库的本子,My Database 为呈现的名称,最终的数字为数据库预估长度(以字节为单位)。

系统日志将系统在某有的时候间的行为操作记录下来,本地数据库为其提供仓库储存帮忙。日志在数据库中蕴藏为表 History,满含 3 个字段,分别为时间,操作,及操作的详细新闻。清单 11 突显了系统是怎么记录日志的。

清单 11. 日记记录

XHTML

var time = new Date(卡塔尔.get提姆e(卡塔尔(英语:State of Qatar); var action = "open app"; var details = "open: " + appId; addHistory(time, action, details卡塔尔(英语:State of Qatar);// 向系统日志中加多一条记下 function addHistory(time, action, details卡塔尔国{ if(openDatabase != undefined) db.transaction( function(tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS History(time INTEGER, action TEXT, details TEXT)',[]卡塔尔(قطر‎;// 创造日志记录表 tx.executeSql('INSERT INTO History VALUES(?, ?, ?卡塔尔国', [time, action, details], // 插入一条日志 function(tx, rs卡塔尔(英语:State of Qatar) { //alert("store: "+time+"-"+action+"-"+details卡塔尔; }, function(tx, error卡塔尔国 { //alert(error.source + "::" + error.message卡塔尔; }卡塔尔; }卡塔尔(قطر‎; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var time = new Date().getTime();  
var action = "open app";
var details = "open: " + appId;
addHistory(time, action, details);// 向系统日志中添加一条记录
 
function addHistory(time, action, details){
if(openDatabase != undefined)
db.transaction(
function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS History(time INTEGER,
action TEXT, details TEXT)',[]);// 创建日志记录表  
tx.executeSql('INSERT INTO History VALUES(?, ?, ?)', [time,
action, details], // 插入一条日志
function(tx, rs) {  
//alert("store: "+time+"-"+action+"-"+details);  
              },  
function(tx, error) {
    //alert(error.source + "::" + error.message);  
});  
});  
}

清单的第生龙活虎有个别显得了什么样调用日志记录,第二有的显得了日记记录的详细进程。在三个transaction 中,首先判定表 History 是还是不是留存,若不设有,则开创它。第二部分进行一条 SQL 语句,向数据库中插入当前的日记。

通过寻觅表 History,大家得以查看系统日志,清单 12 展现了什么从数据库中查询系统日志,并将其出示出来。

清单 12. 日记显示

XHTML

var historyTable = document.getElementById("historyTable"卡塔尔(قطر‎; // 定义表头 historyTable.innerHTML = ""; var th = document.createElement('thead'卡塔尔国; th.style = "color:#CC3300"; var th1 = document.createElement('td'); th1.align = "center"; th1.width=300; th1.innerHTML = "Time"; var th2 = document.createElement('td'); th2.align = "center"; th2.width=100; th2.innerHTML = "Action"; var th3 = document.createElement('td'); th3.align = "center"; th3.width=150; th3.innerHTML = "Details"; th.appendChild(th1); th.appendChild(th2); th.appendChild(th3); historyTable.appendChild(th); if(openDatabase != undefined) db.transaction(function(tx) { tx.executeSql('SELECT * FROM History', [], function(tx, rs卡塔尔国 { // 将日志逐个展现到表的各行中 for(var i = 0; i < rs.rows.length && i<15; i++卡塔尔国 { var tr = document.createElement('tr'卡塔尔(英语:State of Qatar); var td1 = document.createElement('td'卡塔尔(英语:State of Qatar); td1.style.paddingLeft = "3px"; td1.style.paddingRight = "3px"; var t = new Date(卡塔尔; t.setTime(rs.rows.item(i卡塔尔国.time卡塔尔; td1.innerHTML = t.toLocaleDateString(卡塔尔国+ " "+t.toLocaleTimeString(卡塔尔; var td2 = document.createElement('td'卡塔尔(قطر‎; td2.style.paddingLeft = "3px"; td2.style.paddingRight = "3px"; td2.innerHTML = rs.rows.item(i卡塔尔(قطر‎.action; var td3 = document.createElement('td'卡塔尔国; td3.style.paddingLeft = "3px"; td3.style.paddingRight = "3px"; td3.innerHTML = rs.rows.item(i卡塔尔(قطر‎.details; tr.appendChild(td1卡塔尔国; tr.appendChild(td2卡塔尔(英语:State of Qatar); tr.appendChild(td3卡塔尔(قطر‎; historyTable.appendChild(tr卡塔尔国; } }卡塔尔国; }卡塔尔(英语:State of Qatar);

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var historyTable = document.getElementById("historyTable");
 
// 定义表头
historyTable.innerHTML = "";
var th = document.createElement('thead');
th.style = "color:#CC3300";
var th1 = document.createElement('td');
th1.align = "center";
th1.width=300;
th1.innerHTML = "Time";
var th2 = document.createElement('td');
th2.align = "center";
th2.width=100;
th2.innerHTML = "Action";
var th3 = document.createElement('td');
th3.align = "center";
th3.width=150;
th3.innerHTML = "Details";
th.appendChild(th1);  
th.appendChild(th2);  
th.appendChild(th3);
historyTable.appendChild(th);
 
if(openDatabase != undefined)
db.transaction(function(tx) {    
tx.executeSql('SELECT * FROM History', [], function(tx, rs)
{  
      // 将日志逐条显示到表的各行中
for(var i = 0; i < rs.rows.length && i<15; i++) {                    
var tr = document.createElement('tr');
var td1 = document.createElement('td');
td1.style.paddingLeft = "3px";
td1.style.paddingRight = "3px";
 
var t = new Date();  
t.setTime(rs.rows.item(i).time);  
td1.innerHTML = t.toLocaleDateString()+
" "+t.toLocaleTimeString();
 
var td2 = document.createElement('td');  
td2.style.paddingLeft = "3px";
td2.style.paddingRight = "3px";
td2.innerHTML = rs.rows.item(i).action;
 
var td3 = document.createElement('td');
td3.style.paddingLeft = "3px";
td3.style.paddingRight = "3px";
td3.innerHTML = rs.rows.item(i).details;  
 
tr.appendChild(td1);  
tr.appendChild(td2);  
tr.appendChild(td3);
 
historyTable.appendChild(tr);                  
}  
});  
});

清单 12 中,首先拿到用于体现的日记的 HTML 表格 historyTable,并设置其样式及表头。

下一场在三个 transaction( 事务 卡塔尔(英语:State of Qatar) 中,执行一条 SQL 语句,查询系统日志,并将每条日志增加为 historyTable 中的大器晚成行以便呈现。图 6 显示了系统日志的意义。

图 6. 系统日志

图片 7

记事本

系统提供了二个精简的记事本,达成了文本文档的基本操作。文本文书档案包蕴标题和故事情节多少个显式属性,以致三个名称叫id 的隐式属性。与系统日志雷同,本地数据库为文本数据的贮存提供了底层的协助。图 7 呈现了记事本程序的分界面。

图 7. 记事本

图片 8

当编辑完文书档案的标题与内容后,点击左上角的保存开关,将实践 createFile 函数。清单 13 突显了 createFile 函数的事必躬亲进程。

清单 13. 创办理文件件

XHTML

function createFile(fileId, fileTitle, fileContent卡塔尔(قطر‎{ var idx = 1; var update = false;//false 表示新建,true 表示改善 if(openDatabase != undefined) db.transaction(function(tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS TextFiles(idx INTEGER, title TEXT, content TEXT)',[]卡塔尔(قطر‎;// 创设文本文书档案表 tx.executeSql('SELECT * FROM TextFiles', [], function(tx, rs卡塔尔(قطر‎{ for(var i = 0; i < rs.rows.length; i++卡塔尔国 { // 若文书档案存在,则修改它 if(rs.rows.item(i卡塔尔.idx == fileId卡塔尔国{ db.transaction(function(tx卡塔尔(قطر‎ { tx.executeSql('UPDATE TextFiles SET title=?, content=? WHERE idx='+fileId, [fileTitle, fileContent], function(tx, rs卡塔尔国 { alert("update successfully"卡塔尔; }卡塔尔国; }卡塔尔; return; } } // 若文书档案不设有,则新建二个文书档案 if(rs.rows.length>0卡塔尔(قطر‎ idx = rs.rows.item(rs.rows.length-1卡塔尔.idx + 1; db.transaction(function(tx卡塔尔 { tx.executeSql('INSERT INTO TextFiles VALUES(?, ?, ?卡塔尔(英语:State of Qatar)', [idx, fileTitle, fileContent], function(tx, rs){ alert("save successfully: "+idx+"-"+fileTitle+ "-"+fileContent); createFileIcon(idx); }, function(tx, error) { alert(error.source + "::" + error.message); }); }); }); }); }

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
function createFile(fileId, fileTitle, fileContent){
     var idx = 1;
     var update = false;//false 表示新建,true 表示修改
 
     if(openDatabase != undefined)
         db.transaction(function(tx) {
         tx.executeSql('CREATE TABLE IF NOT EXISTS TextFiles(idx INTEGER,
         title TEXT, content TEXT)',[]);// 创建文本文档表
         tx.executeSql('SELECT * FROM TextFiles', [], function(tx, rs){
             for(var i = 0; i < rs.rows.length; i++) {
                // 若文档存在,则修改它
                 if(rs.rows.item(i).idx == fileId){
                     db.transaction(function(tx) {    
                     tx.executeSql('UPDATE TextFiles
                     SET title=?, content=?
                     WHERE idx='+fileId,
                     [fileTitle, fileContent],
                     function(tx, rs) {  
                             alert("update successfully");
                     });  
                 });
                 return;
             }        
}    
// 若文档不存在,则新建一个文档        
if(rs.rows.length>0)
idx = rs.rows.item(rs.rows.length-1).idx + 1;
db.transaction(function(tx) {                        
tx.executeSql('INSERT INTO TextFiles VALUES(?, ?, ?)', [idx, fileTitle, fileContent],
               function(tx, rs){  
               alert("save successfully: "+idx+"-"+fileTitle+ "-"+fileContent);  
               createFileIcon(idx);  
},  
function(tx, error) {
                alert(error.source + "::" + error.message);  
                 });  
             });
         });
     });
}

清单 13 首先在一个 transaction 中,首先判定用于存款和储蓄文本文书档案的表 TextFiles 是不是存在,若不真实,则创制它。然后经过查询表 TextFiles 决断文本文书档案是还是不是留存,若存在,则当前操作为更新操作,程序将实行一条 SQL 语句,对日前文本文书档案举办修正。若官样文章,则取当前最大文书档案 id 并加 1 看成新文书档案的 id,并实施一条 SQL 语句,将文书档案新闻,包罗文书档案id,以致标题和剧情插入到数据库中,并于插入操作结束后的回调方法中,利用 createFileIcon 方法在桌面上为新文书档案创设一个文书档案Logo。项目清单 14 展现了 createFileIcon 方法的活灵活现进度。

清单 14. 创办文书档案Logo

XHTML

function createFileIcon(fileId卡塔尔(英语:State of Qatar){ var iconHolder; for(var i=1;i<=120;i++卡塔尔(قطر‎{// 查询第一个为空之处 iconHolder = document.getElementById('iconHolder' + if(!iconHolder.firstChild 卡塔尔(英语:State of Qatar){ var text = document.createElement('img'卡塔尔; text.src = "images/text.gif"; text.id = fileId; iconHolder.appendChild(text卡塔尔(英语:State of Qatar); text.onclick = function(ev卡塔尔{ if(ev.currentTarget卡塔尔国{ openApp('notebook'卡塔尔(英语:State of Qatar);// 打开记事本应用程序 var saveHolder = document.getElementById('saveHolder'卡塔尔(قطر‎; saveHolder.onclick = function(卡塔尔(英语:State of Qatar){ var title = document.getElementById('title'卡塔尔国; var content = document.getElementById('content'卡塔尔(英语:State of Qatar); createFile(fileId, title.value, content.value卡塔尔(英语:State of Qatar);// 创立文本文书档案 }; var openedFileId = ev.currentTarget.id; if(openDatabase != undefined卡塔尔(英语:State of Qatar)db.transaction(function(tx卡塔尔(قطر‎ {// 查询数据库,彰显文书档案内容 tx.executeSql('SELECT * FROM TextFiles', [], function(tx, rs){ for(var i = 0; i < rs.rows.length; i++) { if((rs.rows.item(i).idx+"") == (openedFileId+"")){ var title = document.getElementById('title'); var content = document.getElementById('content'); title.value = rs.rows.item(i).title; content.value = rs.rows.item(i).content;} } }); }); ev.stopPropagation(); } }; break; } }//for }

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 createFileIcon(fileId){
     var iconHolder;
     for(var i=1;i<=120;i++){// 查询第一个为空的位置
         iconHolder = document.getElementById('iconHolder' + if(!iconHolder.firstChild ){
             var text = document.createElement('img');
             text.src = "images/text.gif";
             text.id = fileId;
             iconHolder.appendChild(text);
             text.onclick =  function(ev){  
                 if(ev.currentTarget){
                 openApp('notebook');// 打开记事本应用程序
                 var saveHolder = document.getElementById('saveHolder');
                 saveHolder.onclick  = function(){
                     var title = document.getElementById('title');
                     var content = document.getElementById('content');
                     createFile(fileId, title.value, content.value);// 创建文本文档
                 };
 
             var openedFileId = ev.currentTarget.id;
             if(openDatabase != undefined)
             db.transaction(function(tx) {// 查询数据库,显示文档内容
             tx.executeSql('SELECT * FROM TextFiles', [], function(tx, rs){
                 for(var i = 0; i < rs.rows.length; i++) {  
                 if((rs.rows.item(i).idx+"") == (openedFileId+"")){
                     var title = document.getElementById('title');
                     var content = document.getElementById('content');          
                     title.value = rs.rows.item(i).title;                  
                     content.value = rs.rows.item(i).content;}    
                              }
                });
});
   ev.stopPropagation();
}
};
break;
}    
}//for
}

项目清单 14 首先在桌面中找寻贰个空的 div,然后创立一个文档图标,并将其填充至 div。文书档案Logo有一个 id 属性对应文书档案id。最终为文书档案Logo增添点击事件管理函数,当点击文书档案Logo时,会首先张开记事本,然后依据文书档案Logo的 id 查询数据库,提取文书档案的标题和故事情节张开彰显。

图 8 展现了创办后的文本文书档案,点击后的效应如图 7 所示。

图 8. 文本文书档案

图片 9时钟

系统提供了一个轻便的机械钟用以展现当即日子,它由三个表面甚至分针和时针组成,能够随着年华的变迁动态地调换。现在的 web 应用使用 JavaScript 或 Flash 实现此类成效,其复杂简单的讲。凭借HTML5 的 draw API,可以轻易地画出所需的图样,一点都不小的有益了此类应用的创设,别的,HTML5 还提供了昔日 JavaScript 不可能支撑的四线程编制程序,大大加强了 web 应用的交互作用性和丰硕性。

钟表有三个主导的表盘,它仅是后生可畏副不难的图纸,如图 9 所示。

图 9. 表盘

图片 10

在表面之上,建有一个 canvas( 画布 卡塔尔(英语:State of Qatar),如清单 15 所示。

清单 15. 画布

JavaScript

<canvas id="canvas" width="128px" height="128px"></canvas>

1
<canvas id="canvas" width="128px" height="128px"></canvas>

接下去,清单 17 就要画布上模拟出石英钟以致分针,在在此以前面,额外部须要要叁个后台线程用以计算时间,它被定义在名称为time.js 的独立脚本文件中,如项目清单 16 所示。

项目清单 16. 后台线程

XHTML

onmessage = function(event) { //var i = 1; setInterval(function() { //i++; postMessage(""); }, 60000); };

1
2
3
4
5
6
7
8
onmessage = function(event)
{
//var i = 1;
    setInterval(function() {
    //i++;
    postMessage("");
    }, 60000);
};

每过 60 秒钟,后台线程将会上前台线程发送四个空音讯,以报告前台线程有 60 分钟已经与世长辞了。

清单 17. 前台线程的初叶化

XHTML

var canvas = document.getElementById("canvas"卡塔尔国; if (canvas == null)return false; var context = canvas.getContext('2d'卡塔尔(قطر‎;// 那是三个二维的图像 context.lineWidth = 2; context.translate(64, 64卡塔尔;// 定义原点 // 带头化分针 context.beginPath(卡塔尔国; context.moveTo(0,0卡塔尔(英语:State of Qatar);// 从原点起头 var date = new Date(卡塔尔; var mhx = 37*Math.cos((date.getMinutes()-15)*Math.PI/30); var mhy = 37*Math.sin((date.getMinutes()-15)*Math.PI/30卡塔尔; context.lineTo(mhx, mhy卡塔尔(قطر‎;// 至分针末端所在地方 context.closePath(卡塔尔(قطر‎; context.stroke(卡塔尔国; // 带头化时针 context.beginPath(卡塔尔; context.moveTo(0,0卡塔尔(قطر‎;// 从原点起头 var date = new Date(卡塔尔(英语:State of Qatar); var hour = date.getHours(卡塔尔(英语:State of Qatar); if(hour>=12卡塔尔国 hour = hour - 12; var minute = date.getMinutes(卡塔尔; var hhx = 27*Math.cos((hour-3)*Math.PI/6 + minute*Math.PI/360); var hhy = 27*Math.sin((hour-3)*Math.PI/6 + minute*Math.PI/360卡塔尔(قطر‎; context.lineTo(hhx, hhy卡塔尔国;// 至时针末端所在地点 context.closePath(卡塔尔(英语:State of Qatar); context.stroke(卡塔尔(英语:State of Qatar);

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
var canvas = document.getElementById("canvas");
if (canvas == null)  
return false;  
var context = canvas.getContext('2d');// 这是一个二维的图像
context.lineWidth = 2;
context.translate(64, 64);// 定义原点
 
// 初始化分针
context.beginPath();
context.moveTo(0,0);// 从原点开始
var date = new Date();
var mhx = 37*Math.cos((date.getMinutes()-15)*Math.PI/30);
var mhy = 37*Math.sin((date.getMinutes()-15)*Math.PI/30);
context.lineTo(mhx, mhy);// 至分针末端所在位置
context.closePath();
context.stroke();
 
// 初始化时针
context.beginPath();
context.moveTo(0,0);// 从原点开始
var date = new Date();
var hour = date.getHours();
if(hour>=12)
hour = hour - 12;
var minute = date.getMinutes();
var hhx = 27*Math.cos((hour-3)*Math.PI/6 + minute*Math.PI/360);
var hhy = 27*Math.sin((hour-3)*Math.PI/6 + minute*Math.PI/360);
context.lineTo(hhx, hhy);// 至时针末端所在位置
context.closePath();
context.stroke();

前台线程首先会拿走 canvas,并安装表盘大旨为坐标原点。然后,获取当前岁月,总结分针当前所应指向的坐标,然后从原点出发,画出分针。对于时针,若系统为 24 小时制,须求首先转变为 12 时辰制,从今以后的拍卖相通于分针。

接下去,须要将前台与后台线程联系起来,利用 HTML5 提供的十二线程编制程序方法,注明 Worker 对象作为后台线程的代办,并运用 onmessage 事件,对后台线程发出的新闻进行拍卖。

项目清单 18. 前台线程的 onmessage 事件

XHTML

var worker = new Worker("js/timer.js"卡塔尔(قطر‎; worker.onmessage = function(event卡塔尔国{ context.clearRect(-64, -64, 128, 128卡塔尔(قطر‎;// 清空分针和时针 // 重画分针 context.beginPath(卡塔尔(قطر‎; context.moveTo(0,0卡塔尔国;// 从原点最先 var date = new Date(卡塔尔(قطر‎; var mhx = 37*Math.cos((date.getMinutes()-15)*Math.PI/30); var mhy = 37*Math.sin((date.getMinutes()-15)*Math.PI/30卡塔尔(英语:State of Qatar); context.lineTo(mhx, mhy卡塔尔(قطر‎;// 至分针末端所在地点 context.closePath(卡塔尔; context.stroke(卡塔尔(英语:State of Qatar); // 重画时针 context.beginPath(卡塔尔; context.moveTo(0,0卡塔尔;// 从原点起始 var date = new Date(卡塔尔(قطر‎; var hour = date.getHours(); if(hour>=12卡塔尔 hour = hour - 12; var minute = date.getMinutes(卡塔尔(قطر‎; var hhx = 27*Math.cos((hour-3)*Math.PI/6 + minute*Math.PI/360); var hhy = 27*Math.sin((hour-3)*Math.PI/6 + minute*Math.PI/360卡塔尔国; context.lineTo(hhx, hhy卡塔尔(قطر‎;// 至时针末端所在地方 context.closePath(卡塔尔(英语:State of Qatar); context.stroke(卡塔尔(英语:State of Qatar); }; worker.postMessage(""卡塔尔(英语:State of Qatar);

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
var worker = new Worker("js/timer.js");
 
worker.onmessage = function(event){
 
    context.clearRect(-64, -64, 128, 128);// 清空分针和时针
 
    // 重画分针
    context.beginPath();
    context.moveTo(0,0);// 从原点开始  
    var date = new Date();
    var mhx = 37*Math.cos((date.getMinutes()-15)*Math.PI/30);
    var mhy = 37*Math.sin((date.getMinutes()-15)*Math.PI/30);
    context.lineTo(mhx, mhy);// 至分针末端所在位置
    context.closePath();
    context.stroke();
 
        // 重画时针
    context.beginPath();
    context.moveTo(0,0);// 从原点开始  
    var date = new Date();
    var hour = date.getHours();
    if(hour>=12)
    hour = hour - 12;
    var minute = date.getMinutes();
    var hhx = 27*Math.cos((hour-3)*Math.PI/6 + minute*Math.PI/360);
    var hhy = 27*Math.sin((hour-3)*Math.PI/6 + minute*Math.PI/360);
    context.lineTo(hhx, hhy);// 至时针末端所在位置
    context.closePath();
    context.stroke();
    };
    worker.postMessage("");

每过 60 分钟,后台线程将会上前台线程发送多少个空新闻,前台线程接收到音讯后,首先,清空 canvas,然后再一次赢妥贴前时光,总括分针以致时针对应的坐标,并又一次画出时针和分针,进而成就对分针以至时针的改善,最后,每过 1 分钟,表盘更新三遍,进而模拟出动态时针的效应,如图 10 所示。

图 10. 时钟

图片 11离线支持

就算如此 Web 操作系统的长处是足以利用网络任何时间任何地方进行访问。不过在不能访问网络的事态下,Web 操作系统便不能够发挥作用。由此 Web 操作系统有供给在离线状态下,还是可以对一些选取及其职能扩充支撑。事实上,各个浏览器已提供了五颜六色的缓存机制以提供对离线应用的支撑,然后这么些缓存机制往往是临时性的,不可控的。HTML5 为开拓人士提供了缓和此难点的另风度翩翩种路子,它提供了大器晚成种永远性的,自定义的缓存方法,使得 Web 操作系统可以在离线的气象下,依然支持部分采纳的功用。

HTML5 离线辅助的主导是叁个缓存项目清单,当中列出了亟需缓存的文本,本系统中的缓存文件 index.manifest,如项目清单 19 所示。

清单 19. 缓存清单

XHTML

CACHE MANIFEST #version 1.10 CACHE: index.html js/app.js js/clock.js js/data.js js/database.js js/desktop.js js/history.js js/taskbar.js js/timer.js js/file.js js/utils.js css/index.css images/appHolder1.png images/background.jpg images/clock.png images/close.gif images/computer.gif images/history.png images/network.gif images/recycleBin.gif images/startIcon.png images/taskBar.png images/vidioplayer.gif images/notebook.gif images/text.gif images/save.gif movs/movie.ogg sounds/WindowsLogonSound.wav

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
CACHE MANIFEST
#version 1.10
CACHE:
index.html
js/app.js
js/clock.js
js/data.js
js/database.js
js/desktop.js
js/history.js
js/taskbar.js
js/timer.js
js/file.js
js/utils.js
css/index.css
images/appHolder1.png
images/background.jpg
images/clock.png
images/close.gif
images/computer.gif
images/history.png
images/network.gif
images/recycleBin.gif
images/startIcon.png
images/taskBar.png
images/vidioplayer.gif
images/notebook.gif
images/text.gif
images/save.gif
movs/movie.ogg
sounds/WindowsLogonSound.wav

中间,CACHE MANIFEST 标示本文件为缓存文件,#version 1.10 标示了本文件的版本。

CACHE 之后所列项支出的则是开辟职员自定义的剧情,个中积攒了颇负在离线状态下客商访谈应用程序所供给的文本。

缓存项目清单定义结束后,在 index.html 中插入这几个清单文件名,那样,当浏览器加载那么些页面包车型大巴时候,会自动缓存项目清单文件中所罗列的文书。

清单 20. 使用缓存清单

XHTML

<html manifest="index.manifest">

1
<html manifest="index.manifest">

值得生龙活虎提的是,若要扶植离线缓存,除顾客端浏览器的帮衬以外,服务端的支撑也是不可能缺少的,就本系统所采取的 tomcat 来讲,需求在其配备文件 web.xml 中增加项目清单 21 所示的规行矩步。

清单 21. 劳动器端缓存配置

XHTML

<mime-mapping> <extension>manifest</extension> <mime-type>text/cache-manifest</mime-type> </mime-mapping>

1
2
3
4
<mime-mapping>
<extension>manifest</extension>
<mime-type>text/cache-manifest</mime-type>
</mime-mapping>

末段,禁止使用当地机械的网络,重新展开浏览器并探访 Web 操作系统所在的网站,系统中的大多数应用程序依旧得以健康专业,如图 11 所示。

图 11. 离线系统

图片 12结束语

正文介绍了 Web 操作系统的基本知识,并与历史观的操作系统实行了相比,进而介绍了 HTML5 这种新本事为 Web 操作系统开采带给的益处,并与守旧的 web 前端开垦本领举办了比较,最后经过创设二个骨干的 Web 操作系统详细的表现了 Web 操作系统的基本方式和职能以致协理其运营的 web 前端开荒手艺是哪些促成其切实成效的。从本文的座谈中能够见见,基于 HTML5 的 Web 操作系统是前程的一大倾向,必定会将渐渐踏入大家的平日生活工作中去。

赞 2 收藏 1 评论

图片 13

本文由3016.com-金沙城中心官网发布于前端,转载请注明出处:基于 HTML5 构建 Web 操作系统

关键词: