您的位置:首页 > Web前端 > JavaScript

Drag 和 Drop 在 JavaScript 中的使用

2009-03-03 09:17 295 查看
这一节描述了我们怎么在 JavaScript 中使用 drag and drop.

The JavaScript Drag and Drop Wrapper

在进行拖拽的时候我们也许会需要处理一些事件和传递数据,那么这个时候我们就需要用到Drag和Drop了。让我们简明的看一下使用方法。(对照文档有简化)
注意你需要在所用的xul页面中导入两个 chrome 路径。

<script src="chrome://global/content/nsDragAndDrop.js" />
<script src="chrome://global/content/nsTransferable.js" />

我们可以参考下这个例子:

<button label="Drag Me" ondraggesture="nsDragAndDrop.startDrag(event,buttonObserver);" />

它的功能是在我们首次拖动这个按钮时会通过触发nsDragAndDrop.startDrag 而执行buttonObserver方法里的onDragStart事件。第一个参数是所触发的事件元素,适用于所有的事件处理。第二个参数是作为监听器的方法,一会儿再具体介绍。 同样我们也可以处理其他的情况而触发相应的方法,例如下面这个例子:

<description value="Click and drag this text."
ondraggesture="nsDragAndDrop.startDrag(event,textObserver)"
ondragover="nsDragAndDrop.dragOver(event,textObserver)"
ondragexit="nsDragAndDrop.dragExit(event,textObserver)"
ondragdrop="nsDragAndDrop.drop(event,textObserver)" />

通常有六个拖动触发事件,拖动是指按住鼠标并移动鼠标的时候,ondrag为有拖动操作就触发,ondraggesture为首次拖动而触发,ondragover为在区域内拖动而触发,ondragenter为拖动至区域内而触发,ondragexit为拖动至区域外而触发,ondragdrop为释放拖动而触发。
这有两种方式处理drag 和 drop 事件。第一个是直接用nsIDragServicensIDragSessionXPCOM接口,第二个是用JavaScript wrapper 方法协助操作。
如上所述,在触发事件时候并没有什么需要特别注意的,一会让我们亲自来测试一下吧。先看一下这些事件的功能。
onDragStart(event, transferData, action)
在拖动开始时你可以定义这个方法,它有三个参数,第一个参数event元素作为被拖动的节点事件,我们可以用event.target取得该DOM节点;第二个transferData是拖拽时候所转移的数据,我们可以在这个方法内给transferData添加数据而进行传递,具体的使用方法请查看nsITransfer接口(尚未确定);第三个是拖拽动作的类型,有四种类型供用户选择,但具体意义还不明确。
nsIDragSession.DRAGDROP_ACTION_NONE 不允许修改。
nsIDragSession.DRAGDROP_ACTION_COPY 拷贝
nsIDragSession.DRAGDROP_ACTION_MOVE 移动
nsIDragSession.DRAGDROP_ACTION_LINK 连接

onDragOver(event, flavour, session)
当拖动在区域内时你可以定义这个方法,第一个参数还是event元素;第二个参数是所此次拖动所带来的传递数据类型相关,里面应该包括着数据;第三个session是会话信息,它有几个参数我个人认为很有用,比如sourceDocument可以得到被拖动的源,sourceNode可以得到被拖动的节点等等,你可以从中直接取到节点属性。

onDragExit(event, session)
当拖动退出区域时你可以定义这个方法,第一个参数又是event元素,第二个是会话信息解释同上。
onDrop(event, transferData, session)
当释放拖动后你可以定义这个方法来做一些处理,第一个依然是event;第二个是传递过来的数据;第三个session是会话信息解释同上。

getSupportedFlavours()
这个方法可以返回可接受的元素类型,通常用在Drop事件中,具体使用方法请参照例子,但好像就是一个数据类型的判定,还需要研究下。

The type of data being dragged is stored as a set of flavours. Often, a dragged object will be available in a number of flavours. That way, a drop target can accept the flavour it finds most suitable. For example, a file may come in two flavours, the file itself and the text name of the file. If the file is dragged and dropped onto a directory, the file flavour will be used. If the file is dropped onto a textbox, the text name flavour will be used. The text is therefore used to insert the name of the file when files can't be dropped directly.
A flavour object has a name, which is a formatted like a MIME type, such as 'text/unicode'. Within the onDragStart function, you specify what flavours are available for the item being dragged. To do this, add data and flavours to the transferDataobject, which is the second argument to onDragStart.
这是mozilla技术文档的例子,在 onDragStart 方法里给transferData 元素添加数据。

var textObserver = {
onDragStart: function (event, transferData, action) {
var htmlText = "<strong>Cabbage</strong>";
var plainText = "Cabbage";
transferData.data = new TransferData();
transferData.data.addDataForFlavour("text/html",htmlText);
transferData.data.addDataForFlavour("text/unicode",plainText);
}
}

