diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js index bff2e2bb..4e28d9d3 100644 --- a/lib/ace/mouse/default_handlers.js +++ b/lib/ace/mouse/default_handlers.js @@ -86,7 +86,7 @@ function DefaultHandlers(mouseHandler) { if (inSelection && !editor.isFocused()) { editor.focus(); if (this.$focusTimout && !this.$clickSelection && !editor.inMultiSelectMode) { - this.mousedownEvent.time = (new Date()).getTime(); + this.mousedownEvent.time = Date.now(); this.setState("focusWait"); this.captureMouse(ev); return; @@ -98,7 +98,7 @@ function DefaultHandlers(mouseHandler) { // a selection. this.startSelect(pos); } else if (inSelection) { - this.mousedownEvent.time = (new Date()).getTime(); + this.mousedownEvent.time = Date.now(); this.startSelect(pos); } this.captureMouse(ev); @@ -110,15 +110,13 @@ function DefaultHandlers(mouseHandler) { var editor = this.editor; // allow double/triple click handlers to change selection var shiftPressed = this.mousedownEvent.getShiftKey(); - setTimeout(function(){ - if (shiftPressed) { - editor.selection.selectToPosition(pos); - } - else if (!this.$clickSelection) { - editor.moveCursorToPosition(pos); - editor.selection.clearSelection(); - } - }.bind(this), 0); + if (shiftPressed) { + editor.selection.selectToPosition(pos); + } + else if (!this.$clickSelection) { + editor.moveCursorToPosition(pos); + editor.selection.clearSelection(); + } if (editor.renderer.scroller.setCapture) { editor.renderer.scroller.setCapture(); } @@ -193,7 +191,7 @@ function DefaultHandlers(mouseHandler) { this.focusWait = function() { var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); - var time = (new Date()).getTime(); + var time = Date.now(); if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) this.startSelect(this.mousedownEvent.getDocumentPosition()); @@ -210,13 +208,13 @@ function DefaultHandlers(mouseHandler) { range.start.column--; range.end.column++; } - this.$clickSelection = range; this.setState("select"); - return; + } else { + range = editor.selection.getWordRange(pos.row, pos.column); + this.setState("selectByWords"); } - - this.$clickSelection = editor.selection.getWordRange(pos.row, pos.column); - this.setState("selectByWords"); + this.$clickSelection = range; + this[this.state] && this[this.state](ev); }; this.onTripleClick = function(ev) { @@ -225,6 +223,7 @@ function DefaultHandlers(mouseHandler) { this.setState("selectByLines"); this.$clickSelection = editor.selection.getLineRange(pos.row); + this[this.state] && this[this.state](ev); }; this.onQuadClick = function(ev) { diff --git a/lib/ace/mouse/dragdrop_handler.js b/lib/ace/mouse/dragdrop_handler.js index 722dcb6a..3a4bc188 100644 --- a/lib/ace/mouse/dragdrop_handler.js +++ b/lib/ace/mouse/dragdrop_handler.js @@ -193,7 +193,7 @@ function DragdropHandler(mouseHandler) { event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler)); function scrollCursorIntoView(cursor, prevCursor) { - var now = new Date().getTime(); + var now = Date.now(); var vMovement = !prevCursor || cursor.row != prevCursor.row; var hMovement = !prevCursor || cursor.column != prevCursor.column; if (!cursorMovedTime || vMovement || hMovement) { @@ -214,7 +214,7 @@ function DragdropHandler(mouseHandler) { } function autoScroll(cursor, prevCursor) { - var now = new Date().getTime(); + var now = Date.now(); var lineHeight = editor.renderer.layerConfig.lineHeight; var characterWidth = editor.renderer.layerConfig.characterWidth; var editorRect = editor.renderer.scroller.getBoundingClientRect(); @@ -330,7 +330,7 @@ function DragdropHandler(mouseHandler) { (function() { this.dragWait = function() { - var interval = (new Date()).getTime() - this.mousedownEvent.time; + var interval = Date.now() - this.mousedownEvent.time; if (interval > this.editor.getDragDelay()) this.startDrag(); }; @@ -384,7 +384,7 @@ function DragdropHandler(mouseHandler) { var button = e.getButton(); var clickCount = e.domEvent.detail || 1; if (clickCount === 1 && button === 0 && inSelection) { - this.mousedownEvent.time = (new Date()).getTime(); + this.mousedownEvent.time = Date.now(); var eventTarget = e.domEvent.target || e.domEvent.srcElement; if ("unselectable" in eventTarget) eventTarget.unselectable = "on"; diff --git a/lib/ace/mouse/mouse_handler_test.js b/lib/ace/mouse/mouse_handler_test.js new file mode 100644 index 00000000..96374d71 --- /dev/null +++ b/lib/ace/mouse/mouse_handler_test.js @@ -0,0 +1,77 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); + require("../test/mockdom"); +} + +define(function(require, exports, module) { +"use strict"; + +var Editor = require("../editor").Editor; +var MockRenderer = require("../test/mockrenderer").MockRenderer; +var assert = require("../test/assertions"); +var MouseEvent = function(type, opts){ + var e = document.createEvent("MouseEvents"); + e.initMouseEvent("mouse" + type, + true, true, window, + opts.detail, + opts.x, opts.y, opts.x, opts.y, + opts.ctrl, opts.alt, opts.shift, opts.meta, + opts.button || 0, opts.relatedTarget); + return e; +}; + +module.exports = { + + setUp : function(next) { + this.editor = new Editor(new MockRenderer()); + this.editor.setValue("Juhu kinners!") + next(); + }, + + "test: double tap. issue #956" : function() { + // mouse up fired immediately after mouse down + var target = this.editor.renderer.getMouseEventTarget(); + target.dispatchEvent(MouseEvent("down", {x: 1, y: 1})); + target.dispatchEvent(MouseEvent("up", {x: 1, y: 1})); + target.dispatchEvent(MouseEvent("down", {x: 1, y: 1, detail: 2})); + target.dispatchEvent(MouseEvent("up", {x: 1, y: 1, detail: 2})); + + assert.equal(this.editor.getSelectedText(), "Juhu"); + } +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec() +} diff --git a/lib/ace/test/mockrenderer.js b/lib/ace/test/mockrenderer.js index 73992111..ba4c9563 100644 --- a/lib/ace/test/mockrenderer.js +++ b/lib/ace/test/mockrenderer.js @@ -194,6 +194,13 @@ MockRenderer.prototype.textToScreenCoordinates = function() { } }; +MockRenderer.prototype.screenToTextCoordinates = function() { + return { + row: 0, + column: 0 + } +}; + MockRenderer.prototype.adjustWrapLimit = function () { };