460 lines
14 KiB
JavaScript
460 lines
14 KiB
JavaScript
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
goog.provide('goog.fx.DraggerTest');
|
|
goog.setTestOnly('goog.fx.DraggerTest');
|
|
|
|
goog.require('goog.dom');
|
|
goog.require('goog.events');
|
|
goog.require('goog.events.BrowserEvent');
|
|
goog.require('goog.events.Event');
|
|
goog.require('goog.events.EventType');
|
|
goog.require('goog.fx.Dragger');
|
|
goog.require('goog.math.Rect');
|
|
goog.require('goog.style.bidi');
|
|
goog.require('goog.testing.StrictMock');
|
|
goog.require('goog.testing.events');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.userAgent');
|
|
|
|
var HAS_SET_CAPTURE = goog.fx.Dragger.HAS_SET_CAPTURE_;
|
|
|
|
var target;
|
|
var targetRtl;
|
|
|
|
function setUp() {
|
|
var sandbox = goog.dom.getElement('sandbox');
|
|
target = goog.dom.createDom('div', {
|
|
'id': 'target',
|
|
'style': 'display:none;position:absolute;top:15px;left:10px'
|
|
});
|
|
sandbox.appendChild(target);
|
|
sandbox.appendChild(goog.dom.createDom('div', {'id': 'handle'}));
|
|
|
|
var sandboxRtl = goog.dom.getElement('sandbox_rtl');
|
|
targetRtl = goog.dom.createDom('div', {
|
|
'id': 'target_rtl',
|
|
'style': 'position:absolute; top:15px; right:10px; width:10px; ' +
|
|
'height: 10px; background: green;'
|
|
});
|
|
sandboxRtl.appendChild(targetRtl);
|
|
sandboxRtl.appendChild(goog.dom.createDom('div', {
|
|
'id': 'background_rtl',
|
|
'style': 'width: 10000px;height:50px;position:absolute;color:blue;'
|
|
}));
|
|
sandboxRtl.appendChild(goog.dom.createDom('div', {'id': 'handle_rtl'}));
|
|
}
|
|
|
|
function tearDown() {
|
|
goog.dom.getElement('sandbox').innerHTML = '';
|
|
goog.dom.getElement('sandbox_rtl').innerHTML = '';
|
|
goog.events.removeAll(document);
|
|
}
|
|
|
|
function testStartDrag() {
|
|
runStartDragTest('handle', target);
|
|
}
|
|
|
|
function testStartDrag_rtl() {
|
|
runStartDragTest('handle_rtl', targetRtl);
|
|
}
|
|
|
|
function runStartDragTest(handleId, targetElement) {
|
|
var dragger =
|
|
new goog.fx.Dragger(targetElement, goog.dom.getElement(handleId));
|
|
if (handleId == 'handle_rtl') {
|
|
dragger.enableRightPositioningForRtl(true);
|
|
}
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEDOWN;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(true);
|
|
e.preventDefault();
|
|
e.isMouseActionButton().$returns(true);
|
|
e.preventDefault();
|
|
e.$replay();
|
|
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function() {
|
|
targetElement.style.display = 'block';
|
|
});
|
|
|
|
dragger.startDrag(e);
|
|
|
|
assertTrue('Start drag with no hysteresis must actually start the drag.',
|
|
dragger.isDragging());
|
|
if (handleId == 'handle_rtl') {
|
|
assertEquals(10, goog.style.bidi.getOffsetStart(targetElement));
|
|
}
|
|
assertEquals('Dragger startX must match event\'s clientX.',
|
|
1, dragger.startX);
|
|
assertEquals('Dragger clientX must match event\'s clientX',
|
|
1, dragger.clientX);
|
|
assertEquals('Dragger startY must match event\'s clientY.',
|
|
2, dragger.startY);
|
|
assertEquals('Dragger clientY must match event\'s clientY',
|
|
2, dragger.clientY);
|
|
assertEquals('Dragger deltaX must match target\'s offsetLeft',
|
|
10, dragger.deltaX);
|
|
assertEquals('Dragger deltaY must match target\'s offsetTop',
|
|
15, dragger.deltaY);
|
|
|
|
dragger = new goog.fx.Dragger(targetElement, goog.dom.getElement(handleId));
|
|
dragger.setHysteresis(1);
|
|
dragger.startDrag(e);
|
|
assertFalse('Start drag with a valid non-zero hysteresis should not start ' +
|
|
'the drag.', dragger.isDragging());
|
|
e.$verify();
|
|
}
|
|
|
|
|
|
/**
|
|
* @bug 1381317 Cancelling start drag didn't end the attempt to drag.
|
|
*/
|
|
function testStartDrag_Cancel() {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEDOWN;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(true);
|
|
e.$replay();
|
|
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
|
|
// Cancel drag.
|
|
e.preventDefault();
|
|
});
|
|
|
|
dragger.startDrag(e);
|
|
|
|
assertFalse('Start drag must have been cancelled.',
|
|
dragger.isDragging());
|
|
assertFalse('Dragger must not have registered mousemove handlers.',
|
|
goog.events.hasListener(dragger.document_,
|
|
goog.events.EventType.MOUSEMOVE, !HAS_SET_CAPTURE));
|
|
assertFalse('Dragger must not have registered mouseup handlers.',
|
|
goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
|
|
!HAS_SET_CAPTURE));
|
|
e.$verify();
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests that start drag happens on left mousedown.
|
|
*/
|
|
function testStartDrag_LeftMouseDownOnly() {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEDOWN;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(false);
|
|
e.$replay();
|
|
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
|
|
fail('No drag START event should have been dispatched');
|
|
});
|
|
|
|
dragger.startDrag(e);
|
|
|
|
assertFalse('Start drag must have been cancelled.',
|
|
dragger.isDragging());
|
|
assertFalse('Dragger must not have registered mousemove handlers.',
|
|
goog.events.hasListener(dragger.document_,
|
|
goog.events.EventType.MOUSEMOVE, true));
|
|
assertFalse('Dragger must not have registered mouseup handlers.',
|
|
goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
|
|
true));
|
|
e.$verify();
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests that start drag happens on other event type than MOUSEDOWN.
|
|
*/
|
|
function testStartDrag_MouseMove() {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEMOVE;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.preventDefault();
|
|
e.$replay();
|
|
|
|
var startDragFired = false;
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
|
|
startDragFired = true;
|
|
});
|
|
|
|
dragger.startDrag(e);
|
|
|
|
assertTrue('Dragging should be in progress.', dragger.isDragging());
|
|
assertTrue('Start drag event should have fired.', startDragFired);
|
|
assertTrue('Dragger must have registered mousemove handlers.',
|
|
goog.events.hasListener(dragger.document_,
|
|
goog.events.EventType.MOUSEMOVE, !HAS_SET_CAPTURE));
|
|
assertTrue('Dragger must have registered mouseup handlers.',
|
|
goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
|
|
!HAS_SET_CAPTURE));
|
|
e.$verify();
|
|
}
|
|
|
|
|
|
/**
|
|
* @bug 1381317 Cancelling start drag didn't end the attempt to drag.
|
|
*/
|
|
function testHandleMove_Cancel() {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
dragger.setHysteresis(5);
|
|
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
|
|
// Cancel drag.
|
|
e.preventDefault();
|
|
});
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(true).
|
|
$anyTimes();
|
|
e.preventDefault();
|
|
e.$replay();
|
|
dragger.startDrag(e);
|
|
assertFalse('Start drag must not start drag because of hysterisis.',
|
|
dragger.isDragging());
|
|
assertTrue('Dragger must have registered mousemove handlers.',
|
|
goog.events.hasListener(dragger.document_,
|
|
goog.events.EventType.MOUSEMOVE, !HAS_SET_CAPTURE));
|
|
assertTrue('Dragger must have registered mouseup handlers.',
|
|
goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
|
|
!HAS_SET_CAPTURE));
|
|
|
|
e.clientX = 10;
|
|
e.clientY = 10;
|
|
dragger.handleMove_(e);
|
|
assertFalse('Drag must be cancelled.', dragger.isDragging());
|
|
assertFalse('Dragger must unregistered mousemove handlers.',
|
|
goog.events.hasListener(dragger.document_,
|
|
goog.events.EventType.MOUSEMOVE, true));
|
|
assertFalse('Dragger must unregistered mouseup handlers.',
|
|
goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
|
|
true));
|
|
e.$verify();
|
|
}
|
|
|
|
|
|
/**
|
|
* @bug 1714667 IE<9 built in drag and drop handling stops dragging.
|
|
*/
|
|
function testIeDragStartCancelling() {
|
|
// Testing only IE<9.
|
|
if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(9)) {
|
|
return;
|
|
}
|
|
|
|
// Built in 'dragstart' cancelling not enabled.
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var e = new goog.events.Event(goog.events.EventType.MOUSEDOWN);
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.button = 1; // IE only constant for left button.
|
|
var be = new goog.events.BrowserEvent(e);
|
|
dragger.startDrag(be);
|
|
assertTrue('The drag should have started.', dragger.isDragging());
|
|
|
|
e = new goog.events.Event(goog.events.EventType.DRAGSTART);
|
|
e.target = dragger.document_.documentElement;
|
|
assertTrue('The event should not be canceled.',
|
|
goog.testing.events.fireBrowserEvent(e));
|
|
|
|
dragger.dispose();
|
|
|
|
// Built in 'dragstart' cancelling enabled.
|
|
dragger = new goog.fx.Dragger(target);
|
|
dragger.setCancelIeDragStart(true);
|
|
|
|
e = new goog.events.Event(goog.events.EventType.MOUSEDOWN);
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.button = 1; // IE only constant for left button.
|
|
be = new goog.events.BrowserEvent(e);
|
|
dragger.startDrag(be);
|
|
assertTrue('The drag should have started.', dragger.isDragging());
|
|
|
|
e = new goog.events.Event(goog.events.EventType.DRAGSTART);
|
|
e.target = dragger.document_.documentElement;
|
|
assertFalse('The event should be canceled.',
|
|
goog.testing.events.fireBrowserEvent(e));
|
|
|
|
dragger.dispose();
|
|
}
|
|
|
|
|
|
/** @bug 1680770 */
|
|
function testOnWindowMouseOut() {
|
|
// Test older Gecko browsers - FireFox 2.
|
|
if (goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9a')) {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var dragCanceled = false;
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
|
|
dragCanceled = e.dragCanceled;
|
|
});
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEDOWN;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(true);
|
|
e.preventDefault();
|
|
e.$replay();
|
|
dragger.startDrag(e);
|
|
e.$verify();
|
|
|
|
assertTrue(dragger.isDragging());
|
|
|
|
e = new goog.events.BrowserEvent();
|
|
e.type = goog.events.EventType.MOUSEOUT;
|
|
e.target = goog.dom.getElement('sandbox');
|
|
e.currentTarget = window.top;
|
|
e.relatedTarget = target;
|
|
dragger.onWindowMouseOut_(e);
|
|
|
|
assertFalse('Drag is not canceled for normal in-window mouseout.',
|
|
dragCanceled);
|
|
assertTrue('Must not stop dragging for normal in-window mouseout.',
|
|
dragger.isDragging());
|
|
|
|
dragCanceled = false;
|
|
delete e.relatedTarget;
|
|
e.target = goog.dom.createDom('iframe');
|
|
dragger.onWindowMouseOut_(e);
|
|
assertFalse('Drag is not canceled for mousing into iframe.',
|
|
dragCanceled);
|
|
assertTrue('Must not stop dragging for mousing into iframe.',
|
|
dragger.isDragging());
|
|
|
|
dragCanceled = false;
|
|
e.target = target;
|
|
dragger.onWindowMouseOut_(e);
|
|
assertTrue('Drag is canceled for real mouse out of top window.',
|
|
dragCanceled);
|
|
assertFalse('Must stop dragging for real mouse out of top window.',
|
|
dragger.isDragging());
|
|
}
|
|
}
|
|
|
|
function testLimits() {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
assertEquals(100, dragger.limitX(100));
|
|
assertEquals(100, dragger.limitY(100));
|
|
|
|
dragger.setLimits(new goog.math.Rect(10, 20, 30, 40));
|
|
|
|
assertEquals(10, dragger.limitX(0));
|
|
assertEquals(40, dragger.limitX(100));
|
|
assertEquals(20, dragger.limitY(0));
|
|
assertEquals(60, dragger.limitY(100));
|
|
}
|
|
|
|
function testWindowBlur() {
|
|
if (!goog.fx.Dragger.HAS_SET_CAPTURE_) {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var dragEnded = false;
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
|
|
dragEnded = true;
|
|
});
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEDOWN;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(true);
|
|
e.preventDefault();
|
|
e.$replay();
|
|
dragger.startDrag(e);
|
|
e.$verify();
|
|
|
|
assertTrue(dragger.isDragging());
|
|
|
|
e = new goog.events.BrowserEvent();
|
|
e.type = goog.events.EventType.BLUR;
|
|
e.target = window;
|
|
e.currentTarget = window;
|
|
goog.testing.events.fireBrowserEvent(e);
|
|
|
|
assertTrue(dragEnded);
|
|
}
|
|
}
|
|
|
|
function testBlur() {
|
|
if (!goog.fx.Dragger.HAS_SET_CAPTURE_) {
|
|
var dragger = new goog.fx.Dragger(target);
|
|
|
|
var dragEnded = false;
|
|
goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
|
|
dragEnded = true;
|
|
});
|
|
|
|
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
|
|
e.type = goog.events.EventType.MOUSEDOWN;
|
|
e.clientX = 1;
|
|
e.clientY = 2;
|
|
e.isMouseActionButton().$returns(true);
|
|
e.preventDefault();
|
|
e.$replay();
|
|
dragger.startDrag(e);
|
|
e.$verify();
|
|
|
|
assertTrue(dragger.isDragging());
|
|
|
|
e = new goog.events.BrowserEvent();
|
|
e.type = goog.events.EventType.BLUR;
|
|
e.target = document.body;
|
|
e.currentTarget = document.body;
|
|
// Blur events do not bubble but the test event system does not emulate that
|
|
// part so we add a capturing listener on the target and stops the
|
|
// propagation at the target, preventing any event from bubbling.
|
|
goog.events.listen(document.body, goog.events.EventType.BLUR, function(e) {
|
|
e.propagationStopped_ = true;
|
|
}, true);
|
|
goog.testing.events.fireBrowserEvent(e);
|
|
|
|
assertFalse(dragEnded);
|
|
}
|
|
}
|
|
|
|
function testCloneNode() {
|
|
var element = goog.dom.createDom('div');
|
|
element.innerHTML =
|
|
'<input type="hidden" value="v0">' +
|
|
'<textarea>v1</textarea>' +
|
|
'<textarea>v2</textarea>';
|
|
element.childNodes[0].value = '\'new\'\n"value"';
|
|
element.childNodes[1].value = '<' + '/textarea><3';
|
|
element.childNodes[2].value = '<script>\n\talert("oops!");<' + '/script>';
|
|
var clone = goog.fx.Dragger.cloneNode(element);
|
|
assertEquals(element.childNodes[0].value, clone.childNodes[0].value);
|
|
assertEquals(element.childNodes[1].value, clone.childNodes[1].value);
|
|
assertEquals(element.childNodes[2].value, clone.childNodes[2].value);
|
|
clone = goog.fx.Dragger.cloneNode(element.childNodes[2]);
|
|
assertEquals(element.childNodes[2].value, clone.value);
|
|
}
|