Here, an observer has been declared and stored in the variable textObserver. It has one property called onDragStart. (In JavaScript, properties can be declared with the syntax name : value). This property is a function which sets the data that is being dragged.
一旦被触发,它会拖拽的数据是“Cabbage”。当然,如果你想得到的是被点击过的元素属性,用我上面说的方法,以event.target取得该DOM节点。
我们在拖拽的时候创建一个传递数据流TransferData 元素,我们在其中添加了两个不同类型的数据,第一个是HTML类型的字符串,第二个是plain类型的字符串。如果用户拖拽的页面能够接受HTML元素的话,那页面会接受HTML类型的元素,文本就会变成粗体。否则会用plain类型的文本来进行替换。
通常你会想提供能够让更多程序接受拖拽的数据,因而你定义的flavours 的次序决定了匹配的优先级。就像上面的情况一样HTML flavour (text/html)优先于text flavour (text/unicode)。
这个例子演示了当拖拽时将节点的label标签的值作为数据而进行传递。

var textObserver = {
onDragStart: function (event) {
var txt = event.target.getAttribute("label");
transferData.data = new TransferData();
transferData.data.addDataForFlavour("text/unicode",txt);
}
}

这个在单元树上进行拖拽是非常有效果的,你可以在某个单元树取值,如果是一个模板建造树那这个值可能会来自RDF文件。假设你储存它是一个字符串,只要是字符串元素的拖拽,它就可以获取到释放过来的数据啦。
如果你想发送更多的数据(例如多选文件),你必须用 TransferDataSet ,如下所写:(但貌似我没测试成功。---chenjian)

var textObserver = {
onDragStart: function (event) {
var txt1 = 'hello';
var txt2 = 'there';
transferData.data = new TransferDataSet();

var tmp = new TransferData();
tmp.addDataForFlavour("text/unicode",txt1);
transferData.data.push(tmp);

new TransferData();
tmp.addDataForFlavour("text/unicode",txt2);
transferData.data.push(tmp);
}
}

//你需要开始拖拽或是接收拖拽元素时候为每一个元素添加监听
You will need to add an observer to each element that can either start a drag action or can accept dropped objects. You can reuse the same observer for multiple elements. For an element that can start a drag, onStartDrag is all that is necessary to implement.
监听器需要实现getSupportedFlavours ,onDragOver 和onDrop这三个方法,那些元素才能够正常拖拽和接受释放,对于这种情况在拖拽元素的界面onStartDrag 方法也是有必要的。
getSupportedFlavours 方法可以传回flavours 的列表,才能够知道哪些类型的元素可以在其区域内进行释放。比如一个文件系统目录显示可以接收文件和文本类型,但他不能接收HTML text。下面的例子我们定义getSupportedFlavours 方法,我们只允许字符串类型的 flavour 。

var textObserver = {
getSupportedFlavours : function () {
var flavours = new FlavourSet();
flavours.appendFlavour("text/unicode");
return flavours;
}
}

在 flavours list 只有一个flavour 'text/unicode'。在FlavourSet 元素中可以加入flavours。在某些情况下你必须提供XPCOM接口,如下个加文件的例子:

var textObserver = {
getSupportedFlavours : function () {
var flavours = new FlavourSet();
flavours.appendFlavour("application/x-moz-file","nsIFile");
flavours.appendFlavour("text/unicode");
return flavours;
}
}

在元素拖拽到区域之内会触发onDragOver 方法。You might use it to change the appearance of the element as it is being dragged over. In many cases the function can do nothing. It must be defined for elements that accept dragged data however.
之后,会触发onDrop 方法。第二个参数transferData是被传进来的数据流,与此同时,某wrapper会查看 getSupportedFlavours 来判断最佳类型flavour, 所以transferData传进来的数据只包含最佳类型选择的那个flavour。
The transfer object has two properties, data which holds the data and flavour which holds the flavour of the data. Once you have the data, you can add it to the element is some way. For example, you might set the value of a textbox.

var textObserver = {
onDrop : function (event, transferData, session) {
event.target.setAttribute("value",transferData.data);
}
}

The flavour system used allows multiple objects of various types to be dragged at once and also allows alternative forms of the data to be dragged. The following table describes some of the flavours you might use. You can also make up your own flavours if necessary.

text/unicode
Text data
text/html
HTML data
text/x-moz-url
A URL
application/x-moz-file
A local file
下面的这些还有待研究。而且是允许自行设置Flavor的。
Flavor
Brief Description
text/unicode
没有格式信息的两字节unicode编码版本,可以发送常用的字符。Two-byte unicode plain text with no formatting information
text/xif
An XML interchange format that includes text and its formatting similar to html
text/html
HTML
text/plain
One-byte plain text, for internal use only.
AOLMAIL
A format used by AOL/AIM for formatted text, similar to HTML
image/png
Binary PNG image data
image/jpg
Binary JPEG image data
image/gif
Binary GIF image data
application/x-moz-file
本地文件。 A file object (supporting nsIFile) for identifying a local file
text/x-moz-url
A url and title for identifying the data is a URL for platforms that care
· chenjian@ceopen.cn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: