南通最专业的开锁公司 南通最好的开锁公司 君威遥控器电池 君威专用汽车钥匙电池雷诺科雷傲汽车钥匙遥控器电池更换方法 南通开锁公司电话_南通修锁 换锁芯 开汽车锁 崇川区 港闸区 如皋 如东开锁 南通开锁公司电话 南通金钥匙开锁服务部-专业开修锁 换锁芯(正规公安工商备案) 南通开锁公司电话 南通开锁公司修锁 装锁电话|崇川区开锁|港闸区开锁 led吸顶灯光源 吸顶灯32w 吸顶灯 灯管 吸顶灯 节能灯泡 led吸顶灯灯泡 三头吸顶灯 led吸顶灯灯管 欧普圆形吸顶灯 55w吸顶灯 吸顶灯光源 旅游壶 真空保温 汉方养生壶 美的电热水壶15s08a2 半球牌电饭煲 美的 mg123-d hd2 飞科 三洋洗衣机全自动 新安怡 学饮杯 黑苦荞黄酮软胶囊 苦荞糖安胶囊 五彩凉山苦荞茶 苦荞茶250g 全胚芽黑苦荞茶500 内蒙特产苦荞茶 富贵康苦荞茶 苦荞面包邮 正中苦荞茶包邮 正中苦荞茶 包邮 苦荞香茶西部 苦荞香茶 西部 轩庆苦荞玫瑰鲜花饼 苦荞真空 苦荞500克 苦荞茶120 苦荞 真空 0.02安全套包邮0.2大力马鱼线0.4mm0.4鱼线0.5l氮纤维高压瓶007sh充电器007电子请柬00高达xn-raiser01102400018401背囊0-25微米千分尺03g101系列全套图集0-3个月婴儿连体哈衣05-08本田奥德赛05ffc23套机05版河南动感地带0603贴片电阻包06年款英派斯06斯巴鲁森林人cd机07军衔07军用水壶07款福克斯两厢07数码迷彩07速腾大灯总成 泰好大门锁 泰好豪华大门锁 cei超b级锁芯 玻璃橱门锁 指纹锁耶鲁4109 耶鲁凯特曼指纹锁 防盗挂锁包邮 包挂锁 包梁挂锁 新君威门锁 新君威门锁扣 指纹锁木门 太空铝黑色门锁 泰好浴室铜门锁 浴室门锁不锈钢 1178冷库门锁 南通配新桑塔纳2000 3000 时代超人 志俊汽车钥匙_配帕桑塔纳钥匙遥控器_帕萨特钥匙全丢重配崇川区 南通配宝来汽车钥匙_配宝来遥控器_宝来钥匙全丢如皋 南通配帕萨特汽车钥匙_配帕萨特遥控器_帕萨特钥匙全丢通州 南通配凯越汽车钥匙_配凯越遥控器_凯越钥匙全丢如东

  • 格子衬衣女 长袖 秋
  • t男恤 短袖 韩版包邮
  • 男士职业衬衫
  • 衬衫 女 长袖点点
  • 衬衫 素色 男 宽松 休闲
  • 职场气质衬衫女
  • t恤男短袖加大码不掉色
  • 帅T 小西装
  • 裤子棕色长裤男
  • 衬衣 女 灯芯绒
  • 衬衣 女商务
  • 女士职业衬衫短袖
  • 休闲裤 男 修身
  • jamesearl纯棉休闲长裤
  • 占姆士女式长袖衬衫
  • 男黑色商务休闲棉长裤
  • 女士长袖衬衫
  • 男士绿色休闲长裤
  • 全棉短袖衬衫 男 薄
  • 女士长袖纯棉衬衫
  • 秋裤男直筒
  • 马自达3汽车挂件吊坠饰品 高档琉璃汽车挂饰品蒙迪欧致胜汽车挂件吊坠饰品 高档琉璃汽车挂饰品 启辰D50汽车挂件吊坠饰品 高档琉璃汽车挂饰品起亚K2汽车挂件吊坠饰品 高档琉璃汽车挂饰品索纳塔汽车挂件吊坠饰品 高档琉璃汽车挂饰品天籁汽车挂件吊坠饰品 高档琉璃汽车挂饰品 天语SX4汽车挂件吊坠饰品 高档琉璃汽车挂饰品英朗GT汽车挂件吊坠饰品 高档琉璃汽车挂饰品英伦SC7汽车挂件吊坠饰品 高档琉璃汽车挂饰品自由舰汽车挂件吊坠饰品 高档琉璃汽车挂饰品雨燕汽车挂件吊坠饰品 高档琉璃汽车挂饰品雪佛兰迈锐宝汽车挂件吊坠饰品 高档琉璃汽车挂饰品

    秋冬季现代瑞纳 宝马5系 帕萨特 日产骐达专用汽车毛绒方向盘套 江苏省盐城市地图2014 最新版 江苏省卫星地图2014 最新版 百度地图-谷歌地图-中国地图-北京地图-搜狗地图google地图 广本凌派汽车座垫 凌派秋冬季汽车坐垫 四季通用 长安福特福克斯油耗详解 宝来汽车遥控钥匙电池 更换方法 图解宝来遥控钥匙的电池换法 宝骏630车钥匙遥控器电池更换步骤 更换方法 迈腾车钥匙电池 迈腾更换遥控器电池详解逍客汽车钥匙电池 遥控器逍客智能钥匙的电池更换步骤 新天籁智能遥控钥匙电池 新天籁智能钥匙如何更换纽扣电池 golf6 汽车钥匙遥控器换电池 图解高尔夫6遥控钥匙的电池换法 长安福特福克斯加速时间详解[图] 福克斯汽车钥匙电池 福克斯钥匙电池更换作业 Q5车钥匙更换电池方法 图解新凯越车钥匙更换电池
  • 汽车坐垫 可爱
  • wrc汽车坐垫
  • 汽车坐垫套四季通用
  • 明锐冰丝 汽车坐套
  • 骐达汽车脚垫全包围
  • 三菱蓝瑟汽车坐垫
  • 捷达汽车脚垫 3d
  • 奥迪S7坐垫
  • 别克荣御坐垫
  • Jeep指南者坐垫
  • 力帆320坐垫
  • 路虎卫士坐垫
  • 双龙爱腾坐垫
  • 斯柯达Yeti坐垫
  • 现代途胜坐垫
  • 一汽威乐坐垫
  • 哈飞路宝汽车坐垫
  • 吉利远景汽车坐垫
  • 吉利全球鹰汽车坐垫
  • 房门锁执手锁 防盗挂锁
  • 运动短裤
  • 短裤 男
  • 半裙
  • 手工拖鞋鞋底
  • iphone4皮套 手机套
  • 机油滤清器扳手工具
  • 桑塔纳3000机油
  • 家居摆件现代
  • 玻璃摆件
  • 瓷器摆件
  • 马到成功摆件
  • 高档瓷器摆件
  • 宝马山地自行车包邮
  • 根雕工艺品摆件
  • 家居摆件吊脚娃娃
  • 泰国佛像摆件工艺品
  • 美利达儿童自行车
  • 天鹅摆件结婚
  • 龙龟摆件纯铜
  • 金摆件聚宝盆
  • 亲子自行车 女式
  • 客厅卧室装饰摆件
  • 贵宾狗摆件
  • 木摆件
  • 羚羊头摆件
  • 招财兔摆件
  • 自行车前包
  • 牛仔短裤
  • 短裤 男 休闲
  • 高腰短裤
  • 夏季短裤
  • 蕾丝短裤
  • 连体短裤
  • 裙裤
  • 裤裙
  • 拖鞋 海外
  • 拖鞋 浴室
  • 拖鞋 防滑
  • 拖 鞋 男
  • 拖鞋 女
  • 浴室拖鞋
  • 家居拖鞋
  • 凉拖鞋
  • 夏天拖鞋
  • 香菇丸
  • 韩国饮料
  • 打草绳小松打草绳二手挖掘机小松 小松割灌机配件 钢木书桌办公桌钢木桌玻璃杯子水壶钢化玻璃水壶钢木办公桌钢木电脑桌进口玻璃水壶玻璃水成份防冻玻璃水包邮防冻玻璃水车用 环保果皮箱环保垃圾袋环保垃圾桶小松120-6常州小松割草机小松打草头小松割灌机小松割灌机配件 咖啡厅员工制服_咖啡厅服务员制服_西餐咖啡服务员制服_咖啡馆制服_咖啡店西餐
  • 5号充电电池8节套装
  • 5-7号电池充电器
  • 充电电池5号正品
  • 可充电电池5号
  • 7号充电电池批发
  • 7号电池包邮
  • 1.5v充电电池5号
  • 5号充电器电池免邮
  • 双鹿电池5号正品
  • 双鹿9v电池
  • 双鹿电池批发
  • 双鹿7号电池
  • 双鹿1号电池
  • 双鹿碱性电池
  • 三星s4电池原装正品
  • 三星s4原装电池后盖
  • n7100原装电池
  • 小米2s原装电池
  • galaxy s4大容量电池
  • galaxy s4原装电池
  • galaxy s3电池
  • galaxy nexus电池
  • 三星galaxy s4电池后盖
  • 品胜小米2s电池
  • 品胜手机电池
  • 小米2a电池品胜
  • 背夹电池iphone4s
  • note2背夹电池
  • 三星s4背夹电池皮套
  • 自行车fixedgear 自行车眼镜 近视 婴儿推车小自行车 自行车骑行眼镜风镜 钻石自行车 山地自行车立管 led自行车气嘴专用灯 三鼎自行车坐椅儿童 自行车线管 金镶玉玉器挂件 自行车脚踏双轴承 铬钼钢架自行车 邦德自行车女式 山地公路自行车 自行车骑行手电筒 自行车灯架 灯夹包邮 自行车水壶支架 自行车 组装 mosso 自行车载mp3 26自行车 男生单车 自行车 折叠 复古 giant山地车 自行车 炫彩自行车 七彩马亲子自行车 ucc山地车 自行车 贝嘉琦 女孩自行车 zxc自行车配件码表 自行车前置安全椅 女童自行车 小龙哈比 自行车碳纤维垫圈 自行车骑行用品 装饰木板板材 美式壁挂装饰 家具装饰配件 衣服装饰亮片 婚礼礼品实用 公司开业庆典礼品 婴儿衣柜 儿童欧式公主床 床围栏护栏嵌入式 床靠背套 派克圆珠笔芯 卧室台灯床头灯现代 个性笔袋 派克im签字笔 彩色铅笔包邮 派克宝珠笔芯 派克笔芯正品 百乐摩可擦笔笔芯 斑马油笔 微型钢笔钓鱼竿 电子教鞭遥控笔 镭射灯激光笔 彩色水笔芯 黑色水笔笔芯 公爵宝珠笔芯 touch3代马克笔 韩国文具笔包邮 水溶性彩色铅笔 马可 sgp触控笔 礼品创意笔筒 铂金 项链 pt950 男 老竹笔筒 竹雕笔筒 六福珠宝铂金手镯 8.9寸笔记本电脑 三菱签字笔1.0 华硕游戏笔记本 插座面板

    基于HTML5构建Web操作系统

    HTML5 是下一代 web 语言的标准,具有兼容性好,安全性高,功能丰富,开发便捷等优点,特别适合如 Web 操作系统一类的富客户端互联网应用的前端开发。本文将展示如何利用 HTML5 提供的多种新技术如:本地数据库、多线程开发、视频支持、离线编程等构建一个基本的 Web 操作系统。

    简介

    传统的操作系统有着一些难以克服的缺点,如仅能在本地终端访问,或仅支持有限的远程访问,限于本地终端的资源,计算能力薄弱,存储空间有 限,缺乏强大的防火墙等一系列安全机制,安全性较差。鉴于以上缺点,Web 操作系统应运而生 - Web 操作系统是一种基于浏览器的虚拟的操作系统,用户通过浏览器可以在其中进行应用程序的操作,以及相关数据的存储。Web 操作系统提供的基本服务有文本文档的创建与存储,音频视频文件的播放与存储,提供对时间信息的支持等,更高级的服务则包含即时通信,邮件甚至游戏等服务。 Web 操作系统克服了传统操作系统的缺点,在网络的支持下,它可以在任何时间,任何地点经由任何支持 Web 的终端进行访问,可以利用服务器端无限的计算及存储资源,用户数据保存在服务器端,安全性较高。

    相关技术

    目前构建 Web 操作系统的前端技术主要有 Flex、Silverlight、ActiveX 插件等等,它们各有一些优缺点。

    Flex

    Flex 是一个优秀的富客户端应用框架,专注于页面显示,Adobe 专业维护,统一稳定,而且其脚本语言 ActionScript3 是面向对象的,非常适合程序员使用。缺点则是耗能高,占用带宽多,对移动应用的支持性差。

    Silverlight

    Silverlight 是由微软推出的用以跟 Flash 抗衡的 RIA(富互联网应用)解决方案,优点是具备硬件级的加速功能,但它目前仍不成熟,对非 Windows 系统的支持性并不够好,且学习难度较大。

    ActiveX 插件

    ActiveX 插件同样是微软推出的 RIA 解决方案,它是一个开放的解决方案,可以兼容多种语言,不过它的缺点也是显而易见的,用户需要调整浏览器的安全等级并下载插件才能运行 RIA 应用,极大地降低了安全性。

    HTML5

    为推动 web 标准化运动的发展,W3C 推出了下一代 HTML 的标准 - HTML5,为众多的公司所支持,因此具有良好的前景。它有以下特点:首先,为增强用户体验,强化了 web 网页的表现性能;其次,为适应 RIA 应用的发展,追加了本地数据库等 web 应用的功能;再次,由于高度标准化以及诸多浏览器厂商的大力支持,它的兼容性和安全性非常高;最后它是一种简洁的语言,容易为广大开发者掌握。更为难得的 是,由于节能和功耗低,在移动设备上 HTML5 将具有更大的优势。因此更适合如 Web 操作系统一类的 RIA 应用的前端开发。

    系统简介

    本系统基于 HTML5 开发,利用 HTML5 引入的多种新技术如拖拽 API、视频标签、本地数据库、draw API、多线程开发、离线编程等提供了一个基本的 Web 操作系统环境,包含了对桌面的支持、应用程序的支持,提供了一个简单的视频播放器和记事本以及一个时钟,并对系统日志进行了记录,此外还提供了对离线状态 的支持。

    回页首

    桌面实现

    系统对桌面的支持主要包括应用程序图标的打开与拖拽,以及桌面的上下文菜单等。

    桌面拖拽

    桌面的布局由一定数量的 div 组成,它们按照次序依次排列在矩形的桌面上,为应用程序图标的打开与拖拽提供了基本的支持。


    清单 1. 创建 div
    				   var iconHolder = document.createElement("div");   iconHolder.id = 'iconHolder' + i;   iconHolder.className = "iconHolder";   mainDiv.appendChild(iconHolder);  

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


    清单 2. 拖拽支持
    				   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 中的应用程序图标转移至目的 div 中。若目标 div 中已包含应用程序图标,则将两个图标的位置互换。若回收站图标处于目标 div 中,回收站将发挥作用并将源 div 中的应用程序图标删除。图 1 显示了桌面拖拽的效果。


    图 1. 桌面拖拽效果
    图 1. 桌面拖拽效果

    程序打开

    程序可以以两种方式打开,左键点击或通过上下文菜单打开。

    通过监听 div 的 onclick 事件,获取要打开的应用程序 id,并利用 openApp 方法打开相应的应用程序可实现对左键点击的支持。


    清单 3. 左键点击
    				   iconHolder.onclick =  function(ev){   if(ev.currentTarget.firstChild){          openApp(ev.currentTarget.firstChild.id);          ev.stopPropagation();   }   };  

    通过监听 div 的 oncontextmenu 事件,获取要打开的应用程序 id,并利用 openAppContextMenu 方法显示相应应用程序的上下文菜单,可实现对右键上下文菜单的支持。


    清单 4. 上下文菜单
    				   iconHolder.oncontextmenu =  function(ev){   if(ev.currentTarget.firstChild){          openAppContextMenu(ev.currentTarget.firstChild.id, ev);          ev.stopPropagation();   }   return false;   };  

    利用相应应用程序的 id,可以获取对应应用程序的脚本,并执行,同时在系统日志中记录下相应的操作。


    清单 5. 程序打开
    				   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. 打开程序上下文菜单
    				   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. 应用程序上下文菜单
    图 2. 应用程序上下文菜单

    上下文菜单

    桌面上下文菜单的实现方式与应用程序上下文菜单的实现方式基本类似,图 3 和图 4 分别是桌面以及任务栏的上下文菜单。


    图 3. 桌面上下文菜单
    图 3. 桌面上下文菜单

    图 4. 任务栏上下文菜单
    图 4. 任务栏上下文菜单

    视频播放器

    系统提供了一个简单的视频播放器,它支持从系统外部拖拽视频文件进行播放。

    顺应网络媒体的发展,HTML5 提供了视频标签 video 以便于加强对视频的支持,大大简化了 web 播放器开发的难度,开发人员仅凭几行代码,就可以开发出一个基本功能完善的视频播放器。


    清单 7. 视频标签的创建
    				   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. 添加拖拽支持
    				   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. 拖拽处理
    				   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( 这里是视频标签 ) 添加文件,然后利用 FileReader 读取文件内容至 fileprocessor 进行处理。

    图 5 显示了拖拽一个视频文件 movie.ogg 到播放器的效果。


    图 5. 视频播放
    图 5. 视频播放

    回页首

    本地存储

    Web 操作系统通常将大部分数据存储于服务器端,这样做的好处显而易见,数据存储空间更大,安全性更好。然而这样做也有不足之处,由于网络的稳定性依然较本地磁 盘差,所以在脱离网络的状况下,Web 操作系统无法获取相应的数据资源,因此 Web 操作系统需要一定的访问本地存储空间的能力,当然本地存储空间仅是作为服务器端存储的一个补充,它的空间有限,访问也受到一定的限制。

    一直以来,HTML 以 Cookie 作为访问本地空间的方式,然而,这种方式有着很多缺点和不足,如存储的数据格式过于简单,通常仅为键值对;存储的空间大小有限。为此,HTML5 提供了本地数据库以增强本地存储空间的访问能力,它是一个简化版的数据库,能够支持模拟的 SQL 以及简单的事务处理等功能。

    系统为支持本地存储,创建了一个名为 MyData 的数据库。清单 10 显示了数据库创建的过程。


    清单 10. 创建数据库
    				   var db;   var openDatabase;   if(openDatabase != undefined)       db = openDatabase('MyData', '', 'My Database', 102400);  

    其中 MyData 为数据库的名称,省略的参数为数据库的版本,My Database 为显示的名称,最后的数字为数据库预估长度(以字节为单位)。

    系统日志将系统在某一时间的行为操作记录下来,本地数据库为其提供存储支持。日志在数据库中存储为表 History,包含 3 个字段,分别为时间,操作,及操作的详细信息。清单 11 显示了系统是如何记录日志的。


    清单 11. 日志记录
    				   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. 日志显示
    				   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( 事务 ) 中,执行一条 SQL 语句,查询系统日志,并将每条日志添加为 historyTable 中的一行以便显示。图 6 显示了系统日志的效果。


    图 6. 系统日志
    图 6. 系统日志

    记事本

    系统提供了一个简单的记事本,实现了文本文档的基本操作。文本文档包含标题和内容两个显式属性,以及一个名为 id 的隐式属性。与系统日志类似,本地数据库为文本数据的存储提供了底层的支持。图 7 显示了记事本程序的界面。


    图 7. 记事本
    图 7. 记事本

    当编辑完文档的标题与内容后,点击左上角的保存按钮,将执行 createFile 函数。清单 13 显示了 createFile 函数的详细过程。


    清单 13. 创建文件
    				   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 方法在桌面上为新文档创建一个文档图标。清单 14 显示了 createFileIcon 方法的具体过程。


    清单 14. 创建文档图标
    				   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。文档图标有一个 id 属性对应文档 id。最后为文档图标添加点击事件处理函数,当点击文档图标时,会首先打开记事本,然后根据文档图标的 id 查询数据库,提取文档的标题和内容进行显示。

    图 8 显示了创建后的文本文档,点击后的效果如图 7 所示。


    图 8. 文本文档
    图 8. 文本文档

    时钟

    系统提供了一个简单的时钟用以显示当前时间,它由一个表盘以及分针和时针组成,能够随着时间的变化动态地变换。以往的 web 应用利用 JavaScript 或 Flash 完成此类功能,其复杂性可想而知。借助 HTML5 的 draw API,可以轻松地画出所需的图形,极大的方便了此类应用的构建,此外,HTML5 还提供了以往 JavaScript 无法支持的多线程编程,大大加强了 web 应用的交互性和丰富性。

    时钟有一个基本的表盘,它仅是一副简单的图片,如图 9 所示。


    图 9. 表盘
    图 9. 表盘

    在表盘之上,建有一个 canvas( 画布 ),如清单 15 所示。


    清单 15. 画布
    				   <canvas id="canvas" width="128px" height="128px" class="canvas"></canvas>  

    接下来,清单 17 将在画布上模拟出时钟以及分针,在这之前,额外需要一个后台线程用以计算时间,它被定义在名为 time.js 的独立脚本文件中,如清单 16 所示。


    清单 16. 后台线程
    				   onmessage = function(event)   {   //var i = 1;      setInterval(function() {      //i++;      postMessage("");      }, 60000);   };  

    每过 60 秒钟,后台线程将会向前台线程发送一个空消息,以告诉前台线程有 60 秒钟已经过去了。


    清单 17. 前台线程的初始化
    				   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 事件
    				   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. 时钟
    图 10. 时钟

    离线支持

    虽然 Web 操作系统的优点是可以利用网络随时随地进行访问。然而在无法访问网络的情况下,Web 操作系统便无法发挥作用。因此 Web 操作系统有必要在离线状态下,仍能对部分应用及其功能进行支持。事实上,各种浏览器已提供了各式各样的缓存机制以提供对离线应用的支持,然后这些缓存机制 往往是临时性的,不可控的。HTML5 为开发人员提供了解决此问题的另一种途径,它提供了一种永久性的,自定义的缓存方法,使得 Web 操作系统可以在离线的状况下,依然支持部分应用的功能。

    HTML5 离线支持的核心是一个缓存清单,其中列出了需要缓存的文件,本系统中的缓存文件 index.manifest,如清单 19 所示。


    清单 19. 缓存清单
    				   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. 应用缓存清单
    				   <html manifest="index.manifest">  

    值得一提的是,若要支持离线缓存,除客户端浏览器的支持以外,服务端的支持也是必不可少的,就本系统所使用的 tomcat 而言,需要在其配置文件 web.xml 中添加清单 21 所示的条目。


    清单 21. 服务器端缓存配置
    				   <mime-mapping>   <extension>manifest</extension>   <mime-type>text/cache-manifest</mime-type>   </mime-mapping>  

    最后,禁用本地机器的网络,重新打开浏览器并访问 Web 操作系统所在的网址,系统中的大部分应用程序依然可以正常工作,如图 11 所示。


    图 11. 离线系统
    图 11. 离线系统

    结束语

    本文介绍了 Web 操作系统的基本知识,并与传统的操作系统进行了比较,进而介绍了 HTML5 这种新技术为 Web 操作系统开发带来的益处,并与传统的 web 前端开发技术进行了比较,最后通过构建一个基本的 Web 操作系统详细的展现了 Web 操作系统的基本模式和功能以及支撑其运行的 web 前端开发技术是如何实现其具体功能的。从本文的讨论中可以看出,基于 HTML5 的 Web 操作系统是未来的一大趋势,必将逐步走入人们的日常生活工作中去。

    posted @ 2012-09-27 18:56  ChaunceyHao  阅读(626)  评论(0编辑  收藏  举报
  • 汽车羊毛坐垫长毛
  • 车垫四季通用
  • 御车宝
  • 凯美瑞坐垫四季通用
  • 手编冰丝坐垫
  • 珍珠戒指新款
  • 汽车皮坐垫四季垫
  • 汽车四季坐垫新款
  • 汽车皮坐垫四季通用
  • 汽车羊毛坐垫短毛
  • 包女
  • 汽车亚麻坐垫包邮
  • 汽车布坐垫
  • 汽车布坐垫套
  • 紫风铃亚麻四季坐垫
  • 蒙奇奇汽车
  • 蒙奇奇汽车毛绒坐垫
  • 蒙奇奇坐垫三件套
  • 尼罗河车坐垫
  • 尼罗河手编坐垫
  • 尼罗河四季垫
  • 羊剪绒坐垫
  • 牧宝冬季坐垫
  • 牧宝四季垫正品
  • 牧宝羽绒坐垫
  • 牧宝汽车垫羊毛
  • 高压洗车机
  • 高压洗车器
  • 高压洗车水泵
  • 高压洗车泵
  • 熊猫洗车
  • 洗车器高压220v
  • 洗车器便携高压
  • 高压水枪洗车机
  • 220v高压水枪洗车机
  • 家用洗车水枪高压枪
  • 汽车洗车水枪
  • 虎贝尔洗车水枪
  • 水枪头洗车
  • 洗车水枪水管
  • 洗车水枪套装
  • 洗车水枪接头
  • 佳百丽洗车水枪
  • 洗车工具套装
  • 洗车用品工具
  • 家用洗车工具
  • 汽车洗车工具
  • 洗车设备工具
  • 洗车刷子
  • 现代途胜保险杠
  • 现代新胜达保险杠
  • 保险杠车贴纸
  • 后保险杠车贴纸
  • 前保险杠车贴
  • 雨燕保险杠
  • 后保险杠贴纸
  • 前保险杠贴纸
  • 汽车保险贴纸
  • rav4后保险杠
  • 专业运动文胸htc c715e evo design 4g
  • htc evo 4g a9292
  • htc x515m g17 evo 3d
  • htc one x s720e
  • htc x920e
  • 名牌手表男正品
  • povos 奔腾 pffn3003苏泊尔电热水壶正品
  • tcl tcl电热水壶ta-kb181a
  • 乔邦181j
  • 乔邦不锈钢电热水壶
  • supor 苏泊尔 swf15j3-150
  • 逸动空气滤芯
  • 空气压缩机喷漆
  • 德国车载空气净化器
  • sr927w手表电池
  • cartier手表蓝气球
  • 机械手表男士名表
  • anne klein手表
  • 手表柜台展示柜
  • 女士皮带 头层牛皮
  • 女士皮带 头层纯牛皮
  • jeep皮带 纯牛皮
  • 女皮带 真皮 牛皮
  • 女士皮带 真皮
  • 头层牛皮皮带
  • 女士皮带 时尚
  • 真皮皮带头层牛皮女
  • 女士皮带 包邮
  • 皮带条 头层牛皮
  • 女士皮带 时尚 宽
  • 头层牛皮纯铜扣皮带
  • 女士皮带 纯牛皮
  • 女士皮带头层纯牛皮
  • 女士皮带头层牛皮
  • jeep皮带纯牛皮
  • 女皮带真皮牛皮
  • 女士皮带真皮
  • 女士牛皮皮带包邮
  • 女士皮带时尚
  • 三星微单镜头
  • 三星单反镜头
  • 三星50-200镜头
  • 三星7100镜头保护膜
  • 三星i9210
  • 三星i9210手机套面包蛋糕酸奶机
  • 鸡蛋牛奶面包干饼干
  • 面包片饼干
  • 摩托车机油