<html>
<head>
<title>Tests for the dragstart event</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<!-- This test checks the dragstart event and the DataTransfer object
-->
<script>
SimpleTest.waitForExplicitFinish();
var gDragInfo; var gDataTransfer = null; var gExtraDragTests = 0;
function runTests()
{
// first, create a selection and try dragging it var draggable = $("draggable");
window.getSelection().selectAllChildren(draggable);
synthesizeMouse(draggable, 6, 6, { type: "mousedown" });
synthesizeMouse(draggable, 14, 14, { type: "mousemove" });
// drags are asynchronous on Linux, so this extra event is needed to make
// sure the drag gets processed
synthesizeMouse(draggable, 15, 15, { type: "mousemove" });
}
function afterDragTests()
{
// the dragstart should have occurred due to moving the mouse. gDataTransfer
// caches the dataTransfer that was used, however it should now be empty and
// be read only.
ok(gDataTransfer instanceof DataTransfer, "DataTransfer after dragstart event");
checkTypes(gDataTransfer, [], 0, "after dragstart event");
expectError(() => gDataTransfer.setData("text/plain", "Some Text"), "NoModificationAllowedError", "setData when read only");
expectError(() => gDataTransfer.clearData("text/plain"), "NoModificationAllowedError", "clearData when read only");
expectError(() => gDataTransfer.addElement(draggable), "NoModificationAllowedError", "addElement when read only");
// next, dragging links and images
sendMouseEventsForDrag("link");
sendMouseEventsForDrag("image");
// disable testing input dragging for now, as it doesn't seem to be testable
// draggable = $("input");
// draggable.setSelectionRange(0, 4);
// synthesizeMouse(draggable, 8, 8, { type: "mousedown" });
// synthesizeMouse(draggable, 15, 15, { type: "mousemove" });
// sendMouseEventsForDrag("input");
// draggable elements inside a shadow root
sendMouseEventsForShadowRootDrag("shadow_host_containing_draggable");
sendMouseEventsForShadowRootDrag("shadow_host_containing_image");
// next, check if the draggable attribute can be used to adjust the drag target
gDragInfo = { target: $("dragtrue"), testid: "draggable true node" };
sendMouseEventsForDrag("dragtrue");
gDragInfo = { target: $("dragtrue"), testid: "draggable true child" };
sendMouseEventsForDrag("spantrue");
var types = dt.types;
ok(Array.isArray(types), "initial types is an Array");
checkTypes(dt, ["text/_moz_htmlcontext", "text/_moz_htmlinfo", "text/html", "text/plain"], 0, "initial selection");
is(dt.getData("text/plain"), "This is a draggable bit of text.", "initial selection text/plain");
is(dt.getData("text/html"), "
draggable\" ondragstart=\"doDragStartSelection(event)\">This is a draggable bit of text.
", "initial selection text/html");
// text/plain and Text are available for compatibility. They retrieve the
// text/plain data. text/unicode is also for compatibility and retreives the plain text.
is(dt.getData("text/plain"), "This is a draggable bit of text.", "initial selection text/plain");
is(dt.getData("Text"), "This is a draggable bit of text.", "initial selection Text");
is(dt.getData("TEXT"), "This is a draggable bit of text.", "initial selection TEXT");
is(dt.getData("text/PLAIN"), "This is a draggable bit of text.", "initial selection text/PLAIN");
is(dt.getData("text/unicode"), "This is a draggable bit of text.", "initial selection text/unicode");
function test_DataTransfer(dt)
{
is(SpecialPowers.wrap(dt).mozItemCount, 0, "empty itemCount");
var types = dt.types;
ok(Array.isArray(types), "empty types is an Array");
// The above test fails if we have SpecialPowers.wrap(dt).types instead of dt.types
// because dt.types will be wrapped and become a proxy.
// So wrap with special powers after the test dt = SpecialPowers.wrap(dt);
checkTypes(dt, [], 0, "empty");
is(dt.getData("text/plain"), "", "empty data is empty");
// calling setDataAt requires an index that is 0 <= index <= dt.itemCount
expectError(() => dt.mozSetDataAt("text/plain", "Some Text", 1), "IndexSizeError", "setDataAt index too high");
is(dt.mozUserCancelled, false, "userCancelled");
// because an exception occurred, the data should not have been added
is(dt.mozItemCount, 0, "empty setDataAt index too high itemCount"); dt.getData("text/plain", "", "empty setDataAt index too high getData");
// if the type is '', do nothing, or return '' dt.setData("", "Invalid Type");
is(dt.types.length, 0, "invalid type setData");
is(dt.getData(""), "", "invalid type getData"); dt.mozSetDataAt("", "Invalid Type", 0);
is(dt.types.length, 0, "invalid type setDataAt");
is(dt.mozGetDataAt("", 0), null, "invalid type getDataAt");
// similar with clearDataAt and getDataAt
expectError(() => dt.mozGetDataAt("text/plain", 1), "IndexSizeError", "getDataAt index too high");
expectError(() => dt.mozClearDataAt("text/plain", 1), "IndexSizeError", "clearDataAt index too high");
// after all those exceptions, the data should still be the same
checkOneDataItem(dt, ["text/plain"], ["Sample Text"], 0, "added plaintext after exception");
// modifying the data associated with the format should give it the new value dt.setData("text/plain", "Modified Text");
is(dt.mozItemCount, 1, "modified plaintext itemCount");
checkOneDataItem(dt, ["text/plain"], ["Modified Text"], 0, "modified plaintext");
// modifying data for a type that already exists should adjust it in place,
// not reinsert it at the beginning dt.setData("text/plain", "New Text");
is(dt.mozItemCount, 1, "modified text again itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],
["New Text", "Modified Text"],
0, "modified text again");
dt.clearData(); // no argument means clear all
is(dt.mozItemCount, 0, "itemCount after clearData no argument");
checkTypes(dt, [], 0, "empty after clearData no argument");
// check 'Text' type which should convert into text/plain dt.setData("Text", "Sample Text");
checkOneDataItem(dt, ["text/plain"], ["Sample Text"], 0, "set Text");
is(dt.getData("Text"), "Sample Text", "getData Text");
is(dt.mozGetDataAt("Text", 0), "Sample Text", "getDataAt Text"); dt.setData("text/plain", "More Text");
checkOneDataItem(dt, ["text/plain"], ["More Text"], 0, "set text/plain after set Text");
dt.mozClearDataAt("", 0); // null means clear all
is(dt.mozItemCount, 0, "itemCount after clearDataAt empty string");
checkTypes(dt, [], 0, "empty after clearDataAt empty string");
// now test adding multiple items to be dragged using the setDataAt method dt.clearData(); dt.mozSetDataAt("text/plain", "First Item", 0); dt.mozSetDataAt("text/plain", "Second Item", 1);
expectError(() => dt.mozSetDataAt("text/plain", "Some Text", 3), "IndexSizeError", "setDataAt index too high with two items");
is(dt.mozItemCount, 2, "setDataAt item itemCount");
checkOneDataItem(dt, ["text/plain"], ["First Item"], 0, "setDataAt item at index 0");
checkOneDataItem(dt, ["text/plain"], ["Second Item"], 1, "setDataAt item at index 1");
dt.mozSetDataAt("text/html", "First Item", 0); dt.mozSetDataAt("text/html", "Second Item", 1);
is(dt.mozItemCount, 2, "setDataAt two types item itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "First Item"], 0, "setDataAt two types item at index 0");
checkOneDataItem(dt, ["text/plain", "text/html"],
["Second Item", "Second Item"], 1, "setDataAt two types item at index 1");
dt.mozSetDataAt("text/html", "Changed First Item", 0); dt.mozSetDataAt("text/plain", "Changed Second Item", 1);
is(dt.mozItemCount, 2, "changed with setDataAt item itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed First Item"], 0, "changed with setDataAt item at index 0");
checkOneDataItem(dt, ["text/plain", "text/html"],
["Changed Second Item", "Second Item"], 1, "changed with setDataAt item at index 1");
dt.setData("text/html", "Changed with setData");
is(dt.mozItemCount, 2, "changed with setData");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed with setData"], 0, "changed with setData item at index 0");
checkOneDataItem(dt, ["text/plain", "text/html"],
["Changed Second Item", "Second Item"], 1, "changed with setData item at index 1");
dt.mozSetDataAt("application/-moz-node", "draggable", 2);
is(dt.mozItemCount, 3, "setDataAt node itemCount");
checkOneDataItem(dt, ["application/-moz-node"], ["draggable"], 2, "setDataAt node item at index 2");
// Try to add and then remove a non-string type to the DataTransfer and ensure
// that the type appears in DataTransfer.types.
{ dt.mozSetDataAt("application/-x-body", document.body, 0);
let found = false;
for (let i = 0; i < dt.types.length; ++i) {
if (dt.types[i] == "application/-x-body") {
found = true;
break;
}
}
ok(found, "Data should appear in datatransfer.types despite having a non-string type"); dt.mozClearDataAt("application/-x-body", 0);
}
dt.mozClearDataAt("text/html", 1);
is(dt.mozItemCount, 3, "clearDataAt itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed with setData"], 0, "clearDataAt item at index 0");
checkOneDataItem(dt, ["text/plain"], ["Changed Second Item"], 1, "clearDataAt item at index 1");
dt.mozClearDataAt("text/plain", 1);
is(dt.mozItemCount, 2, "clearDataAt last type itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed with setData"], 0, "clearDataAt last type at index 0");
checkOneDataItem(dt, ["application/-moz-node"], ["draggable"], 1, "clearDataAt last type item at index 2");
expectError(() => dt.mozGetDataAt("text/plain", 2), "IndexSizeError", "getDataAt after item removed index too high");
dt.mozSetDataAt("text/unknown", "Unknown type", 2); dt.mozSetDataAt("text/unknown", "Unknown type", 1);
is(dt.mozItemCount, 3, "add unknown type");
checkOneDataItem(dt, ["application/-moz-node", "text/unknown"],
["draggable", "Unknown type"], 1, "add unknown type item at index 1");
checkOneDataItem(dt, ["text/unknown"], ["Unknown type"], 2, "add unknown type item at index 2");
dt.mozClearDataAt("", 1);
is(dt.mozItemCount, 2, "clearDataAt empty string");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed with setData"], 0, "clearDataAt empty string item at index 0");
checkOneDataItem(dt, ["text/unknown"],
["Unknown type"], 1, "clearDataAt empty string item at index 1");
// passing a format that doesn't exist to clearData or clearDataAt should just
// do nothing dt.clearData("text/something"); dt.mozClearDataAt("text/something", 1);
is(dt.mozItemCount, 2, "clearData type that does not exist");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed with setData"], 0, "clearData type that does not exist item at index 0");
checkOneDataItem(dt, ["text/unknown"],
["Unknown type"], 1, "clearData type that does not exist item at index 1");
expectError(() => dt.mozClearDataAt("text/plain", 3), "IndexSizeError", "clearData index too high with two items");
// ensure that clearData() removes all data associated with the first item, but doesn't
// shift the second item down into the first item's slot. dt.clearData();
is(dt.mozItemCount, 2, "clearData no argument with multiple items itemCount");
checkOneDataItem(dt, [], [], 0, "clearData no argument with multiple items item at index 0");
checkOneDataItem(dt, ["text/unknown"],
["Unknown type"], 1, "clearData no argument with multiple items item at index 1");
// remove tha remaining data in index 1. As index 0 is empty at this point, this will actually
// drop mozItemCount to 0. (XXX: This is because of spec-compliance reasons related
// to the more-recent dt.item API. It's an unfortunate, but hopefully rare edge case) dt.mozClearDataAt("", 1);
is(dt.mozItemCount, 0, "all data cleared");
// now check the effectAllowed and dropEffect properties
is(dt.dropEffect, "none", "initial dropEffect");
is(dt.effectAllowed, "uninitialized", "initial effectAllowed");
["copy", "none", "link", "", "other", "copyMove", "all", "uninitialized", "move"].forEach(
function (i) { dt.dropEffect = i;
is(dt.dropEffect, i == "" || i == "other" || i == "copyMove" ||
i == "all" || i == "uninitialized" ? "link" : i, "dropEffect set to " + i);
is(dt.effectAllowed, "uninitialized", "effectAllowed not modified by dropEffect set to " + i);
}
);
["move", "copy", "link", "", "other", "moveCopy", "copyMove", "linkMove", "copyLink", "all", "uninitialized", "none"].forEach(
function (i) { dt.effectAllowed = i;
is(dt.dropEffect, "move", "dropEffect not modified by effectAllowed set to " + i);
is(dt.effectAllowed, i == "" || i == "other" || i == "moveCopy" ? "link" : i, "effectAllowed set to " + i);
}
);
}
function doDragStartShadowRootImage(event)
{ vardt = event.dataTransfer;
checkTypes(dt, ["text/x-moz-url", "text/x-moz-url-data", "text/x-moz-url-desc", "text/uri-list", "text/_moz_htmlcontext", "text/_moz_htmlinfo", "text/html", "text/plain"], 0, "shadow root link with image");
is(dt.getData("text/uri-list"), "http://example.org/", "shadow root link text/uri-list");
is(dt.getData("text/plain"), "http://example.org/", "shadow root link text/plain");
event.preventDefault();
gExtraDragTests++;
}
function doDragStartSynthetic(event)
{
is(event.type, "dragstart", "synthetic dragstart event type");
vardt = event.dataTransfer;
todo(dt instanceof DataTransfer, "synthetic dragstart dataTransfer is DataTransfer");
// Uncomment next line once the todo instanceof above is fixed.
// checkTypes(dt, [], 0, "synthetic dragstart");
// Uncomment next two lines once the todo instanceof above is fixed.
// dt.setData("text/plain", "Text");
// is(dt.getData("text/plain"), "Text", "synthetic dragstart data is set after adding");
}
function doDragOverSynthetic(event)
{
is(event.type, "dragover", "synthetic dragover event type");
vardt = event.dataTransfer;
todo(dt instanceof DataTransfer, "synthetic dragover dataTransfer is DataTransfer");
// Uncomment next line once the todo instanceof above is fixed.
// checkTypes(dt, [], 0, "synthetic dragover");
// Uncomment next two lines once the todo instanceof above is fixed.
// dt.setData("text/plain", "Text");
// is(dt.getData("text/plain"), "Text", "synthetic dragover data is set after adding");
}
<input id="input" value="Text in a box" ondragstart="doDragStartInput(event)">
<div ondragstart="onDragStartDraggable(event)">
<div id="dragtrue" draggable="true">
This is a <span id="spantrue">draggable</span> area.
</div>
<div id="dragfalse" draggable="false">
This is a <span id="spanfalse">non-draggable</span> area.
</div>
</div>
<a href="http://example.org" id="link_user_select_none_child" draggable="false" ondragstart="onDragOverDraggableFalse(event)">
<span id="userselectnone"style="user-select: none">
This is an unselectable, undraggable area.
</span>
</a>
<div id="draggable_with_undraggable_descendant" draggable="true" ondragstart="onDragStartDraggable(event)">
<a id="undraggable_inside_draggable" href="http://example.org" draggable="false" ondragstart="onDragOverDraggableFalse(event)">
This is an undraggable link inside a draggable ancestor.
</a>
</div>
<a id="link_to_file" href="file:///" ondragstart="onDragStartUnlinkable(event)">This is an undraggable 'file'link</a>
<a id="link_to_windows_file" href="c:/Users/" ondragstart="onDragStartUnlinkable(event)">This is an undraggable 'file'link</a>
<a id="link_to_backslash_windows_file" href="c:\\Users\\" ondragstart="onDragStartUnlinkable(event)">This is an undraggable 'file'link</a>
<img id="broken_file_image" src="file:///" ondragstart="onDragStartUnlinkable(event)">
<img id="broken_windows_file_image" src="c:/Users/" ondragstart="onDragStartUnlinkable(event)">
<img id="broken_backslash_windows_file_image" src="c:\\Users\\" ondragstart="onDragStartUnlinkable(event)">
</body>
</html>
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.53Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.