blob: 8a571031bd4b6c3cb1b5495c4d8bc3e590ce3342 [file]
// Copyright 2014 The Cloud Input Tools 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.
/**
* @fileoverview Drag Utilities allow target and handle cross iframe.
*/
goog.provide('i18n.input.common.Dragger');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.events.Event');
goog.require('goog.events.EventType');
goog.require('goog.fx.Dragger');
goog.require('goog.userAgent');
/**
* Inherits from goog.fx.Dragger. It allow target and handle element cross
* different iframe.
*
* @param {Element} target The element that will be dragged.
* @param {Element=} opt_handle An optional handle to control the drag, if null
* the target is used.
* @param {goog.math.Rect=} opt_limits Object containing left, top, width,
* and height.
*
* @extends {goog.fx.Dragger}
* @constructor
* @suppress {visibility}
*/
i18n.input.common.Dragger = function(target, opt_handle, opt_limits) {
goog.base(this, target, opt_handle, opt_limits);
// Not allow target and handle cross multiple iframe layers.
if (opt_handle && this.document_ != goog.dom.getOwnerDocument(opt_handle)) {
var win = goog.dom.getWindow(goog.dom.getOwnerDocument(opt_handle));
goog.asserts.assert(goog.dom.getWindow(this.document_) == win.parent);
/**
* The iframe container element.
*
* @type {Element}
* @private
*/
this.frameElement_ = win.frameElement;
}
};
goog.inherits(i18n.input.common.Dragger, goog.fx.Dragger);
/** @override */
i18n.input.common.Dragger.prototype.startDrag = function(e) {
this.fixClientPositon_(e);
goog.base(this, 'startDrag', e);
};
/**
* @override
* @suppress {visibility}
*/
i18n.input.common.Dragger.prototype.setupDragHandlers = function() {
this.setupDragHandlersOnDocument_(this.document_);
var doc = goog.dom.getOwnerDocument(this.handle);
// If target and handle in different documents, need to set up handlers on
// the additional document.
if (doc != this.document_) {
this.setupDragHandlersOnDocument_(doc);
}
if (this.scrollTarget_) {
this.eventHandler_.listen(this.scrollTarget_, goog.events.EventType.SCROLL,
this.onScroll_, !goog.fx.Dragger.HAS_SET_CAPTURE_);
}
};
/**
* Sets up event handlers on given document.
*
* @param {Document} doc The document to set up handlers.
* @suppress {visibility}
* @private
*/
i18n.input.common.Dragger.prototype.setupDragHandlersOnDocument_ =
function(doc) {
var docEl = doc.documentElement;
// Use bubbling when we have setCapture since we got reports that IE has
// problems with the capturing events in combination with setCapture.
var useCapture = !goog.fx.Dragger.HAS_SET_CAPTURE_;
this.eventHandler_.listen(doc,
[goog.events.EventType.TOUCHMOVE, goog.events.EventType.MOUSEMOVE],
this.handleMoveOverride_, useCapture);
this.eventHandler_.listen(doc,
[goog.events.EventType.TOUCHEND, goog.events.EventType.MOUSEUP],
this.endDrag, useCapture);
if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
docEl.setCapture(false);
this.eventHandler_.listen(docEl,
goog.events.EventType.LOSECAPTURE,
this.endDrag);
} else {
// Make sure we stop the dragging if the window loses focus.
// Don't use capture in this listener because we only want to end the drag
// if the actual window loses focus. Since blur events do not bubble we use
// a bubbling listener on the window.
this.eventHandler_.listen(goog.dom.getWindow(doc),
goog.events.EventType.BLUR,
this.endDrag);
}
if (goog.userAgent.IE && this.ieDragStartCancellingOn_) {
// Cancel IE's 'ondragstart' event.
this.eventHandler_.listen(doc, goog.events.EventType.DRAGSTART,
goog.events.Event.preventDefault);
}
};
/**
* Event handler that is used on mouse / touch move to update the drag. Have to
* change original name 'handleMove_' to 'handleMoveOverride_'. Without
* '@override' annotation will cause a compliant error. However, with the
* annotation will cause a lint error which not allow override a private
* member.
*
* @param {goog.events.BrowserEvent} e Event object.
* @suppress {visibility}
* @private
*/
i18n.input.common.Dragger.prototype.handleMoveOverride_ = function(e) {
this.fixClientPositon_(e);
this.handleMove_(e);
};
/**
* Fixes the event clientX/Y relative to the target element document.
*
* @param {goog.events.BrowserEvent} e The event.
* @suppress {visibility}
* @private
*/
i18n.input.common.Dragger.prototype.fixClientPositon_ = function(e) {
if (goog.dom.getOwnerDocument(e.target) != this.document_ &&
this.frameElement_) {
e.clientX += this.frameElement_.offsetLeft;
e.clientY += this.frameElement_.offsetTop;
}
};