如臂使指——Dojo框架下让浮动窗口跟随鼠标而动

介绍

在web应用的很多场合,需要让浮动窗口跟随鼠标而动。比如这儿举的一个例子:当用户选中网页上一段内容时,弹出工具条让用户进行标记。可以想象一下,有一个在线看书的应用,支持读者在阅读的时候随时做笔记。当读者选中一段文字时,弹出一个小工具条,让用户保存成笔记标题或笔记内容在这种场景下,让小工具条出现在选中文字的旁边是必要的用户体验。在实际应用场合,还必须确保在不同的浏览器中、当文字内容有滚动条时,小工具条的位置都不错。

下面就来看看如何实现这种效果代码已经在Firefox 17.0.9,Chrome 30.0.1599.101,IE 10下面测过)。

首先用Dojo widget(Dojo 1.7.3)搭建一个网页框架。在主模块中放入文字内容。接下来要做的就是创建一个浮动窗口,让它在用户选中一段文字内容的时候出现。

代码实现

test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@import "../js/dijit/themes/tundra/tundra.css";
@import "../css/main.css";
</style>

</head>
<body class="tundra">
<div data-dojo-type="dijit.layout.BorderContainer"
		style="width: 100%; height: 100%; margin: 0px; padding: 0px; ">
	<div data-dojo-type="dojox.layout.ContentPane"
		data-dojo-props="region:'top'"
		style="height:38px;width:100%;background-color: black; color: white;font-family: arial;font-size: 28px;">
		在线阅读器
	</div>
	<div data-dojo-type="dojox.layout.ContentPane"
		data-dojo-props="region:'center',splitter: true"
		style="width: 100%; height: 100%; border: none; padding: 0px; background-color: #ffffff;">
		<div style="width: 99%; margin: -3px 0px -2px 2px;">
			<button id="open_model_btn" data-dojo-type="dijit.form.Button"
				class="menu_button" type="button">打开文章</button>
		</div>
		<div data-dojo-type="dijit.layout.BorderContainer"
			data-dojo-props="design:'sidebar',gutters:true,liveSplitters:true"
			style="width: 100%; height: 300px;">
			<div data-dojo-type="dojox.layout.ContentPane" data-dojo-props="splitter:true,region:'left'"
				style="width: 300px;">
				<div style="background-color: lightgray;">笔记列表</div>
			</div>
			<div data-dojo-type="dojox.layout.ContentPane" style="font-size: 16px;"
				data-dojo-props="splitter:true,region:'center'">
				<div id="resource_text_container">
					<div>阅读 reading</div>
					<div>1、从书面材料中获取信息的过程。书面材料主要是文字,也包括符号、公式、图表等。首先是把文字符号变成声音,后达到对书面材料的理解。阅读是一种主动的过程,是由阅读者根据不同的目的加以调节控制的。</div>
					<div>2、朗读是一种阅读方式。朗读是指出声诵读,读则指没有明显发声的诵读。在某些情况下,如诗词欣赏。朗读有特殊功用,可高度集中注意力,但就从书面材料中获取知识而言,读更为重要,理解文字材料主要靠读。阅读时的眼动是一系列的跳动,跳动本身历时很短,而且不能产生对文字的清晰视觉。对文字的清晰视觉都是在注视时得到的。</div>
					<div>3、影响阅读理解的外部因素包括文字材料和情境的物理特点,如照明条件,文字的字体、型号等;文字材料的易读度,如字词的常用程度
						,句子的长短与结构的繁简
						,命题密度(即在一定长度的材料中出现的概念数)等;材料的概括与抽象的程度;由外部确定的阅读目的等等。影响阅读理解的内部因素主要是阅读者的知识基础。此外,阅读者的注意、记忆和思维也都是重要的内部因素。</div>
					<div>阅读可以分成四种情况。第一种是信息式阅读法。这类阅读的目的只是为了了解情况。我们阅读报纸、广告、说明书等属于这种阅读方法。对于大多数这类资料,读者应该使用一目十行的速读法,眼睛象电子扫描一样地在文字快速浏览,及时捕捉自己所需的内容,舍弃无关的部分。任何人想及时了解当前形势或者研究某一段历史,速读法是不可少的,然而,是否需要中断、精读或停顿下来稍加思考,视所读的材料而定。</div>
					<div>第二种是文学作品阅读法。文学作品除了内容之外,还有修辞和韵律上的意义。因此阅读时应该非常缓慢,自己能听到其中每一个词的声音,嘴唇没动,是因为偷懒。例如读“压力”这个词时,喉部肌肉应同时运动。阅读诗词更要注意听到声音,即使是一行诗中漏掉了一个音节,照样也能听得出来。阅读散文要注意它的韵律,聆听词句前后的声音,还需要从隐喻或词与词之间的组合中获取自己的感知。文学家的作品,唯有充分运用这种接受语言的能力,才能汲取他们的聪明才智、想象能力和写作技巧。这种依赖耳听—一通过眼睛接受文字信号,将它们转译成声音,到达喉咙,然后加以理解的阅读方法,最终同我们的臆想能力相关。</div>
					<div>第三种是经典著作阅读法,这种方法用来阅读哲学、经济、军事和古典著作。阅读这些著作要象读文学作品一样的慢,但读者的眼睛经常离开书本,对书中的一字一句都细加思索,捕捉作者的真正的用意。从而理解其中的深奥的哲理。值得注意的是,如果用经典著作阅读法阅读文学作品,往往容易忽略文学作品的特色,以
						使读者自己钻进所谓文学观念史的牛角尖中去。</div>
					<div>第四种阅读方法是麻醉性的阅读法。这种阅读只是为了消遣。如同服用麻醉品那样使读者忘却了自己的存在,飘飘然于无限的幻想之中。这类读者一般对自己的经历和感受不感兴趣,把自己完全置身于书本之外。如果使用麻醉性的阅读方法阅读名著,读者只能得到一些已经添加了自己的幻想的肤浅的情节,使不朽的名著下降到鸳鸯蝴蝶派作家的庸俗作品的水平。如果漫不经心地阅读《安娜•卡列尼娜》,犹如读一本拙劣的三角恋爱小说。麻醉性的阅读在将进入成年的时候达到顶峰。年轻人的麻醉阅读是造成大量的文学作品质量低劣的原因。</div>
				</div>
				<div id="resource_text_floating_pane" 
					style="border: 1px solid #BBBBBB;position: absolute;width: 85px;z-index: 10;display:none;">
					<div data-dojo-type="dijit.Toolbar" style="padding: 3px 0 0 3px;">
					    <div id="add_paragraph" data-dojo-type="dijit.form.Button" data-dojo-props="showLabel:true">
					        	段落
					    </div>
						<div id="add_content" data-dojo-type="dijit.form.Button" data-dojo-props="showLabel:true">
					        	内容
					    </div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>

