Dojo——拖放操作

Web用户对于在这种媒体上实现的拖放操作不是很习惯。因为这个原因,我们需要对于提供支持拖放功能
的界面保持谨慎,也许需要提供一个可以不单独依赖拖放操作的界面。
提供拖放支持可以使得一些任务更加容易使用。在我们的应用中,用户可以在路线中可视化地移动站点,
而不是必须要进入一些编辑模式来将它们从奇怪的列表中移动。
为dojo配置拖放功能实际上要比你可能想象的更加容易。我们将通过3个阶段来完成这件工作:

  1. 连接day元素,告诉系统什么可以拖拽,什么可以放置拖拽的元素。
  2. 给定某一天,连接它的子元素。
  3. 告诉浏览器来做这个连接

1.1 连接所有的天
最初的函数将遍历所有的天,告诉每一天准备好放置站点,然后将所有的站点设置为可拖拽的对象。一旦
天被设置好了,也会配置未使用的站点区域(unused sites area)。
function enableSiteMoving() {
for (var d=1; d <= numberOfDays; d++) {
var dl = dojo.byId(“day-” + d);
setupDayForDND(dl);
var lis = dl.getElementsByTagName(“li”);
for(var x=0; x<lis.length; x++){
new dojo.dnd.HtmlDragSource(lis[x], “daylist”);
}
}
// configure the unused sites
var unusedSitesDiv = dojo.byId(“unused-sites”);
var lis = unusedSitesDiv.getElementsByTagName(“li”);
for (var x=0; x<lis.length; x++){
new dojo.dnd.HtmlDragSource(lis[x], “daylist”);
}
}

1.2 连接单个的天
大量的神奇效果发生在以下的几行代码中。为了设置天,我们获得通过enableSiteMoving()传递进来的
天的列表,然后我们初次使用dojo.event的API。
这个API允许你连接并且截取DOM节点上的方法,以及任何的JavaScript函数。这正是AOP式开发的用武
之地。例如,如果你想要记录(log)某个函数的每一次调用,你可以获取这个函数对象,与实现记录所需的
代码相连接。

在我们这里,我们想要连接拖拽的目标。当你将站点放置到天的列表中后,我们配置了onDrop()函数来
完成需要的处理。当站点被放置下来,我们使用Dojo Effects的package来除去移走的站点。我们检查这一
天先前是否是空的,如果它是空的,就将注释“empty…”删掉。然后我们调用Ajax函数
remoteMoveSiteOntop()来告诉服务器这次移动,将移动节点的id传递进来。
我们为列表中的节点选择了特殊的ID,格式为“siteid-occurance”,这使得我们在后端可以确切地知
道前端发生了什么事情。
function setupDayForDND(dl) {
var dt = new dojo.dnd.HtmlDropTarget(dl, [“daylist”]);
dojo.event.connect(dt, “onDrop”, function(e) {
dojo.fx.wipeIn(e.dragObject.domNode.id, 300);
checkEmptyDay(dl.id.substring(3));
remoteMoveSiteOntop(e.dragObject.domNode.id, e.target.id);
});
}

1.3 onLoad
如果你想要将一些东西加载进浏览器,在DOM加载完成后,你通常会这样设置onLoad处理函数:

或者: window.onload = function() { … } 这在一些场合是适用的,但是如果多于一个库使用这种方法呢?你就会遇到冲突,在后面设置 window.onload处理函数的库将会胜出,而设置在前面的那个处理函数中的代码永远也不会被调用。 为了解决这个问题,你可以很方便地使用Dojo的辅助函数: dojo.addOnLoad(function() { enableSiteMoving(); }); addOnLoad将确保所有以这种方式添加的函数将会被排队,并且都将会被调用。 addOnLoad还有另外一种调用风格,dojo.addOnLoad(object, ‘functionName’)。这将调用传递进来的 对象上的指定的functionName。