diff --git a/core/blockly.js b/core/blockly.js index 782b117a8..14d52d9ea 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -452,26 +452,32 @@ Blockly.bindEventWithChecks_ = function(node, name, thisObject, func, }; var bindData = []; - // Don't register the mouse event if an equivalent pointer event is supported. - if ((window && !window.PointerEvent) || !(name in Blockly.Touch.TOUCH_MAP)) { + var bindData = []; + if (window && window.PointerEvent && + (name in Blockly.Touch.TOUCH_MAP)) { + for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) { + node.addEventListener(type, wrapFunc, false); + bindData.push([node, type, wrapFunc]); + } + } else { node.addEventListener(name, wrapFunc, false); bindData.push([node, name, wrapFunc]); - } - // Add equivalent touch or pointer event. - if (name in Blockly.Touch.TOUCH_MAP) { - var touchWrapFunc = function(e) { - wrapFunc(e); - // Calling preventDefault stops the browser from scrolling/zooming the - // page. - var preventDef = !opt_noPreventDefault; - if (handled && preventDef) { - e.preventDefault(); + // Add equivalent touch event. + if (name in Blockly.Touch.TOUCH_MAP) { + var touchWrapFunc = function(e) { + wrapFunc(e); + // Calling preventDefault stops the browser from scrolling/zooming the + // page. + var preventDef = !opt_noPreventDefault; + if (handled && preventDef) { + e.preventDefault(); + } + }; + for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) { + node.addEventListener(type, touchWrapFunc, false); + bindData.push([node, type, touchWrapFunc]); } - }; - for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) { - node.addEventListener(type, touchWrapFunc, false); - bindData.push([node, type, touchWrapFunc]); } } return bindData; @@ -501,29 +507,35 @@ Blockly.bindEvent_ = function(node, name, thisObject, func) { }; var bindData = []; - // Don't register the mouse event if an equivalent pointer event is supported. - if ((window && !window.PointerEvent) || !(name in Blockly.Touch.TOUCH_MAP)) { + if (window && window.PointerEvent && + (name in Blockly.Touch.TOUCH_MAP)) { + for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) { + node.addEventListener(type, wrapFunc, false); + bindData.push([node, type, wrapFunc]); + } + } else { node.addEventListener(name, wrapFunc, false); bindData.push([node, name, wrapFunc]); - } - // Add equivalent touch or pointer event. - if (name in Blockly.Touch.TOUCH_MAP) { - var touchWrapFunc = function(e) { - // Punt on multitouch events. - if (e.changedTouches && e.changedTouches.length == 1) { - // Map the touch event's properties to the event. - var touchPoint = e.changedTouches[0]; - e.clientX = touchPoint.clientX; - e.clientY = touchPoint.clientY; - } - wrapFunc(e); - // Stop the browser from scrolling/zooming the page. - e.preventDefault(); - }; - for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) { - node.addEventListener(type, touchWrapFunc, false); - bindData.push([node, type, touchWrapFunc]); + // Add equivalent touch event. + if (name in Blockly.Touch.TOUCH_MAP) { + var touchWrapFunc = function(e) { + // Punt on multitouch events. + if (e.changedTouches && e.changedTouches.length == 1) { + // Map the touch event's properties to the event. + var touchPoint = e.changedTouches[0]; + e.clientX = touchPoint.clientX; + e.clientY = touchPoint.clientY; + } + wrapFunc(e); + + // Stop the browser from scrolling/zooming the page. + e.preventDefault(); + }; + for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) { + node.addEventListener(type, touchWrapFunc, false); + bindData.push([node, type, touchWrapFunc]); + } } } return bindData; diff --git a/core/bubble.js b/core/bubble.js index d08edb728..73cfa67a0 100644 --- a/core/bubble.js +++ b/core/bubble.js @@ -345,11 +345,16 @@ Blockly.Bubble.prototype.registerResizeEvent = function(callback) { /** * Move this bubble to the top of the stack. + * @return {!boolean} Whether or not the bubble has been moved. * @private */ Blockly.Bubble.prototype.promote_ = function() { var svgGroup = this.bubbleGroup_.parentNode; - svgGroup.appendChild(this.bubbleGroup_); + if (svgGroup.lastChild !== this.bubbleGroup_) { + svgGroup.appendChild(this.bubbleGroup_); + return true; + } + return false; }; /** diff --git a/core/comment.js b/core/comment.js index 0fa3a4171..f6815a30a 100644 --- a/core/comment.js +++ b/core/comment.js @@ -122,7 +122,7 @@ Blockly.Comment.prototype.createEditor_ = function() { body.appendChild(textarea); this.textarea_ = textarea; this.foreignObject_.appendChild(body); - Blockly.bindEventWithChecks_(textarea, 'mouseup', this, this.textareaFocus_); + Blockly.bindEventWithChecks_(textarea, 'mouseup', this, this.textareaFocus_, true, true); // Don't zoom with mousewheel. Blockly.bindEventWithChecks_(textarea, 'wheel', this, function(e) { e.stopPropagation(); @@ -224,10 +224,11 @@ Blockly.Comment.prototype.textareaFocus_ = function( // Ideally this would be hooked to the focus event for the comment. // However doing so in Firefox swallows the cursor for unknown reasons. // So this is hooked to mouseup instead. No big deal. - this.bubble_.promote_(); - // Since the act of moving this node within the DOM causes a loss of focus, - // we need to reapply the focus. - this.textarea_.focus(); + if (this.bubble_.promote_()) { + // Since the act of moving this node within the DOM causes a loss of focus, + // we need to reapply the focus. + this.textarea_.focus(); + } }; /** diff --git a/core/css.js b/core/css.js index 57c244d3c..ea1c44475 100644 --- a/core/css.js +++ b/core/css.js @@ -386,9 +386,12 @@ Blockly.Css.CONTENT = [ '.blocklyCommentTextarea {', 'background-color: #ffc;', 'border: 0;', + 'outline: 0;', 'margin: 0;', 'padding: 2px;', 'resize: none;', + 'display: block;', + 'overflow: none;', '}', '.blocklyHtmlInput {', diff --git a/core/gesture.js b/core/gesture.js index 91e483808..26e85ada9 100644 --- a/core/gesture.js +++ b/core/gesture.js @@ -498,7 +498,7 @@ Blockly.Gesture.prototype.doStart = function(e) { } if (goog.string.caseInsensitiveEquals(e.type, 'touchstart') || - goog.string.caseInsensitiveEquals(e.type, 'pointerdown')) { + (goog.string.caseInsensitiveEquals(e.type, 'pointerdown') && e.pointerType != 'mouse')) { Blockly.longStart_(e, this); } diff --git a/core/touch.js b/core/touch.js index 78e6f5e72..24a741d43 100644 --- a/core/touch.js +++ b/core/touch.js @@ -51,8 +51,14 @@ Blockly.Touch.TOUCH_MAP = {}; if (window && window.PointerEvent) { Blockly.Touch.TOUCH_MAP = { 'mousedown': ['pointerdown'], + 'mouseenter': ['pointerenter'], + 'mouseleave': ['pointerleave'], 'mousemove': ['pointermove'], - 'mouseup': ['pointerup', 'pointercancel'] + 'mouseout': ['pointerout'], + 'mouseover': ['pointerover'], + 'mouseup': ['pointerup', 'pointercancel'], + 'touchend': ['pointerup'], + 'touchcancel': ['pointercancel'] }; } else if (goog.events.BrowserFeature.TOUCH_ENABLED) { Blockly.Touch.TOUCH_MAP = { diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 492cec80d..901ed4ca2 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -402,7 +402,7 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { if (!this.isFlyout) { Blockly.bindEventWithChecks_(this.svgGroup_, 'mousedown', this, - this.onMouseDown_); + this.onMouseDown_, false, true); if (this.options.zoomOptions && this.options.zoomOptions.wheel) { // Mouse-wheel. Blockly.bindEventWithChecks_(this.svgGroup_, 'wheel', this,