<script>
		dojoConfig = {
			isDebug : false,parSEOnLoad : true,async : true
		};
	</script>
	<script type="text/javascript" src="../js/dojo/dojo.js"></script>
	<script>
		require([ "dojo/parser","dijit/form/Button","dijit/Toolbar","dijit/layout/BorderContainer","dojox/layout/ContentPane"]);
	</script>
	<script>
		require(
				[ "dojo/ready","dijit/registry","dojo/dom","dojo/on"
				  ],function(ready,registry,dom,on) {
					ready(function() {
						var resource_text_container = dom.byId("resource_text_container");
						on(resource_text_container,"mouseup",function(e){
							//拿到鼠标位置
							var selection = document.getSelection();
							var start = selection.anchorOffset;
							var end = selection.focusOffset;
							
							var fp = dom.byId("resource_text_floating_pane");
							if(start-end != 0){
								//根据鼠标位置,计算浮动窗口的位置
								if(dojo.isChrome != undefined){//Chrome
									var cx = e.layerX;
									var cy = resource_text_container.parentElement.scrollTop + e.layerY;								
								}else if(dojo.isIE != undefined){//IE
									var cx = e.layerX - resource_text_container.parentElement.offsetLeft;
									var cy = resource_text_container.parentElement.scrollTop + e.layerY;	
								}else {//Firefox
									var cx = e.layerX;
									var cy = e.layerY;
								}
								fp.style.left = (cx + 0) + "px";
								fp.style.top = (cy + 0) + "px";
								fp.style.display = "block";
							}else{
								fp.style.display = "none";
							}
						});
						
						on(registry.byId("add_paragraph"),"click",function(e){
							alert("新建段落");
						});
						
						on(registry.byId("add_content"),function(e){
							alert("新建内容");
						});
					});
				});
	</script>
</body>
</html>

总结

在确定浮动窗口位置时,我们主要使用了鼠标事件的layerX和layerY属性。关于Event对象与定位相关的属性,和浏览器的版本密切相关。想支持其他版本的,可以参考这篇文章

相关文章

我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易...
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以...
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部...
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforja...
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑...
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这...