Merge branch 'master' of github.com:openlayers/ol3

This commit is contained in:
Mike Adair
2012-06-22 08:14:42 -04:00
4 changed files with 78 additions and 93 deletions
+9 -7
View File
@@ -12,13 +12,19 @@ goog.require('goog.functions');
/** /**
* @constructor * @constructor
* @param {Element} target The element that will be dragged. * @param {ol.event.Events} target The Events instance that handles events.
* @extends {goog.fx.Dragger} * @extends {goog.fx.Dragger}
* @implements {ol.event.ISequence} * @implements {ol.event.ISequence}
* @export * @export
*/ */
ol.event.Drag = function(target) { ol.event.Drag = function(target) {
goog.base(this, target); goog.base(this, target.getElement());
/**
* @private
* @type {ol.event.Events}
*/
this.target_ = target;
/** /**
* @private * @private
@@ -47,6 +53,7 @@ ol.event.Drag.prototype.dispatchEvent = function(e) {
e.type = ol.event.Drag.EventType.DRAGEND; e.type = ol.event.Drag.EventType.DRAGEND;
} }
} }
this.target_.dispatchEvent(/** @type {Event} */ (e));
return goog.base(this, 'dispatchEvent', e); return goog.base(this, 'dispatchEvent', e);
}; };
@@ -67,11 +74,6 @@ ol.event.Drag.prototype.doDrag = function(e, x, y, dragFromScroll) {
/** @override */ /** @override */
ol.event.Drag.prototype.defaultAction = function(x, y) {}; ol.event.Drag.prototype.defaultAction = function(x, y) {};
/** @inheritDoc */
ol.event.Drag.prototype.getEventTypes = function() {
return ol.event.Drag.EventType;
};
/** @inheritDoc */ /** @inheritDoc */
ol.event.Drag.prototype.destroy = ol.event.Drag.prototype.dispose; ol.event.Drag.prototype.destroy = ol.event.Drag.prototype.dispose;
+36 -52
View File
@@ -47,7 +47,7 @@ ol.event.isMultiTouch = function(evt) {
* @constructor * @constructor
* @extends {goog.events.EventTarget} * @extends {goog.events.EventTarget}
* @param {Object} object The object we are creating this instance for. * @param {Object} object The object we are creating this instance for.
* @param {!EventTarget=} opt_element An optional element that we want to * @param {!Element=} opt_element An optional element that we want to
* listen to browser events on. * listen to browser events on.
* @param {boolean=} opt_includeXY Should the 'xy' property automatically be * @param {boolean=} opt_includeXY Should the 'xy' property automatically be
* created for browser pointer events? In general, this should be false. If * created for browser pointer events? In general, this should be false. If
@@ -71,7 +71,7 @@ ol.event.Events = function(object, opt_element, opt_includeXY, opt_sequences) {
/** /**
* @private * @private
* @type {EventTarget} * @type {Element}
* The element that this instance listens to mouse events on. * The element that this instance listens to mouse events on.
*/ */
this.element_ = null; this.element_ = null;
@@ -115,7 +115,7 @@ ol.event.Events.prototype.setIncludeXY = function(includeXY) {
}; };
/** /**
* @return {EventTarget} The element that this instance currently * @return {Element} The element that this instance currently
* listens to browser events on. * listens to browser events on.
*/ */
ol.event.Events.prototype.getElement = function() { ol.event.Events.prototype.getElement = function() {
@@ -126,18 +126,17 @@ ol.event.Events.prototype.getElement = function() {
* Attach this instance to a DOM element. When called, all browser events fired * Attach this instance to a DOM element. When called, all browser events fired
* on the provided element will be relayed by this instance. * on the provided element will be relayed by this instance.
* *
* @param {EventTarget} element A DOM element to attach * @param {Element} element A DOM element to attach
* browser events to. If called without this argument, all browser events * browser events to. If called without this argument, all browser events
* will be detached from the element they are currently attached to. * will be detached from the element they are currently attached to.
*/ */
ol.event.Events.prototype.setElement = function(element) { ol.event.Events.prototype.setElement = function(element) {
var types, t; var types = goog.events.EventType, t;
if (this.element_) { if (this.element_) {
types = this.getBrowserEventTypes();
for (t in types) { for (t in types) {
// register the event cross-browser // register the event cross-browser
goog.events.unlisten( goog.events.unlisten(
this.element_, types[t], this.handleBrowserEvent, false, this this.element_, types[t], this.dispatchEvent, true, this
); );
} }
this.destroySequences(); this.destroySequences();
@@ -145,25 +144,21 @@ ol.event.Events.prototype.setElement = function(element) {
} }
this.element_ = element || null; this.element_ = element || null;
if (goog.isDefAndNotNull(element)) { if (goog.isDefAndNotNull(element)) {
this.createSequences(element); this.createSequences();
types = this.getBrowserEventTypes();
for (t in types) { for (t in types) {
// register the event cross-browser // register the event cross-browser
goog.events.listen( goog.events.listen(
element, types[t], this.handleBrowserEvent, false, this element, types[t], this.dispatchEvent, true, this
); );
} }
} }
}; };
/** ol.event.Events.prototype.createSequences = function() {
* @param {EventTarget} target
*/
ol.event.Events.prototype.createSequences = function(target) {
for (var i=0, ii=this.sequenceProviders_.length; i<ii; ++i) { for (var i=0, ii=this.sequenceProviders_.length; i<ii; ++i) {
this.sequences_.push( this.sequences_.push(
new ol.event.SEQUENCE_PROVIDER_MAP[this.sequenceProviders_[i]]( new ol.event.SEQUENCE_PROVIDER_MAP[this.sequenceProviders_[i]](
target this
) )
); );
} }
@@ -176,18 +171,6 @@ ol.event.Events.prototype.destroySequences = function() {
this.sequences_ = []; this.sequences_ = [];
}; };
/**
* @return {Object.<string, string>}
*/
ol.event.Events.prototype.getBrowserEventTypes = function() {
var types = {};
goog.object.extend(types, goog.events.EventType);
for (var i=this.sequences_.length-1; i>=0; --i) {
goog.object.extend(types, this.sequences_[i].getEventTypes());
}
return types;
};
/** /**
* Register a listener for an event. * Register a listener for an event.
* *
@@ -257,39 +240,40 @@ ol.event.Events.prototype.triggerEvent = function(type, opt_evt) {
}; };
/** /**
* Basically just a wrapper to the triggerEvent() function, but takes * Basically just a wrapper to the parent's dispatchEvent() function, but takes
* care to set a property 'xy' on the event with the current mouse position. * care to set a property 'xy' on the event with the current mouse position and
* normalize clientX and clientY for multi-touch events.
* *
* @param {Event} evt * @param {Event} evt Event object.
* @return {boolean} If anyone called preventDefault on the event object (or
* if any of the handlers returns false this will also return false.
*/ */
ol.event.Events.prototype.handleBrowserEvent = function(evt) { ol.event.Events.prototype.dispatchEvent = function(evt) {
var type = evt.type, var type = evt.type,
listeners = goog.events.getListeners(this.element_, type, false) listeners = goog.events.getListeners(this.element_, type, false)
.concat(goog.events.getListeners(this.element_, type, true)); .concat(goog.events.getListeners(this.element_, type, true));
if (!listeners || listeners.length === 0) { if (listeners && listeners.length > 0) {
// noone's listening, bail out // noone's listening, bail out
return; // add clientX & clientY to all events - corresponds to average x, y
} var touches = evt.touches;
// add clientX & clientY to all events - corresponds to average x, y if (touches && touches[0]) {
var touches = evt.touches; var x = 0;
if (touches && touches[0]) { var y = 0;
var x = 0; var num = touches.length;
var y = 0; var touch;
var num = touches.length; for (var i=0; i<num; ++i) {
var touch; touch = touches[i];
for (var i=0; i<num; ++i) { x += touch.clientX;
touch = touches[i]; y += touch.clientY;
x += touch.clientX; }
y += touch.clientY; evt.clientX = x / num;
evt.clientY = y / num;
}
if (this.includeXY_) {
evt.xy = goog.style.getRelativePosition(evt, this.element_);
} }
evt.clientX = x / num;
evt.clientY = y / num;
} }
if (this.includeXY_) { return goog.base(this, 'dispatchEvent', evt);
var element = /** @type {!Element} */ this.element_;
evt.xy = goog.style.getRelativePosition(evt, element);
}
this.dispatchEvent(evt);
}; };
/** /**
+10 -8
View File
@@ -1,19 +1,21 @@
goog.provide('ol.event.ISequence'); goog.provide('ol.event.ISequence');
/** /**
* Interface for event sequences * Interface for event sequences. Event sequences map sequences of native
* browser events to high level events that the sequence provides.
*
* Implementations are expected to call dispatchEvent on the {@code target} to
* to fire their high level events.
*
* Implementations can expect the {@code target}'s {@code getElement()} method
* to return an {Element} at construction time.
* *
* @interface * @interface
* @param {Element} target The element that will be listened to for browser * @param {ol.event.Events} target The Events instance that receives the
* events. * sequence's events.
*/ */
ol.event.ISequence = function(target) {}; ol.event.ISequence = function(target) {};
/**
* @return {Object.<string, string>} element
*/
ol.event.ISequence.prototype.getEventTypes = function() {};
/** /**
* Destroys the sequence * Destroys the sequence
*/ */
+23 -26
View File
@@ -123,38 +123,35 @@ describe("ol.event.Events", function() {
events.destroy(); events.destroy();
}); });
it("can be extended with event sequences", function() { it("can be extended with sequences implementing ol.event.ISequence", function() {
var element = document.createElement("div"), var sequence;
events = new ol.event.Events("foo", element, false, ["drag"]), var Sequence = function(target) {
mockEvt; sequence = this;
this.target = target;
};
Sequence.prototype.fire = function() {
this.target.dispatchEvent("myevent");
};
Sequence.prototype.destroy = function() {
this.destroyed = true;
};
ol.event.addSequenceProvider("myseq", Sequence);
var element = document.createElement("div");
events = new ol.event.Events("foo", undefined, false, ["myseq"]);
// mock dom object expect(sequence).toBeUndefined();
goog.object.extend(element, new goog.events.EventTarget());
log = []; log = [];
events.register('dragstart', logFn); events.setElement(element);
events.register('drag', logFn); events.register('myevent', logFn);
events.register('dragend', logFn); sequence.fire();
mockEvt = new goog.events.BrowserEvent({ expect(log.length).toBe(1);
type: "dragstart", button: null expect(log[0].evt.type).toBe("myevent");
});
element.dispatchEvent(mockEvt);
mockEvt = new goog.events.BrowserEvent({
type: "drag", button: null
});
element.dispatchEvent(mockEvt);
mockEvt = new goog.events.BrowserEvent({
type: "dragend", button: null
});
element.dispatchEvent(mockEvt);
expect(log.length).toBe(3);
expect(log[0].evt.type).toBe("dragstart");
expect(log[1].evt.type).toBe("drag");
expect(log[2].evt.type).toBe("dragend");
events.destroy(); events.destroy();
expect(sequence.destroyed).toBe(true);
}); });
it("provides an isSingleTouch() function", function() { it("provides an isSingleTouch() function", function() {