diff --git a/src/drag.js b/src/drag.js index 804931d1..2946050c 100644 --- a/src/drag.js +++ b/src/drag.js @@ -38,6 +38,8 @@ var DragonDrop = { html5drag : false, focusWindow : null, + dragging : false, + /** * Performs a series of dragStart, dragEnter, dragOver and drop operations to simulate a dragDrop @@ -88,46 +90,94 @@ var DragonDrop = { _dragStart: function(node){ - var options = { bubbles:false, cancelable:false }; + var options = { bubbles:true, cancelable:true, button: 0, buttons: 1 }; this.createAndDispatchEvent(node, 'dragstart', options); }, _drag: function(node){ - var options = { bubbles:true, cancelable:true }; + var options = { bubbles:true, cancelable:true, button: 0, buttons: 1 }; this.createAndDispatchEvent(node, 'drag', options); }, _dragEnter: function(node){ - var options = { bubbles:true, cancelable:true }; + var options = { bubbles:true, cancelable:true, button: 0, buttons: 0 }; this.createAndDispatchEvent(node, 'dragenter', options); }, _dragOver: function(node){ - var options = { bubbles:true, cancelable:true }; + var options = { bubbles:true, cancelable:true, button: 0, buttons: 0 }; this.createAndDispatchEvent(node, 'dragover', options); }, _dragLeave: function(node){ - var options = { bubbles:true, cancelable:false }; + var options = { bubbles:true, cancelable:false, button: 0, buttons: 0 }; this.createAndDispatchEvent(node, 'dragleave', options); }, _drop: function(node){ - var options = { bubbles:true, cancelable:true, buttons:1 }; + var options = { bubbles:true, cancelable:true, button: 0, buttons: 0 }; this.createAndDispatchEvent(node, 'drop', options); }, _dragEnd: function(node){ - var options = { bubbles:true, cancelable:false }; + var options = { bubbles:true, cancelable:false, button: 0, buttons: 0 }; this.createAndDispatchEvent(node, 'dragend', options); + DragonDrop.dragging = false; }, - _mouseDown: function(node, options){ this.createAndDispatchEvent(node, 'mousedown', options); }, - _mouseMove: function(node, options){ this.createAndDispatchEvent(node, 'mousemove', options); }, - _mouseEnter: function(node, options){ this.createAndDispatchEvent(node, 'mouseenter', options); }, - _mouseOver: function(node, options){ this.createAndDispatchEvent(node, 'mouseover', options); }, - _mouseOut: function(node, options){ this.createAndDispatchEvent(node, 'mouseout', options); }, - _mouseLeave: function(node, options){ this.createAndDispatchEvent(node, 'mouseleave', options); }, + _mouseDown: function(node, options){ + if (!options) { options = {}; } + options.bubbles = true; + options.cancelable = true; + options.button = 0; + options.buttons = 1; + this.createAndDispatchEvent(node, 'mousedown', options); + }, + + _mouseMove: function(node, options){ + if (!options) { options = {}; } + options.bubbles = true; + options.cancelable = true; + options.button = 0; + options.buttons = DragonDrop.dragging ? 1: 0; + this.createAndDispatchEvent(node, 'mousemove', options); + }, + + _mouseEnter: function(node, options){ + if (!options) { options = {}; } + options.bubbles = false; + options.cancelable = false; + options.button = 0; + options.buttons = DragonDrop.dragging ? 1: 0; + this.createAndDispatchEvent(node, 'mouseenter', options); + }, + + _mouseOver: function(node, options){ + if (!options) { options = {}; } + options.bubbles = true; + options.cancelable = true; + options.button = 0; + options.buttons = DragonDrop.dragging ? 1: 0; + this.createAndDispatchEvent(node, 'mouseover', options); + }, + + _mouseOut: function(node, options){ + if (!options) { options = {}; } + options.bubbles = true; + options.cancelable = true; + options.button = 0; + options.buttons = DragonDrop.dragging ? 1: 0; + this.createAndDispatchEvent(node, 'mouseout', options); + }, + + _mouseLeave: function(node, options){ + if (!options) { options = {}; } + options.bubbles = false; + options.cancelable = false; + options.button = 0; + options.buttons = DragonDrop.dragging ? 1: 0; + this.createAndDispatchEvent(node, 'mouseleave', options); + }, /** @@ -374,9 +424,7 @@ syn.create.dragend = { if(syn.support.pointerEvents){syn.trigger(el || win, "pointermove", point);} if(syn.support.touchEvents){syn.trigger(el || win, "touchmove", point);} - - //console.log("DRAGGED: " + DragonDrop.html5drag); - + /* The following code needs some explanation. Firefox and Chrome DO NOT issue mousemove events during HTML5-dragdrops However, they do issue mousemoves during jQuery-dragdrops. I am making the assumption here (which may or may not @@ -389,7 +437,6 @@ syn.create.dragend = { syn.trigger(el || win, "mousemove", point); } - return el; }, @@ -399,9 +446,10 @@ syn.create.dragend = { //creates an event at a certain point. Note: Redundant to DragonDrop.createAndDispatchEvent // TODO: Consolidate this with DragonDrop.createAndDispatchEvent !!! - createEventAtPoint = function (event, point, win) { + createEventAtPoint = function (eventName, point, win) { var el = elementFromPoint(point, win); - syn.trigger(el || win, event, point); + var options = { clientX:point.clientX, clientY:point.clientY }; + syn.trigger(el || win, eventName, options); return el; }, @@ -476,6 +524,7 @@ syn.create.dragend = { if(syn.support.pointerEvents){createEventAtPoint("pointerup", toPoint, win);} if(syn.support.touchEvents){createEventAtPoint("touchend", toPoint, win);} createEventAtPoint("mouseup", toPoint, win); + DragonDrop.dragging = false; if(syn.support.pointerEvents){createEventAtPoint("pointerleave", toPoint, win);} createEventAtPoint("mouseleave", toPoint, win); callback(); @@ -715,6 +764,7 @@ syn.helpers.extend(syn.init.prototype, { } DragonDrop.html5drag = from.draggable; + DragonDrop.dragging = true; if(DragonDrop.html5drag){ DragonDrop.dragAndDrop(win, sourceCoordinates, destinationCoordinates, options.duration || 500, callback); diff --git a/src/mouse.js b/src/mouse.js index 4b8ebb07..9fd07aec 100644 --- a/src/mouse.js +++ b/src/mouse.js @@ -98,6 +98,21 @@ h.extend(syn.create, { //browser might not be loaded yet (doing support code) left = syn.mouse.browser && syn.mouse.browser.left[type], right = syn.mouse.browser && syn.mouse.browser.right[type]; + + + + var leftClick = (type === 'click'); + var doubleLeftClick = (type === 'dblclick'); + var contextMenuClick = (type === 'contextmenu'); + + // NOTE: I don't know if this undefined is correct, but if this is set to anything (including 0), jQuery will fail to dragdrop + // The rules about when buttons = 0 vs buttons = undef, seem very squishy. (Kevin.D) + var buttonsCode = undefined; + if(options.buttons){ buttonsCode = options.buttons; } + else if(leftClick){ buttonsCode = 1; } + else if(doubleLeftClick){ buttonsCode = 1; } + else if(contextMenuClick){ buttonsCode = 2; } + return h.extend({ bubbles: true, cancelable: true, @@ -111,7 +126,13 @@ h.extend(syn.create, { altKey: !! syn.key.altKey, shiftKey: !! syn.key.shiftKey, metaKey: !! syn.key.metaKey, - button: left && left.button !== null ? left.button : right && right.button || (type === 'contextmenu' ? 2 : 0), + button: left && left.button !== null ? left.button : right && right.button || (contextMenuClick ? 2 : 0), + // NOTE: 'buttons' doesn't work because we need to identify the button that is currently held-down vs no-button. + // For example: "button" is 0 regardless of whether left button is down or not. For events like click(), this doesn't matter (since + // we can infer that a button was clicked, and that button was 0.) However, for buttonS, left is 1 and nothing is 0. + // Because FuncUnit doesn't keep track of button state, if you want to set buttonS, you need to set it in options when passing + // the event request to syn.trigger . (Kevin.D) + buttons: buttonsCode, relatedTarget: document.documentElement }, options); }, @@ -137,7 +158,8 @@ h.extend(syn.create, { defaults.clientX, defaults.clientY, defaults.ctrlKey, defaults.altKey, defaults.shiftKey, defaults.metaKey, - defaults.button, defaults.relatedTarget); + defaults.button, defaults.buttons, + defaults.relatedTarget); } catch (e) { event = h.createBasicStandardEvent(type, defaults, doc); } diff --git a/test/mouse_regressions_test.js b/test/mouse_regressions_test.js index b072f8f4..41544f37 100644 --- a/test/mouse_regressions_test.js +++ b/test/mouse_regressions_test.js @@ -3,9 +3,11 @@ var locate = require('test/locate_test'); var QUnit = require("steal-qunit"); QUnit.module("synthetic/mouse/regressions"); +QUnit.module("syn/drag"); var frameHeight = 200; -var frameUrl = 'testpages/regressions_mouse.html'; +var regressionsTestpage = 'testpages/regressions_mouse.html'; +var buttonCodeTestpage = 'testpages/button_number_tests.html'; @@ -34,9 +36,8 @@ QUnit.test("Testing Button codes: left click", 2, function () { }); }); - // TODO: Boilerplate. Can we move this to a setup function? testFrame.height = frameHeight; - testFrame.src = frameUrl; + testFrame.src = regressionsTestpage; }); @@ -64,14 +65,141 @@ QUnit.test("Testing Button codes: right click", 1, function () { }); }); - // TODO: Boilerplate. Can we move this to a setup function? testFrame.height = frameHeight; - testFrame.src = frameUrl; + testFrame.src = regressionsTestpage; }); +QUnit.test("Testing ButtonS codes: left click", 2, function () { + stop(); + + var testFrame = document.getElementById('pageUnderTest'); + + testFrame.addEventListener('load', function loadListener(){ + testFrame.removeEventListener('load', loadListener); + + var pageUnderTest = document.getElementById('pageUnderTest').contentDocument.querySelector('body'); + var clickable = pageUnderTest.querySelector('#clickbutton'); + var buttonNumber = pageUnderTest.querySelector('#buttonNumber'); + var buttonsNumber = pageUnderTest.querySelector('#buttonsNumber'); + + syn.click(clickable, {}, function () { + + var buttonCode = buttonNumber.innerText; + ok( buttonCode == 'Button Number: 0', "Mouse 'button' code expected: '0', received: '" + buttonCode + "'."); + var buttonsCode = buttonsNumber.innerText; + ok( buttonsCode == 'ButtonS Number: 1', "Mouse 'buttons' code expected: '1', received: '" + buttonsCode + "'."); + + start(); + }); + }); + + testFrame.height = 300; + testFrame.src = buttonCodeTestpage; +}); + + + + +QUnit.test("Testing ButtonS codes: right click", 2, function () { + stop(); + + var testFrame = document.getElementById('pageUnderTest'); + + testFrame.addEventListener('load', function loadListener(){ + testFrame.removeEventListener('load', loadListener); + + var pageUnderTest = document.getElementById('pageUnderTest').contentDocument.querySelector('body'); + var clickable = pageUnderTest.querySelector('#clickbutton'); + var buttonNumber = pageUnderTest.querySelector('#buttonNumber'); + var buttonsNumber = pageUnderTest.querySelector('#buttonsNumber'); + + syn.rightClick(clickable, {}, function () { + + var buttonCode = buttonNumber.innerText; + ok( buttonCode == 'Button Number: 2', "Mouse 'button' code expected: '2', received: '" + buttonCode + "'."); + var buttonsCode = buttonsNumber.innerText; + ok( buttonsCode == 'ButtonS Number: 2', "Mouse 'buttons' code expected: '2', received: '" + buttonsCode + "'."); + + start(); + }); + }); + + testFrame.height = 300; + testFrame.src = buttonCodeTestpage; +}); + + + + +QUnit.test("Testing ButtonS codes: double click", 2, function () { + stop(); + + var testFrame = document.getElementById('pageUnderTest'); + + testFrame.addEventListener('load', function loadListener(){ + testFrame.removeEventListener('load', loadListener); + + var pageUnderTest = document.getElementById('pageUnderTest').contentDocument.querySelector('body'); + var clickable = pageUnderTest.querySelector('#clickbutton'); + var buttonNumber = pageUnderTest.querySelector('#buttonNumber'); + var buttonsNumber = pageUnderTest.querySelector('#buttonsNumber'); + + syn.dblclick(clickable, {}, function () { + + var buttonCode = buttonNumber.innerText; + ok( buttonCode == 'Button Number: 0 0', "Mouse 'button' code expected: '0 0', received: '" + buttonCode + "'."); + var buttonsCode = buttonsNumber.innerText; + ok( buttonsCode == 'ButtonS Number: 1 1', "Mouse 'buttons' code expected: '1 1', received: '" + buttonsCode + "'."); + + start(); + }); + }); + + testFrame.height = 300; + testFrame.src = buttonCodeTestpage; +}); + + + + +QUnit.test("Testing ButtonS codes: drag", 2, function () { + stop(); + + var testFrame = document.getElementById('pageUnderTest'); + + testFrame.addEventListener('load', function loadListener(){ + testFrame.removeEventListener('load', loadListener); + + var pageUnderTest = document.getElementById('pageUnderTest').contentDocument.querySelector('body'); + var buttonNumber = pageUnderTest.querySelector('#buttonNumber'); + var buttonsNumber = pageUnderTest.querySelector('#buttonsNumber'); + var draggable = pageUnderTest.querySelector('#drag1'); + var target = pageUnderTest.querySelector('#cell_a2'); + + syn.drag(draggable, {to: target}, function () { + + + var buttonCode = buttonNumber.innerText; + ok( buttonCode == 'Button Number: 0 0 0 0', "Mouse 'button' code expected: '0 0 0 0', received: '" + buttonCode + "'."); + var buttonsCode = buttonsNumber.innerText; + // EXPLANATION: Mousedown and drag are 1, mouseup and leave are 0 + ok( buttonsCode == 'ButtonS Number: 1 1 0 0', "Mouse 'buttons' code expected: '1 1 0 0', received: '" + buttonsCode + "'."); + + start(); + }); + }); + + testFrame.height = 300; + testFrame.src = buttonCodeTestpage; +}); + + + + + function getValue(needle, haystack){ diff --git a/test/testpages/button_number_tests.html b/test/testpages/button_number_tests.html new file mode 100644 index 00000000..e455a382 --- /dev/null +++ b/test/testpages/button_number_tests.html @@ -0,0 +1,159 @@ + + + + + Dragon Drop testing + + + + + + + + + + + + +
+ + + + + +
+
+ + + + + +
+
+ + + + + + + +
+ +
Button Number:
+
ButtonS Number:
+ + + + + + + \ No newline at end of file diff --git a/test/testpages/html5_dragdrop.html b/test/testpages/html5_dragdrop.html index 7d25a191..e578fc2a 100644 --- a/test/testpages/html5_dragdrop.html +++ b/test/testpages/html5_dragdrop.html @@ -11,6 +11,7 @@ function drag(ev) { ev.dataTransfer.setData("text", ev.target.id); + console.log(ev); } function drop(ev) { diff --git a/test/testpages/jquery_dragdrop.html b/test/testpages/jquery_dragdrop.html index 0d7ccbe1..ca8da32f 100644 --- a/test/testpages/jquery_dragdrop.html +++ b/test/testpages/jquery_dragdrop.html @@ -21,7 +21,7 @@ $("#draggable").removeClass("leftOfMark"); } } - +