See the class list to the right and especially take a look at ol.Map and ol.layer.Layer because those are the central objects.
+
+
In general every use of OpenLayers starts by initializing a map, then adding the required layers. Controls and interactions can be added to change the behavior of the map.
+
+
Projections
+
+
A ol.Projection defines which point on earth is represented by a pair of coordinates.
+Coordinates within OpenLayers can be used in various projections where some common projections are always supported,
+others can be used via Proj4js.
+
+
Maps and Layers
+
+
A map in OpenLayers is essentially a staple of layers that is viewed from the top. Layers are responsible for retieving data and displaying it.
+
+
Contributing
+
+
See CONTRIBUTING.md for instructions
+on building and tesing OpenLayers. The file does also describe how to commit your changes to OpenLayers.
Get a reference to the underlying Array object. Warning: if the array
+is mutated, no events will be dispatched by the collection, and the
+collection's "length" property won't be in sync with the actual length
+of the array.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
collection.js, line 129
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Array.
+
+
+
+
+
+
+ Type
+
+
+
+Array
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getAt
+
+
+
+
+
+
+
+
Get the element at the provided index.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
index
+
+
+
+
+
+number
+
+
+
+
+
+
+
+
+
+
Index.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
collection.js, line 139
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Element.
+
+
+
+
+
+
+ Type
+
+
+
+*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getLength
+
+
+
+
+
+
+
+
Get the length of this collection.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
collection.js, line 148
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Length.
+
+
+
+
+
+
+ Type
+
+
+
+number
+
+
+
+
+
+
+
+
+
+
+
+
+
+
insertAt
+
+
+
+
+
+
+
+
Insert an element at the provided index.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
index
+
+
+
+
+
+number
+
+
+
+
+
+
+
+
+
+
Index.
+
+
+
+
+
+
+
elem
+
+
+
+
+
+*
+
+
+
+
+
+
+
+
+
+
Element.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
collection.js, line 158
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
notify
+
+
+
+
+
+
+
+
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
The ol.DeviceOrientation class provides access to DeviceOrientation
+information and events, see the [HTML 5 DeviceOrientation Specification](
+http://dev.w3.org/geo/api/spec-source-orientation) for more details.
+
+
Many new computers, and especially mobile phones
+and tablets, provide hardware support for device orientation. Web
+developers targetting mobile devices will be especially interested in this
+class.
+
+
Device orientation data are relative to a common starting point. For mobile
+devices, the starting point is to lay your phone face up on a table with the
+top of the phone pointing north. This represents the zero state. All
+angles are then relative to this state. For computers, it is the same except
+the screen is open at 90 degrees.
+
+
Device orientation is reported as three angles - alpha, beta, and
+gamma - relative to the starting position along the three planar axes X, Y
+and Z. The X axis runs from the left edge to the right edge through the
+middle of the device. Similarly, the Y axis runs from the bottom to the top
+of the device through the middle. The Z axis runs from the back to the front
+through the middle. In the starting position, the X axis points to the
+right, the Y axis points away from you and the Z axis points straight up
+from the device lying flat.
+
+
The three angles representing the device orientation are relative to the
+three axes. alpha indicates how much the device has been rotated around the
+Z axis, which is commonly interpreted as the compass heading (see note
+below). beta indicates how much the device has been rotated around the X
+axis, or how much it is tilted from front to back. gamma indicates how
+much the device has been rotated around the Y axis, or how much it is tilted
+from left to right.
+
+
For most browsers, the alpha value returns the compass heading so if the
+device points north, it will be 0. With Safari on iOS, the 0 value of
+alpha is calculated from when device orientation was first requested.
+ol.DeviceOrientation provides the heading property which normalizes this
+behavior across all browsers for you.
+
+
It is important to note that the HTML 5 DeviceOrientation specification
+indicates that alpha, beta and gamma are in degrees while the
+equivalent properties in ol.DeviceOrientation are in radians for consistency
+with all other uses of angles throughout OpenLayers.
The alpha value of the DeviceOrientation,
+in radians.
+
+
+
+
+
+
+ Type
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getBeta
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
deviceorientation.js, line 161
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
The beta value of the DeviceOrientation,
+in radians.
+
+
+
+
+
+
+ Type
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getGamma
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
deviceorientation.js, line 175
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
The gamma value of the DeviceOrientation,
+in radians.
+
+
+
+
+
+
+ Type
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getHeading
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
deviceorientation.js, line 189
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
The heading of the device relative to
+north, in radians, normalizing for different browser behavior.
+
+
+
+
+
+
+ Type
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getTracking
+
+
+
+
+
+
+
+
Are we tracking the device's orientation?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
deviceorientation.js, line 203
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
The current tracking state, true if tracking is on.
+
+
+
+
+
+
+ Type
+
+
+
+boolean
+
+
+
+
+
+
+
+
+
+
+
+
+
+
notify
+
+
+
+
+
+
+
+
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Helper class for providing HTML5 Geolocation capabilities.
+The Geolocation API
+is used to locate a user's position.
+
+
Example:
+
+
var geolocation = new ol.Geolocation();
+// take the projection to use from the map's view
+geolocation.bindTo('projection', map.getView());
+// listen to changes in position
+geolocation.on('change:position', function(evt) {
+ window.console.log(geolocation.getPosition());
+});
+
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
- The map's overlay container. Elements added to this
-container won't let mousedown and touchstart events through to the map, so
-clicks and gestures on an overlay don't trigger any MapBrowserEvent.
-
-
-
-
-
-
-
-
@@ -2133,28 +532,6 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
-
Returns:
-
-
-
- Container.
-
-
-
-
-
-
- Type
-
-
-
-Element
-
-
-
-
-
-
@@ -2162,13 +539,19 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
-
getTilePriority
+
beforeRender
+
+
Add functions to be called before rendering. This can be used for attaching
+animations before updating the map's view. The ol.animation
+namespace provides several static methods for creating prerender functions.
+
+
@@ -2200,13 +583,13 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
-
tile
+
var_args
-ol.Tile
+ol.PreRenderFunction
@@ -2216,53 +599,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
-
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
key
+
+
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
Key.
@@ -3058,6 +2108,563 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
+
+
+
+
+
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
key
+
+
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
Key.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 208
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
on
+
+
+
+
+
+
+
+
Listen for a certain type of event.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
Argument
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
type
+
+
+
+
+
+string
+|
+
+Array.<string>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The event type or array of event types.
+
+
+
+
+
+
+
listener
+
+
+
+
+
+Function
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The listener function.
+
+
+
+
+
+
+
scope
+
+
+
+
+
+Object
+
+
+
+
+
+
+
+
+ <optional>
+
+
+
+
+
+
+
+
+
(Optional)
Object is whose scope to call
+ the listener.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 240
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Unique key for the listener.
+
+
+
+
+
+
+ Type
+
+
+
+goog.events.Key
+
+
+
+
+
+
+
+
+
+
+
+
+
+
once
+
+
+
+
+
+
+
+
Listen once for a certain type of event.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
Argument
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
type
+
+
+
+
+
+string
+|
+
+Array.<string>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The event type or array of event types.
+
+
+
+
+
+
+
listener
+
+
+
+
+
+Function
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The listener function.
+
+
+
+
+
+
+
scope
+
+
+
+
+
+Object
+
+
+
+
+
+
+
+
+ <optional>
+
+
+
+
+
+
+
+
+
(Optional)
Object is whose scope to call
+ the listener.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 253
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Unique key for the listener.
+
+
+
+
+
+
+ Type
+
+
+
+goog.events.Key
+
+
+
+
+
+
+
+
+
+
+
+
+
+
set
+
+
+
+
+
+
+
+
Sets a value.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
key
+
+
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
Key.
+
+
+
+
+
+
+
value
+
+
+
+
+
+*
+
+
+
+
+
+
+
+
+
+
Value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 263
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
setValues
+
+
+
+
+
+
+
+
Sets a collection of key-value pairs.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
values
+
+
+
+
+
+Object.<string, *>
+
+
+
+
+
+
+
+
+
+
Values.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 286
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
un
+
+
+
+
+
+
+
+
Unlisten for a certain type of event.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
Argument
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
type
+
+
+
+
+
+string
+|
+
+Array.<string>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The event type or array of event types.
+
+
+
+
+
+
+
listener
+
+
+
+
+
+Function
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The listener function.
+
+
+
+
+
+
+
scope
+
+
+
+
+
+Object
+
+
+
+
+
+
+
+
+ <optional>
+
+
+
+
+
+
+
+
+
(Optional)
Object is whose scope to call
+ the listener.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 326
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
unbind
+
+
+
+
+
+
+
+
Removes a binding. Unbinding will set the unbound property to the current
+ value. The object will not be notified, as the value has not changed.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
key
+
+
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
Key.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 305
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
unbindAll
+
+
+
+
+
+
+
+
Removes all bindings.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
object.js, line 344
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
unByKey
+
+
+
+
+
+
+
+
Removes an event listener which was added with listen() by the key returned
+ by on().
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Get the resolution of the point in degrees. For projections with degrees as
+the unit this will simply return the provided resolution. For other
+projections the point resolution is estimated by transforming the center
+pixel to EPSG:4326, measuring its width and height on the normal sphere,
+and taking the average of the width and height.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
proj.js, line 129
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Methods
+
+
+
+
+
getAxisOrientation
+
+
+
+
+
+
+
+
Get the axis orientation of this projection.
+Example values are:
+enu - the default easting, northing, elevation.
+neu - northing, easting, up - useful for "lat/long" geographic coordinates,
+ or south orientated transverse mercator.
+wnu - westing, northing, up - some planetary coordinate systems have
+ "west positive" coordinate systems
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
proj.js, line 161
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Axis orientation.
+
+
+
+
+
+
+ Type
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getCode
+
+
+
+
+
+
+
+
Get the code for this projection, e.g. 'EPSG:4326'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
proj.js, line 105
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Code.
+
+
+
+
+
+
+ Type
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getExtent
+
+
+
+
+
+
+
+
Get the validity extent for this projection.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Source:
+
proj.js, line 114
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns:
+
+
+
+
Extent.
+
+
+
+
+
+
+ Type
+
+
+
+ol.Extent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getMetersPerUnit
+
+
+
+
+
+
+
+
Get the amount of meters per unit of this projection. If the projection is
+not configured with a units identifier, the return is undefined.
An ol.View2D object represents a simple 2D view of the map.
+
+
This is the object to act upon to change the center, resolution,
+and rotation of the map.
+
+
The view states
+
+
An ol.View2D is determined by three states: center, resolution,
+and rotation. To each state corresponds a getter and a setter. E.g.
+getCenter and setCenter for the center state.
+
+
An ol.View2D has a projection. The projection determines the
+coordinate system of the center, and its units determine the units of the
+resolution (projection units per pixel). The default projection is
+Spherical Mercator (EPSG:3857).
+
+
The constraints
+
+
setCenter, setResolution and setRotation can be used to change the
+states of the view. Any value can be passed to the setters. And the value
+that is passed to a setter will effectively be the value set in the view,
+and returned by the corresponding getter.
+
+
But an ol.View2D object also has a resolution constraint and a
+rotation constraint. There's currently no center constraint, but
+this may change in the future.
+
+
As said above no constraints are applied when the setters are used to set
+new states for the view. Applying constraints is done explicitly through
+the use of the constrain* functions (constrainResolution and
+constrainRotation).
+
+
The main users of the constraints are the interactions and the
+controls. For example, double-clicking on the map changes the view to
+the "next" resolution. And releasing the fingers after pinch-zooming
+snaps to the closest resolution (with an animation).
+
+
So the resolution constraint snaps to specific resolutions. It is
+determined by the following options: resolutions, maxResolution,
+maxZoom, and zoomFactor. If resolutions is set, the other three
+options are ignored. See ol.View2DOptions for more information.
+
+
The rotation constaint is currently not configurable. It snaps the
+rotation value to zero when approaching the horizontal.
Create a new attribution control to show all the attributions associated
+with the layer sources in the map. A default map has this control included.
+By default it will show in the bottom right portion of the map, but it can
+be changed by using a css selector for .ol-attribution.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Provides a button that when clicked fills up the full screen with the map.
+When in full screen mode, a close button is shown to exit full screen mode.
+The Fullscreen API is used to
+toggle the map in full screen mode.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Shows a logo for all the layer sources in the map that have a logo
+associated with them, such as Bing. This control is part of a default map.
+By default it will show in the bottom-left portion of the map, but it can
+be styled by using a css selector for .ol-logo.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Create a new control to show the position of the mouse in the map's
+projection (or any other supplied projection). By default the control is
+shown in the top right corner of the map but this can be changed by using
+a css selector .ol-mouse-position.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Create a new control with 2 buttons, one for zoom in and one for zoom out.
+This control is part of the default controls of a map. To style this control
+use css selectors .ol-zoom-in and .ol-zoom-out.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Create a control that adds a button, which, when pressed, changes
+the map view to a specific extent. To style this control use the
+css selector .ol-zoom-extent.
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
Remove the control from its current map and attach it to the new map.
+Subclasses may set up event handlers to get notified about changes to
+the map here.
Helper class for binding HTML input to an ol.Object
+
+
Example:
+
+
// bind a checkbox with id 'visible' to a layer's visibility
+var visible = new ol.dom.Input(document.getElementById('visible'));
+visible.bindTo('checked', layer, 'visible');
+
Notify all observers of a change on this property. This notifies both
+objects that are bound to the object's property as well as the object
+that it is bound to.
+
+
@@ -1512,7 +875,7 @@
-
Key.
+
Key.
@@ -1570,217 +933,7 @@
-
pop
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Source:
-
collection.js, line 146
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
-
- Element.
-
-
-
-
-
-
- Type
-
-
-
-*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
push
-
-
-
-
-
-
-
-
-
-
-
-
-
Parameters:
-
-
-
-
-
-
-
Name
-
-
-
Type
-
-
-
-
-
-
Description
-
-
-
-
-
-
-
-
-
elem
-
-
-
-
-
-*
-
-
-
-
-
-
-
-
-
-
Element.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Source:
-
collection.js, line 155
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
-
- Length.
-
-
-
-
-
-
- Type
-
-
-
-number
-
-
-
-
-
-
-
-
-
-
-
-
-
-
remove
+
on
@@ -1788,7 +941,7 @@
- Removes the first occurence of elem from the collection.
+
An expression instance that can be
+ evaluated within some scope to provide a value.
+
+
+
+
+
+
+ Type
+
+
+
+ol.expr.Expression
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<static> register
+
+
+
+
+
+
+
+
Register a library function to be used in expressions.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
name
+
+
+
+
+
+string
+
+
+
+
+
+
+
+
+
+
The function name (e.g. 'myFunc').
+
+
+
+
+
+
+
func
+
+
+
+
+
+function
+
+
+
+
+
+
+
+
+
+
The function to be called in an
+ expression. This function will be called with a feature as the this
+ argument when the expression is evaluated in the context of a features.
Create a polygon from an array of vertex arrays. Coordinates for the
+exterior ring will be forced to clockwise order. Coordinates for any
+interior rings will be forced to counter-clockwise order. In cases where
+the opposite winding order occurs in the passed vertex arrays, they will
+be modified in place.
+
+
+
+
+
+
+
+
+
Parameters:
+
+
+
+
+
+
+
Name
+
+
+
Type
+
+
+
Argument
+
+
+
+
+
Description
+
+
+
+
+
+
+
+
+
coordinates
+
+
+
+
+
+Array.<ol.CoordinateArray>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Array of rings. First
+ is outer, any remaining are inner.
Layers to restrict the
+ query to. All map layers will be queried if not provided.
+
+
+
+
+
+
+
success
+
+
+
+
+
+function
+
+
+
+
+
+
+
+
+
+
Callback for
+ successful queries. The passed argument is the resulting feature
+ information for each layer, with array indices being the same as in the
+ passed layers array or in the layer collection as returned from
+ ol.Map#getLayers() if no layers were provided.
+
+
+
+
+
+
+
error
+
+
+
+
+
+function
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Callback for unsuccessful queries.
+ Note that queries with no matching features trigger the success callback,
+ not the error callback.
Layers to restrict the
+ query to. All layers will be queried if not provided.
+
+
+
+
+
+
+
success
+
+
+
+
+
+function
+
+
+
+
+
+
+
+
+
+
Callback
+ for successful queries. The passed argument is the resulting features for
+ each layer, with array indices being the same as in the passed layers
+ array or in the layer collection as returned from ol.Map#getLayers() if
+ no layers were provided.
+
+
+
+
+
+
+
error
+
+
+
+
+
+function
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Callback for unsuccessful queries.
+ Note that queries with no matching features trigger the success callback,
+ not the error callback.
The initial center for the view.
+ The coordinate system for the center is specified with the projection
+ option.
+
+
+
+
+
+
+
maxResolution
+
+
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
The maximum resolution used to
+ determine the resolution constraint. It is used together with maxZoom
+ and zoomFactor. If unspecified it is calculated in such a way that the
+ projection's validity extent fits in a 256x256 px tile. If the projection
+ is Spherical Mercator (the default) then maxResolution defaults to
+ 40075016.68557849 / 256 = 156543.03392804097.
+
+
+
+
+
+
+
maxZoom
+
+
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
The maximum zoom level used to determine
+ the resolution constraint. It is used together with maxResolution and
+ zoomFactor. Default is 28.
The projection. Default is
+ EPSG:3857 (Spherical Mercator).
+
+
+
+
+
+
+
resolution
+
+
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
The initial resolution for the view.
+ The units are projection units per pixel (e.g. meters per pixel).
+
+
+
+
+
+
+
resolutions
+
+
+
+
+
+Array.<number>
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Resolutions to determine the
+ resolution constraint. If set the maxResolution, maxZoom and
+ zoomFactor options are ignored.
+
+
+
+
+
+
+
rotation
+
+
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
The initial rotation for the view
+ in radians (positive rotation clockwise).
+
+
+
+
+
+
+
zoom
+
+
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Zoom level used to calculate the initial
+ resolution for the view. The initial resolution is determined using the
+ ol.View2D#constrainResolution method.
+
+
+
+
+
+
+
zoomFactor
+
+
+
+
+
+number
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
The zoom factor used to determine the
+ resolution constraint. It is together with maxResolution and maxZoom.
+ Default is 2.
Function to render an array of
+ features into feature info markup. If not provided, a comma separated
+ list of the unique ids of the resulting features will be returned.
Write gml:Curve instead of
+ gml:LineString elements. This also affects the elements in multi-part
+ geometries. Default is `false´. This only applies to GML version 3.
+
+
+
+
+
+
+
extractAttributes
+
+
+
+
+
+boolean
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Should we extract attributes
+ from the GML? Default is `true´.
+
+
+
+
+
+
+
featureNS
+
+
+
+
+
+string
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
The feature namespace. If not set it
+ will be automatically configured from the GML.
Name of geometry element.
+ Defaults to `geometry´. If null, it will be set on when the
+ first geometry is parsed.
+
+
+
+
+
+
+
multiCurve
+
+
+
+
+
+boolean
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Write gml:MultiCurve instead of
+ gml:MultiLineString. Since the latter is deprecated in GML 3, the
+ default is `true´. This only applies to GML version 3.
+
+
+
+
+
+
+
multiSurface
+
+
+
+
+
+boolean
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Write gml:multiSurface instead
+ of gml:MultiPolygon. Since the latter is deprecated in GML 3, the
+ default is `true´. This only applies to GML version 3.
+
+
+
+
+
+
+
schemaLocation
+
+
+
+
+
+string
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Optional schemaLocation to use
+ when writing out the GML, this will override the default provided.
+
+
+
+
+
+
+
surface
+
+
+
+
+
+boolean
+|
+
+undefined
+
+
+
+
+
+
+
+
+
+
Write gml:Surface instead of
+ gml:Polygon elements. This also affects the elements in multi-part
+ geometries. Default is `false´. This only applies to GML version 3.
Given the projection-like objects this method searches for a transformation
+function to convert a coordinates array from the source projection to the
+destination projection.
WMS request parameters. At least a
+ LAYERS param is required. STYLES is '' by default. VERSION is
+ '1.3.0' by default. WIDTH, HEIGHT, BBOX and CRS (SRS for WMS
+ version < 1.3.0) will be set dynamically.
WMS request parameters. At least a
+ LAYERS param is required. STYLES is '' by default. VERSION is
+ '1.3.0' by default. WIDTH, HEIGHT, BBOX and CRS (SRS for WMS
+ version < 1.3.0) will be set dynamically.
Projection. Usually the
+ projection is provided by the parser, so this only needs to be set if
+ the parser does not know the SRS (e.g. in some GML flavors), or if the
+ projection determined by the parser needs to be overridden.
property type property with type, trailing ? indicates unsure, getters and setters are assumed to exist.
+
f(args) -> type function taking args returning type.
+
f(args) -> type = something f is a trivial wrapper around something.
+
fires 'x' fires events of type 'x'.
+
+
+
Principles:
+
+
+
All non-trivial objects inherit from MVCObject.
+
All non-trivial collections are either MVCArrays or a child class thereof.
+
Resolutions are Array., infinitely scalable resources (e.g. vectore layers) have resolutions == null.
+
+
+
MVCObject
+ as Google Maps MVCObject
+ freeze()
+ unfreeze()
+
+TileCoord
+ clone() -> TileCoord
+ getHash() -> number
+
+TileBounds
+ forEachTileCoord(z, function(tileCoord))
+
+Tile
+ tileCoord TileCoord
+ url string
+ state UNLOADED | LOADING | LOADED
+ fires 'loaded' // when loaded
+ fires 'aborted' // when loading is aborted
+
+Camera
+ position goog.math.Coordinate
+ resolution number
+ rotation number
+
+Layer
+ projections Array.
+ extent Extent
+ getResolutions() -> Array.|null
+ fires 'change' // when data changes
+
+LayerArray
+ getResolutions() -> Array.|null
+ getMaxResolution() = this.getResolutions()[0] | null
+
+LayerRendererOptions
+ layer Layer
+ visible boolean
+ opacity number
+ brightness number
+ color number
+ hue number
+ saturation number
+
+Map
+ projection Projection
+ renderer Renderer
+ layers LayerArray
+ addLayer(layer) = layers.push(layer)
+ getExtent() -> Extent
+ getMaxResolution() = layers.getMaxResolution()
+
+TileGrid
+ resolutions Array.
+ extent ol.Extent
+ xEast boolean
+ ySouth boolean
+ origin(s) Coord|Array.
+ tileSize goog.math.Size
+ forEachTileCoordChild(tileCoord, function(z, TileBounds))
+ forEachTileCoordParent(tileCoord, function(z, TileBounds))
+ getExtentTileBounds(z, extent) -> TileBounds
+ getTileCoord(coordinate) -> TileCoord
+ getTileCoordCenter(tileCoord) -> goog.math.Coordinate
+ getTileCoordExtent(tileCoord) -> ol.Extent
+ getTileCoordResolution(tileCoord) -> number
+ getZForResolution(resolution) -> number
+
+TileLayer
+ tileGrid TileGrid
+ tileUrl function(tileCoord) -> string
+ getTileCoordUrl(tileCoord) -> string = this.tileUrl(tileCoord)
+
+TileQueue
+ camera Camera // or maybe MVCArray. ?
+ getTileCoordPriority(tileCoord) -> number // private
+ enqueueTile(Tile)
+
+VectorLayer
+ forEachFeature(resolution, extent, projection, function(Feature))
+
+Renderer
+ target HTMLDivElement
+ map Map
+ camera Camera
+ getCapabilities() -> Array. // maybe ?
+
+
+
Questions:
+
+
+
Store tile layer extent in TileLayer or in TileGrid? (not clear)
+
+
+
Two concepts: tile coordinate system range and and available data extent.
+TileGrid extent is range (or validity extent) of the tile coordinate system.
+TileLayer extent is the available data extent. A particular TileGrid may range
+from 0,0 to 10,10. My cache may conform to that grid but I may only have tiles
+ranging from 2,2 to 8,8. When you need to wrap multiple worlds, you pay
+attention to the TileGrid extent. When you need to decide whether or not to
+bother requesting a tile, you pay attention to the TileLayer extent.
+
+
+
Who determines "best" resolution? (static function?)
+
+
+
Todo: if tile layer extent stored in TileLayer rather than TileGrid then extent
+will occasionally need to be passed to TileGrid functions for cropping.
+
+
DESIGN ASSERTIONS
+
+
Map
+
+
+
A map has a renderer (the map renderer).
+
A map has a camera.
+
Multiple maps can share the same camera.
+
A map has a layer list.
+
+
+
Layer
+
+
+
A layer can have multiple projections (the supported projections).
+
A layer advertizes the projections it supports.
+
A layer returns no data if asked data for an unsupported projection.
+
+
+
LayerRendererOptions
+
+
+
A layer renderer options object stores view-related states for a layer.
+
Options include visibility, opacity, saturation, hue, etc.
+
A layer renderer options object has a layer.
+
Multiple layer renderer options can share the same layer.
+
In other words a layer can be viewed in different manners.
+
+
+
Renderer
+
+
+
The map renderer responds to events.
+
The map renderer receives events from the camera.
+
The map renderer creates layer renderers.
+
+
+
Control
+
+
+
A control may listen to map events.
+
A control may listen to camera events.
+
A map navigation control acts on the camera.
+
+
+
MVC
+
+
+
Types can be described in MVC terms.
+
Models don't know what rendering means.
+
Maps are models.
+
Layers are models.
+
Layer views are models (sorry!).
+
Cameras are models.
+
Layer lists are collections.
+
Renderers are views.
+
Controls are views or controllers or both.
+
An attribution control is a view.
+
A map navigation control is a controller.
+
A zoom slider control is both a view and a controller.
+ *
+ * TODO(user): Consider writing a parallel class to this that
+ * does not implement goog.Disposable.
+ *
+ * @constructor
+ * @extends {goog.Disposable}
+ * @implements {goog.events.Listenable}
+ */
+goog.events.EventTarget = function() {
+ goog.Disposable.call(this);
+
+ /**
+ * Maps of event type to an array of listeners.
+ * @private {!goog.events.ListenerMap}
+ */
+ this.eventTargetListeners_ = new goog.events.ListenerMap(this);
+
+ /**
+ * The object to use for event.target. Useful when mixing in an
+ * EventTarget to another object.
+ * @private {!Object}
+ */
+ this.actualEventTarget_ = this;
+};
+goog.inherits(goog.events.EventTarget, goog.Disposable);
+goog.events.Listenable.addImplementation(goog.events.EventTarget);
+
+
+/**
+ * An artificial cap on the number of ancestors you can have. This is mainly
+ * for loop detection.
+ * @const {number}
+ * @private
+ */
+goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
+
+
+/**
+ * Parent event target, used during event bubbling.
+ *
+ * TODO(user): Change this to goog.events.Listenable. This
+ * currently breaks people who expect getParentEventTarget to return
+ * goog.events.EventTarget.
+ *
+ * @type {goog.events.EventTarget}
+ * @private
+ */
+goog.events.EventTarget.prototype.parentEventTarget_ = null;
+
+
+/**
+ * Returns the parent of this event target to use for bubbling.
+ *
+ * @return {goog.events.EventTarget} The parent EventTarget or null if
+ * there is no parent.
+ * @override
+ */
+goog.events.EventTarget.prototype.getParentEventTarget = function() {
+ return this.parentEventTarget_;
+};
+
+
+/**
+ * Sets the parent of this event target to use for capture/bubble
+ * mechanism.
+ * @param {goog.events.EventTarget} parent Parent listenable (null if none).
+ */
+goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
+ this.parentEventTarget_ = parent;
+};
+
+
+/**
+ * Adds an event listener to the event target. The same handler can only be
+ * added once per the type. Even if you add the same handler multiple times
+ * using the same type then it will only be called once when the event is
+ * dispatched.
+ *
+ * Supported for legacy but use goog.events.listen(src, type, handler) instead.
+ *
+ * TODO(user): Deprecate this.
+ *
+ * @param {string} type The type of the event to listen for.
+ * @param {Function|Object} handler The function to handle the event. The
+ * handler can also be an object that implements the handleEvent method
+ * which takes the event object as argument.
+ * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase
+ * of the event.
+ * @param {Object=} opt_handlerScope Object in whose scope to call
+ * the listener.
+ */
+goog.events.EventTarget.prototype.addEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
+};
+
+
+/**
+ * Removes an event listener from the event target. The handler must be the
+ * same object as the one added. If the handler has not been added then
+ * nothing is done.
+ *
+ * TODO(user): Deprecate this.
+ *
+ * @param {string} type The type of the event to listen for.
+ * @param {Function|Object} handler The function to handle the event. The
+ * handler can also be an object that implements the handleEvent method
+ * which takes the event object as argument.
+ * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase
+ * of the event.
+ * @param {Object=} opt_handlerScope Object in whose scope to call
+ * the listener.
+ */
+goog.events.EventTarget.prototype.removeEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.dispatchEvent = function(e) {
+ this.assertInitialized_();
+
+ var ancestorsTree, ancestor = this.getParentEventTarget();
+ if (ancestor) {
+ ancestorsTree = [];
+ var ancestorCount = 1;
+ for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
+ ancestorsTree.push(ancestor);
+ goog.asserts.assert(
+ (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),
+ 'infinite loop');
+ }
+ }
+
+ return goog.events.EventTarget.dispatchEventInternal_(
+ this.actualEventTarget_, e, ancestorsTree);
+};
+
+
+/**
+ * Removes listeners from this object. Classes that extend EventTarget may
+ * need to override this method in order to remove references to DOM Elements
+ * and additional listeners.
+ * @override
+ */
+goog.events.EventTarget.prototype.disposeInternal = function() {
+ goog.events.EventTarget.superClass_.disposeInternal.call(this);
+
+ this.removeAllListeners();
+ this.parentEventTarget_ = null;
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.listen = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ this.assertInitialized_();
+ return this.eventTargetListeners_.add(
+ type, listener, false /* callOnce */, opt_useCapture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.listenOnce = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ return this.eventTargetListeners_.add(
+ type, listener, true /* callOnce */, opt_useCapture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.unlisten = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ return this.eventTargetListeners_.remove(
+ type, listener, opt_useCapture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.unlistenByKey = function(key) {
+ return this.eventTargetListeners_.removeByKey(key);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
+ // TODO(user): Previously, removeAllListeners can be called on
+ // uninitialized EventTarget, so we preserve that behavior. We
+ // should remove this when usages that rely on that fact are purged.
+ if (!this.eventTargetListeners_) {
+ return 0;
+ }
+ return this.eventTargetListeners_.removeAll(opt_type);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.fireListeners = function(
+ type, capture, eventObject) {
+ // TODO(user): Original code avoids array creation when there
+ // is no listener, so we do the same. If this optimization turns
+ // out to be not required, we can replace this with
+ // getListeners(type, capture) instead, which is simpler.
+ var listenerArray = this.eventTargetListeners_.listeners[type];
+ if (!listenerArray) {
+ return true;
+ }
+ listenerArray = goog.array.clone(listenerArray);
+
+ var rv = true;
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listener = listenerArray[i];
+ // We might not have a listener if the listener was removed.
+ if (listener && !listener.removed && listener.capture == capture) {
+ var listenerFn = listener.listener;
+ var listenerHandler = listener.handler || listener.src;
+
+ if (listener.callOnce) {
+ this.unlistenByKey(listener);
+ }
+ rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
+ }
+ }
+
+ return rv && eventObject.returnValue_ != false;
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.getListeners = function(type, capture) {
+ return this.eventTargetListeners_.getListeners(type, capture);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.getListener = function(
+ type, listener, capture, opt_listenerScope) {
+ return this.eventTargetListeners_.getListener(
+ type, listener, capture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.hasListener = function(
+ opt_type, opt_capture) {
+ return this.eventTargetListeners_.hasListener(opt_type, opt_capture);
+};
+
+
+/**
+ * Sets the target to be used for {@code event.target} when firing
+ * event. Mainly used for testing. For example, see
+ * {@code goog.testing.events.mixinListenable}.
+ * @param {!Object} target The target.
+ */
+goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
+ this.actualEventTarget_ = target;
+};
+
+
+/**
+ * Asserts that the event target instance is initialized properly.
+ * @private
+ */
+goog.events.EventTarget.prototype.assertInitialized_ = function() {
+ goog.asserts.assert(
+ this.eventTargetListeners_,
+ 'Event target is not initialized. Did you call the superclass ' +
+ '(goog.events.EventTarget) constructor?');
+};
+
+
+/**
+ * Dispatches the given event on the ancestorsTree.
+ *
+ * TODO(user): Look for a way to reuse this logic in
+ * goog.events, if possible.
+ *
+ * @param {!Object} target The target to dispatch on.
+ * @param {goog.events.Event|Object|string} e The event object.
+ * @param {Array.=} opt_ancestorsTree The ancestors
+ * tree of the target, in reverse order from the closest ancestor
+ * to the root event target. May be null if the target has no ancestor.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the listeners returns false) this will also return false.
+ * @private
+ */
+goog.events.EventTarget.dispatchEventInternal_ = function(
+ target, e, opt_ancestorsTree) {
+ var type = e.type || /** @type {string} */ (e);
+
+ // If accepting a string or object, create a custom event object so that
+ // preventDefault and stopPropagation work with the event.
+ if (goog.isString(e)) {
+ e = new goog.events.Event(e, target);
+ } else if (!(e instanceof goog.events.Event)) {
+ var oldEvent = e;
+ e = new goog.events.Event(type, target);
+ goog.object.extend(e, oldEvent);
+ } else {
+ e.target = e.target || target;
+ }
+
+ var rv = true, currentTarget;
+
+ // Executes all capture listeners on the ancestors, if any.
+ if (opt_ancestorsTree) {
+ for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;
+ i--) {
+ currentTarget = e.currentTarget = opt_ancestorsTree[i];
+ rv = currentTarget.fireListeners(type, true, e) && rv;
+ }
+ }
+
+ // Executes capture and bubble listeners on the target.
+ if (!e.propagationStopped_) {
+ currentTarget = e.currentTarget = target;
+ rv = currentTarget.fireListeners(type, true, e) && rv;
+ if (!e.propagationStopped_) {
+ rv = currentTarget.fireListeners(type, false, e) && rv;
+ }
+ }
+
+ // Executes all bubble listeners on the ancestors, if any.
+ if (opt_ancestorsTree) {
+ for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {
+ currentTarget = e.currentTarget = opt_ancestorsTree[i];
+ rv = currentTarget.fireListeners(type, false, e) && rv;
+ }
+ }
+
+ return rv;
+};
diff --git a/edit/closure-library/closure/goog/events/eventtargettester.js b/edit/closure-library/closure/goog/events/eventtargettester.js
new file mode 100644
index 0000000000..6243db9055
--- /dev/null
+++ b/edit/closure-library/closure/goog/events/eventtargettester.js
@@ -0,0 +1,1028 @@
+// Copyright 2012 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.
+
+/**
+ * @fileoverview goog.events.EventTarget tester.
+ */
+
+goog.provide('goog.events.eventTargetTester');
+goog.setTestOnly('goog.events.eventTargetTester');
+goog.provide('goog.events.eventTargetTester.KeyType');
+goog.setTestOnly('goog.events.eventTargetTester.KeyType');
+goog.provide('goog.events.eventTargetTester.UnlistenReturnType');
+goog.setTestOnly('goog.events.eventTargetTester.UnlistenReturnType');
+
+goog.require('goog.array');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventTarget');
+goog.require('goog.testing.asserts');
+goog.require('goog.testing.recordFunction');
+
+
+/**
+ * Setup step for the test functions. This needs to be called from the
+ * test setUp.
+ * @param {Function} listenFn Function that, given the same signature
+ * as goog.events.listen, will add listener to the given event
+ * target.
+ * @param {Function} unlistenFn Function that, given the same
+ * signature as goog.events.unlisten, will remove listener from
+ * the given event target.
+ * @param {Function} unlistenByKeyFn Function that, given 2
+ * parameters: src and key, will remove the corresponding
+ * listener.
+ * @param {Function} listenOnceFn Function that, given the same
+ * signature as goog.events.listenOnce, will add a one-time
+ * listener to the given event target.
+ * @param {Function} dispatchEventFn Function that, given the same
+ * signature as goog.events.dispatchEvent, will dispatch the event
+ * on the given event target.
+ * @param {Function} removeAllFn Function that, given the same
+ * signature as goog.events.removeAll, will remove all listeners
+ * according to the contract of goog.events.removeAll.
+ * @param {Function} getListenersFn Function that, given the same
+ * signature as goog.events.getListeners, will retrieve listeners.
+ * @param {Function} getListenerFn Function that, given the same
+ * signature as goog.events.getListener, will retrieve the
+ * listener object.
+ * @param {Function} hasListenerFn Function that, given the same
+ * signature as goog.events.hasListener, will determine whether
+ * listeners exist.
+ * @param {goog.events.eventTargetTester.KeyType} listenKeyType The
+ * key type returned by listen call.
+ * @param {goog.events.eventTargetTester.UnlistenReturnType}
+ * unlistenFnReturnType
+ * Whether we should check return value from
+ * unlisten call. If unlisten does not return a value, this should
+ * be set to false.
+ * @param {boolean} objectListenerSupported Whether listener of type
+ * Object is supported.
+ */
+goog.events.eventTargetTester.setUp = function(
+ listenFn, unlistenFn, unlistenByKeyFn, listenOnceFn,
+ dispatchEventFn, removeAllFn,
+ getListenersFn, getListenerFn, hasListenerFn,
+ listenKeyType, unlistenFnReturnType, objectListenerSupported) {
+ listen = listenFn;
+ unlisten = unlistenFn;
+ unlistenByKey = unlistenByKeyFn;
+ listenOnce = listenOnceFn;
+ dispatchEvent = dispatchEventFn;
+ removeAll = removeAllFn;
+ getListeners = getListenersFn;
+ getListener = getListenerFn;
+ hasListener = hasListenerFn;
+ keyType = listenKeyType;
+ unlistenReturnType = unlistenFnReturnType;
+ objectTypeListenerSupported = objectListenerSupported;
+
+ listeners = [];
+ for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
+ listeners[i] = createListener();
+ }
+
+ eventTargets = [];
+ for (i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
+ eventTargets[i] = new goog.events.EventTarget();
+ }
+};
+
+
+/**
+ * Teardown step for the test functions. This needs to be called from
+ * test teardown.
+ */
+goog.events.eventTargetTester.tearDown = function() {
+ for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
+ goog.dispose(eventTargets[i]);
+ }
+};
+
+
+/**
+ * The type of key returned by key-returning functions (listen).
+ * @enum {number}
+ */
+goog.events.eventTargetTester.KeyType = {
+ /**
+ * Returns number for key.
+ */
+ NUMBER: 0,
+
+ /**
+ * Returns undefined (no return value).
+ */
+ UNDEFINED: 1
+};
+
+
+/**
+ * The type of unlisten function's return value.
+ */
+goog.events.eventTargetTester.UnlistenReturnType = {
+ /**
+ * Returns boolean indicating whether unlisten is successful.
+ */
+ BOOLEAN: 0,
+
+ /**
+ * Returns undefind (no return value).
+ */
+ UNDEFINED: 1
+};
+
+
+/**
+ * Expando property used on "listener" function to determine if a
+ * listener has already been checked. This is what allows us to
+ * implement assertNoOtherListenerIsCalled.
+ * @type {string}
+ */
+goog.events.eventTargetTester.ALREADY_CHECKED_PROP = '__alreadyChecked';
+
+
+/**
+ * Expando property used on "listener" function to record the number
+ * of times it has been called the last time assertListenerIsCalled is
+ * done. This allows us to verify that it has not been called more
+ * times in assertNoOtherListenerIsCalled.
+ */
+goog.events.eventTargetTester.NUM_CALLED_PROP = '__numCalled';
+
+
+/**
+ * The maximum number of initialized event targets (in eventTargets
+ * array) and listeners (in listeners array).
+ * @type {number}
+ * @private
+ */
+goog.events.eventTargetTester.MAX_ = 10;
+
+
+/**
+ * Contains test event types.
+ * @enum {string}
+ */
+var EventType = {
+ A: goog.events.getUniqueId('a'),
+ B: goog.events.getUniqueId('b'),
+ C: goog.events.getUniqueId('c')
+};
+
+
+var listen, unlisten, unlistenByKey, listenOnce, dispatchEvent;
+var removeAll, getListeners, getListener, hasListener;
+var keyType, unlistenReturnType, objectTypeListenerSupported;
+var eventTargets, listeners;
+
+
+
+/**
+ * Custom event object for testing.
+ * @constructor
+ * @extends {goog.events.Event}
+ */
+var TestEvent = function() {
+ goog.base(this, EventType.A);
+};
+goog.inherits(TestEvent, goog.events.Event);
+
+
+/**
+ * Creates a listener that executes the given function (optional).
+ * @param {!Function=} opt_listenerFn The optional function to execute.
+ * @return {!Function} The listener function.
+ */
+function createListener(opt_listenerFn) {
+ return goog.testing.recordFunction(opt_listenerFn);
+}
+
+
+/**
+ * Asserts that the given listener is called numCount number of times.
+ * @param {!Function} listener The listener to check.
+ * @param {number} numCount The number of times. See also the times()
+ * function below.
+ */
+function assertListenerIsCalled(listener, numCount) {
+ assertEquals('Listeners is not called the correct number of times.',
+ numCount, listener.getCallCount());
+ listener[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = true;
+ listener[goog.events.eventTargetTester.NUM_CALLED_PROP] = numCount;
+}
+
+
+/**
+ * Asserts that no other listeners, other than those verified via
+ * assertListenerIsCalled, have been called since the last
+ * resetListeners().
+ */
+function assertNoOtherListenerIsCalled() {
+ goog.array.forEach(listeners, function(l, index) {
+ if (!l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP]) {
+ assertEquals(
+ 'Listeners ' + index + ' is unexpectedly called.',
+ 0, l.getCallCount());
+ } else {
+ assertEquals(
+ 'Listeners ' + index + ' is unexpectedly called.',
+ l[goog.events.eventTargetTester.NUM_CALLED_PROP], l.getCallCount());
+ }
+ });
+}
+
+
+/**
+ * Resets all listeners call count to 0.
+ */
+function resetListeners() {
+ goog.array.forEach(listeners, function(l) {
+ l.reset();
+ l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = false;
+ });
+}
+
+
+/**
+ * The number of times a listener should have been executed. This
+ * exists to make assertListenerIsCalled more readable. This is used
+ * like so: assertListenerIsCalled(listener, times(2));
+ * @param {number} n The number of times a listener should have been
+ * executed.
+ * @return {number} The number n.
+ */
+function times(n) {
+ return n;
+}
+
+
+function testNoListener() {
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testOneListener() {
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertNoOtherListenerIsCalled();
+
+ resetListeners();
+
+ dispatchEvent(eventTargets[0], EventType.B);
+ dispatchEvent(eventTargets[0], EventType.C);
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testTwoListenersOfSameType() {
+ var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
+ var key2 = listen(eventTargets[0], EventType.A, listeners[1]);
+
+ if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
+ assertNotEquals(key1, key2);
+ } else {
+ assertUndefined(key1);
+ assertUndefined(key2);
+ }
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testInstallingSameListeners() {
+ var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
+ var key2 = listen(eventTargets[0], EventType.A, listeners[0]);
+ var key3 = listen(eventTargets[0], EventType.B, listeners[0]);
+
+ if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
+ assertEquals(key1, key2);
+ assertNotEquals(key1, key3);
+ } else {
+ assertUndefined(key1);
+ assertUndefined(key2);
+ assertUndefined(key3);
+ }
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+
+ dispatchEvent(eventTargets[0], EventType.B);
+ assertListenerIsCalled(listeners[0], times(2));
+
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testScope() {
+ listeners[0] = createListener(function(e) {
+ assertEquals('Wrong scope with undefined scope', eventTargets[0], this);
+ });
+ listeners[1] = createListener(function(e) {
+ assertEquals('Wrong scope with null scope', eventTargets[0], this);
+ });
+ var scope = {};
+ listeners[2] = createListener(function(e) {
+ assertEquals('Wrong scope with specific scope object', scope, this);
+ });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1], false, null);
+ listen(eventTargets[0], EventType.A, listeners[2], false, scope);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(1));
+}
+
+
+function testDispatchEventDoesNotThrowWithDisposedEventTarget() {
+ goog.dispose(eventTargets[0]);
+ assertTrue(dispatchEvent(eventTargets[0], EventType.A));
+}
+
+
+function testDispatchEventWithObjectLiteral() {
+ listen(eventTargets[0], EventType.A, listeners[0]);
+
+ assertTrue(dispatchEvent(eventTargets[0], {type: EventType.A}));
+ assertListenerIsCalled(listeners[0], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testDispatchEventWithCustomEventObject() {
+ listen(eventTargets[0], EventType.A, listeners[0]);
+
+ var e = new TestEvent();
+ assertTrue(dispatchEvent(eventTargets[0], e));
+ assertListenerIsCalled(listeners[0], times(1));
+ assertNoOtherListenerIsCalled();
+
+ var actualEvent = listeners[0].getLastCall().getArgument(0);
+
+ assertEquals(e, actualEvent);
+ assertEquals(eventTargets[0], actualEvent.target);
+}
+
+
+function testDisposingEventTargetRemovesListeners() {
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ goog.dispose(eventTargets[0]);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertNoOtherListenerIsCalled();
+}
+
+
+/**
+ * Unlisten/unlistenByKey should still work after disposal. There are
+ * many circumstances when this is actually necessary. For example, a
+ * user may have listened to an event target and stored the key
+ * (e.g. in a goog.events.EventHandler) and only unlisten after the
+ * target has been disposed.
+ */
+function testUnlistenWorksAfterDisposal() {
+ var key = listen(eventTargets[0], EventType.A, listeners[0]);
+ goog.dispose(eventTargets[0]);
+ unlisten(eventTargets[0], EventType.A, listeners[1]);
+ if (unlistenByKey) {
+ unlistenByKey(eventTargets[0], key);
+ }
+}
+
+
+function testRemovingListener() {
+ var ret1 = unlisten(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ var ret2 = unlisten(eventTargets[0], EventType.A, listeners[1]);
+ var ret3 = unlisten(eventTargets[0], EventType.B, listeners[0]);
+ var ret4 = unlisten(eventTargets[1], EventType.A, listeners[0]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+
+ var ret5 = unlisten(eventTargets[0], EventType.A, listeners[0]);
+ var ret6 = unlisten(eventTargets[0], EventType.A, listeners[0]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+
+ assertNoOtherListenerIsCalled();
+
+ if (unlistenReturnType ==
+ goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN) {
+ assertFalse(ret1);
+ assertFalse(ret2);
+ assertFalse(ret3);
+ assertFalse(ret4);
+ assertTrue(ret5);
+ assertFalse(ret6);
+ } else {
+ assertUndefined(ret1);
+ assertUndefined(ret2);
+ assertUndefined(ret3);
+ assertUndefined(ret4);
+ assertUndefined(ret5);
+ assertUndefined(ret6);
+ }
+}
+
+
+function testCapture() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ eventTargets[9].setParentEventTarget(eventTargets[0]);
+
+ var ordering = 0;
+ listeners[0] = createListener(
+ function(e) {
+ assertEquals(eventTargets[2], e.currentTarget);
+ assertEquals(eventTargets[0], e.target);
+ assertEquals('First capture listener is not called first', 0, ordering);
+ ordering++;
+ });
+ listeners[1] = createListener(
+ function(e) {
+ assertEquals(eventTargets[1], e.currentTarget);
+ assertEquals(eventTargets[0], e.target);
+ assertEquals('2nd capture listener is not called 2nd', 1, ordering);
+ ordering++;
+ });
+ listeners[2] = createListener(
+ function(e) {
+ assertEquals(eventTargets[0], e.currentTarget);
+ assertEquals(eventTargets[0], e.target);
+ assertEquals('3rd capture listener is not called 3rd', 2, ordering);
+ ordering++;
+ });
+
+ listen(eventTargets[2], EventType.A, listeners[0], true);
+ listen(eventTargets[1], EventType.A, listeners[1], true);
+ listen(eventTargets[0], EventType.A, listeners[2], true);
+
+ // These should not be called.
+ listen(eventTargets[3], EventType.A, listeners[3], true);
+
+ listen(eventTargets[0], EventType.B, listeners[4], true);
+ listen(eventTargets[0], EventType.C, listeners[5], true);
+ listen(eventTargets[1], EventType.B, listeners[6], true);
+ listen(eventTargets[1], EventType.C, listeners[7], true);
+ listen(eventTargets[2], EventType.B, listeners[8], true);
+ listen(eventTargets[2], EventType.C, listeners[9], true);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testBubble() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ eventTargets[9].setParentEventTarget(eventTargets[0]);
+
+ var ordering = 0;
+ listeners[0] = createListener(
+ function(e) {
+ assertEquals(eventTargets[0], e.currentTarget);
+ assertEquals(eventTargets[0], e.target);
+ assertEquals('First bubble listener is not called first', 0, ordering);
+ ordering++;
+ });
+ listeners[1] = createListener(
+ function(e) {
+ assertEquals(eventTargets[1], e.currentTarget);
+ assertEquals(eventTargets[0], e.target);
+ assertEquals('2nd bubble listener is not called 2nd', 1, ordering);
+ ordering++;
+ });
+ listeners[2] = createListener(
+ function(e) {
+ assertEquals(eventTargets[2], e.currentTarget);
+ assertEquals(eventTargets[0], e.target);
+ assertEquals('3rd bubble listener is not called 3rd', 2, ordering);
+ ordering++;
+ });
+
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[1], EventType.A, listeners[1]);
+ listen(eventTargets[2], EventType.A, listeners[2]);
+
+ // These should not be called.
+ listen(eventTargets[3], EventType.A, listeners[3]);
+
+ listen(eventTargets[0], EventType.B, listeners[4]);
+ listen(eventTargets[0], EventType.C, listeners[5]);
+ listen(eventTargets[1], EventType.B, listeners[6]);
+ listen(eventTargets[1], EventType.C, listeners[7]);
+ listen(eventTargets[2], EventType.B, listeners[8]);
+ listen(eventTargets[2], EventType.C, listeners[9]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testCaptureAndBubble() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+ listen(eventTargets[1], EventType.A, listeners[1], true);
+ listen(eventTargets[2], EventType.A, listeners[2], true);
+
+ listen(eventTargets[0], EventType.A, listeners[3]);
+ listen(eventTargets[1], EventType.A, listeners[4]);
+ listen(eventTargets[2], EventType.A, listeners[5]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(1));
+ assertListenerIsCalled(listeners[3], times(1));
+ assertListenerIsCalled(listeners[4], times(1));
+ assertListenerIsCalled(listeners[5], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testPreventDefaultByReturningFalse() {
+ listeners[0] = createListener(function(e) { return false; });
+ listeners[1] = createListener(function(e) { return true; });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+
+ var result = dispatchEvent(eventTargets[0], EventType.A);
+ assertFalse(result);
+}
+
+
+function testPreventDefault() {
+ listeners[0] = createListener(function(e) { e.preventDefault(); });
+ listeners[1] = createListener(function(e) { return true; });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+
+ var result = dispatchEvent(eventTargets[0], EventType.A);
+ assertFalse(result);
+}
+
+
+function testPreventDefaultAtCapture() {
+ listeners[0] = createListener(function(e) { e.preventDefault(); });
+ listeners[1] = createListener(function(e) { return true; });
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+ listen(eventTargets[0], EventType.A, listeners[1], true);
+
+ var result = dispatchEvent(eventTargets[0], EventType.A);
+ assertFalse(result);
+}
+
+
+function testStopPropagation() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ listeners[0] = createListener(function(e) { e.stopPropagation(); });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+ listen(eventTargets[1], EventType.A, listeners[2]);
+ listen(eventTargets[2], EventType.A, listeners[3]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testStopPropagation2() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ listeners[1] = createListener(function(e) { e.stopPropagation(); });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+ listen(eventTargets[1], EventType.A, listeners[2]);
+ listen(eventTargets[2], EventType.A, listeners[3]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testStopPropagation3() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ listeners[2] = createListener(function(e) { e.stopPropagation(); });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+ listen(eventTargets[1], EventType.A, listeners[2]);
+ listen(eventTargets[2], EventType.A, listeners[3]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testStopPropagationAtCapture() {
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ eventTargets[1].setParentEventTarget(eventTargets[2]);
+
+ listeners[0] = createListener(function(e) { e.stopPropagation(); });
+ listen(eventTargets[2], EventType.A, listeners[0], true);
+ listen(eventTargets[1], EventType.A, listeners[1], true);
+ listen(eventTargets[0], EventType.A, listeners[2], true);
+ listen(eventTargets[0], EventType.A, listeners[3]);
+ listen(eventTargets[1], EventType.A, listeners[4]);
+ listen(eventTargets[2], EventType.A, listeners[5]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testHandleEvent() {
+ if (!objectTypeListenerSupported) {
+ return;
+ }
+
+ var obj = {};
+ obj.handleEvent = goog.testing.recordFunction();
+
+ listen(eventTargets[0], EventType.A, obj);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertEquals(1, obj.handleEvent.getCallCount());
+}
+
+
+function testListenOnce() {
+ if (!listenOnce) {
+ return;
+ }
+
+ listenOnce(eventTargets[0], EventType.A, listeners[0], true);
+ listenOnce(eventTargets[0], EventType.A, listeners[1]);
+ listenOnce(eventTargets[0], EventType.B, listeners[2]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(0));
+ assertNoOtherListenerIsCalled();
+ resetListeners();
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(0));
+ assertListenerIsCalled(listeners[1], times(0));
+ assertListenerIsCalled(listeners[2], times(0));
+
+ dispatchEvent(eventTargets[0], EventType.B);
+ assertListenerIsCalled(listeners[2], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testUnlistenInListen() {
+ listeners[1] = createListener(
+ function(e) {
+ unlisten(eventTargets[0], EventType.A, listeners[1]);
+ unlisten(eventTargets[0], EventType.A, listeners[2]);
+ });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+ listen(eventTargets[0], EventType.A, listeners[2]);
+ listen(eventTargets[0], EventType.A, listeners[3]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(0));
+ assertListenerIsCalled(listeners[3], times(1));
+ assertNoOtherListenerIsCalled();
+ resetListeners();
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(0));
+ assertListenerIsCalled(listeners[2], times(0));
+ assertListenerIsCalled(listeners[3], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testUnlistenByKeyInListen() {
+ if (!unlistenByKey) {
+ return;
+ }
+
+ var key1, key2;
+ listeners[1] = createListener(
+ function(e) {
+ unlistenByKey(eventTargets[0], key1);
+ unlistenByKey(eventTargets[0], key2);
+ });
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ key1 = listen(eventTargets[0], EventType.A, listeners[1]);
+ key2 = listen(eventTargets[0], EventType.A, listeners[2]);
+ listen(eventTargets[0], EventType.A, listeners[3]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(0));
+ assertListenerIsCalled(listeners[3], times(1));
+ assertNoOtherListenerIsCalled();
+ resetListeners();
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(0));
+ assertListenerIsCalled(listeners[2], times(0));
+ assertListenerIsCalled(listeners[3], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testSetParentEventTarget() {
+ assertNull(eventTargets[0].getParentEventTarget());
+
+ eventTargets[0].setParentEventTarget(eventTargets[1]);
+ assertEquals(eventTargets[1], eventTargets[0].getParentEventTarget());
+ assertNull(eventTargets[1].getParentEventTarget());
+
+ eventTargets[0].setParentEventTarget(null);
+ assertNull(eventTargets[0].getParentEventTarget());
+}
+
+
+function testListenOnceAfterListenDoesNotChangeExistingListener() {
+ if (!listenOnce) {
+ return;
+ }
+
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(3));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {
+ if (!listenOnce) {
+ return;
+ }
+
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testListenAfterListenOnceRemoveOnceness() {
+ if (!listenOnce) {
+ return;
+ }
+
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[0]);
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertListenerIsCalled(listeners[0], times(3));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testUnlistenAfterListenOnce() {
+ if (!listenOnce) {
+ return;
+ }
+
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ unlisten(eventTargets[0], EventType.A, listeners[0]);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ unlisten(eventTargets[0], EventType.A, listeners[0]);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ listen(eventTargets[0], EventType.A, listeners[0]);
+ unlisten(eventTargets[0], EventType.A, listeners[0]);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ listenOnce(eventTargets[0], EventType.A, listeners[0]);
+ unlisten(eventTargets[0], EventType.A, listeners[0]);
+ dispatchEvent(eventTargets[0], EventType.A);
+
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testRemoveAllWithType() {
+ if (!removeAll) {
+ return;
+ }
+
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+ listen(eventTargets[0], EventType.C, listeners[2], true);
+ listen(eventTargets[0], EventType.C, listeners[3]);
+ listen(eventTargets[0], EventType.B, listeners[4], true);
+ listen(eventTargets[0], EventType.B, listeners[5], true);
+ listen(eventTargets[0], EventType.B, listeners[6]);
+ listen(eventTargets[0], EventType.B, listeners[7]);
+
+ assertEquals(4, removeAll(eventTargets[0], EventType.B));
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.B);
+ dispatchEvent(eventTargets[0], EventType.C);
+
+ assertListenerIsCalled(listeners[0], times(1));
+ assertListenerIsCalled(listeners[1], times(1));
+ assertListenerIsCalled(listeners[2], times(1));
+ assertListenerIsCalled(listeners[3], times(1));
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testRemoveAll() {
+ if (!removeAll) {
+ return;
+ }
+
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+ listen(eventTargets[0], EventType.A, listeners[1]);
+ listen(eventTargets[0], EventType.C, listeners[2], true);
+ listen(eventTargets[0], EventType.C, listeners[3]);
+ listen(eventTargets[0], EventType.B, listeners[4], true);
+ listen(eventTargets[0], EventType.B, listeners[5], true);
+ listen(eventTargets[0], EventType.B, listeners[6]);
+ listen(eventTargets[0], EventType.B, listeners[7]);
+
+ assertEquals(8, removeAll(eventTargets[0]));
+
+ dispatchEvent(eventTargets[0], EventType.A);
+ dispatchEvent(eventTargets[0], EventType.B);
+ dispatchEvent(eventTargets[0], EventType.C);
+
+ assertNoOtherListenerIsCalled();
+}
+
+
+function testGetListeners() {
+ if (!getListeners) {
+ return;
+ }
+
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+ listen(eventTargets[0], EventType.A, listeners[1], true);
+ listen(eventTargets[0], EventType.A, listeners[2]);
+ listen(eventTargets[0], EventType.A, listeners[3]);
+
+ var l = getListeners(eventTargets[0], EventType.A, true);
+ assertEquals(2, l.length);
+ assertEquals(listeners[0], l[0].listener);
+ assertEquals(listeners[1], l[1].listener);
+
+ l = getListeners(eventTargets[0], EventType.A, false);
+ assertEquals(2, l.length);
+ assertEquals(listeners[2], l[0].listener);
+ assertEquals(listeners[3], l[1].listener);
+
+ l = getListeners(eventTargets[0], EventType.B, true);
+ assertEquals(0, l.length);
+}
+
+
+function testGetListener() {
+ if (!getListener) {
+ return;
+ }
+
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+
+ assertNotNull(getListener(eventTargets[0], EventType.A, listeners[0], true));
+ assertNull(
+ getListener(eventTargets[0], EventType.A, listeners[0], true, {}));
+ assertNull(getListener(eventTargets[1], EventType.A, listeners[0], true));
+ assertNull(getListener(eventTargets[0], EventType.B, listeners[0], true));
+ assertNull(getListener(eventTargets[0], EventType.A, listeners[1], true));
+}
+
+
+function testHasListener() {
+ if (!hasListener) {
+ return;
+ }
+
+ assertFalse(hasListener(eventTargets[0]));
+
+ listen(eventTargets[0], EventType.A, listeners[0], true);
+
+ assertTrue(hasListener(eventTargets[0]));
+ assertTrue(hasListener(eventTargets[0], EventType.A));
+ assertTrue(hasListener(eventTargets[0], EventType.A, true));
+ assertTrue(hasListener(eventTargets[0], undefined, true));
+ assertFalse(hasListener(eventTargets[0], EventType.A, false));
+ assertFalse(hasListener(eventTargets[0], undefined, false));
+ assertFalse(hasListener(eventTargets[0], EventType.B));
+ assertFalse(hasListener(eventTargets[0], EventType.B, true));
+ assertFalse(hasListener(eventTargets[1]));
+}
+
+
+function testFiringEventBeforeDisposeInternalWorks() {
+ /**
+ * @extends {goog.events.EventTarget}
+ * @constructor
+ */
+ var MockTarget = function() {
+ goog.base(this);
+ };
+ goog.inherits(MockTarget, goog.events.EventTarget);
+
+ MockTarget.prototype.disposeInternal = function() {
+ dispatchEvent(this, EventType.A);
+ goog.base(this, 'disposeInternal');
+ };
+
+ var t = new MockTarget();
+ try {
+ listen(t, EventType.A, listeners[0]);
+ t.dispose();
+ assertListenerIsCalled(listeners[0], times(1));
+ } catch (e) {
+ goog.dispose(t);
+ }
+}
+
+
+function testLoopDetection() {
+ var target = new goog.events.EventTarget();
+ target.setParentEventTarget(target);
+
+ try {
+ target.dispatchEvent('string');
+ fail('expected error');
+ } catch (e) {
+ assertContains('infinite', e.message);
+ }
+}
diff --git a/master/closure-library/closure/goog/events/eventtype.js b/edit/closure-library/closure/goog/events/eventtype.js
similarity index 73%
rename from master/closure-library/closure/goog/events/eventtype.js
rename to edit/closure-library/closure/goog/events/eventtype.js
index eaac23c682..ea1fe469c7 100644
--- a/master/closure-library/closure/goog/events/eventtype.js
+++ b/edit/closure-library/closure/goog/events/eventtype.js
@@ -69,10 +69,12 @@ goog.events.EventType = {
// Drag and drop
DRAGSTART: 'dragstart',
+ DRAG: 'drag',
DRAGENTER: 'dragenter',
DRAGOVER: 'dragover',
DRAGLEAVE: 'dragleave',
DROP: 'drop',
+ DRAGEND: 'dragend',
// WebKit touch events.
TOUCHSTART: 'touchstart',
@@ -81,7 +83,10 @@ goog.events.EventType = {
TOUCHCANCEL: 'touchcancel',
// Misc
+ BEFOREUNLOAD: 'beforeunload',
+ CONSOLEMESSAGE: 'consolemessage',
CONTEXTMENU: 'contextmenu',
+ DOMCONTENTLOADED: 'DOMContentLoaded',
ERROR: 'error',
HELP: 'help',
LOAD: 'load',
@@ -121,5 +126,40 @@ goog.events.EventType = {
// CSS transition events. Based on the browser support described at:
// https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility
TRANSITIONEND: goog.userAgent.WEBKIT ? 'webkitTransitionEnd' :
- (goog.userAgent.OPERA ? 'oTransitionEnd' : 'transitionend')
+ (goog.userAgent.OPERA ? 'oTransitionEnd' : 'transitionend'),
+
+ // IE specific events.
+ // See http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx
+ MSGESTURECHANGE: 'MSGestureChange',
+ MSGESTUREEND: 'MSGestureEnd',
+ MSGESTUREHOLD: 'MSGestureHold',
+ MSGESTURESTART: 'MSGestureStart',
+ MSGESTURETAP: 'MSGestureTap',
+ MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',
+ MSINERTIASTART: 'MSInertiaStart',
+ MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',
+ MSPOINTERCANCEL: 'MSPointerCancel',
+ MSPOINTERDOWN: 'MSPointerDown',
+ MSPOINTERMOVE: 'MSPointerMove',
+ MSPOINTEROVER: 'MSPointerOver',
+ MSPOINTEROUT: 'MSPointerOut',
+ MSPOINTERUP: 'MSPointerUp',
+
+ // Native IMEs/input tools events.
+ TEXTINPUT: 'textinput',
+ COMPOSITIONSTART: 'compositionstart',
+ COMPOSITIONUPDATE: 'compositionupdate',
+ COMPOSITIONEND: 'compositionend',
+
+ // Webview tag events
+ // See http://developer.chrome.com/dev/apps/webview_tag.html
+ EXIT: 'exit',
+ LOADABORT: 'loadabort',
+ LOADCOMMIT: 'loadcommit',
+ LOADREDIRECT: 'loadredirect',
+ LOADSTART: 'loadstart',
+ LOADSTOP: 'loadstop',
+ RESPONSIVE: 'responsive',
+ SIZECHANGED: 'sizechanged',
+ UNRESPONSIVE: 'unresponsive'
};
diff --git a/master/closure-library/closure/goog/events/eventwrapper.js b/edit/closure-library/closure/goog/events/eventwrapper.js
similarity index 92%
rename from master/closure-library/closure/goog/events/eventwrapper.js
rename to edit/closure-library/closure/goog/events/eventwrapper.js
index c556bc1d00..aedfeaa256 100644
--- a/master/closure-library/closure/goog/events/eventwrapper.js
+++ b/edit/closure-library/closure/goog/events/eventwrapper.js
@@ -35,8 +35,7 @@ goog.events.EventWrapper = function() {
* implemented {@link goog.events.EventTarget}. A listener can only be added
* once to an object.
*
- * @param {EventTarget|goog.events.EventTarget} src The node to listen to
- * events on.
+ * @param {goog.events.ListenableType} src The node to listen to events on.
* @param {Function|Object} listener Callback method, or an object with a
* handleEvent function.
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
@@ -53,8 +52,7 @@ goog.events.EventWrapper.prototype.listen = function(src, listener, opt_capt,
/**
* Removes an event listener added using goog.events.EventWrapper.listen.
*
- * @param {EventTarget|goog.events.EventTarget} src The node to remove listener
- * from.
+ * @param {goog.events.ListenableType} src The node to remove listener from.
* @param {Function|Object} listener Callback method, or an object with a
* handleEvent function.
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
diff --git a/master/closure-library/closure/goog/events/filedrophandler.js b/edit/closure-library/closure/goog/events/filedrophandler.js
similarity index 89%
rename from master/closure-library/closure/goog/events/filedrophandler.js
rename to edit/closure-library/closure/goog/events/filedrophandler.js
index be6ea2c9c7..9b24f730cd 100644
--- a/master/closure-library/closure/goog/events/filedrophandler.js
+++ b/edit/closure-library/closure/goog/events/filedrophandler.js
@@ -23,13 +23,13 @@ goog.provide('goog.events.FileDropHandler');
goog.provide('goog.events.FileDropHandler.EventType');
goog.require('goog.array');
-goog.require('goog.debug.Logger');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
+goog.require('goog.log');
@@ -101,11 +101,11 @@ goog.events.FileDropHandler.prototype.dndContainsFiles_ = false;
/**
* A logger, used to help us debug the algorithm.
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @private
*/
goog.events.FileDropHandler.prototype.logger_ =
- goog.debug.Logger.getLogger('goog.events.FileDropHandler');
+ goog.log.getLogger('goog.events.FileDropHandler');
/**
@@ -130,7 +130,7 @@ goog.events.FileDropHandler.prototype.disposeInternal = function() {
* @private
*/
goog.events.FileDropHandler.prototype.dispatch_ = function(e) {
- this.logger_.fine('Firing DROP event...');
+ goog.log.fine(this.logger_, 'Firing DROP event...');
var event = new goog.events.BrowserEvent(e.getBrowserEvent());
event.type = goog.events.FileDropHandler.EventType.DROP;
this.dispatchEvent(event);
@@ -143,8 +143,8 @@ goog.events.FileDropHandler.prototype.dispatch_ = function(e) {
* @private
*/
goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {
- this.logger_.finer('"' + e.target.id + '" (' + e.target + ') dispatched: ' +
- e.type);
+ goog.log.log(this.logger_, goog.log.Level.FINER,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
var dt = e.getBrowserEvent().dataTransfer;
// Check whether the drag event contains files.
this.dndContainsFiles_ = !!(dt &&
@@ -157,7 +157,8 @@ goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {
// Prevent default actions.
e.preventDefault();
}
- this.logger_.finer('dndContainsFiles_: ' + this.dndContainsFiles_);
+ goog.log.log(this.logger_, goog.log.Level.FINER,
+ 'dndContainsFiles_: ' + this.dndContainsFiles_);
};
@@ -167,8 +168,8 @@ goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {
* @private
*/
goog.events.FileDropHandler.prototype.onDocDragOver_ = function(e) {
- this.logger_.finest('"' + e.target.id + '" (' + e.target + ') dispatched: ' +
- e.type);
+ goog.log.log(this.logger_, goog.log.Level.FINEST,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
if (this.dndContainsFiles_) {
// Prevent default actions.
e.preventDefault();
@@ -185,8 +186,8 @@ goog.events.FileDropHandler.prototype.onDocDragOver_ = function(e) {
* @private
*/
goog.events.FileDropHandler.prototype.onElemDragOver_ = function(e) {
- this.logger_.finest('"' + e.target.id + '" (' + e.target + ') dispatched: ' +
- e.type);
+ goog.log.log(this.logger_, goog.log.Level.FINEST,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
if (this.dndContainsFiles_) {
// Prevent default actions and stop the event from propagating further to
// the document. Both lines are needed! (See comment above).
@@ -206,8 +207,8 @@ goog.events.FileDropHandler.prototype.onElemDragOver_ = function(e) {
* @private
*/
goog.events.FileDropHandler.prototype.onElemDrop_ = function(e) {
- this.logger_.finer('"' + e.target.id + '" (' + e.target + ') dispatched: ' +
- e.type);
+ goog.log.log(this.logger_, goog.log.Level.FINER,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
// If the drag and drop event contains files.
if (this.dndContainsFiles_) {
// Prevent default actions and stop the event from propagating further to
diff --git a/master/closure-library/closure/goog/events/focushandler.js b/edit/closure-library/closure/goog/events/focushandler.js
similarity index 95%
rename from master/closure-library/closure/goog/events/focushandler.js
rename to edit/closure-library/closure/goog/events/focushandler.js
index 8a13e8635e..a4fc9332ab 100644
--- a/master/closure-library/closure/goog/events/focushandler.js
+++ b/edit/closure-library/closure/goog/events/focushandler.js
@@ -57,18 +57,18 @@ goog.events.FocusHandler = function(element) {
/**
* Store the listen key so it easier to unlisten in dispose.
* @private
- * @type {number}
+ * @type {goog.events.Key}
*/
- this.listenKeyIn_ = (/** @type {number} */
- goog.events.listen(this.element_, typeIn, this, !goog.userAgent.IE));
+ this.listenKeyIn_ =
+ goog.events.listen(this.element_, typeIn, this, !goog.userAgent.IE);
/**
* Store the listen key so it easier to unlisten in dispose.
* @private
- * @type {number}
+ * @type {goog.events.Key}
*/
- this.listenKeyOut_ = (/** @type {number} */
- goog.events.listen(this.element_, typeOut, this, !goog.userAgent.IE));
+ this.listenKeyOut_ =
+ goog.events.listen(this.element_, typeOut, this, !goog.userAgent.IE);
};
goog.inherits(goog.events.FocusHandler, goog.events.EventTarget);
diff --git a/master/closure-library/closure/goog/events/imehandler.js b/edit/closure-library/closure/goog/events/imehandler.js
similarity index 99%
rename from master/closure-library/closure/goog/events/imehandler.js
rename to edit/closure-library/closure/goog/events/imehandler.js
index aba4a477cf..238b7903a5 100644
--- a/master/closure-library/closure/goog/events/imehandler.js
+++ b/edit/closure-library/closure/goog/events/imehandler.js
@@ -49,7 +49,6 @@ goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.events.KeyCodes');
goog.require('goog.userAgent');
-goog.require('goog.userAgent.product');
@@ -143,7 +142,7 @@ goog.inherits(goog.events.ImeHandler.Event, goog.events.Event);
*/
goog.events.ImeHandler.USES_COMPOSITION_EVENTS =
goog.userAgent.GECKO ||
- (goog.userAgent.WEBKIT && goog.userAgent.isVersion(532));
+ (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher(532));
/**
diff --git a/master/closure-library/closure/goog/events/inputhandler.js b/edit/closure-library/closure/goog/events/inputhandler.js
similarity index 80%
rename from master/closure-library/closure/goog/events/inputhandler.js
rename to edit/closure-library/closure/goog/events/inputhandler.js
index 7c3c9ed14a..a910183e9d 100644
--- a/master/closure-library/closure/goog/events/inputhandler.js
+++ b/edit/closure-library/closure/goog/events/inputhandler.js
@@ -40,7 +40,6 @@ goog.provide('goog.events.InputHandler.EventType');
goog.require('goog.Timer');
goog.require('goog.dom');
-goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
@@ -58,7 +57,7 @@ goog.require('goog.userAgent');
* @extends {goog.events.EventTarget}
*/
goog.events.InputHandler = function(element) {
- goog.events.EventTarget.call(this);
+ goog.base(this);
/**
* The element that you want to listen for input events on.
@@ -67,21 +66,17 @@ goog.events.InputHandler = function(element) {
*/
this.element_ = element;
- /**
- * Whether input event is emulated.
- * IE doesn't support input events. We could use property change events but
- * they are broken in many ways:
- * - Fire even if value was changed programmatically.
- * - Aren't always delivered. For example, if you change value or even width
- * of input programmatically, next value change made by user won't fire an
- * event.
- * WebKit before version 531 did not support input events for textareas.
- * @type {boolean}
- * @private
- */
- this.inputEventEmulation_ =
- goog.userAgent.IE ||
- (goog.userAgent.WEBKIT && !goog.userAgent.isVersion('531') &&
+ // Determine whether input event should be emulated.
+ // IE8 doesn't support input events. We could use property change events but
+ // they are broken in many ways:
+ // - Fire even if value was changed programmatically.
+ // - Aren't always delivered. For example, if you change value or even width
+ // of input programmatically, next value change made by user won't fire an
+ // event.
+ // IE9 supports input events when characters are inserted, but not deleted.
+ // WebKit before version 531 did not support input events for textareas.
+ var emulateInputEvents = goog.userAgent.IE ||
+ (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('531') &&
element.tagName == 'TEXTAREA');
/**
@@ -89,9 +84,19 @@ goog.events.InputHandler = function(element) {
* @private
*/
this.eventHandler_ = new goog.events.EventHandler(this);
+
+ // Even if input event emulation is enabled, still listen for input events
+ // since they may be partially supported by the browser (such as IE9).
+ // If the input event does fire, we will be able to dispatch synchronously.
+ // (InputHandler events being asynchronous for IE is a common issue for
+ // cases like auto-grow textareas where they result in a quick flash of
+ // scrollbars between the textarea content growing and it being resized to
+ // fit.)
this.eventHandler_.listen(
this.element_,
- this.inputEventEmulation_ ? ['keydown', 'paste', 'cut', 'drop'] : 'input',
+ emulateInputEvents ?
+ ['keydown', 'paste', 'cut', 'drop', 'input'] :
+ 'input',
this);
};
goog.inherits(goog.events.InputHandler, goog.events.EventTarget);
@@ -119,7 +124,21 @@ goog.events.InputHandler.prototype.timer_ = null;
* @param {goog.events.BrowserEvent} e The underlying browser event.
*/
goog.events.InputHandler.prototype.handleEvent = function(e) {
- if (this.inputEventEmulation_) {
+ if (e.type == 'input') {
+ // This event happens after all the other events we listen to, so cancel
+ // an asynchronous event dispatch if we have it queued up. Otherwise, we
+ // will end up firing an extra event.
+ this.cancelTimerIfSet_();
+
+ // Unlike other browsers, Opera fires an extra input event when an element
+ // is blurred after the user has input into it. Since Opera doesn't fire
+ // input event on drop, it's enough to check whether element still has focus
+ // to suppress bogus notification.
+ if (!goog.userAgent.OPERA || this.element_ ==
+ goog.dom.getOwnerDocument(this.element_).activeElement) {
+ this.dispatchEvent(this.createInputEvent_(e));
+ }
+ } else {
// Filter out key events that don't modify text.
if (e.type == 'keydown' &&
!goog.events.KeyCodes.isTextModifyingKeyEvent(e)) {
@@ -156,15 +175,6 @@ goog.events.InputHandler.prototype.handleEvent = function(e) {
this.dispatchEvent(inputEvent);
}
}, 0, this);
- } else {
- // Unlike other browsers, Opera fires an extra input event when an element
- // is blurred after the user has input into it. Since Opera doesn't fire
- // input event on drop, it's enough to check whether element still has focus
- // to suppress bogus notification.
- if (!goog.userAgent.OPERA || this.element_ ==
- goog.dom.getOwnerDocument(this.element_).activeElement) {
- this.dispatchEvent(this.createInputEvent_(e));
- }
}
};
@@ -196,7 +206,7 @@ goog.events.InputHandler.prototype.createInputEvent_ = function(be) {
/** @override */
goog.events.InputHandler.prototype.disposeInternal = function() {
- goog.events.InputHandler.superClass_.disposeInternal.call(this);
+ goog.base(this, 'disposeInternal');
this.eventHandler_.dispose();
this.cancelTimerIfSet_();
delete this.element_;
diff --git a/master/closure-library/closure/goog/events/keycodes.js b/edit/closure-library/closure/goog/events/keycodes.js
similarity index 91%
rename from master/closure-library/closure/goog/events/keycodes.js
rename to edit/closure-library/closure/goog/events/keycodes.js
index cfb3da66e7..53126a6b94 100644
--- a/master/closure-library/closure/goog/events/keycodes.js
+++ b/edit/closure-library/closure/goog/events/keycodes.js
@@ -240,7 +240,7 @@ goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
opt_shiftKey, opt_ctrlKey, opt_altKey) {
if (!goog.userAgent.IE &&
- !(goog.userAgent.WEBKIT && goog.userAgent.isVersion('525'))) {
+ !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) {
return true;
}
@@ -258,10 +258,31 @@ goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
// check the user agent.
if (!opt_shiftKey &&
(opt_heldKeyCode == goog.events.KeyCodes.CTRL ||
- opt_heldKeyCode == goog.events.KeyCodes.ALT)) {
+ opt_heldKeyCode == goog.events.KeyCodes.ALT ||
+ goog.userAgent.MAC &&
+ opt_heldKeyCode == goog.events.KeyCodes.META)) {
return false;
}
+ // Some keys with Ctrl/Shift do not issue keypress in WEBKIT.
+ if (goog.userAgent.WEBKIT && opt_ctrlKey && opt_shiftKey) {
+ switch (keyCode) {
+ case goog.events.KeyCodes.BACKSLASH:
+ case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
+ case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
+ case goog.events.KeyCodes.TILDE:
+ case goog.events.KeyCodes.SEMICOLON:
+ case goog.events.KeyCodes.DASH:
+ case goog.events.KeyCodes.EQUALS:
+ case goog.events.KeyCodes.COMMA:
+ case goog.events.KeyCodes.PERIOD:
+ case goog.events.KeyCodes.SLASH:
+ case goog.events.KeyCodes.APOSTROPHE:
+ case goog.events.KeyCodes.SINGLE_QUOTE:
+ return false;
+ }
+ }
+
// When Ctrl+ is held in IE, it only fires a keypress once, but it
// continues to fire keydown events as the event repeats.
if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) {
@@ -271,7 +292,7 @@ goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
switch (keyCode) {
case goog.events.KeyCodes.ENTER:
// IE9 does not fire KEYPRESS on ENTER.
- return !(goog.userAgent.IE && goog.userAgent.isDocumentMode(9));
+ return !(goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9));
case goog.events.KeyCodes.ESC:
return !goog.userAgent.WEBKIT;
}
diff --git a/master/closure-library/closure/goog/events/keyhandler.js b/edit/closure-library/closure/goog/events/keyhandler.js
similarity index 93%
rename from master/closure-library/closure/goog/events/keyhandler.js
rename to edit/closure-library/closure/goog/events/keyhandler.js
index 68d65f9441..df565fe640 100644
--- a/master/closure-library/closure/goog/events/keyhandler.js
+++ b/edit/closure-library/closure/goog/events/keyhandler.js
@@ -145,7 +145,7 @@ goog.events.KeyHandler.prototype.element_ = null;
/**
* The key for the key press listener.
- * @type {?number}
+ * @type {goog.events.Key}
* @private
*/
goog.events.KeyHandler.prototype.keyPressKey_ = null;
@@ -153,7 +153,7 @@ goog.events.KeyHandler.prototype.keyPressKey_ = null;
/**
* The key for the key down listener.
- * @type {?number}
+ * @type {goog.events.Key}
* @private
*/
goog.events.KeyHandler.prototype.keyDownKey_ = null;
@@ -161,7 +161,7 @@ goog.events.KeyHandler.prototype.keyDownKey_ = null;
/**
* The key for the key up listener.
- * @type {?number}
+ * @type {goog.events.Key}
* @private
*/
goog.events.KeyHandler.prototype.keyUpKey_ = null;
@@ -279,7 +279,7 @@ goog.events.KeyHandler.keyIdentifier_ = {
* @private
*/
goog.events.KeyHandler.USES_KEYDOWN_ = goog.userAgent.IE ||
- goog.userAgent.WEBKIT && goog.userAgent.isVersion('525');
+ goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525');
/**
@@ -301,15 +301,28 @@ goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_ = goog.userAgent.MAC &&
* @private
*/
goog.events.KeyHandler.prototype.handleKeyDown_ = function(e) {
-
// Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
// before we've caught a key-up event. If the last-key was one of these we
// reset the state.
- if (goog.userAgent.WEBKIT &&
- (this.lastKey_ == goog.events.KeyCodes.CTRL && !e.ctrlKey ||
- this.lastKey_ == goog.events.KeyCodes.ALT && !e.altKey)) {
- this.lastKey_ = -1;
- this.keyCode_ = -1;
+
+ if (goog.userAgent.WEBKIT) {
+ if (this.lastKey_ == goog.events.KeyCodes.CTRL && !e.ctrlKey ||
+ this.lastKey_ == goog.events.KeyCodes.ALT && !e.altKey ||
+ goog.userAgent.MAC &&
+ this.lastKey_ == goog.events.KeyCodes.META && !e.metaKey) {
+ this.lastKey_ = -1;
+ this.keyCode_ = -1;
+ }
+ }
+
+ if (this.lastKey_ == -1) {
+ if (e.ctrlKey && e.keyCode != goog.events.KeyCodes.CTRL) {
+ this.lastKey_ = goog.events.KeyCodes.CTRL;
+ } else if (e.altKey && e.keyCode != goog.events.KeyCodes.ALT) {
+ this.lastKey_ = goog.events.KeyCodes.ALT;
+ } else if (e.metaKey && e.keyCode != goog.events.KeyCodes.META) {
+ this.lastKey_ = goog.events.KeyCodes.META;
+ }
}
if (goog.events.KeyHandler.USES_KEYDOWN_ &&
@@ -327,6 +340,17 @@ goog.events.KeyHandler.prototype.handleKeyDown_ = function(e) {
};
+/**
+ * Resets the stored previous values. Needed to be called for webkit which will
+ * not generate a key up for meta key operations. This should only be called
+ * when having finished with repeat key possiblities.
+ */
+goog.events.KeyHandler.prototype.resetState = function() {
+ this.lastKey_ = -1;
+ this.keyCode_ = -1;
+};
+
+
/**
* Clears the stored previous key value, resetting the key repeat status. Uses
* -1 because the Safari 3 Windows beta reports 0 for certain keys (like Home
@@ -335,8 +359,7 @@ goog.events.KeyHandler.prototype.handleKeyDown_ = function(e) {
* @private
*/
goog.events.KeyHandler.prototype.handleKeyup_ = function(e) {
- this.lastKey_ = -1;
- this.keyCode_ = -1;
+ this.resetState();
this.altKey_ = e.altKey;
};
diff --git a/master/closure-library/closure/goog/events/keynames.js b/edit/closure-library/closure/goog/events/keynames.js
similarity index 100%
rename from master/closure-library/closure/goog/events/keynames.js
rename to edit/closure-library/closure/goog/events/keynames.js
diff --git a/edit/closure-library/closure/goog/events/listenable.js b/edit/closure-library/closure/goog/events/listenable.js
new file mode 100644
index 0000000000..bc8c04a86f
--- /dev/null
+++ b/edit/closure-library/closure/goog/events/listenable.js
@@ -0,0 +1,323 @@
+// Copyright 2012 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.
+
+/**
+ * @fileoverview An interface for a listenable JavaScript object.
+ */
+
+goog.provide('goog.events.Listenable');
+goog.provide('goog.events.ListenableKey');
+
+
+
+/**
+ * A listenable interface. A listenable is an object with the ability
+ * to dispatch/broadcast events to "event listeners" registered via
+ * listen/listenOnce.
+ *
+ * The interface allows for an event propagation mechanism similar
+ * to one offered by native browser event targets, such as
+ * capture/bubble mechanism, stopping propagation, and preventing
+ * default actions. Capture/bubble mechanism depends on the ancestor
+ * tree constructed via {@code #getParentEventTarget}; this tree
+ * must be directed acyclic graph. The meaning of default action(s)
+ * in preventDefault is specific to a particular use case.
+ *
+ * Implementations that do not support capture/bubble or can not have
+ * a parent listenable can simply not implement any ability to set the
+ * parent listenable (and have {@code #getParentEventTarget} return
+ * null).
+ *
+ * Implementation of this class can be used with or independently from
+ * goog.events.
+ *
+ * Implementation must call {@code #addImplementation(implClass)}.
+ *
+ * @interface
+ * @see goog.events
+ * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html
+ */
+goog.events.Listenable = function() {};
+
+
+/**
+ * An expando property to indicate that an object implements
+ * goog.events.Listenable.
+ *
+ * See addImplementation/isImplementedBy.
+ *
+ * @type {string}
+ * @const
+ */
+goog.events.Listenable.IMPLEMENTED_BY_PROP =
+ 'closure_listenable_' + ((Math.random() * 1e6) | 0);
+
+
+/**
+ * Marks a given class (constructor) as an implementation of
+ * Listenable, do that we can query that fact at runtime. The class
+ * must have already implemented the interface.
+ * @param {!Function} cls The class constructor. The corresponding
+ * class must have already implemented the interface.
+ */
+goog.events.Listenable.addImplementation = function(cls) {
+ cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;
+};
+
+
+/**
+ * @param {Object} obj The object to check.
+ * @return {boolean} Whether a given instance implements
+ * Listenable. The class/superclass of the instance must call
+ * addImplementation.
+ */
+goog.events.Listenable.isImplementedBy = function(obj) {
+ return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);
+};
+
+
+/**
+ * Adds an event listener. A listener can only be added once to an
+ * object and if it is added again the key for the listener is
+ * returned. Note that if the existing listener is a one-off listener
+ * (registered via listenOnce), it will no longer be a one-off
+ * listener after a call to listen().
+ *
+ * @param {string} type Event type or array of event types.
+ * @param {!Function} listener Callback method, or an object
+ * with a handleEvent function.
+ * @param {boolean=} opt_useCapture Whether to fire in capture phase
+ * (defaults to false).
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ */
+goog.events.Listenable.prototype.listen;
+
+
+/**
+ * Adds an event listener that is removed automatically after the
+ * listener fired once.
+ *
+ * If an existing listener already exists, listenOnce will do
+ * nothing. In particular, if the listener was previously registered
+ * via listen(), listenOnce() will not turn the listener into a
+ * one-off listener. Similarly, if there is already an existing
+ * one-off listener, listenOnce does not modify the listeners (it is
+ * still a once listener).
+ *
+ * @param {string} type Event type or array of event types.
+ * @param {!Function} listener Callback method, or an object
+ * with a handleEvent function.
+ * @param {boolean=} opt_useCapture Whether to fire in capture phase
+ * (defaults to false).
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ */
+goog.events.Listenable.prototype.listenOnce;
+
+
+/**
+ * Removes an event listener which was added with listen() or listenOnce().
+ *
+ * @param {string} type Event type or array of event types.
+ * @param {!Function} listener Callback method, or an object
+ * with a handleEvent function.
+ * @param {boolean=} opt_useCapture Whether to fire in capture phase
+ * (defaults to false).
+ * @param {Object=} opt_listenerScope Object in whose scope to call
+ * the listener.
+ * @return {boolean} Whether any listener was removed.
+ */
+goog.events.Listenable.prototype.unlisten;
+
+
+/**
+ * Removes an event listener which was added with listen() by the key
+ * returned by listen().
+ *
+ * @param {goog.events.ListenableKey} key The key returned by
+ * listen() or listenOnce().
+ * @return {boolean} Whether any listener was removed.
+ */
+goog.events.Listenable.prototype.unlistenByKey;
+
+
+/**
+ * Dispatches an event (or event like object) and calls all listeners
+ * listening for events of this type. The type of the event is decided by the
+ * type property on the event object.
+ *
+ * If any of the listeners returns false OR calls preventDefault then this
+ * function will return false. If one of the capture listeners calls
+ * stopPropagation, then the bubble listeners won't fire.
+ *
+ * @param {goog.events.EventLike} e Event object.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the listeners returns false) this will also return false.
+ */
+goog.events.Listenable.prototype.dispatchEvent;
+
+
+/**
+ * Removes all listeners from this listenable. If type is specified,
+ * it will only remove listeners of the particular type. otherwise all
+ * registered listeners will be removed.
+ *
+ * @param {string=} opt_type Type of event to remove, default is to
+ * remove all types.
+ * @return {number} Number of listeners removed.
+ */
+goog.events.Listenable.prototype.removeAllListeners;
+
+
+/**
+ * Returns the parent of this event target to use for capture/bubble
+ * mechanism.
+ *
+ * NOTE(user): The name reflects the original implementation of
+ * custom event target ({@code goog.events.EventTarget}). We decided
+ * that changing the name is not worth it.
+ *
+ * @return {goog.events.Listenable} The parent EventTarget or null if
+ * there is no parent.
+ */
+goog.events.Listenable.prototype.getParentEventTarget;
+
+
+/**
+ * Fires all registered listeners in this listenable for the given
+ * type and capture mode, passing them the given eventObject. This
+ * does not perform actual capture/bubble. Only implementors of the
+ * interface should be using this.
+ *
+ * @param {string} type The type of the listeners to fire.
+ * @param {boolean} capture The capture mode of the listeners to fire.
+ * @param {goog.events.Event} eventObject The event object to fire.
+ * @return {boolean} Whether all listeners succeeded without
+ * attempting to prevent default behavior. If any listener returns
+ * false or called goog.events.Event#preventDefault, this returns
+ * false.
+ */
+goog.events.Listenable.prototype.fireListeners;
+
+
+/**
+ * Gets all listeners in this listenable for the given type and
+ * capture mode.
+ *
+ * @param {string} type The type of the listeners to fire.
+ * @param {boolean} capture The capture mode of the listeners to fire.
+ * @return {!Array.} An array of registered
+ * listeners.
+ */
+goog.events.Listenable.prototype.getListeners;
+
+
+/**
+ * Gets the goog.events.ListenableKey for the event or null if no such
+ * listener is in use.
+ *
+ * @param {string} type The name of the event without the 'on' prefix.
+ * @param {!Function} listener The listener function to get.
+ * @param {boolean} capture Whether the listener is a capturing listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} the found listener or null if not found.
+ */
+goog.events.Listenable.prototype.getListener;
+
+
+/**
+ * Whether there is any active listeners matching the specified
+ * signature. If either the type or capture parameters are
+ * unspecified, the function will match on the remaining criteria.
+ *
+ * @param {string=} opt_type Event type.
+ * @param {boolean=} opt_capture Whether to check for capture or bubble
+ * listeners.
+ * @return {boolean} Whether there is any active listeners matching
+ * the requested type and/or capture phase.
+ */
+goog.events.Listenable.prototype.hasListener;
+
+
+
+/**
+ * An interface that describes a single registered listener.
+ * @interface
+ */
+goog.events.ListenableKey = function() {};
+
+
+/**
+ * Counter used to create a unique key
+ * @type {number}
+ * @private
+ */
+goog.events.ListenableKey.counter_ = 0;
+
+
+/**
+ * Reserves a key to be used for ListenableKey#key field.
+ * @return {number} A number to be used to fill ListenableKey#key
+ * field.
+ */
+goog.events.ListenableKey.reserveKey = function() {
+ return ++goog.events.ListenableKey.counter_;
+};
+
+
+/**
+ * The source event target.
+ * @type {!(Object|goog.events.Listenable|goog.events.EventTarget)}
+ */
+goog.events.ListenableKey.prototype.src;
+
+
+/**
+ * The event type the listener is listening to.
+ * @type {string}
+ */
+goog.events.ListenableKey.prototype.type;
+
+
+/**
+ * The listener function.
+ * TODO(user): Narrow the type if possible.
+ * @type {Function|Object}
+ */
+goog.events.ListenableKey.prototype.listener;
+
+
+/**
+ * Whether the listener works on capture phase.
+ * @type {boolean}
+ */
+goog.events.ListenableKey.prototype.capture;
+
+
+/**
+ * The 'this' object for the listener function's scope.
+ * @type {Object}
+ */
+goog.events.ListenableKey.prototype.handler;
+
+
+/**
+ * A globally unique number to identify the key.
+ * @type {number}
+ */
+goog.events.ListenableKey.prototype.key;
diff --git a/edit/closure-library/closure/goog/events/listener.js b/edit/closure-library/closure/goog/events/listener.js
new file mode 100644
index 0000000000..60c737021b
--- /dev/null
+++ b/edit/closure-library/closure/goog/events/listener.js
@@ -0,0 +1,131 @@
+// Copyright 2005 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.
+
+/**
+ * @fileoverview Listener object.
+ * @see ../demos/events.html
+ */
+
+goog.provide('goog.events.Listener');
+
+goog.require('goog.events.ListenableKey');
+
+
+
+/**
+ * Simple class that stores information about a listener
+ * @param {!Function} listener Callback function.
+ * @param {Function} proxy Wrapper for the listener that patches the event.
+ * @param {EventTarget|goog.events.Listenable} src Source object for
+ * the event.
+ * @param {string} type Event type.
+ * @param {boolean} capture Whether in capture or bubble phase.
+ * @param {Object=} opt_handler Object in whose context to execute the callback.
+ * @implements {goog.events.ListenableKey}
+ * @constructor
+ */
+goog.events.Listener = function(
+ listener, proxy, src, type, capture, opt_handler) {
+ if (goog.events.Listener.ENABLE_MONITORING) {
+ this.creationStack = new Error().stack;
+ }
+
+ /**
+ * Callback function.
+ * @type {Function}
+ */
+ this.listener = listener;
+
+ /**
+ * A wrapper over the original listener. This is used solely to
+ * handle native browser events (it is used to simulate the capture
+ * phase and to patch the event object).
+ * @type {Function}
+ */
+ this.proxy = proxy;
+
+ /**
+ * Object or node that callback is listening to
+ * @type {EventTarget|goog.events.Listenable}
+ */
+ this.src = src;
+
+ /**
+ * The event type.
+ * @const {string}
+ */
+ this.type = type;
+
+ /**
+ * Whether the listener is being called in the capture or bubble phase
+ * @const {boolean}
+ */
+ this.capture = !!capture;
+
+ /**
+ * Optional object whose context to execute the listener in
+ * @type {Object|undefined}
+ */
+ this.handler = opt_handler;
+
+ /**
+ * The key of the listener.
+ * @const {number}
+ * @override
+ */
+ this.key = goog.events.ListenableKey.reserveKey();
+
+ /**
+ * Whether to remove the listener after it has been called.
+ * @type {boolean}
+ */
+ this.callOnce = false;
+
+ /**
+ * Whether the listener has been removed.
+ * @type {boolean}
+ */
+ this.removed = false;
+};
+
+
+/**
+ * @define {boolean} Whether to enable the monitoring of the
+ * goog.events.Listener instances. Switching on the monitoring is only
+ * recommended for debugging because it has a significant impact on
+ * performance and memory usage. If switched off, the monitoring code
+ * compiles down to 0 bytes.
+ */
+goog.define('goog.events.Listener.ENABLE_MONITORING', false);
+
+
+/**
+ * If monitoring the goog.events.Listener instances is enabled, stores the
+ * creation stack trace of the Disposable instance.
+ * @type {string}
+ */
+goog.events.Listener.prototype.creationStack;
+
+
+/**
+ * Marks this listener as removed. This also remove references held by
+ * this listener object (such as listener and event source).
+ */
+goog.events.Listener.prototype.markAsRemoved = function() {
+ this.removed = true;
+ this.listener = null;
+ this.proxy = null;
+ this.src = null;
+ this.handler = null;
+};
diff --git a/edit/closure-library/closure/goog/events/listenermap.js b/edit/closure-library/closure/goog/events/listenermap.js
new file mode 100644
index 0000000000..31eb1a318d
--- /dev/null
+++ b/edit/closure-library/closure/goog/events/listenermap.js
@@ -0,0 +1,299 @@
+// Copyright 2013 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.
+
+/**
+ * @fileoverview A map of listeners that provides utility functions to
+ * deal with listeners on an event target. Used by
+ * {@code goog.events.EventTarget}.
+ *
+ * WARNING: Do not use this class from outside goog.events package.
+ *
+ * @visibility {//closure/goog/events:__pkg__}
+ */
+
+goog.provide('goog.events.ListenerMap');
+
+goog.require('goog.array');
+goog.require('goog.events.Listener');
+goog.require('goog.object');
+
+
+
+/**
+ * Creates a new listener map.
+ * @param {EventTarget|goog.events.Listenable} src The src object.
+ * @constructor
+ */
+goog.events.ListenerMap = function(src) {
+ /** @type {EventTarget|goog.events.Listenable} */
+ this.src = src;
+
+ /**
+ * Maps of event type to an array of listeners.
+ * @type {Object.>}
+ */
+ this.listeners = {};
+
+ /**
+ * The count of types in this map that have registered listeners.
+ * @private {number}
+ */
+ this.typeCount_ = 0;
+};
+
+
+/**
+ * @return {number} The count of event types in this map that actually
+ * have registered listeners.
+ */
+goog.events.ListenerMap.prototype.getTypeCount = function() {
+ return this.typeCount_;
+};
+
+
+/**
+ * @return {number} Total number of registered listeners.
+ */
+goog.events.ListenerMap.prototype.getListenerCount = function() {
+ var count = 0;
+ for (var type in this.listeners) {
+ count += this.listeners[type].length;
+ }
+ return count;
+};
+
+
+/**
+ * Adds an event listener. A listener can only be added once to an
+ * object and if it is added again the key for the listener is
+ * returned.
+ *
+ * Note that a one-off listener will not change an existing listener,
+ * if any. On the other hand a normal listener will change existing
+ * one-off listener to become a normal listener.
+ *
+ * @param {string} type The listener event type.
+ * @param {!Function} listener This listener callback method.
+ * @param {boolean} callOnce Whether the listener is a one-off
+ * listener.
+ * @param {boolean=} opt_useCapture The capture mode of the listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ */
+goog.events.ListenerMap.prototype.add = function(
+ type, listener, callOnce, opt_useCapture, opt_listenerScope) {
+ var listenerArray = this.listeners[type];
+ if (!listenerArray) {
+ listenerArray = this.listeners[type] = [];
+ this.typeCount_++;
+ }
+
+ var listenerObj;
+ var index = goog.events.ListenerMap.findListenerIndex_(
+ listenerArray, listener, opt_useCapture, opt_listenerScope);
+ if (index > -1) {
+ listenerObj = listenerArray[index];
+ if (!callOnce) {
+ // Ensure that, if there is an existing callOnce listener, it is no
+ // longer a callOnce listener.
+ listenerObj.callOnce = false;
+ }
+ } else {
+ listenerObj = new goog.events.Listener(
+ listener, null, this.src, type, !!opt_useCapture, opt_listenerScope);
+ listenerObj.callOnce = callOnce;
+ listenerArray.push(listenerObj);
+ }
+ return listenerObj;
+};
+
+
+/**
+ * Removes a matching listener.
+ * @param {string} type The listener event type.
+ * @param {!Function} listener This listener callback method.
+ * @param {boolean=} opt_useCapture The capture mode of the listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {boolean} Whether any listener was removed.
+ */
+goog.events.ListenerMap.prototype.remove = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ if (!(type in this.listeners)) {
+ return false;
+ }
+
+ var listenerArray = this.listeners[type];
+ var index = goog.events.ListenerMap.findListenerIndex_(
+ listenerArray, listener, opt_useCapture, opt_listenerScope);
+ if (index > -1) {
+ var listenerObj = listenerArray[index];
+ listenerObj.markAsRemoved();
+ goog.array.removeAt(listenerArray, index);
+ if (listenerArray.length == 0) {
+ delete this.listeners[type];
+ this.typeCount_--;
+ }
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes the given listener object.
+ * @param {goog.events.ListenableKey} listener The listener to remove.
+ * @return {boolean} Whether the listener is removed.
+ */
+goog.events.ListenerMap.prototype.removeByKey = function(listener) {
+ var type = listener.type;
+ if (!(type in this.listeners)) {
+ return false;
+ }
+
+ var removed = goog.array.remove(this.listeners[type], listener);
+ if (removed) {
+ listener.markAsRemoved();
+ if (this.listeners[type].length == 0) {
+ delete this.listeners[type];
+ this.typeCount_--;
+ }
+ }
+ return removed;
+};
+
+
+/**
+ * Removes all listeners from this map. If opt_type is provided, only
+ * listeners that match the given type are removed.
+ * @param {string=} opt_type Type of event to remove.
+ * @return {number} Number of listeners removed.
+ */
+goog.events.ListenerMap.prototype.removeAll = function(opt_type) {
+ var count = 0;
+ for (var type in this.listeners) {
+ if (!opt_type || type == opt_type) {
+ var listenerArray = this.listeners[type];
+ for (var i = 0; i < listenerArray.length; i++) {
+ ++count;
+ listenerArray[i].removed = true;
+ }
+ delete this.listeners[type];
+ this.typeCount_--;
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Gets all listeners that match the given type and capture mode. The
+ * returned array is a copy (but the listener objects are not).
+ * @param {string} type The type of the listeners to retrieve.
+ * @param {boolean} capture The capture mode of the listeners to retrieve.
+ * @return {!Array.} An array of matching
+ * listeners.
+ */
+goog.events.ListenerMap.prototype.getListeners = function(type, capture) {
+ var listenerArray = this.listeners[type];
+ var rv = [];
+ if (listenerArray) {
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listenerObj = listenerArray[i];
+ if (listenerObj.capture == capture) {
+ rv.push(listenerObj);
+ }
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Gets the goog.events.ListenableKey for the event or null if no such
+ * listener is in use.
+ *
+ * @param {string} type The type of the listener to retrieve.
+ * @param {!Function} listener The listener function to get.
+ * @param {boolean} capture Whether the listener is a capturing listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} the found listener or null if not found.
+ */
+goog.events.ListenerMap.prototype.getListener = function(
+ type, listener, capture, opt_listenerScope) {
+ var listenerArray = this.listeners[type];
+ var i = -1;
+ if (listenerArray) {
+ i = goog.events.ListenerMap.findListenerIndex_(
+ listenerArray, listener, capture, opt_listenerScope);
+ }
+ return i > -1 ? listenerArray[i] : null;
+};
+
+
+/**
+ * Whether there is a matching listener. If either the type or capture
+ * parameters are unspecified, the function will match on the
+ * remaining criteria.
+ *
+ * @param {string=} opt_type The type of the listener.
+ * @param {boolean=} opt_capture The capture mode of the listener.
+ * @return {boolean} Whether there is an active listener matching
+ * the requested type and/or capture phase.
+ */
+goog.events.ListenerMap.prototype.hasListener = function(
+ opt_type, opt_capture) {
+ var hasType = goog.isDef(opt_type);
+ var hasCapture = goog.isDef(opt_capture);
+
+ return goog.object.some(
+ this.listeners, function(listenerArray, type) {
+ for (var i = 0; i < listenerArray.length; ++i) {
+ if ((!hasType || listenerArray[i].type == opt_type) &&
+ (!hasCapture || listenerArray[i].capture == opt_capture)) {
+ return true;
+ }
+ }
+
+ return false;
+ });
+};
+
+
+/**
+ * Finds the index of a matching goog.events.Listener in the given
+ * listenerArray.
+ * @param {!Array.} listenerArray Array of listener.
+ * @param {!Function} listener The listener function.
+ * @param {boolean=} opt_useCapture The capture flag for the listener.
+ * @param {Object=} opt_listenerScope The listener scope.
+ * @return {number} The index of the matching listener within the
+ * listenerArray.
+ * @private
+ */
+goog.events.ListenerMap.findListenerIndex_ = function(
+ listenerArray, listener, opt_useCapture, opt_listenerScope) {
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listenerObj = listenerArray[i];
+ if (!listenerObj.removed &&
+ listenerObj.listener == listener &&
+ listenerObj.capture == !!opt_useCapture &&
+ listenerObj.handler == opt_listenerScope) {
+ return i;
+ }
+ }
+ return -1;
+};
diff --git a/edit/closure-library/closure/goog/events/listenermap_test.js b/edit/closure-library/closure/goog/events/listenermap_test.js
new file mode 100644
index 0000000000..4b00727b05
--- /dev/null
+++ b/edit/closure-library/closure/goog/events/listenermap_test.js
@@ -0,0 +1,116 @@
+// Copyright 2013 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.
+
+/**
+ * @fileoverview Tests for listenermap.js.
+ *
+ * Most of this class functionality is already tested by
+ * goog.events.EventTarget tests. This test file only provides tests
+ * for features that are not direct duplicates of tests in
+ * goog.events.EventTarget.
+ */
+
+goog.provide('goog.events.ListenerMapTest');
+goog.setTestOnly('goog.events.ListenerMapTest');
+
+goog.require('goog.dispose');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.ListenerMap');
+goog.require('goog.testing.jsunit');
+
+
+var et, map;
+var handler1 = function() {};
+var handler2 = function() {};
+var handler3 = function() {};
+var handler4 = function() {};
+var handler5 = function() {};
+
+
+function setUp() {
+ et = new goog.events.EventTarget();
+ map = new goog.events.ListenerMap(et);
+}
+
+
+function tearDown() {
+ goog.dispose(et);
+}
+
+
+function testGetTypeCount() {
+ assertEquals(0, map.getTypeCount());
+
+ map.add('click', handler1, false);
+ assertEquals(1, map.getTypeCount());
+ map.remove('click', handler1);
+ assertEquals(0, map.getTypeCount());
+
+ map.add('click', handler1, false, true);
+ assertEquals(1, map.getTypeCount());
+ map.remove('click', handler1, true);
+ assertEquals(0, map.getTypeCount());
+
+ map.add('click', handler1, false);
+ map.add('click', handler1, false, true);
+ assertEquals(1, map.getTypeCount());
+ map.remove('click', handler1);
+ assertEquals(1, map.getTypeCount());
+ map.remove('click', handler1, true);
+ assertEquals(0, map.getTypeCount());
+
+ map.add('click', handler1, false);
+ map.add('touchstart', handler2, false);
+ assertEquals(2, map.getTypeCount());
+ map.remove('touchstart', handler2);
+ assertEquals(1, map.getTypeCount());
+ map.remove('click', handler1);
+ assertEquals(0, map.getTypeCount());
+}
+
+
+function testGetListenerCount() {
+ assertEquals(0, map.getListenerCount());
+
+ map.add('click', handler1, false);
+ assertEquals(1, map.getListenerCount());
+ map.remove('click', handler1);
+ assertEquals(0, map.getListenerCount());
+
+ map.add('click', handler1, false, true);
+ assertEquals(1, map.getListenerCount());
+ map.remove('click', handler1, true);
+ assertEquals(0, map.getListenerCount());
+
+ map.add('click', handler1, false);
+ map.add('click', handler1, false, true);
+ assertEquals(2, map.getListenerCount());
+ map.remove('click', handler1);
+ map.remove('click', handler1, true);
+ assertEquals(0, map.getListenerCount());
+
+ map.add('click', handler1, false);
+ map.add('touchstart', handler2, false);
+ assertEquals(2, map.getListenerCount());
+ map.remove('touchstart', handler2);
+ map.remove('click', handler1);
+ assertEquals(0, map.getListenerCount());
+}
+
+
+function testListenerSourceIsSetCorrectly() {
+ map.add('click', handler1, false);
+ var listener = map.getListener('click', handler1);
+ assertEquals(et, listener.src);
+}
diff --git a/master/closure-library/closure/goog/events/mousewheelhandler.js b/edit/closure-library/closure/goog/events/mousewheelhandler.js
similarity index 95%
rename from master/closure-library/closure/goog/events/mousewheelhandler.js
rename to edit/closure-library/closure/goog/events/mousewheelhandler.js
index 6ed76caea9..55a3b3807c 100644
--- a/master/closure-library/closure/goog/events/mousewheelhandler.js
+++ b/edit/closure-library/closure/goog/events/mousewheelhandler.js
@@ -32,6 +32,7 @@ goog.provide('goog.events.MouseWheelEvent');
goog.provide('goog.events.MouseWheelHandler');
goog.provide('goog.events.MouseWheelHandler.EventType');
+goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventTarget');
@@ -46,10 +47,12 @@ goog.require('goog.userAgent');
* manner.
* @param {Element|Document} element The element to listen to the mouse wheel
* event on.
+ * @param {boolean=} opt_capture Whether to handle the mouse wheel event in
+ * capture phase.
* @constructor
* @extends {goog.events.EventTarget}
*/
-goog.events.MouseWheelHandler = function(element) {
+goog.events.MouseWheelHandler = function(element, opt_capture) {
goog.events.EventTarget.call(this);
/**
@@ -60,8 +63,8 @@ goog.events.MouseWheelHandler = function(element) {
this.element_ = element;
var rtlElement = goog.dom.isElement(this.element_) ?
- (/** @type {Element} */ this.element_) :
- (this.element_ ? (/** @type {Document} */ this.element_).body : null);
+ /** @type {Element} */ (this.element_) :
+ (this.element_ ? /** @type {Document} */ (this.element_).body : null);
/**
* True if the element exists and is RTL, false otherwise.
@@ -74,10 +77,10 @@ goog.events.MouseWheelHandler = function(element) {
/**
* The key returned from the goog.events.listen.
- * @type {?number}
+ * @type {goog.events.Key}
* @private
*/
- this.listenKey_ = goog.events.listen(this.element_, type, this);
+ this.listenKey_ = goog.events.listen(this.element_, type, this, opt_capture);
};
goog.inherits(goog.events.MouseWheelHandler, goog.events.EventTarget);
@@ -138,7 +141,7 @@ goog.events.MouseWheelHandler.prototype.handleEvent = function(e) {
var wheelDeltaScaleFactor = 1;
if (goog.userAgent.IE ||
goog.userAgent.WEBKIT &&
- (goog.userAgent.WINDOWS || goog.userAgent.isVersion('532.0'))) {
+ (goog.userAgent.WINDOWS || goog.userAgent.isVersionOrHigher('532.0'))) {
// In IE we get a multiple of 120; we adjust to a multiple of 3 to
// represent number of lines scrolled (like Gecko).
// Newer versions of Webkit match IE behavior, and WebKit on
@@ -238,7 +241,7 @@ goog.events.MouseWheelHandler.smartScale_ = function(mouseWheelDelta,
goog.events.MouseWheelHandler.prototype.disposeInternal = function() {
goog.events.MouseWheelHandler.superClass_.disposeInternal.call(this);
goog.events.unlistenByKey(this.listenKey_);
- delete this.listenKey_;
+ this.listenKey_ = null;
};
diff --git a/master/closure-library/closure/goog/events/onlinehandler.js b/edit/closure-library/closure/goog/events/onlinehandler.js
similarity index 83%
rename from master/closure-library/closure/goog/events/onlinehandler.js
rename to edit/closure-library/closure/goog/events/onlinehandler.js
index c782e1d073..4efdc07edc 100644
--- a/master/closure-library/closure/goog/events/onlinehandler.js
+++ b/edit/closure-library/closure/goog/events/onlinehandler.js
@@ -38,6 +38,8 @@ goog.require('goog.Timer');
goog.require('goog.events.BrowserFeature');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.net.NetworkStatusMonitor');
goog.require('goog.userAgent');
@@ -46,10 +48,14 @@ goog.require('goog.userAgent');
* Basic object for detecting whether the online state changes.
* @constructor
* @extends {goog.events.EventTarget}
+ * @implements {goog.net.NetworkStatusMonitor}
*/
goog.events.OnlineHandler = function() {
- goog.events.EventTarget.call(this);
+ goog.base(this);
+ /**
+ * @private {goog.events.EventHandler}
+ */
this.eventHandler_ = new goog.events.EventHandler(this);
// Some browsers do not support navigator.onLine and therefore we don't
@@ -62,8 +68,9 @@ goog.events.OnlineHandler = function() {
var target =
goog.events.BrowserFeature.HTML5_NETWORK_EVENTS_FIRE_ON_BODY ?
document.body : window;
- this.eventHandler_.listen(target, ['online', 'offline'],
- this.handleChange_);
+ this.eventHandler_.listen(target,
+ [goog.events.EventType.ONLINE, goog.events.EventType.OFFLINE],
+ this.handleChange_);
} else {
this.online_ = this.isOnline();
this.timer_ = new goog.Timer(goog.events.OnlineHandler.POLL_INTERVAL_);
@@ -77,11 +84,9 @@ goog.inherits(goog.events.OnlineHandler, goog.events.EventTarget);
/**
* Enum for the events dispatched by the OnlineHandler.
* @enum {string}
+ * @deprecated Use goog.net.NetworkStatusMonitor.EventType instead.
*/
-goog.events.OnlineHandler.EventType = {
- ONLINE: 'online',
- OFFLINE: 'offline'
-};
+goog.events.OnlineHandler.EventType = goog.net.NetworkStatusMonitor.EventType;
/**
@@ -109,19 +114,7 @@ goog.events.OnlineHandler.prototype.online_;
goog.events.OnlineHandler.prototype.timer_;
-/**
- * Event handler to simplify event listening.
- * @type {goog.events.EventHandler}
- * @private
- */
-goog.events.OnlineHandler.prototype.eventHandler_;
-
-
-/**
- * Returns whether or not the system is online. This method works properly
- * regardless of whether or not the listener IsListening.
- * @return {boolean} Whether the browser is currently thinking it is online.
- */
+/** @override */
goog.events.OnlineHandler.prototype.isOnline = function() {
return goog.events.BrowserFeature.HAS_NAVIGATOR_ONLINE_PROPERTY ?
navigator.onLine : true;
@@ -151,19 +144,19 @@ goog.events.OnlineHandler.prototype.handleTick_ = function(e) {
*/
goog.events.OnlineHandler.prototype.handleChange_ = function(e) {
var type = this.isOnline() ?
- goog.events.OnlineHandler.EventType.ONLINE :
- goog.events.OnlineHandler.EventType.OFFLINE;
+ goog.net.NetworkStatusMonitor.EventType.ONLINE :
+ goog.net.NetworkStatusMonitor.EventType.OFFLINE;
this.dispatchEvent(type);
};
/** @override */
goog.events.OnlineHandler.prototype.disposeInternal = function() {
- goog.events.OnlineHandler.superClass_.disposeInternal.call(this);
+ goog.base(this, 'disposeInternal');
this.eventHandler_.dispose();
- delete this.eventHandler_;
+ this.eventHandler_ = null;
if (this.timer_) {
this.timer_.dispose();
- delete this.timer_;
+ this.timer_ = null;
}
};
diff --git a/master/closure-library/closure/goog/events/pastehandler.js b/edit/closure-library/closure/goog/events/pastehandler.js
similarity index 93%
rename from master/closure-library/closure/goog/events/pastehandler.js
rename to edit/closure-library/closure/goog/events/pastehandler.js
index 70c370e64d..926dd1d943 100644
--- a/master/closure-library/closure/goog/events/pastehandler.js
+++ b/edit/closure-library/closure/goog/events/pastehandler.js
@@ -38,12 +38,13 @@ goog.provide('goog.events.PasteHandler.State');
goog.require('goog.Timer');
goog.require('goog.async.ConditionalDelay');
-goog.require('goog.debug.Logger');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.events.KeyCodes');
+goog.require('goog.log');
+goog.require('goog.userAgent');
@@ -93,7 +94,7 @@ goog.events.PasteHandler = function(element) {
if (goog.userAgent.WEBKIT ||
goog.userAgent.IE ||
- goog.userAgent.GECKO && goog.userAgent.isVersion('1.9')) {
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')) {
// Most modern browsers support the paste event.
this.eventHandler_.listen(element, goog.events.EventType.PASTE,
this.dispatch_);
@@ -200,11 +201,11 @@ goog.events.PasteHandler.prototype.previousEvent_;
/**
* A logger, used to help us debug the algorithm.
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @private
*/
goog.events.PasteHandler.prototype.logger_ =
- goog.debug.Logger.getLogger('goog.events.PasteHandler');
+ goog.log.getLogger('goog.events.PasteHandler');
/** @override */
@@ -248,7 +249,7 @@ goog.events.PasteHandler.prototype.checkUpdatedText_ = function() {
if (this.oldValue_ == this.element_.value) {
return false;
}
- this.logger_.info('detected textchange after paste');
+ goog.log.info(this.logger_, 'detected textchange after paste');
this.dispatchEvent(goog.events.PasteHandler.EventType.AFTER_PASTE);
return true;
};
@@ -345,12 +346,12 @@ goog.events.PasteHandler.prototype.handleEvent_ = function(e) {
break;
}
default: {
- this.logger_.severe('invalid ' + this.state_ + ' state');
+ goog.log.error(this.logger_, 'invalid ' + this.state_ + ' state');
}
}
this.lastTime_ = goog.now();
this.oldValue_ = this.element_.value;
- this.logger_.info(e.type + ' -> ' + this.state_);
+ goog.log.info(this.logger_, e.type + ' -> ' + this.state_);
this.previousEvent_ = e.type;
};
@@ -381,13 +382,14 @@ goog.events.PasteHandler.prototype.handleUnderInit_ = function(e) {
case goog.events.EventType.MOUSEOVER: {
this.state_ = goog.events.PasteHandler.State.INIT;
if (this.element_.value != this.oldValue_) {
- this.logger_.info('paste by dragdrop while on init!');
+ goog.log.info(this.logger_, 'paste by dragdrop while on init!');
this.dispatch_(e);
}
break;
}
default: {
- this.logger_.severe('unexpected event ' + e.type + 'during init');
+ goog.log.error(this.logger_,
+ 'unexpected event ' + e.type + 'during init');
}
}
};
@@ -432,7 +434,7 @@ goog.events.PasteHandler.prototype.handleUnderFocused_ = function(e) {
MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER;
if (goog.now() > minimumMilisecondsBetweenInputEvents ||
this.previousEvent_ == goog.events.EventType.FOCUS) {
- this.logger_.info('paste by textchange while focused!');
+ goog.log.info(this.logger_, 'paste by textchange while focused!');
this.dispatch_(e);
}
break;
@@ -442,7 +444,7 @@ goog.events.PasteHandler.prototype.handleUnderFocused_ = function(e) {
break;
}
case goog.events.EventType.KEYDOWN: {
- this.logger_.info('key down ... looking for ctrl+v');
+ goog.log.info(this.logger_, 'key down ... looking for ctrl+v');
// Opera + MAC does not set e.ctrlKey. Instead, it gives me e.keyCode = 0.
// http://www.quirksmode.org/js/keys.html
if (goog.userAgent.MAC && goog.userAgent.OPERA && e.keyCode == 0 ||
@@ -454,13 +456,14 @@ goog.events.PasteHandler.prototype.handleUnderFocused_ = function(e) {
}
case goog.events.EventType.MOUSEOVER: {
if (this.element_.value != this.oldValue_) {
- this.logger_.info('paste by dragdrop while focused!');
+ goog.log.info(this.logger_, 'paste by dragdrop while focused!');
this.dispatch_(e);
}
break;
}
default: {
- this.logger_.severe('unexpected event ' + e.type + ' during focused');
+ goog.log.error(this.logger_,
+ 'unexpected event ' + e.type + ' during focused');
}
}
};
@@ -492,20 +495,21 @@ goog.events.PasteHandler.prototype.handleUnderTyping_ = function(e) {
if (e.ctrlKey && e.keyCode == goog.events.KeyCodes.V ||
e.shiftKey && e.keyCode == goog.events.KeyCodes.INSERT ||
e.metaKey && e.keyCode == goog.events.KeyCodes.V) {
- this.logger_.info('paste by ctrl+v while keypressed!');
+ goog.log.info(this.logger_, 'paste by ctrl+v while keypressed!');
this.dispatch_(e);
}
break;
}
case goog.events.EventType.MOUSEOVER: {
if (this.element_.value != this.oldValue_) {
- this.logger_.info('paste by dragdrop while keypressed!');
+ goog.log.info(this.logger_, 'paste by dragdrop while keypressed!');
this.dispatch_(e);
}
break;
}
default: {
- this.logger_.severe('unexpected event ' + e.type + ' during keypressed');
+ goog.log.error(this.logger_,
+ 'unexpected event ' + e.type + ' during keypressed');
}
}
};
diff --git a/master/closure-library/closure/goog/format/emailaddress.js b/edit/closure-library/closure/goog/format/emailaddress.js
similarity index 96%
rename from master/closure-library/closure/goog/format/emailaddress.js
rename to edit/closure-library/closure/goog/format/emailaddress.js
index cdaeef70bc..e74bd3f487 100644
--- a/master/closure-library/closure/goog/format/emailaddress.js
+++ b/edit/closure-library/closure/goog/format/emailaddress.js
@@ -198,10 +198,11 @@ goog.format.EmailAddress.isValidAddress = function(str) {
*/
goog.format.EmailAddress.isValidAddrSpec = function(str) {
// This is a fairly naive implementation, but it covers 99% of use cases.
- // For example, having two dots in a row isn't valid, but I don't think we
- // need that level of validation. Also, things like [a@b]@c.com is valid, but
- // I don't think anyone would accept it.
- var filter = /^[+a-zA-Z0-9_.-]+@([a-zA-Z0-9-]+\.)+[a-zA-Z0-9]{2,6}$/;
+ // For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
+ // TODO(mariakhomenko): we should also be handling i18n domain names as per
+ // http://en.wikipedia.org/wiki/Internationalized_domain_name
+ var filter =
+ /^[+a-zA-Z0-9_.!#$%&'*\/=?^`{|}~-]+@([a-zA-Z0-9-]+\.)+[a-zA-Z0-9]{2,6}$/;
return filter.test(str);
};
diff --git a/master/closure-library/closure/goog/format/format.js b/edit/closure-library/closure/goog/format/format.js
similarity index 99%
rename from master/closure-library/closure/goog/format/format.js
rename to edit/closure-library/closure/goog/format/format.js
index d9feb569fe..2ac1327912 100644
--- a/master/closure-library/closure/goog/format/format.js
+++ b/edit/closure-library/closure/goog/format/format.js
@@ -460,7 +460,7 @@ goog.format.insertWordBreaksBasic = function(str, opt_maxlen) {
* @private
*/
goog.format.IS_IE8_OR_ABOVE_ = goog.userAgent.IE &&
- goog.userAgent.isVersion(8);
+ goog.userAgent.isVersionOrHigher(8);
/**
diff --git a/master/closure-library/closure/goog/format/htmlprettyprinter.js b/edit/closure-library/closure/goog/format/htmlprettyprinter.js
similarity index 100%
rename from master/closure-library/closure/goog/format/htmlprettyprinter.js
rename to edit/closure-library/closure/goog/format/htmlprettyprinter.js
diff --git a/master/closure-library/closure/goog/format/jsonprettyprinter.js b/edit/closure-library/closure/goog/format/jsonprettyprinter.js
similarity index 100%
rename from master/closure-library/closure/goog/format/jsonprettyprinter.js
rename to edit/closure-library/closure/goog/format/jsonprettyprinter.js
diff --git a/edit/closure-library/closure/goog/fs/entry.js b/edit/closure-library/closure/goog/fs/entry.js
new file mode 100644
index 0000000000..eeec036360
--- /dev/null
+++ b/edit/closure-library/closure/goog/fs/entry.js
@@ -0,0 +1,272 @@
+// Copyright 2011 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.
+
+/**
+ * @fileoverview Wrappers for HTML5 Entry objects. These are all in the same
+ * file to avoid circular dependency issues.
+ *
+ * When adding or modifying functionality in this namespace, be sure to update
+ * the mock counterparts in goog.testing.fs.
+ *
+ */
+goog.provide('goog.fs.DirectoryEntry');
+goog.provide('goog.fs.DirectoryEntry.Behavior');
+goog.provide('goog.fs.Entry');
+goog.provide('goog.fs.FileEntry');
+
+
+
+/**
+ * The interface for entries in the filesystem.
+ * @interface
+ */
+goog.fs.Entry = function() {};
+
+
+/**
+ * @return {boolean} Whether or not this entry is a file.
+ */
+goog.fs.Entry.prototype.isFile = function() {};
+
+
+/**
+ * @return {boolean} Whether or not this entry is a directory.
+ */
+goog.fs.Entry.prototype.isDirectory = function() {};
+
+
+/**
+ * @return {string} The name of this entry.
+ */
+goog.fs.Entry.prototype.getName = function() {};
+
+
+/**
+ * @return {string} The full path to this entry.
+ */
+goog.fs.Entry.prototype.getFullPath = function() {};
+
+
+/**
+ * @return {!goog.fs.FileSystem} The filesystem backing this entry.
+ */
+goog.fs.Entry.prototype.getFileSystem = function() {};
+
+
+/**
+ * Retrieves the last modified date for this entry.
+ *
+ * @return {!goog.async.Deferred} The deferred Date for this entry. If an error
+ * occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.getLastModified = function() {};
+
+
+/**
+ * Retrieves the metadata for this entry.
+ *
+ * @return {!goog.async.Deferred} The deferred Metadata for this entry. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.getMetadata = function() {};
+
+
+/**
+ * Move this entry to a new location.
+ *
+ * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
+ * @param {string=} opt_newName The new name of the entry. If omitted, the entry
+ * retains its original name.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
+ * {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
+ * errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.moveTo = function(parent, opt_newName) {};
+
+
+/**
+ * Copy this entry to a new location.
+ *
+ * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
+ * @param {string=} opt_newName The name of the new entry. If omitted, the new
+ * entry has the same name as the original.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
+ * {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
+ * errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.copyTo = function(parent, opt_newName) {};
+
+
+/**
+ * Wrap an HTML5 entry object in an appropriate subclass instance.
+ *
+ * @param {!Entry} entry The underlying Entry object.
+ * @return {!goog.fs.Entry} The appropriate subclass wrapper.
+ * @protected
+ */
+goog.fs.Entry.prototype.wrapEntry = function(entry) {};
+
+
+/**
+ * Get the URL for this file.
+ *
+ * @param {string=} opt_mimeType The MIME type that will be served for the URL.
+ * @return {string} The URL.
+ */
+goog.fs.Entry.prototype.toUrl = function(opt_mimeType) {};
+
+
+/**
+ * Get the URI for this file.
+ *
+ * @deprecated Use {@link #toUrl} instead.
+ * @param {string=} opt_mimeType The MIME type that will be served for the URI.
+ * @return {string} The URI.
+ */
+goog.fs.Entry.prototype.toUri = function(opt_mimeType) {};
+
+
+/**
+ * Remove this entry.
+ *
+ * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
+ * the callback is called with true. If an error occurs, the errback is
+ * called a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.remove = function() {};
+
+
+/**
+ * Gets the parent directory.
+ *
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
+ * If an error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.getParent = function() {};
+
+
+
+/**
+ * A directory in a local FileSystem.
+ *
+ * @interface
+ * @extends {goog.fs.Entry}
+ */
+goog.fs.DirectoryEntry = function() {};
+
+
+/**
+ * Behaviors for getting files and directories.
+ * @enum {number}
+ */
+goog.fs.DirectoryEntry.Behavior = {
+ /**
+ * Get the file if it exists, error out if it doesn't.
+ */
+ DEFAULT: 1,
+ /**
+ * Get the file if it exists, create it if it doesn't.
+ */
+ CREATE: 2,
+ /**
+ * Error out if the file exists, create it if it doesn't.
+ */
+ CREATE_EXCLUSIVE: 3
+};
+
+
+/**
+ * Get a file in the directory.
+ *
+ * @param {string} path The path to the file, relative to this directory.
+ * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
+ * handling an existing file, or the lack thereof.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry}. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.getFile = function(path, opt_behavior) {};
+
+
+/**
+ * Get a directory within this directory.
+ *
+ * @param {string} path The path to the directory, relative to this directory.
+ * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
+ * handling an existing directory, or the lack thereof.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
+ * If an error occurs, the errback is called a {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.getDirectory = function(path, opt_behavior) {};
+
+
+/**
+ * Opens the directory for the specified path, creating the directory and any
+ * intermediate directories as necessary.
+ *
+ * @param {string} path The directory path to create. May be absolute or
+ * relative to the current directory. The parent directory ".." and current
+ * directory "." are supported.
+ * @return {!goog.async.Deferred} A deferred {@link goog.fs.DirectoryEntry} for
+ * the requested path. If an error occurs, the errback is called with a
+ * {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.createPath = function(path) {};
+
+
+/**
+ * Gets a list of all entries in this directory.
+ *
+ * @return {!goog.async.Deferred} The deferred list of {@link goog.fs.Entry}
+ * results. If an error occurs, the errback is called with a
+ * {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.listDirectory = function() {};
+
+
+/**
+ * Removes this directory and all its contents.
+ *
+ * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
+ * the callback is called with true. If an error occurs, the errback is
+ * called a {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.removeRecursively = function() {};
+
+
+
+/**
+ * A file in a local filesystem.
+ *
+ * @interface
+ * @extends {goog.fs.Entry}
+ */
+goog.fs.FileEntry = function() {};
+
+
+/**
+ * Create a writer for writing to the file.
+ *
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileWriter}. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileEntry.prototype.createWriter = function() {};
+
+
+/**
+ * Get the file contents as a File blob.
+ *
+ * @return {!goog.async.Deferred} The deferred File. If an error occurs, the
+ * errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileEntry.prototype.file = function() {};
diff --git a/master/closure-library/closure/goog/fs/entry.js b/edit/closure-library/closure/goog/fs/entryimpl.js
similarity index 51%
rename from master/closure-library/closure/goog/fs/entry.js
rename to edit/closure-library/closure/goog/fs/entryimpl.js
index 0e6c559a78..4c38932dc3 100644
--- a/master/closure-library/closure/goog/fs/entry.js
+++ b/edit/closure-library/closure/goog/fs/entryimpl.js
@@ -1,4 +1,4 @@
-// Copyright 2011 The Closure Library Authors. All Rights Reserved.
+// Copyright 2013 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.
@@ -13,22 +13,19 @@
// limitations under the License.
/**
- * @fileoverview Wrappers for HTML5 Entry objects. These are all in the same
- * file to avoid circular dependency issues.
- *
- * When adding or modifying functionality in this namespace, be sure to update
- * the mock counterparts in goog.testing.fs.
- *
+ * @fileoverview Concrete implementations of the
+ * goog.fs.DirectoryEntry, and goog.fs.FileEntry interfaces.
*/
-
-goog.provide('goog.fs.DirectoryEntry');
-goog.provide('goog.fs.DirectoryEntry.Behavior');
-goog.provide('goog.fs.Entry');
-goog.provide('goog.fs.FileEntry');
+goog.provide('goog.fs.DirectoryEntryImpl');
+goog.provide('goog.fs.EntryImpl');
+goog.provide('goog.fs.FileEntryImpl');
goog.require('goog.array');
goog.require('goog.async.Deferred');
+goog.require('goog.fs.DirectoryEntry');
+goog.require('goog.fs.Entry');
goog.require('goog.fs.Error');
+goog.require('goog.fs.FileEntry');
goog.require('goog.fs.FileWriter');
goog.require('goog.functions');
goog.require('goog.string');
@@ -36,13 +33,13 @@ goog.require('goog.string');
/**
- * The abstract class for entries in the filesystem.
- *
+ * Base class for concrete implementations of goog.fs.Entry.
* @param {!goog.fs.FileSystem} fs The wrapped filesystem.
* @param {!Entry} entry The underlying Entry object.
* @constructor
+ * @implements {goog.fs.Entry}
*/
-goog.fs.Entry = function(fs, entry) {
+goog.fs.EntryImpl = function(fs, entry) {
/**
* The wrapped filesystem.
*
@@ -61,66 +58,46 @@ goog.fs.Entry = function(fs, entry) {
};
-/**
- * @return {boolean} Whether or not this entry is a file.
- */
-goog.fs.Entry.prototype.isFile = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.isFile = function() {
return this.entry_.isFile;
};
-/**
- * @return {boolean} Whether or not this entry is a directory.
- */
-goog.fs.Entry.prototype.isDirectory = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.isDirectory = function() {
return this.entry_.isDirectory;
};
-/**
- * @return {string} The name of this entry.
- */
-goog.fs.Entry.prototype.getName = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.getName = function() {
return this.entry_.name;
};
-/**
- * @return {string} The full path to this entry.
- */
-goog.fs.Entry.prototype.getFullPath = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.getFullPath = function() {
return this.entry_.fullPath;
};
-/**
- * @return {!goog.fs.FileSystem} The filesystem backing this entry.
- */
-goog.fs.Entry.prototype.getFileSystem = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.getFileSystem = function() {
return this.fs_;
};
-/**
- * Retrieves the last modified date for this entry.
- *
- * @return {!goog.async.Deferred} The deferred Date for this entry. If an error
- * occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.Entry.prototype.getLastModified = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.getLastModified = function() {
return this.getMetadata().addCallback(function(metadata) {
return metadata.modificationTime;
});
};
-/**
- * Retrieves the metadata for this entry.
- *
- * @return {!goog.async.Deferred} The deferred Metadata for this entry. If an
- * error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.Entry.prototype.getMetadata = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.getMetadata = function() {
var d = new goog.async.Deferred();
this.entry_.getMetadata(
@@ -133,17 +110,8 @@ goog.fs.Entry.prototype.getMetadata = function() {
};
-/**
- * Move this entry to a new location.
- *
- * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
- * @param {string=} opt_newName The new name of the entry. If omitted, the entry
- * retains its original name.
- * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
- * {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
- * errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.Entry.prototype.moveTo = function(parent, opt_newName) {
+/** @override */
+goog.fs.EntryImpl.prototype.moveTo = function(parent, opt_newName) {
var d = new goog.async.Deferred();
this.entry_.moveTo(
parent.dir_, opt_newName,
@@ -158,17 +126,8 @@ goog.fs.Entry.prototype.moveTo = function(parent, opt_newName) {
};
-/**
- * Copy this entry to a new location.
- *
- * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
- * @param {string=} opt_newName The name of the new entry. If omitted, the new
- * entry has the same name as the original.
- * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
- * {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
- * errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.Entry.prototype.copyTo = function(parent, opt_newName) {
+/** @override */
+goog.fs.EntryImpl.prototype.copyTo = function(parent, opt_newName) {
var d = new goog.async.Deferred();
this.entry_.copyTo(
parent.dir_, opt_newName,
@@ -183,50 +142,27 @@ goog.fs.Entry.prototype.copyTo = function(parent, opt_newName) {
};
-/**
- * Wrap an HTML5 entry object in an appropriate subclass instance.
- *
- * @param {!Entry} entry The underlying Entry object.
- * @return {!goog.fs.Entry} The appropriate subclass wrapper.
- * @protected
- */
-goog.fs.Entry.prototype.wrapEntry = function(entry) {
+/** @override */
+goog.fs.EntryImpl.prototype.wrapEntry = function(entry) {
return entry.isFile ?
- new goog.fs.FileEntry(this.fs_, /** @type {!FileEntry} */ (entry)) :
- new goog.fs.DirectoryEntry(
+ new goog.fs.FileEntryImpl(this.fs_, /** @type {!FileEntry} */ (entry)) :
+ new goog.fs.DirectoryEntryImpl(
this.fs_, /** @type {!DirectoryEntry} */ (entry));
};
-/**
- * Get the URL for this file.
- *
- * @param {string=} opt_mimeType The MIME type that will be served for the URL.
- * @return {string} The URL.
- */
-goog.fs.Entry.prototype.toUrl = function(opt_mimeType) {
+/** @override */
+goog.fs.EntryImpl.prototype.toUrl = function(opt_mimeType) {
return this.entry_.toURL(opt_mimeType);
};
-/**
- * Get the URI for this file.
- *
- * @deprecated Use {@link #toUrl} instead.
- * @param {string=} opt_mimeType The MIME type that will be served for the URI.
- * @return {string} The URI.
- */
-goog.fs.Entry.prototype.toUri = goog.fs.Entry.prototype.toUrl;
+/** @override */
+goog.fs.EntryImpl.prototype.toUri = goog.fs.EntryImpl.prototype.toUrl;
-/**
- * Remove this entry.
- *
- * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
- * the callback is called with true. If an error occurs, the errback is
- * called a {@link goog.fs.Error}.
- */
-goog.fs.Entry.prototype.remove = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.remove = function() {
var d = new goog.async.Deferred();
this.entry_.remove(
goog.bind(d.callback, d, true /* result */),
@@ -238,17 +174,12 @@ goog.fs.Entry.prototype.remove = function() {
};
-/**
- * Gets the parent directory.
- *
- * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
- * If an error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.Entry.prototype.getParent = function() {
+/** @override */
+goog.fs.EntryImpl.prototype.getParent = function() {
var d = new goog.async.Deferred();
this.entry_.getParent(
goog.bind(function(parent) {
- d.callback(new goog.fs.DirectoryEntry(this.fs_, parent));
+ d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, parent));
}, this),
goog.bind(function(err) {
var msg = 'getting parent of ' + this.getFullPath();
@@ -269,9 +200,10 @@ goog.fs.Entry.prototype.getParent = function() {
* @param {!goog.fs.FileSystem} fs The wrapped filesystem.
* @param {!DirectoryEntry} dir The underlying DirectoryEntry object.
* @constructor
- * @extends {goog.fs.Entry}
+ * @extends {goog.fs.EntryImpl}
+ * @implements {goog.fs.DirectoryEntry}
*/
-goog.fs.DirectoryEntry = function(fs, dir) {
+goog.fs.DirectoryEntryImpl = function(fs, dir) {
goog.base(this, fs, dir);
/**
@@ -282,44 +214,16 @@ goog.fs.DirectoryEntry = function(fs, dir) {
*/
this.dir_ = dir;
};
-goog.inherits(goog.fs.DirectoryEntry, goog.fs.Entry);
+goog.inherits(goog.fs.DirectoryEntryImpl, goog.fs.EntryImpl);
-/**
- * Behaviors for getting files and directories.
- * @enum {number}
- */
-goog.fs.DirectoryEntry.Behavior = {
- /**
- * Get the file if it exists, error out if it doesn't.
- */
- DEFAULT: 1,
- /**
- * Get the file if it exists, create it if it doesn't.
- */
- CREATE: 2,
- /**
- * Error out if the file exists, create it if it doesn't.
- */
- CREATE_EXCLUSIVE: 3
-};
-
-
-/**
- * Get a file in the directory.
- *
- * @param {string} path The path to the file, relative to this directory.
- * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
- * handling an existing file, or the lack thereof.
- * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry}. If an
- * error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.DirectoryEntry.prototype.getFile = function(path, opt_behavior) {
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.getFile = function(path, opt_behavior) {
var d = new goog.async.Deferred();
this.dir_.getFile(
path, this.getOptions_(opt_behavior),
goog.bind(function(entry) {
- d.callback(new goog.fs.FileEntry(this.fs_, entry));
+ d.callback(new goog.fs.FileEntryImpl(this.fs_, entry));
}, this),
goog.bind(function(err) {
var msg = 'loading file ' + path + ' from ' + this.getFullPath();
@@ -329,21 +233,14 @@ goog.fs.DirectoryEntry.prototype.getFile = function(path, opt_behavior) {
};
-/**
- * Get a directory within this directory.
- *
- * @param {string} path The path to the directory, relative to this directory.
- * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
- * handling an existing directory, or the lack thereof.
- * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
- * If an error occurs, the errback is called a {@link goog.fs.Error}.
- */
-goog.fs.DirectoryEntry.prototype.getDirectory = function(path, opt_behavior) {
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.getDirectory =
+ function(path, opt_behavior) {
var d = new goog.async.Deferred();
this.dir_.getDirectory(
path, this.getOptions_(opt_behavior),
goog.bind(function(entry) {
- d.callback(new goog.fs.DirectoryEntry(this.fs_, entry));
+ d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, entry));
}, this),
goog.bind(function(err) {
var msg = 'loading directory ' + path + ' from ' + this.getFullPath();
@@ -353,18 +250,8 @@ goog.fs.DirectoryEntry.prototype.getDirectory = function(path, opt_behavior) {
};
-/**
- * Opens the directory for the specified path, creating the directory and any
- * intermediate directories as necessary.
- *
- * @param {string} path The directory path to create. May be absolute or
- * relative to the current directory. The parent directory ".." and current
- * directory "." are supported.
- * @return {!goog.async.Deferred} A deferred {@link goog.fs.DirectoryEntry} for
- * the requested path. If an error occurs, the errback is called with a
- * {@link goog.fs.Error}.
- */
-goog.fs.DirectoryEntry.prototype.createPath = function(path) {
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.createPath = function(path) {
// If the path begins at the root, reinvoke createPath on the root directory.
if (goog.string.startsWith(path, '/')) {
var root = this.getFileSystem().getRoot();
@@ -399,14 +286,8 @@ goog.fs.DirectoryEntry.prototype.createPath = function(path) {
};
-/**
- * Gets a list of all entries in this directory.
- *
- * @return {!goog.async.Deferred} The deferred list of {@link goog.fs.Entry}
- * results. If an error occurs, the errback is called with a
- * {@link goog.fs.Error}.
- */
-goog.fs.DirectoryEntry.prototype.listDirectory = function() {
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.listDirectory = function() {
var d = new goog.async.Deferred();
var reader = this.dir_.createReader();
var results = [];
@@ -432,14 +313,8 @@ goog.fs.DirectoryEntry.prototype.listDirectory = function() {
};
-/**
- * Removes this directory and all its contents.
- *
- * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
- * the callback is called with true. If an error occurs, the errback is
- * called a {@link goog.fs.Error}.
- */
-goog.fs.DirectoryEntry.prototype.removeRecursively = function() {
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.removeRecursively = function() {
var d = new goog.async.Deferred();
this.dir_.removeRecursively(
goog.bind(d.callback, d, true /* result */),
@@ -460,7 +335,7 @@ goog.fs.DirectoryEntry.prototype.removeRecursively = function() {
* @return {Object.} The options object expected by the File API.
* @private
*/
-goog.fs.DirectoryEntry.prototype.getOptions_ = function(opt_behavior) {
+goog.fs.DirectoryEntryImpl.prototype.getOptions_ = function(opt_behavior) {
if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE) {
return {'create': true};
} else if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE) {
@@ -476,14 +351,15 @@ goog.fs.DirectoryEntry.prototype.getOptions_ = function(opt_behavior) {
* A file in a local filesystem.
*
* This should not be instantiated directly. Instead, it should be accessed via
- * {@link goog.fs.DirectoryEntry#getDirectoryEntry}.
+ * {@link goog.fs.DirectoryEntry#getFile}.
*
* @param {!goog.fs.FileSystem} fs The wrapped filesystem.
* @param {!FileEntry} file The underlying FileEntry object.
* @constructor
- * @extends {goog.fs.Entry}
+ * @extends {goog.fs.EntryImpl}
+ * @implements {goog.fs.FileEntry}
*/
-goog.fs.FileEntry = function(fs, file) {
+goog.fs.FileEntryImpl = function(fs, file) {
goog.base(this, fs, file);
/**
@@ -494,16 +370,11 @@ goog.fs.FileEntry = function(fs, file) {
*/
this.file_ = file;
};
-goog.inherits(goog.fs.FileEntry, goog.fs.Entry);
+goog.inherits(goog.fs.FileEntryImpl, goog.fs.EntryImpl);
-/**
- * Create a writer for writing to the file.
- *
- * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileWriter}. If an
- * error occurs, the errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.FileEntry.prototype.createWriter = function() {
+/** @override */
+goog.fs.FileEntryImpl.prototype.createWriter = function() {
var d = new goog.async.Deferred();
this.file_.createWriter(
function(w) { d.callback(new goog.fs.FileWriter(w)); },
@@ -515,13 +386,8 @@ goog.fs.FileEntry.prototype.createWriter = function() {
};
-/**
- * Get the file contents as a File blob.
- *
- * @return {!goog.async.Deferred} The deferred File. If an error occurs, the
- * errback is called with a {@link goog.fs.Error}.
- */
-goog.fs.FileEntry.prototype.file = function() {
+/** @override */
+goog.fs.FileEntryImpl.prototype.file = function() {
var d = new goog.async.Deferred();
this.file_.file(
function(f) { d.callback(f); },
diff --git a/master/closure-library/closure/goog/fs/error.js b/edit/closure-library/closure/goog/fs/error.js
similarity index 100%
rename from master/closure-library/closure/goog/fs/error.js
rename to edit/closure-library/closure/goog/fs/error.js
diff --git a/master/closure-library/closure/goog/fs/filereader.js b/edit/closure-library/closure/goog/fs/filereader.js
similarity index 100%
rename from master/closure-library/closure/goog/fs/filereader.js
rename to edit/closure-library/closure/goog/fs/filereader.js
diff --git a/master/closure-library/closure/goog/fs/filesaver.js b/edit/closure-library/closure/goog/fs/filesaver.js
similarity index 100%
rename from master/closure-library/closure/goog/fs/filesaver.js
rename to edit/closure-library/closure/goog/fs/filesaver.js
diff --git a/master/closure-library/closure/goog/fs/filesystem.js b/edit/closure-library/closure/goog/fs/filesystem.js
similarity index 60%
rename from master/closure-library/closure/goog/fs/filesystem.js
rename to edit/closure-library/closure/goog/fs/filesystem.js
index 303600c81a..b120b92dd5 100644
--- a/master/closure-library/closure/goog/fs/filesystem.js
+++ b/edit/closure-library/closure/goog/fs/filesystem.js
@@ -19,41 +19,23 @@
goog.provide('goog.fs.FileSystem');
-goog.require('goog.fs.DirectoryEntry');
-
/**
* A local filesystem.
*
- * This shouldn't be instantiated directly. Instead, it should be accessed via
- * {@link goog.fs.getTemporary} or {@link goog.fs.getPersistent}.
- *
- * @param {!FileSystem} fs The underlying FileSystem object.
- * @constructor
+ * @interface
*/
-goog.fs.FileSystem = function(fs) {
- /**
- * The underlying FileSystem object.
- *
- * @type {!FileSystem}
- * @private
- */
- this.fs_ = fs;
-};
+goog.fs.FileSystem = function() {};
/**
* @return {string} The name of the filesystem.
*/
-goog.fs.FileSystem.prototype.getName = function() {
- return this.fs_.name;
-};
+goog.fs.FileSystem.prototype.getName = function() {};
/**
* @return {!goog.fs.DirectoryEntry} The root directory of the filesystem.
*/
-goog.fs.FileSystem.prototype.getRoot = function() {
- return new goog.fs.DirectoryEntry(this, this.fs_.root);
-};
+goog.fs.FileSystem.prototype.getRoot = function() {};
diff --git a/edit/closure-library/closure/goog/fs/filesystemimpl.js b/edit/closure-library/closure/goog/fs/filesystemimpl.js
new file mode 100644
index 0000000000..3f53c825dc
--- /dev/null
+++ b/edit/closure-library/closure/goog/fs/filesystemimpl.js
@@ -0,0 +1,64 @@
+// Copyright 2013 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.
+
+/**
+ * @fileoverview Concrete implementation of the goog.fs.FileSystem interface
+ * using an HTML FileSystem object.
+ */
+goog.provide('goog.fs.FileSystemImpl');
+
+goog.require('goog.fs.DirectoryEntryImpl');
+goog.require('goog.fs.FileSystem');
+
+
+
+/**
+ * A local filesystem.
+ *
+ * This shouldn't be instantiated directly. Instead, it should be accessed via
+ * {@link goog.fs.getTemporary} or {@link goog.fs.getPersistent}.
+ *
+ * @param {!FileSystem} fs The underlying FileSystem object.
+ * @constructor
+ * @implements {goog.fs.FileSystem}
+ */
+goog.fs.FileSystemImpl = function(fs) {
+ /**
+ * The underlying FileSystem object.
+ *
+ * @type {!FileSystem}
+ * @private
+ */
+ this.fs_ = fs;
+};
+
+
+/** @override */
+goog.fs.FileSystemImpl.prototype.getName = function() {
+ return this.fs_.name;
+};
+
+
+/** @override */
+goog.fs.FileSystemImpl.prototype.getRoot = function() {
+ return new goog.fs.DirectoryEntryImpl(this, this.fs_.root);
+};
+
+
+/**
+ * @return {!FileSystem} The underlying FileSystem object.
+ */
+goog.fs.FileSystemImpl.prototype.getBrowserFileSystem = function() {
+ return this.fs_;
+};
diff --git a/master/closure-library/closure/goog/fs/filewriter.js b/edit/closure-library/closure/goog/fs/filewriter.js
similarity index 100%
rename from master/closure-library/closure/goog/fs/filewriter.js
rename to edit/closure-library/closure/goog/fs/filewriter.js
diff --git a/master/closure-library/closure/goog/fs/fs.js b/edit/closure-library/closure/goog/fs/fs.js
similarity index 93%
rename from master/closure-library/closure/goog/fs/fs.js
rename to edit/closure-library/closure/goog/fs/fs.js
index ceb324ba0d..7ea8b00acd 100644
--- a/master/closure-library/closure/goog/fs/fs.js
+++ b/edit/closure-library/closure/goog/fs/fs.js
@@ -25,11 +25,11 @@
goog.provide('goog.fs');
+goog.require('goog.array');
goog.require('goog.async.Deferred');
-goog.require('goog.events');
goog.require('goog.fs.Error');
goog.require('goog.fs.FileReader');
-goog.require('goog.fs.FileSystem');
+goog.require('goog.fs.FileSystemImpl');
goog.require('goog.userAgent');
@@ -52,7 +52,7 @@ goog.fs.get_ = function(type, size) {
var d = new goog.async.Deferred();
requestFileSystem(type, size, function(fs) {
- d.callback(new goog.fs.FileSystem(fs));
+ d.callback(new goog.fs.FileSystemImpl(fs));
}, function(err) {
d.errback(new goog.fs.Error(err.code, 'requesting filesystem'));
});
@@ -168,11 +168,16 @@ goog.fs.getUrlObject_ = function() {
*/
goog.fs.getBlob = function(var_args) {
var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
- var bb = new BlobBuilder();
- for (var i = 0; i < arguments.length; i++) {
- bb.append(arguments[i]);
+
+ if (goog.isDef(BlobBuilder)) {
+ var bb = new BlobBuilder();
+ for (var i = 0; i < arguments.length; i++) {
+ bb.append(arguments[i]);
+ }
+ return bb.getBlob();
+ } else {
+ return new Blob(goog.array.toArray(arguments));
}
- return bb.getBlob();
};
@@ -221,8 +226,8 @@ goog.fs.sliceBlob = function(blob, start, opt_end) {
// Negative indices are not accepted, only range end is clamped and
// range end specification is obligatory.
// See http://www.w3.org/TR/2009/WD-FileAPI-20091117/
- if ((goog.userAgent.GECKO && !goog.userAgent.isVersion('13.0')) ||
- (goog.userAgent.WEBKIT && !goog.userAgent.isVersion('537.1'))) {
+ if ((goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('13.0')) ||
+ (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('537.1'))) {
if (start < 0) {
start += blob.size;
}
diff --git a/master/closure-library/closure/goog/fs/progressevent.js b/edit/closure-library/closure/goog/fs/progressevent.js
similarity index 100%
rename from master/closure-library/closure/goog/fs/progressevent.js
rename to edit/closure-library/closure/goog/fs/progressevent.js
diff --git a/master/closure-library/closure/goog/functions/functions.js b/edit/closure-library/closure/goog/functions/functions.js
similarity index 86%
rename from master/closure-library/closure/goog/functions/functions.js
rename to edit/closure-library/closure/goog/functions/functions.js
index 280e31ca80..8e85889966 100644
--- a/master/closure-library/closure/goog/functions/functions.js
+++ b/edit/closure-library/closure/goog/functions/functions.js
@@ -25,8 +25,9 @@ goog.provide('goog.functions');
/**
* Creates a function that always returns the same value.
- * @param {*} retValue The value to return.
- * @return {!Function} The new function.
+ * @param {T} retValue The value to return.
+ * @return {function():T} The new function.
+ * @template T
*/
goog.functions.constant = function(retValue) {
return function() {
@@ -59,10 +60,10 @@ goog.functions.NULL = goog.functions.constant(null);
/**
* A simple function that returns the first argument of whatever is passed
* into it.
- * @param {*=} opt_returnValue The single value that will be returned.
+ * @param {T=} opt_returnValue The single value that will be returned.
* @param {...*} var_args Optional trailing arguments. These are ignored.
- * @return {?} The first argument passed in, or undefined if nothing was passed.
- * We can't know the type -- just pass it along without type.
+ * @return {T} The first argument passed in, or undefined if nothing was passed.
+ * @template T
*/
goog.functions.identity = function(opt_returnValue, var_args) {
return opt_returnValue;
@@ -81,6 +82,18 @@ goog.functions.error = function(message) {
};
+/**
+ * Creates a function that throws the given object.
+ * @param {*} err An object to be thrown.
+ * @return {!Function} The error-throwing function.
+ */
+goog.functions.fail = function(err) {
+ return function() {
+ throw err;
+ }
+};
+
+
/**
* Given a function, create a function that keeps opt_numArgs arguments and
* silently discards all additional arguments.
@@ -101,8 +114,9 @@ goog.functions.lock = function(f, opt_numArgs) {
* Given a function, create a new function that swallows its return value
* and replaces it with a new one.
* @param {Function} f A function.
- * @param {*} retValue A new return value.
- * @return {!Function} A new function.
+ * @param {T} retValue A new return value.
+ * @return {function(...[?]):T} A new function.
+ * @template T
*/
goog.functions.withReturnValue = function(f, retValue) {
return goog.functions.sequence(f, goog.functions.constant(retValue));
@@ -112,10 +126,12 @@ goog.functions.withReturnValue = function(f, retValue) {
/**
* Creates the composition of the functions passed in.
* For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
+ * @param {function(...[?]):T} fn The final function.
* @param {...Function} var_args A list of functions.
- * @return {!Function} The composition of all inputs.
+ * @return {function(...[?]):T} The composition of all inputs.
+ * @template T
*/
-goog.functions.compose = function(var_args) {
+goog.functions.compose = function(fn, var_args) {
var functions = arguments;
var length = functions.length;
return function() {
@@ -158,7 +174,8 @@ goog.functions.sequence = function(var_args) {
* short-circuited as soon as a function returns false.
* For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
* @param {...Function} var_args A list of functions.
- * @return {!Function} A function that ANDs its component functions.
+ * @return {function(...[?]):boolean} A function that ANDs its component
+ * functions.
*/
goog.functions.and = function(var_args) {
var functions = arguments;
@@ -180,7 +197,8 @@ goog.functions.and = function(var_args) {
* short-circuited as soon as a function returns true.
* For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
* @param {...Function} var_args A list of functions.
- * @return {!Function} A function that ORs its component functions.
+ * @return {function(...[?]):boolean} A function that ORs its component
+ * functions.
*/
goog.functions.or = function(var_args) {
var functions = arguments;
@@ -200,7 +218,8 @@ goog.functions.or = function(var_args) {
* Creates a function that returns the Boolean opposite of a provided function.
* For example, (goog.functions.not(f))(x) is equivalent to !f(x).
* @param {!Function} f The original function.
- * @return {!Function} A function that delegates to f and returns opposite.
+ * @return {function(...[?]):boolean} A function that delegates to f and returns
+ * opposite.
*/
goog.functions.not = function(f) {
return function() {
diff --git a/master/closure-library/closure/goog/fx/abstractdragdrop.js b/edit/closure-library/closure/goog/fx/abstractdragdrop.js
similarity index 97%
rename from master/closure-library/closure/goog/fx/abstractdragdrop.js
rename to edit/closure-library/closure/goog/fx/abstractdragdrop.js
index e15465e471..288d9d08d9 100644
--- a/master/closure-library/closure/goog/fx/abstractdragdrop.js
+++ b/edit/closure-library/closure/goog/fx/abstractdragdrop.js
@@ -30,6 +30,7 @@ goog.require('goog.dom');
goog.require('goog.dom.classes');
goog.require('goog.events');
goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.fx.Dragger');
@@ -1251,6 +1252,14 @@ goog.fx.DragDropItem = function(element, opt_data) {
*/
this.parent_ = null;
+ /**
+ * Event handler for listeners on events that can initiate a drag.
+ * @type {!goog.events.EventHandler}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+ this.registerDisposable(this.eventHandler_);
+
if (!this.element) {
throw Error('Invalid argument');
}
@@ -1347,12 +1356,18 @@ goog.fx.DragDropItem.prototype.setParent = function(parent) {
* @private
*/
goog.fx.DragDropItem.prototype.maybeStartDrag_ = function(event, element) {
- goog.events.listen(element, goog.events.EventType.MOUSEMOVE,
- this.mouseMove_, false, this);
- goog.events.listen(element, goog.events.EventType.MOUSEOUT,
- this.mouseMove_, false, this);
- goog.events.listen(element, goog.events.EventType.MOUSEUP,
- this.mouseUp_, false, this);
+ var eventType = goog.events.EventType;
+ this.eventHandler_.
+ listen(element, eventType.MOUSEMOVE, this.mouseMove_, false).
+ listen(element, eventType.MOUSEOUT, this.mouseMove_, false);
+
+ // Capture the MOUSEUP on the document to ensure that we cancel the start
+ // drag handlers even if the mouse up occurs on some other element. This can
+ // happen for instance when the mouse down changes the geometry of the element
+ // clicked on (e.g. through changes in activation styling) such that the mouse
+ // up occurs outside the original element.
+ var doc = goog.dom.getOwnerDocument(element);
+ this.eventHandler_.listen(doc, eventType.MOUSEUP, this.mouseUp_, true);
this.currentDragElement_ = element;
@@ -1383,13 +1398,7 @@ goog.fx.DragDropItem.prototype.mouseMove_ = function(event) {
var mouseOutOnDragElement = event.type == goog.events.EventType.MOUSEOUT &&
event.target == currentDragElement;
if (distanceAboveThreshold || mouseOutOnDragElement) {
- goog.events.unlisten(currentDragElement, goog.events.EventType.MOUSEMOVE,
- this.mouseMove_, false, this);
- goog.events.unlisten(currentDragElement, goog.events.EventType.MOUSEOUT,
- this.mouseMove_, false, this);
- goog.events.unlisten(currentDragElement, goog.events.EventType.MOUSEUP,
- this.mouseUp_, false, this);
-
+ this.eventHandler_.removeAll();
this.parent_.startDrag(event, this);
}
};
@@ -1403,13 +1412,7 @@ goog.fx.DragDropItem.prototype.mouseMove_ = function(event) {
* @private
*/
goog.fx.DragDropItem.prototype.mouseUp_ = function(event) {
- var currentDragElement = this.currentDragElement_;
- goog.events.unlisten(currentDragElement, goog.events.EventType.MOUSEMOVE,
- this.mouseMove_, false, this);
- goog.events.unlisten(currentDragElement, goog.events.EventType.MOUSEOUT,
- this.mouseMove_, false, this);
- goog.events.unlisten(currentDragElement, goog.events.EventType.MOUSEUP,
- this.mouseUp_, false, this);
+ this.eventHandler_.removeAll();
delete this.startPosition_;
this.currentDragElement_ = null;
};
diff --git a/master/closure-library/closure/goog/fx/anim/anim.js b/edit/closure-library/closure/goog/fx/anim/anim.js
similarity index 98%
rename from master/closure-library/closure/goog/fx/anim/anim.js
rename to edit/closure-library/closure/goog/fx/anim/anim.js
index d0444e7c5d..efb0ad9451 100644
--- a/master/closure-library/closure/goog/fx/anim/anim.js
+++ b/edit/closure-library/closure/goog/fx/anim/anim.js
@@ -24,6 +24,7 @@ goog.require('goog.async.Delay');
goog.require('goog.object');
+
/**
* An interface for programatically animated objects. I.e. rendered in
* javascript frame by frame.
@@ -166,8 +167,8 @@ goog.fx.anim.requestAnimationFrame_ = function() {
// time in ms, as returned from goog.now().
goog.fx.anim.animationDelay_ = new goog.async.AnimationDelay(
function(now) {
- goog.fx.anim.cycleAnimations_(now);
- }, goog.fx.anim.animationWindow_);
+ goog.fx.anim.cycleAnimations_(now);
+ }, goog.fx.anim.animationWindow_);
} else {
goog.fx.anim.animationDelay_ = new goog.async.Delay(function() {
goog.fx.anim.cycleAnimations_(goog.now());
diff --git a/master/closure-library/closure/goog/fx/animation.js b/edit/closure-library/closure/goog/fx/animation.js
similarity index 99%
rename from master/closure-library/closure/goog/fx/animation.js
rename to edit/closure-library/closure/goog/fx/animation.js
index 852317236b..a8878375c1 100644
--- a/master/closure-library/closure/goog/fx/animation.js
+++ b/edit/closure-library/closure/goog/fx/animation.js
@@ -371,7 +371,7 @@ goog.fx.Animation.prototype.destroy = function() {
};
-/** @inheritDoc */
+/** @override */
goog.fx.Animation.prototype.onAnimationFrame = function(now) {
this.cycle(now);
};
diff --git a/master/closure-library/closure/goog/fx/animationqueue.js b/edit/closure-library/closure/goog/fx/animationqueue.js
similarity index 97%
rename from master/closure-library/closure/goog/fx/animationqueue.js
rename to edit/closure-library/closure/goog/fx/animationqueue.js
index d18a908056..7d3c3dad78 100644
--- a/master/closure-library/closure/goog/fx/animationqueue.js
+++ b/edit/closure-library/closure/goog/fx/animationqueue.js
@@ -126,7 +126,7 @@ goog.fx.AnimationParallelQueue = function() {
goog.inherits(goog.fx.AnimationParallelQueue, goog.fx.AnimationQueue);
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationParallelQueue.prototype.play = function(opt_restart) {
if (this.queue.length == 0) {
return false;
@@ -159,7 +159,7 @@ goog.fx.AnimationParallelQueue.prototype.play = function(opt_restart) {
};
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationParallelQueue.prototype.pause = function() {
if (this.isPlaying()) {
goog.array.forEach(this.queue, function(anim) {
@@ -174,7 +174,7 @@ goog.fx.AnimationParallelQueue.prototype.pause = function() {
};
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationParallelQueue.prototype.stop = function(opt_gotoEnd) {
goog.array.forEach(this.queue, function(anim) {
if (!anim.isStopped()) {
@@ -190,7 +190,7 @@ goog.fx.AnimationParallelQueue.prototype.stop = function(opt_gotoEnd) {
};
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationParallelQueue.prototype.onAnimationFinish = function(e) {
this.finishedCounter_++;
if (this.finishedCounter_ == this.queue.length) {
@@ -223,7 +223,7 @@ goog.fx.AnimationSerialQueue = function() {
goog.inherits(goog.fx.AnimationSerialQueue, goog.fx.AnimationQueue);
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationSerialQueue.prototype.play = function(opt_restart) {
if (this.queue.length == 0) {
return false;
@@ -256,7 +256,7 @@ goog.fx.AnimationSerialQueue.prototype.play = function(opt_restart) {
};
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationSerialQueue.prototype.pause = function() {
if (this.isPlaying()) {
this.queue[this.current_].pause();
@@ -266,7 +266,7 @@ goog.fx.AnimationSerialQueue.prototype.pause = function() {
};
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationSerialQueue.prototype.stop = function(opt_gotoEnd) {
this.setStateStopped();
this.endTime = goog.now();
@@ -290,7 +290,7 @@ goog.fx.AnimationSerialQueue.prototype.stop = function(opt_gotoEnd) {
};
-/** @inheritDoc */
+/** @override */
goog.fx.AnimationSerialQueue.prototype.onAnimationFinish = function(e) {
if (this.isPlaying()) {
this.current_++;
diff --git a/master/closure-library/closure/goog/fx/css3/fx.js b/edit/closure-library/closure/goog/fx/css3/fx.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/css3/fx.js
rename to edit/closure-library/closure/goog/fx/css3/fx.js
diff --git a/master/closure-library/closure/goog/fx/css3/transition.js b/edit/closure-library/closure/goog/fx/css3/transition.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/css3/transition.js
rename to edit/closure-library/closure/goog/fx/css3/transition.js
diff --git a/master/closure-library/closure/goog/fx/cssspriteanimation.js b/edit/closure-library/closure/goog/fx/cssspriteanimation.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/cssspriteanimation.js
rename to edit/closure-library/closure/goog/fx/cssspriteanimation.js
diff --git a/master/closure-library/closure/goog/fx/dom.js b/edit/closure-library/closure/goog/fx/dom.js
similarity index 99%
rename from master/closure-library/closure/goog/fx/dom.js
rename to edit/closure-library/closure/goog/fx/dom.js
index 0d32cf1f4a..5eee5b3158 100644
--- a/master/closure-library/closure/goog/fx/dom.js
+++ b/edit/closure-library/closure/goog/fx/dom.js
@@ -206,14 +206,14 @@ goog.fx.dom.Swipe = function(element, start, end, time, opt_acc) {
}
goog.fx.dom.PredefinedEffect.apply(this, arguments);
- /*
+ /**
* Maximum width for element.
* @type {number}
* @private
*/
this.maxWidth_ = Math.max(this.endPoint[0], this.startPoint[0]);
- /*
+ /**
* Maximum height for element.
* @type {number}
* @private
diff --git a/master/closure-library/closure/goog/fx/dragdrop.js b/edit/closure-library/closure/goog/fx/dragdrop.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/dragdrop.js
rename to edit/closure-library/closure/goog/fx/dragdrop.js
diff --git a/master/closure-library/closure/goog/fx/dragdropgroup.js b/edit/closure-library/closure/goog/fx/dragdropgroup.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/dragdropgroup.js
rename to edit/closure-library/closure/goog/fx/dragdropgroup.js
diff --git a/master/closure-library/closure/goog/fx/dragger.js b/edit/closure-library/closure/goog/fx/dragger.js
similarity index 97%
rename from master/closure-library/closure/goog/fx/dragger.js
rename to edit/closure-library/closure/goog/fx/dragger.js
index 2f85a48a67..e2f13f7800 100644
--- a/master/closure-library/closure/goog/fx/dragger.js
+++ b/edit/closure-library/closure/goog/fx/dragger.js
@@ -28,7 +28,6 @@ goog.provide('goog.fx.Dragger.EventType');
goog.require('goog.dom');
goog.require('goog.events');
-goog.require('goog.events.BrowserEvent.MouseButton');
goog.require('goog.events.Event');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
@@ -61,6 +60,7 @@ goog.fx.Dragger = function(target, opt_handle, opt_limits) {
this.document_ = goog.dom.getOwnerDocument(target);
this.eventHandler_ = new goog.events.EventHandler(this);
+ this.registerDisposable(this.eventHandler_);
// Add listener. Do not use the event handler here since the event handler is
// used for listeners added and removed during the drag operation.
@@ -80,7 +80,7 @@ goog.fx.Dragger.HAS_SET_CAPTURE_ =
// IE and Gecko after 1.9.3 has setCapture
// WebKit does not yet: https://bugs.webkit.org/show_bug.cgi?id=27330
goog.userAgent.IE ||
- goog.userAgent.GECKO && goog.userAgent.isVersion('1.9.3');
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.3');
/**
@@ -236,14 +236,6 @@ goog.fx.Dragger.prototype.mouseDownTime_ = 0;
goog.fx.Dragger.prototype.document_;
-/**
- * Event handler used to simplify managing events.
- * @type {goog.events.EventHandler}
- * @private
- */
-goog.fx.Dragger.prototype.eventHandler_;
-
-
/**
* The SCROLL event target used to make drag element follow scrolling.
* @type {EventTarget}
@@ -376,7 +368,6 @@ goog.fx.Dragger.prototype.disposeInternal = function() {
this.target = null;
this.handle = null;
- this.eventHandler_ = null;
};
@@ -532,13 +523,6 @@ goog.fx.Dragger.prototype.endDrag = function(e, opt_dragCanceled) {
} else {
this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
}
-
- // Call preventDefault to prevent mouseup from being raised if this is a
- // touchend event.
- if (e.type == goog.events.EventType.TOUCHEND ||
- e.type == goog.events.EventType.TOUCHCANCEL) {
- e.preventDefault();
- }
};
diff --git a/master/closure-library/closure/goog/fx/draglistgroup.js b/edit/closure-library/closure/goog/fx/draglistgroup.js
similarity index 95%
rename from master/closure-library/closure/goog/fx/draglistgroup.js
rename to edit/closure-library/closure/goog/fx/draglistgroup.js
index 6f36719afc..2216a82c5e 100644
--- a/master/closure-library/closure/goog/fx/draglistgroup.js
+++ b/edit/closure-library/closure/goog/fx/draglistgroup.js
@@ -410,33 +410,7 @@ goog.fx.DragListGroup.prototype.init = function() {
var dragItems = goog.dom.getChildren(dragList);
for (var j = 0, numItems = dragItems.length; j < numItems; ++j) {
- var dragItem = dragItems[j];
- var dragItemHandle = this.getHandleForDragItem_(dragItem);
-
- var uid = goog.getUid(dragItemHandle);
- this.dragItemForHandle_[uid] = dragItem;
-
- if (this.dragItemHoverClasses_) {
- this.eventHandler_.listen(
- dragItem, goog.events.EventType.MOUSEOVER,
- this.handleDragItemMouseover_);
- this.eventHandler_.listen(
- dragItem, goog.events.EventType.MOUSEOUT,
- this.handleDragItemMouseout_);
- }
- if (this.dragItemHandleHoverClasses_) {
- this.eventHandler_.listen(
- dragItemHandle, goog.events.EventType.MOUSEOVER,
- this.handleDragItemHandleMouseover_);
- this.eventHandler_.listen(
- dragItemHandle, goog.events.EventType.MOUSEOUT,
- this.handleDragItemHandleMouseout_);
- }
-
- this.dragItems_.push(dragItem);
- this.eventHandler_.listen(dragItemHandle,
- [goog.events.EventType.MOUSEDOWN, goog.events.EventType.TOUCHSTART],
- this.handlePotentialDragStart_);
+ this.listenForDragEvents(dragItems[j]);
}
}
@@ -444,6 +418,28 @@ goog.fx.DragListGroup.prototype.init = function() {
};
+/**
+ * Adds a single item to the given drag list and sets up the drag listeners for
+ * it.
+ * If opt_index is specified the item is inserted at this index, otherwise the
+ * item is added as the last child of the list.
+ *
+ * @param {!Element} list The drag list where to add item to.
+ * @param {!Element} item The new element to add.
+ * @param {number=} opt_index Index where to insert the item in the list. If not
+ * specified item is inserted as the last child of list.
+ */
+goog.fx.DragListGroup.prototype.addItemToDragList = function(list, item,
+ opt_index) {
+ if (goog.isDef(opt_index)) {
+ goog.dom.insertChildAt(list, item, opt_index);
+ } else {
+ goog.dom.appendChild(list, item);
+ }
+ this.listenForDragEvents(item);
+};
+
+
/** @override */
goog.fx.DragListGroup.prototype.disposeInternal = function() {
this.eventHandler_.dispose();
@@ -491,6 +487,43 @@ goog.fx.DragListGroup.prototype.recacheListAndItemBounds_ = function(
};
+/**
+ * Listens for drag events on the given drag item. This method is currently used
+ * to initialize drag items.
+ *
+ * @param {Element} dragItem the element to initialize. This element has to be
+ * in one of the drag lists.
+ * @protected
+ */
+goog.fx.DragListGroup.prototype.listenForDragEvents = function(dragItem) {
+ var dragItemHandle = this.getHandleForDragItem_(dragItem);
+ var uid = goog.getUid(dragItemHandle);
+ this.dragItemForHandle_[uid] = dragItem;
+
+ if (this.dragItemHoverClasses_) {
+ this.eventHandler_.listen(
+ dragItem, goog.events.EventType.MOUSEOVER,
+ this.handleDragItemMouseover_);
+ this.eventHandler_.listen(
+ dragItem, goog.events.EventType.MOUSEOUT,
+ this.handleDragItemMouseout_);
+ }
+ if (this.dragItemHandleHoverClasses_) {
+ this.eventHandler_.listen(
+ dragItemHandle, goog.events.EventType.MOUSEOVER,
+ this.handleDragItemHandleMouseover_);
+ this.eventHandler_.listen(
+ dragItemHandle, goog.events.EventType.MOUSEOUT,
+ this.handleDragItemHandleMouseout_);
+ }
+
+ this.dragItems_.push(dragItem);
+ this.eventHandler_.listen(dragItemHandle,
+ [goog.events.EventType.MOUSEDOWN, goog.events.EventType.TOUCHSTART],
+ this.handlePotentialDragStart_);
+};
+
+
/**
* Handles mouse and touch events which may start a drag action.
* @param {!goog.events.BrowserEvent} e MOUSEDOWN or TOUCHSTART event.
diff --git a/master/closure-library/closure/goog/fx/dragscrollsupport.js b/edit/closure-library/closure/goog/fx/dragscrollsupport.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/dragscrollsupport.js
rename to edit/closure-library/closure/goog/fx/dragscrollsupport.js
diff --git a/master/closure-library/closure/goog/fx/easing.js b/edit/closure-library/closure/goog/fx/easing.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/easing.js
rename to edit/closure-library/closure/goog/fx/easing.js
diff --git a/master/closure-library/closure/goog/fx/fx.js b/edit/closure-library/closure/goog/fx/fx.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/fx.js
rename to edit/closure-library/closure/goog/fx/fx.js
diff --git a/master/closure-library/closure/goog/fx/transition.js b/edit/closure-library/closure/goog/fx/transition.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/transition.js
rename to edit/closure-library/closure/goog/fx/transition.js
diff --git a/master/closure-library/closure/goog/fx/transitionbase.js b/edit/closure-library/closure/goog/fx/transitionbase.js
similarity index 100%
rename from master/closure-library/closure/goog/fx/transitionbase.js
rename to edit/closure-library/closure/goog/fx/transitionbase.js
diff --git a/master/closure-library/closure/goog/gears/basestore.js b/edit/closure-library/closure/goog/gears/basestore.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/basestore.js
rename to edit/closure-library/closure/goog/gears/basestore.js
diff --git a/master/closure-library/closure/goog/gears/database.js b/edit/closure-library/closure/goog/gears/database.js
similarity index 98%
rename from master/closure-library/closure/goog/gears/database.js
rename to edit/closure-library/closure/goog/gears/database.js
index 91ac75e0e3..04023f07c4 100644
--- a/master/closure-library/closure/goog/gears/database.js
+++ b/edit/closure-library/closure/goog/gears/database.js
@@ -22,11 +22,11 @@ goog.provide('goog.gears.Database.TransactionEvent');
goog.require('goog.array');
goog.require('goog.debug');
-goog.require('goog.debug.Logger');
goog.require('goog.events.Event');
goog.require('goog.events.EventTarget');
goog.require('goog.gears');
goog.require('goog.json');
+goog.require('goog.log');
@@ -58,7 +58,7 @@ goog.gears.Database = function(userId, appName) {
var dbId = userId + '-' + appName;
var safeDbId = goog.gears.makeSafeFileName(dbId);
if (dbId != safeDbId) {
- this.logger_.info('database name ' + dbId + '->' + safeDbId);
+ goog.log.info(this.logger_, 'database name ' + dbId + '->' + safeDbId);
}
this.safeDbId_ = safeDbId;
this.database_.open(safeDbId);
@@ -98,11 +98,11 @@ goog.inherits(goog.gears.Database.TransactionEvent, goog.events.Event);
/**
* Logger object
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @private
*/
goog.gears.Database.prototype.logger_ =
- goog.debug.Logger.getLogger('goog.gears.Database');
+ goog.log.getLogger('goog.gears.Database');
/**
@@ -314,7 +314,7 @@ goog.gears.Database.resultSetToArray = function(rs) {
* @return {GearsResultSet} The results.
*/
goog.gears.Database.prototype.execute = function(sql, var_args) {
- this.logger_.finer('Executing SQL: ' + sql);
+ goog.log.log(this.logger_, goog.log.Level.FINER, 'Executing SQL: ' + sql);
// TODO(user): Remove when Gears adds more rubust type handling.
// Safety measure since Gears behaves very badly if it gets an unexpected
@@ -332,7 +332,7 @@ goog.gears.Database.prototype.execute = function(sql, var_args) {
} else {
args = goog.array.slice(arguments, 1);
}
- this.logger_.finest('SQL arguments: ' + args);
+ goog.log.log(this.logger_, goog.log.Level.FINEST, 'SQL arguments: ' + args);
// TODO(user): Type safety checking for args?
return this.database_.execute(sql, args);
@@ -367,7 +367,8 @@ goog.gears.Database.prototype.executeVarArgs_ = function(sql, params,
if (goog.isArray(params[startIndex])) {
return this.execute(sql, params[startIndex]);
}
- var args = Array.prototype.slice.call(params, startIndex);
+ var args = Array.prototype.slice.call(
+ /** @type {{length:number}} */ (params), startIndex);
return this.execute(sql, args);
}
};
@@ -838,7 +839,7 @@ goog.gears.Database.prototype.isInTransaction = function() {
*/
goog.gears.Database.prototype.ensureNoTransaction = function(opt_logMsgPrefix) {
if (this.isInTransaction()) {
- this.logger_.warning((opt_logMsgPrefix || 'ensureNoTransaction') +
+ goog.log.warning(this.logger_, (opt_logMsgPrefix || 'ensureNoTransaction') +
' - rolling back unexpected transaction');
do {
this.rollback();
diff --git a/master/closure-library/closure/goog/gears/gears.js b/edit/closure-library/closure/goog/gears/gears.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/gears.js
rename to edit/closure-library/closure/goog/gears/gears.js
diff --git a/master/closure-library/closure/goog/gears/httprequest.js b/edit/closure-library/closure/goog/gears/httprequest.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/httprequest.js
rename to edit/closure-library/closure/goog/gears/httprequest.js
diff --git a/master/closure-library/closure/goog/gears/loggerclient.js b/edit/closure-library/closure/goog/gears/loggerclient.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/loggerclient.js
rename to edit/closure-library/closure/goog/gears/loggerclient.js
diff --git a/master/closure-library/closure/goog/gears/loggerserver.js b/edit/closure-library/closure/goog/gears/loggerserver.js
similarity index 95%
rename from master/closure-library/closure/goog/gears/loggerserver.js
rename to edit/closure-library/closure/goog/gears/loggerserver.js
index 56469f785e..698ea88253 100644
--- a/master/closure-library/closure/goog/gears/loggerserver.js
+++ b/edit/closure-library/closure/goog/gears/loggerserver.js
@@ -22,9 +22,9 @@
goog.provide('goog.gears.LoggerServer');
goog.require('goog.Disposable');
-goog.require('goog.debug.Logger');
-goog.require('goog.debug.Logger.Level');
goog.require('goog.gears.Worker.EventType');
+goog.require('goog.log');
+goog.require('goog.log.Level');
@@ -123,11 +123,11 @@ goog.gears.LoggerServer.prototype.onCommand_ = function(e) {
i++;
}
var levelValue = params[i++];
- var level = goog.debug.Logger.Level.getPredefinedLevelByValue(levelValue);
+ var level = goog.log.Level.getPredefinedLevelByValue(levelValue);
if (level) {
var msg = (this.useMessagePrefix_ ? this.msgPrefix_ : '') + params[i++];
var exception = params[i++];
- var logger = goog.debug.Logger.getLogger(name);
+ var logger = goog.log.getLogger(name);
var logRecord = logger.getLogRecord(level, msg, exception);
if (this.workerName_) {
logRecord.workerName = this.workerName_;
diff --git a/master/closure-library/closure/goog/gears/logstore.js b/edit/closure-library/closure/goog/gears/logstore.js
similarity index 91%
rename from master/closure-library/closure/goog/gears/logstore.js
rename to edit/closure-library/closure/goog/gears/logstore.js
index 48f8e8f6db..88bfd46684 100644
--- a/master/closure-library/closure/goog/gears/logstore.js
+++ b/edit/closure-library/closure/goog/gears/logstore.js
@@ -21,12 +21,12 @@ goog.provide('goog.gears.LogStore.Query');
goog.require('goog.async.Delay');
goog.require('goog.debug.LogManager');
-goog.require('goog.debug.LogRecord');
-goog.require('goog.debug.Logger');
-goog.require('goog.debug.Logger.Level');
goog.require('goog.gears.BaseStore');
goog.require('goog.gears.BaseStore.SchemaType');
goog.require('goog.json');
+goog.require('goog.log');
+goog.require('goog.log.Level');
+goog.require('goog.log.LogRecord');
@@ -57,7 +57,7 @@ goog.gears.LogStore = function(database, opt_tableName) {
'id INTEGER PRIMARY KEY AUTOINCREMENT',
// Timestamp.
'millis BIGINT',
- // #goog.debug.Logger.Level value.
+ // #goog.log.Level value.
'level INTEGER',
// Message.
'msg TEXT',
@@ -87,7 +87,7 @@ goog.gears.LogStore = function(database, opt_tableName) {
/**
* Buffered log records not yet flushed to DB.
- * @type {Array.}
+ * @type {Array.}
* @private
*/
this.records_ = [];
@@ -140,11 +140,11 @@ goog.gears.LogStore.prototype.isFlushing_ = false;
/**
* Logger.
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @private
*/
goog.gears.LogStore.prototype.logger_ =
- goog.debug.Logger.getLogger('goog.gears.LogStore');
+ goog.log.getLogger('goog.gears.LogStore');
/**
@@ -189,7 +189,7 @@ goog.gears.LogStore.prototype.flush = function() {
this.isFlushing_ = true;
// Grab local copy of records so database can log during this process.
- this.logger_.info('flushing ' + this.records_.length + ' records');
+ goog.log.info(this.logger_, 'flushing ' + this.records_.length + ' records');
var records = this.records_;
this.records_ = [];
@@ -284,7 +284,7 @@ goog.gears.LogStore.prototype.pruneBeforeCount = function(opt_count) {
}
var count = typeof opt_count == 'number' ?
opt_count : goog.gears.LogStore.DEFAULT_PRUNE_KEEPER_COUNT_;
- this.logger_.info('pruning before ' + count + ' records ago');
+ goog.log.info(this.logger_, 'pruning before ' + count + ' records ago');
this.flush();
this.getDatabaseInternal().execute('DELETE FROM ' + this.tableName_ +
' WHERE id <= ((SELECT MAX(id) FROM ' + this.tableName_ + ') - ?)',
@@ -301,7 +301,8 @@ goog.gears.LogStore.prototype.pruneBeforeSequenceNumber =
if (!this.getDatabaseInternal()) {
return;
}
- this.logger_.info('pruning before sequence number ' + sequenceNumber);
+ goog.log.info(this.logger_,
+ 'pruning before sequence number ' + sequenceNumber);
this.flush();
this.getDatabaseInternal().execute(
'DELETE FROM ' + this.tableName_ + ' WHERE id <= ?',
@@ -329,11 +330,11 @@ goog.gears.LogStore.prototype.setCapturing = function(capturing) {
// Attach or detach handler from the root logger.
var rootLogger = goog.debug.LogManager.getRoot();
if (capturing) {
- rootLogger.addHandler(this.publishHandler_);
- this.logger_.info('enabled');
+ goog.log.addHandler(rootLogger, this.publishHandler_);
+ goog.log.info(this.logger_, 'enabled');
} else {
- this.logger_.info('disabling');
- rootLogger.removeHandler(this.publishHandler_);
+ goog.log.info(this.logger_, 'disabling');
+ goog.log.removeHandler(rootLogger, this.publishHandler_);
}
}
};
@@ -341,7 +342,7 @@ goog.gears.LogStore.prototype.setCapturing = function(capturing) {
/**
* Adds a log record.
- * @param {goog.debug.LogRecord} logRecord the LogRecord.
+ * @param {goog.log.LogRecord} logRecord the LogRecord.
*/
goog.gears.LogStore.prototype.addLogRecord = function(logRecord) {
this.records_.push(logRecord);
@@ -359,7 +360,7 @@ goog.gears.LogStore.prototype.addLogRecord = function(logRecord) {
/**
* Select log records.
* @param {goog.gears.LogStore.Query} query Query object.
- * @return {Array.} Selected logs in descending
+ * @return {Array.} Selected logs in descending
* order of creation time.
*/
goog.gears.LogStore.prototype.select = function(query) {
@@ -387,7 +388,7 @@ goog.gears.LogStore.prototype.select = function(query) {
// Parse fields, allowing for invalid values.
var sequenceNumber = Number(row['id']) || 0;
- var level = goog.debug.Logger.Level.getPredefinedLevelByValue(
+ var level = goog.log.Level.getPredefinedLevelByValue(
Number(row['level']) || 0);
var msg = row['msg'] || '';
var loggerName = row['logger'] || '';
@@ -398,7 +399,7 @@ goog.gears.LogStore.prototype.select = function(query) {
var exceptionText = row['exceptionText'] || '';
// Create record.
- var record = new goog.debug.LogRecord(level, msg, loggerName,
+ var record = new goog.log.LogRecord(level, msg, loggerName,
millis, sequenceNumber);
if (exception) {
record.setException(exception);
@@ -435,9 +436,9 @@ goog.gears.LogStore.Query = function() {
/**
* Minimum logging level.
- * @type {goog.debug.Logger.Level}
+ * @type {goog.log.Level}
*/
-goog.gears.LogStore.Query.prototype.level = goog.debug.Logger.Level.ALL;
+goog.gears.LogStore.Query.prototype.level = goog.log.Level.ALL;
/**
diff --git a/master/closure-library/closure/goog/gears/managedresourcestore.js b/edit/closure-library/closure/goog/gears/managedresourcestore.js
similarity index 98%
rename from master/closure-library/closure/goog/gears/managedresourcestore.js
rename to edit/closure-library/closure/goog/gears/managedresourcestore.js
index 7bf9b2fe40..2f8ff4a79f 100644
--- a/master/closure-library/closure/goog/gears/managedresourcestore.js
+++ b/edit/closure-library/closure/goog/gears/managedresourcestore.js
@@ -22,10 +22,10 @@ goog.provide('goog.gears.ManagedResourceStore.EventType');
goog.provide('goog.gears.ManagedResourceStore.UpdateStatus');
goog.provide('goog.gears.ManagedResourceStoreEvent');
-goog.require('goog.debug.Logger');
goog.require('goog.events.Event');
goog.require('goog.events.EventTarget');
goog.require('goog.gears');
+goog.require('goog.log');
goog.require('goog.string');
@@ -55,12 +55,14 @@ goog.require('goog.string');
*/
goog.gears.ManagedResourceStore = function(name, requiredCookie,
opt_localServer) {
+ goog.base(this);
+
this.localServer_ = opt_localServer ||
goog.gears.getFactory().create('beta.localserver', '1.0');
this.name_ = goog.gears.makeSafeFileName(name);
if (name != this.name_) {
- this.logger_.info(
+ goog.log.info(this.logger_,
'managed resource store name ' + name + '->' + this.name_);
}
@@ -95,11 +97,11 @@ goog.gears.ManagedResourceStore.UpdateStatus = {
/**
* Logger.
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @private
*/
goog.gears.ManagedResourceStore.prototype.logger_ =
- goog.debug.Logger.getLogger('goog.gears.ManagedResourceStore');
+ goog.log.getLogger('goog.gears.ManagedResourceStore');
/**
diff --git a/master/closure-library/closure/goog/gears/multipartformdata.js b/edit/closure-library/closure/goog/gears/multipartformdata.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/multipartformdata.js
rename to edit/closure-library/closure/goog/gears/multipartformdata.js
diff --git a/master/closure-library/closure/goog/gears/statustype.js b/edit/closure-library/closure/goog/gears/statustype.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/statustype.js
rename to edit/closure-library/closure/goog/gears/statustype.js
diff --git a/master/closure-library/closure/goog/gears/urlcapture.js b/edit/closure-library/closure/goog/gears/urlcapture.js
similarity index 92%
rename from master/closure-library/closure/goog/gears/urlcapture.js
rename to edit/closure-library/closure/goog/gears/urlcapture.js
index a646847ebd..df99eac1ea 100644
--- a/master/closure-library/closure/goog/gears/urlcapture.js
+++ b/edit/closure-library/closure/goog/gears/urlcapture.js
@@ -24,10 +24,10 @@ goog.provide('goog.gears.UrlCapture.Event');
goog.provide('goog.gears.UrlCapture.EventType');
goog.require('goog.Uri');
-goog.require('goog.debug.Logger');
goog.require('goog.events.Event');
goog.require('goog.events.EventTarget');
goog.require('goog.gears');
+goog.require('goog.log');
@@ -50,7 +50,7 @@ goog.gears.UrlCapture = function(name, requiredCookie, opt_localServer) {
*/
this.storeName_ = goog.gears.makeSafeFileName(name);
if (name != this.storeName_) {
- this.logger_.info(
+ goog.log.info(this.logger_,
'local store name ' + name + '->' + this.storeName_);
}
@@ -97,11 +97,11 @@ goog.inherits(goog.gears.UrlCapture, goog.events.EventTarget);
/**
* Logger.
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @private
*/
goog.gears.UrlCapture.prototype.logger_ =
- goog.debug.Logger.getLogger('goog.gears.UrlCapture');
+ goog.log.getLogger('goog.gears.UrlCapture');
/**
@@ -131,7 +131,7 @@ goog.gears.UrlCapture.EventType = {
*/
goog.gears.UrlCapture.prototype.getResourceStore_ = function() {
if (!this.resourceStore_) {
- this.logger_.info('creating resource store: ' + this.storeName_);
+ goog.log.info(this.logger_, 'creating resource store: ' + this.storeName_);
this.resourceStore_ = this.localServer_['createStore'](
this.storeName_, this.requiredCookie_);
}
@@ -145,7 +145,7 @@ goog.gears.UrlCapture.prototype.getResourceStore_ = function() {
*/
goog.gears.UrlCapture.prototype.exists = function() {
if (!this.resourceStore_) {
- this.logger_.info('opening resource store: ' + this.storeName_);
+ goog.log.info(this.logger_, 'opening resource store: ' + this.storeName_);
this.resourceStore_ = this.localServer_['openStore'](
this.storeName_, this.requiredCookie_);
}
@@ -157,7 +157,7 @@ goog.gears.UrlCapture.prototype.exists = function() {
* Remove this resource store.
*/
goog.gears.UrlCapture.prototype.removeStore = function() {
- this.logger_.info('removing resource store: ' + this.storeName_);
+ goog.log.info(this.logger_, 'removing resource store: ' + this.storeName_);
this.localServer_['removeStore'](this.storeName_, this.requiredCookie_);
this.resourceStore_ = null;
};
@@ -192,7 +192,7 @@ goog.gears.UrlCapture.prototype.copy = function(srcUri, dstUri) {
*/
goog.gears.UrlCapture.prototype.capture = function(uris) {
var count = uris.length;
- this.logger_.fine('capture: count==' + count);
+ goog.log.fine(this.logger_, 'capture: count==' + count);
if (!count) {
throw Error('No URIs to capture');
}
@@ -206,7 +206,7 @@ goog.gears.UrlCapture.prototype.capture = function(uris) {
var id = this.getResourceStore_()['capture'](
captureStrings, goog.bind(this.captureCallback_, this));
- this.logger_.fine('capture started: ' + id);
+ goog.log.fine(this.logger_, 'capture started: ' + id);
this.uris_[id] = uris;
this.errorUris_[id] = [];
this.numCompleted_[id] = 0;
@@ -219,7 +219,7 @@ goog.gears.UrlCapture.prototype.capture = function(uris) {
* @param {number} captureId The id of the capture to abort, from #capture.
*/
goog.gears.UrlCapture.prototype.abort = function(captureId) {
- this.logger_.fine('abort: ' + captureId);
+ goog.log.fine(this.logger_, 'abort: ' + captureId);
// TODO(user) Remove when Gears adds more rubust type handling.
// Safety measure since Gears behaves very badly if it gets an unexpected
@@ -230,7 +230,7 @@ goog.gears.UrlCapture.prototype.abort = function(captureId) {
// Only need to abort if the capture is still in progress.
if (this.uris_[captureId] || this.numCompleted_[captureId]) {
- this.logger_.info('aborting capture: ' + captureId);
+ goog.log.info(this.logger_, 'aborting capture: ' + captureId);
this.getResourceStore_()['abortCapture'](captureId);
this.cleanupCapture_(captureId);
this.dispatchEvent(new goog.gears.UrlCapture.Event(
@@ -245,7 +245,7 @@ goog.gears.UrlCapture.prototype.abort = function(captureId) {
* @return {boolean} true if captured, false otherwise.
*/
goog.gears.UrlCapture.prototype.isCaptured = function(uri) {
- this.logger_.fine('isCaptured: ' + uri);
+ goog.log.fine(this.logger_, 'isCaptured: ' + uri);
return this.getResourceStore_()['isCaptured'](uri.toString());
};
@@ -255,7 +255,7 @@ goog.gears.UrlCapture.prototype.isCaptured = function(uri) {
* @param {string|goog.Uri} uri The URI to remove from the store.
*/
goog.gears.UrlCapture.prototype.remove = function(uri) {
- this.logger_.fine('remove: ' + uri);
+ goog.log.fine(this.logger_, 'remove: ' + uri);
this.getResourceStore_()['remove'](uri.toString());
};
@@ -270,7 +270,7 @@ goog.gears.UrlCapture.prototype.remove = function(uri) {
*/
goog.gears.UrlCapture.prototype.captureCallback_ = function(
url, success, captureId) {
- this.logger_.fine('captureCallback_: ' + captureId);
+ goog.log.fine(this.logger_, 'captureCallback_: ' + captureId);
if (!this.uris_[captureId] && !this.numCompleted_[captureId]) {
// This probably means we were aborted and then a capture event came in.
@@ -307,7 +307,7 @@ goog.gears.UrlCapture.prototype.captureCallback_ = function(
* @param {number} captureId The id of the capture to clean up.
*/
goog.gears.UrlCapture.prototype.cleanupCapture_ = function(captureId) {
- this.logger_.fine('cleanupCapture_: ' + captureId);
+ goog.log.fine(this.logger_, 'cleanupCapture_: ' + captureId);
delete this.uris_[captureId];
delete this.numCompleted_[captureId];
delete this.errorUris_[captureId];
diff --git a/master/closure-library/closure/goog/gears/worker.js b/edit/closure-library/closure/goog/gears/worker.js
similarity index 99%
rename from master/closure-library/closure/goog/gears/worker.js
rename to edit/closure-library/closure/goog/gears/worker.js
index 8fa2c9138a..4899191275 100644
--- a/master/closure-library/closure/goog/gears/worker.js
+++ b/edit/closure-library/closure/goog/gears/worker.js
@@ -144,7 +144,7 @@ goog.gears.Worker.prototype.getId = function() {
*/
goog.gears.Worker.isCommandLike = function(obj) {
return goog.isArray(obj) && obj.length == 2 &&
- goog.isNumber((/** @type {Array} */ obj)[0]);
+ goog.isNumber(/** @type {Array} */ (obj)[0]);
};
diff --git a/master/closure-library/closure/goog/gears/workerchannel.js b/edit/closure-library/closure/goog/gears/workerchannel.js
similarity index 88%
rename from master/closure-library/closure/goog/gears/workerchannel.js
rename to edit/closure-library/closure/goog/gears/workerchannel.js
index 750584c198..0273329962 100644
--- a/master/closure-library/closure/goog/gears/workerchannel.js
+++ b/edit/closure-library/closure/goog/gears/workerchannel.js
@@ -25,12 +25,12 @@ goog.provide('goog.gears.WorkerChannel');
goog.require('goog.Disposable');
goog.require('goog.debug');
-goog.require('goog.debug.Logger');
goog.require('goog.events');
goog.require('goog.gears.Worker');
goog.require('goog.gears.Worker.EventType');
goog.require('goog.gears.WorkerEvent');
goog.require('goog.json');
+goog.require('goog.log');
goog.require('goog.messaging.AbstractChannel');
@@ -86,12 +86,12 @@ goog.gears.WorkerChannel.prototype.peerOrigin;
/**
* Logger for this class.
- * @type {goog.debug.Logger}
+ * @type {goog.log.Logger}
* @protected
* @override
*/
goog.gears.WorkerChannel.prototype.logger =
- goog.debug.Logger.getLogger('goog.gears.WorkerChannel');
+ goog.log.getLogger('goog.gears.WorkerChannel');
/**
@@ -148,16 +148,16 @@ goog.gears.WorkerChannel.prototype.deliver_ = function(e) {
*/
goog.gears.WorkerChannel.prototype.validateMessage_ = function(body) {
if (!('serviceName' in body)) {
- this.logger.warning('GearsWorkerChannel::deliver_(): ' +
- 'Message object doesn\'t contain service name: ' +
- goog.debug.deepExpose(body));
+ goog.log.warning(this.logger, 'GearsWorkerChannel::deliver_(): ' +
+ 'Message object doesn\'t contain service name: ' +
+ goog.debug.deepExpose(body));
return false;
}
if (!('payload' in body)) {
- this.logger.warning('GearsWorkerChannel::deliver_(): ' +
- 'Message object doesn\'t contain payload: ' +
- goog.debug.deepExpose(body));
+ goog.log.warning(this.logger, 'GearsWorkerChannel::deliver_(): ' +
+ 'Message object doesn\'t contain payload: ' +
+ goog.debug.deepExpose(body));
return false;
}
@@ -197,8 +197,9 @@ goog.gears.WorkerChannel.prototype.checkMessageOrigin = function(
return true;
}
- this.logger.warning('Message from unexpected origin "' + messageOrigin +
- '"; expected only messages from origin "' + peerOrigin +
- '"');
+ goog.log.warning(this.logger,
+ 'Message from unexpected origin "' + messageOrigin +
+ '"; expected only messages from origin "' + peerOrigin +
+ '"');
return false;
};
diff --git a/master/closure-library/closure/goog/gears/workerpool.js b/edit/closure-library/closure/goog/gears/workerpool.js
similarity index 100%
rename from master/closure-library/closure/goog/gears/workerpool.js
rename to edit/closure-library/closure/goog/gears/workerpool.js
diff --git a/master/closure-library/closure/goog/graphics/abstractgraphics.js b/edit/closure-library/closure/goog/graphics/abstractgraphics.js
similarity index 99%
rename from master/closure-library/closure/goog/graphics/abstractgraphics.js
rename to edit/closure-library/closure/goog/graphics/abstractgraphics.js
index 2b1a54a0ab..811c87d8b4 100644
--- a/master/closure-library/closure/goog/graphics/abstractgraphics.js
+++ b/edit/closure-library/closure/goog/graphics/abstractgraphics.js
@@ -21,6 +21,7 @@
goog.provide('goog.graphics.AbstractGraphics');
+goog.require('goog.dom');
goog.require('goog.graphics.Path');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');
diff --git a/master/closure-library/closure/goog/graphics/affinetransform.js b/edit/closure-library/closure/goog/graphics/affinetransform.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/affinetransform.js
rename to edit/closure-library/closure/goog/graphics/affinetransform.js
diff --git a/master/closure-library/closure/goog/graphics/canvaselement.js b/edit/closure-library/closure/goog/graphics/canvaselement.js
similarity index 98%
rename from master/closure-library/closure/goog/graphics/canvaselement.js
rename to edit/closure-library/closure/goog/graphics/canvaselement.js
index e99fa67b86..c566860663 100644
--- a/master/closure-library/closure/goog/graphics/canvaselement.js
+++ b/edit/closure-library/closure/goog/graphics/canvaselement.js
@@ -37,6 +37,9 @@ goog.require('goog.graphics.Path');
goog.require('goog.graphics.PathElement');
goog.require('goog.graphics.RectElement');
goog.require('goog.graphics.TextElement');
+goog.require('goog.math');
+goog.require('goog.string');
+
/**
@@ -48,6 +51,9 @@ goog.require('goog.graphics.TextElement');
* this element.
* @constructor
* @extends {goog.graphics.GroupElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.CanvasGroupElement = function(graphics) {
goog.graphics.GroupElement.call(this, null, graphics);
@@ -395,6 +401,7 @@ goog.graphics.CanvasPathElement.prototype.setPath = function(path) {
/**
* Draw the path. Should be treated as package scope.
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ * @suppress {deprecated} goog.graphics is deprecated.
*/
goog.graphics.CanvasPathElement.prototype.draw = function(ctx) {
this.drawn_ = true;
diff --git a/master/closure-library/closure/goog/graphics/canvasgraphics.js b/edit/closure-library/closure/goog/graphics/canvasgraphics.js
similarity index 98%
rename from master/closure-library/closure/goog/graphics/canvasgraphics.js
rename to edit/closure-library/closure/goog/graphics/canvasgraphics.js
index cf210aba00..3cd6e18d96 100644
--- a/master/closure-library/closure/goog/graphics/canvasgraphics.js
+++ b/edit/closure-library/closure/goog/graphics/canvasgraphics.js
@@ -23,7 +23,6 @@
goog.provide('goog.graphics.CanvasGraphics');
-goog.require('goog.dom');
goog.require('goog.events.EventType');
goog.require('goog.graphics.AbstractGraphics');
goog.require('goog.graphics.CanvasEllipseElement');
@@ -32,11 +31,9 @@ goog.require('goog.graphics.CanvasImageElement');
goog.require('goog.graphics.CanvasPathElement');
goog.require('goog.graphics.CanvasRectElement');
goog.require('goog.graphics.CanvasTextElement');
-goog.require('goog.graphics.Font');
-goog.require('goog.graphics.LinearGradient');
goog.require('goog.graphics.SolidFill');
-goog.require('goog.graphics.Stroke');
goog.require('goog.math.Size');
+goog.require('goog.style');
@@ -54,6 +51,9 @@ goog.require('goog.math.Size');
* document we want to render in.
* @constructor
* @extends {goog.graphics.AbstractGraphics}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.CanvasGraphics = function(width, height,
opt_coordWidth, opt_coordHeight,
diff --git a/master/closure-library/closure/goog/graphics/element.js b/edit/closure-library/closure/goog/graphics/element.js
similarity index 93%
rename from master/closure-library/closure/goog/graphics/element.js
rename to edit/closure-library/closure/goog/graphics/element.js
index 342439e42a..6f93ce7260 100644
--- a/master/closure-library/closure/goog/graphics/element.js
+++ b/edit/closure-library/closure/goog/graphics/element.js
@@ -26,6 +26,7 @@ goog.provide('goog.graphics.Element');
goog.require('goog.events');
goog.require('goog.events.EventTarget');
+goog.require('goog.events.Listenable');
goog.require('goog.graphics.AffineTransform');
goog.require('goog.math');
@@ -41,7 +42,9 @@ goog.require('goog.math');
* this element.
* @constructor
* @extends {goog.events.EventTarget}
- * @suppress {visibility} Accessing private field of superclass (see TODO).
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.Element = function(element, graphics) {
goog.events.EventTarget.call(this);
@@ -49,7 +52,7 @@ goog.graphics.Element = function(element, graphics) {
this.graphics_ = graphics;
// Overloading EventTarget field to state that this is not a custom event.
// TODO(user) Should be handled in EventTarget.js (see bug 846824).
- this.customEvent_ = false;
+ this[goog.events.Listenable.IMPLEMENTED_BY_PROP] = false;
};
goog.inherits(goog.graphics.Element, goog.events.EventTarget);
diff --git a/master/closure-library/closure/goog/graphics/ellipseelement.js b/edit/closure-library/closure/goog/graphics/ellipseelement.js
similarity index 90%
rename from master/closure-library/closure/goog/graphics/ellipseelement.js
rename to edit/closure-library/closure/goog/graphics/ellipseelement.js
index d9f1424224..ef515df728 100644
--- a/master/closure-library/closure/goog/graphics/ellipseelement.js
+++ b/edit/closure-library/closure/goog/graphics/ellipseelement.js
@@ -37,6 +37,9 @@ goog.require('goog.graphics.StrokeAndFillElement');
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.EllipseElement = function(element, graphics, stroke, fill) {
goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
diff --git a/master/closure-library/closure/goog/graphics/ext/coordinates.js b/edit/closure-library/closure/goog/graphics/ext/coordinates.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/coordinates.js
rename to edit/closure-library/closure/goog/graphics/ext/coordinates.js
diff --git a/master/closure-library/closure/goog/graphics/ext/element.js b/edit/closure-library/closure/goog/graphics/ext/element.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/element.js
rename to edit/closure-library/closure/goog/graphics/ext/element.js
diff --git a/master/closure-library/closure/goog/graphics/ext/ellipse.js b/edit/closure-library/closure/goog/graphics/ext/ellipse.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/ellipse.js
rename to edit/closure-library/closure/goog/graphics/ext/ellipse.js
diff --git a/master/closure-library/closure/goog/graphics/ext/ext.js b/edit/closure-library/closure/goog/graphics/ext/ext.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/ext.js
rename to edit/closure-library/closure/goog/graphics/ext/ext.js
diff --git a/master/closure-library/closure/goog/graphics/ext/graphics.js b/edit/closure-library/closure/goog/graphics/ext/graphics.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/graphics.js
rename to edit/closure-library/closure/goog/graphics/ext/graphics.js
diff --git a/master/closure-library/closure/goog/graphics/ext/group.js b/edit/closure-library/closure/goog/graphics/ext/group.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/group.js
rename to edit/closure-library/closure/goog/graphics/ext/group.js
diff --git a/master/closure-library/closure/goog/graphics/ext/image.js b/edit/closure-library/closure/goog/graphics/ext/image.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/image.js
rename to edit/closure-library/closure/goog/graphics/ext/image.js
diff --git a/master/closure-library/closure/goog/graphics/ext/path.js b/edit/closure-library/closure/goog/graphics/ext/path.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/path.js
rename to edit/closure-library/closure/goog/graphics/ext/path.js
diff --git a/master/closure-library/closure/goog/graphics/ext/rectangle.js b/edit/closure-library/closure/goog/graphics/ext/rectangle.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/rectangle.js
rename to edit/closure-library/closure/goog/graphics/ext/rectangle.js
diff --git a/master/closure-library/closure/goog/graphics/ext/shape.js b/edit/closure-library/closure/goog/graphics/ext/shape.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/shape.js
rename to edit/closure-library/closure/goog/graphics/ext/shape.js
diff --git a/master/closure-library/closure/goog/graphics/ext/strokeandfillelement.js b/edit/closure-library/closure/goog/graphics/ext/strokeandfillelement.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/ext/strokeandfillelement.js
rename to edit/closure-library/closure/goog/graphics/ext/strokeandfillelement.js
diff --git a/master/closure-library/closure/goog/graphics/fill.js b/edit/closure-library/closure/goog/graphics/fill.js
similarity index 64%
rename from master/closure-library/closure/goog/graphics/fill.js
rename to edit/closure-library/closure/goog/graphics/fill.js
index 86338d53b0..92e460e253 100644
--- a/master/closure-library/closure/goog/graphics/fill.js
+++ b/edit/closure-library/closure/goog/graphics/fill.js
@@ -26,5 +26,21 @@ goog.provide('goog.graphics.Fill');
/**
* Creates a fill object
* @constructor
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.Fill = function() {};
+
+
+/**
+ * @return {string} The start color of a gradient fill.
+ */
+goog.graphics.Fill.prototype.getColor1 = goog.abstractMethod;
+
+
+/**
+ * @return {string} The end color of a gradient fill.
+ */
+goog.graphics.Fill.prototype.getColor2 = goog.abstractMethod;
+
diff --git a/master/closure-library/closure/goog/graphics/font.js b/edit/closure-library/closure/goog/graphics/font.js
similarity index 87%
rename from master/closure-library/closure/goog/graphics/font.js
rename to edit/closure-library/closure/goog/graphics/font.js
index 082c8b70e8..045ee6b1a6 100644
--- a/master/closure-library/closure/goog/graphics/font.js
+++ b/edit/closure-library/closure/goog/graphics/font.js
@@ -29,6 +29,9 @@ goog.provide('goog.graphics.Font');
* @param {number} size The font size.
* @param {string} family The font family.
* @constructor
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.Font = function(size, family) {
/**
diff --git a/master/closure-library/closure/goog/graphics/graphics.js b/edit/closure-library/closure/goog/graphics/graphics.js
similarity index 80%
rename from master/closure-library/closure/goog/graphics/graphics.js
rename to edit/closure-library/closure/goog/graphics/graphics.js
index 7733fe8c70..d94f166cf8 100644
--- a/master/closure-library/closure/goog/graphics/graphics.js
+++ b/edit/closure-library/closure/goog/graphics/graphics.js
@@ -47,15 +47,19 @@ goog.require('goog.userAgent');
* @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
* document we want to render in.
* @return {goog.graphics.AbstractGraphics} The created instance.
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.createGraphics = function(width, height, opt_coordWidth,
opt_coordHeight, opt_domHelper) {
var graphics;
- if (goog.userAgent.IE && !goog.userAgent.isVersion('9')) {
+ if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) {
graphics = new goog.graphics.VmlGraphics(width, height,
opt_coordWidth, opt_coordHeight, opt_domHelper);
- } else if (goog.userAgent.WEBKIT && (!goog.userAgent.isVersion('420') ||
- goog.userAgent.MOBILE)) {
+ } else if (goog.userAgent.WEBKIT &&
+ (!goog.userAgent.isVersionOrHigher('420') ||
+ goog.userAgent.MOBILE)) {
graphics = new goog.graphics.CanvasGraphics(width, height,
opt_coordWidth, opt_coordHeight, opt_domHelper);
} else {
@@ -85,11 +89,14 @@ goog.graphics.createGraphics = function(width, height, opt_coordWidth,
* @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
* document we want to render in.
* @return {goog.graphics.AbstractGraphics} The created instance.
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.createSimpleGraphics = function(width, height,
opt_coordWidth, opt_coordHeight, opt_domHelper) {
if (goog.userAgent.MAC && goog.userAgent.GECKO &&
- !goog.userAgent.isVersion('1.9a')) {
+ !goog.userAgent.isVersionOrHigher('1.9a')) {
// Canvas is 6x faster than SVG on Mac FF 2.0
var graphics = new goog.graphics.CanvasGraphics(
width, height, opt_coordWidth, opt_coordHeight,
@@ -107,19 +114,22 @@ goog.graphics.createSimpleGraphics = function(width, height,
/**
* Static function to check if the current browser has Graphics support.
* @return {boolean} True if the current browser has Graphics support.
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.isBrowserSupported = function() {
if (goog.userAgent.IE) {
- return goog.userAgent.isVersion('5.5');
+ return goog.userAgent.isVersionOrHigher('5.5');
}
if (goog.userAgent.GECKO) {
- return goog.userAgent.isVersion('1.8');
+ return goog.userAgent.isVersionOrHigher('1.8');
}
if (goog.userAgent.OPERA) {
- return goog.userAgent.isVersion('9.0');
+ return goog.userAgent.isVersionOrHigher('9.0');
}
if (goog.userAgent.WEBKIT) {
- return goog.userAgent.isVersion('412');
+ return goog.userAgent.isVersionOrHigher('412');
}
return false;
};
diff --git a/master/closure-library/closure/goog/graphics/groupelement.js b/edit/closure-library/closure/goog/graphics/groupelement.js
similarity index 89%
rename from master/closure-library/closure/goog/graphics/groupelement.js
rename to edit/closure-library/closure/goog/graphics/groupelement.js
index 537af71439..e8ba5ea1a4 100644
--- a/master/closure-library/closure/goog/graphics/groupelement.js
+++ b/edit/closure-library/closure/goog/graphics/groupelement.js
@@ -35,6 +35,9 @@ goog.require('goog.graphics.Element');
* this element.
* @constructor
* @extends {goog.graphics.Element}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.GroupElement = function(element, graphics) {
goog.graphics.Element.call(this, element, graphics);
diff --git a/master/closure-library/closure/goog/graphics/imageelement.js b/edit/closure-library/closure/goog/graphics/imageelement.js
similarity index 90%
rename from master/closure-library/closure/goog/graphics/imageelement.js
rename to edit/closure-library/closure/goog/graphics/imageelement.js
index 7489ee9f65..2f2d9b792c 100644
--- a/master/closure-library/closure/goog/graphics/imageelement.js
+++ b/edit/closure-library/closure/goog/graphics/imageelement.js
@@ -35,6 +35,9 @@ goog.require('goog.graphics.Element');
* this element.
* @constructor
* @extends {goog.graphics.Element}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.ImageElement = function(element, graphics) {
goog.graphics.Element.call(this, element, graphics);
diff --git a/master/closure-library/closure/goog/graphics/lineargradient.js b/edit/closure-library/closure/goog/graphics/lineargradient.js
similarity index 94%
rename from master/closure-library/closure/goog/graphics/lineargradient.js
rename to edit/closure-library/closure/goog/graphics/lineargradient.js
index 4710dd8254..c63cac017e 100644
--- a/master/closure-library/closure/goog/graphics/lineargradient.js
+++ b/edit/closure-library/closure/goog/graphics/lineargradient.js
@@ -41,6 +41,9 @@ goog.require('goog.graphics.Fill');
* @param {?number=} opt_opacity2 End opacity of the gradient.
* @constructor
* @extends {goog.graphics.Fill}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.LinearGradient =
function(x1, y1, x2, y2, color1, color2, opt_opacity1, opt_opacity2) {
@@ -140,7 +143,7 @@ goog.graphics.LinearGradient.prototype.getY2 = function() {
/**
- * @return {string} The start color of the gradient.
+ * @override
*/
goog.graphics.LinearGradient.prototype.getColor1 = function() {
return this.color1_;
@@ -148,7 +151,7 @@ goog.graphics.LinearGradient.prototype.getColor1 = function() {
/**
- * @return {string} The end color of the gradient.
+ * @override
*/
goog.graphics.LinearGradient.prototype.getColor2 = function() {
return this.color2_;
diff --git a/master/closure-library/closure/goog/graphics/path.js b/edit/closure-library/closure/goog/graphics/path.js
similarity index 99%
rename from master/closure-library/closure/goog/graphics/path.js
rename to edit/closure-library/closure/goog/graphics/path.js
index 858a52670b..08bf03e6fe 100644
--- a/master/closure-library/closure/goog/graphics/path.js
+++ b/edit/closure-library/closure/goog/graphics/path.js
@@ -430,6 +430,7 @@ goog.graphics.Path.prototype.isSimple = function() {
* A map from segment type to the path function to call to simplify a path.
* @type {!Object}
* @private
+ * @suppress {deprecated} goog.graphics.Path is deprecated.
*/
goog.graphics.Path.simplifySegmentMap_ = (function() {
var map = {};
@@ -451,6 +452,7 @@ goog.graphics.Path.simplifySegmentMap_ = (function() {
*
* @param {!goog.graphics.Path} src The path to simplify.
* @return {!goog.graphics.Path} A new simplified path.
+ * @suppress {deprecated} goog.graphics is deprecated.
*/
goog.graphics.Path.createSimplifiedPath = function(src) {
if (src.isSimple()) {
diff --git a/master/closure-library/closure/goog/graphics/pathelement.js b/edit/closure-library/closure/goog/graphics/pathelement.js
similarity index 89%
rename from master/closure-library/closure/goog/graphics/pathelement.js
rename to edit/closure-library/closure/goog/graphics/pathelement.js
index 6707816d64..e381c49fe1 100644
--- a/master/closure-library/closure/goog/graphics/pathelement.js
+++ b/edit/closure-library/closure/goog/graphics/pathelement.js
@@ -37,6 +37,9 @@ goog.require('goog.graphics.StrokeAndFillElement');
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.PathElement = function(element, graphics, stroke, fill) {
goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
diff --git a/master/closure-library/closure/goog/graphics/paths.js b/edit/closure-library/closure/goog/graphics/paths.js
similarity index 100%
rename from master/closure-library/closure/goog/graphics/paths.js
rename to edit/closure-library/closure/goog/graphics/paths.js
diff --git a/master/closure-library/closure/goog/graphics/rectelement.js b/edit/closure-library/closure/goog/graphics/rectelement.js
similarity index 90%
rename from master/closure-library/closure/goog/graphics/rectelement.js
rename to edit/closure-library/closure/goog/graphics/rectelement.js
index e5568e0d1b..9a50ce70e9 100644
--- a/master/closure-library/closure/goog/graphics/rectelement.js
+++ b/edit/closure-library/closure/goog/graphics/rectelement.js
@@ -37,6 +37,9 @@ goog.require('goog.graphics.StrokeAndFillElement');
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.RectElement = function(element, graphics, stroke, fill) {
goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
diff --git a/master/closure-library/closure/goog/graphics/solidfill.js b/edit/closure-library/closure/goog/graphics/solidfill.js
similarity index 89%
rename from master/closure-library/closure/goog/graphics/solidfill.js
rename to edit/closure-library/closure/goog/graphics/solidfill.js
index 99dfaebe82..fae3fc4248 100644
--- a/master/closure-library/closure/goog/graphics/solidfill.js
+++ b/edit/closure-library/closure/goog/graphics/solidfill.js
@@ -35,6 +35,9 @@ goog.require('goog.graphics.Fill');
* equal to 1 (opaque).
* @constructor
* @extends {goog.graphics.Fill}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.SolidFill = function(color, opt_opacity) {
/**
diff --git a/master/closure-library/closure/goog/graphics/stroke.js b/edit/closure-library/closure/goog/graphics/stroke.js
similarity index 87%
rename from master/closure-library/closure/goog/graphics/stroke.js
rename to edit/closure-library/closure/goog/graphics/stroke.js
index 9283abf660..5091194825 100644
--- a/master/closure-library/closure/goog/graphics/stroke.js
+++ b/edit/closure-library/closure/goog/graphics/stroke.js
@@ -29,6 +29,9 @@ goog.provide('goog.graphics.Stroke');
* @param {number|string} width The width of the stroke.
* @param {string} color The color of the stroke.
* @constructor
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.Stroke = function(width, color) {
/**
diff --git a/master/closure-library/closure/goog/graphics/strokeandfillelement.js b/edit/closure-library/closure/goog/graphics/strokeandfillelement.js
similarity index 93%
rename from master/closure-library/closure/goog/graphics/strokeandfillelement.js
rename to edit/closure-library/closure/goog/graphics/strokeandfillelement.js
index fcfc3db9db..dce2c19dba 100644
--- a/master/closure-library/closure/goog/graphics/strokeandfillelement.js
+++ b/edit/closure-library/closure/goog/graphics/strokeandfillelement.js
@@ -41,6 +41,9 @@ goog.require('goog.graphics.Element');
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.Element}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.StrokeAndFillElement = function(element, graphics, stroke, fill) {
goog.graphics.Element.call(this, element, graphics);
diff --git a/master/closure-library/closure/goog/graphics/svgelement.js b/edit/closure-library/closure/goog/graphics/svgelement.js
similarity index 96%
rename from master/closure-library/closure/goog/graphics/svgelement.js
rename to edit/closure-library/closure/goog/graphics/svgelement.js
index da3514e2d1..cf76bfa3aa 100644
--- a/master/closure-library/closure/goog/graphics/svgelement.js
+++ b/edit/closure-library/closure/goog/graphics/svgelement.js
@@ -47,6 +47,9 @@ goog.require('goog.graphics.TextElement');
* this element.
* @constructor
* @extends {goog.graphics.GroupElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.SvgGroupElement = function(element, graphics) {
goog.graphics.GroupElement.call(this, element, graphics);
@@ -189,7 +192,8 @@ goog.inherits(goog.graphics.SvgPathElement, goog.graphics.PathElement);
*/
goog.graphics.SvgPathElement.prototype.setPath = function(path) {
this.getGraphics().setElementAttributes(this.getElement(),
- {'d': goog.graphics.SvgGraphics.getSvgPath(path)});
+ {'d': /** @suppress {missingRequire} */
+ goog.graphics.SvgGraphics.getSvgPath(path)});
};
diff --git a/master/closure-library/closure/goog/graphics/svggraphics.js b/edit/closure-library/closure/goog/graphics/svggraphics.js
similarity index 98%
rename from master/closure-library/closure/goog/graphics/svggraphics.js
rename to edit/closure-library/closure/goog/graphics/svggraphics.js
index 2e463fe37a..1f717828a0 100644
--- a/master/closure-library/closure/goog/graphics/svggraphics.js
+++ b/edit/closure-library/closure/goog/graphics/svggraphics.js
@@ -26,8 +26,8 @@ goog.require('goog.dom');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventType');
goog.require('goog.graphics.AbstractGraphics');
-goog.require('goog.graphics.Font');
goog.require('goog.graphics.LinearGradient');
+goog.require('goog.graphics.Path');
goog.require('goog.graphics.SolidFill');
goog.require('goog.graphics.Stroke');
goog.require('goog.graphics.SvgEllipseElement');
@@ -36,6 +36,7 @@ goog.require('goog.graphics.SvgImageElement');
goog.require('goog.graphics.SvgPathElement');
goog.require('goog.graphics.SvgRectElement');
goog.require('goog.graphics.SvgTextElement');
+goog.require('goog.math');
goog.require('goog.math.Size');
goog.require('goog.style');
goog.require('goog.userAgent');
@@ -56,6 +57,9 @@ goog.require('goog.userAgent');
* document we want to render in.
* @constructor
* @extends {goog.graphics.AbstractGraphics}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.SvgGraphics = function(width, height,
opt_coordWidth, opt_coordHeight,
@@ -82,7 +86,7 @@ goog.graphics.SvgGraphics = function(width, height,
* @private
*/
this.useManualViewbox_ = goog.userAgent.WEBKIT &&
- !goog.userAgent.isVersion(526);
+ !goog.userAgent.isVersionOrHigher(526);
/**
* Event handler.
@@ -651,6 +655,7 @@ goog.graphics.SvgGraphics.prototype.drawPath = function(
*
* @param {goog.graphics.Path} path The logical path.
* @return {string} The SVG path representation.
+ * @suppress {deprecated} goog.graphics is deprecated.
*/
goog.graphics.SvgGraphics.getSvgPath = function(path) {
var list = [];
@@ -752,6 +757,7 @@ goog.graphics.SvgGraphics.prototype.getDef = function(defKey) {
return defKey in this.defs_ ? this.defs_[defKey] : null;
};
+
/**
* Removes a definition of an elemnt from the global definitions.
* @param {string} defKey This is a key that should be unique in a way that
@@ -759,7 +765,7 @@ goog.graphics.SvgGraphics.prototype.getDef = function(defKey) {
*/
goog.graphics.SvgGraphics.prototype.removeDef = function(defKey) {
var id = this.getDef(defKey);
- if (id) {
+ if (id) {
var element = this.dom_.getElement(id);
this.defsElement_.removeChild(element);
delete this.defs_[defKey];
diff --git a/master/closure-library/closure/goog/graphics/textelement.js b/edit/closure-library/closure/goog/graphics/textelement.js
similarity index 89%
rename from master/closure-library/closure/goog/graphics/textelement.js
rename to edit/closure-library/closure/goog/graphics/textelement.js
index 39adcc20a4..8afd918fe8 100644
--- a/master/closure-library/closure/goog/graphics/textelement.js
+++ b/edit/closure-library/closure/goog/graphics/textelement.js
@@ -38,6 +38,9 @@ goog.require('goog.graphics.StrokeAndFillElement');
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.TextElement = function(element, graphics, stroke, fill) {
goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
diff --git a/master/closure-library/closure/goog/graphics/vmlelement.js b/edit/closure-library/closure/goog/graphics/vmlelement.js
similarity index 80%
rename from master/closure-library/closure/goog/graphics/vmlelement.js
rename to edit/closure-library/closure/goog/graphics/vmlelement.js
index 57d7a9df9b..1a8ed71fe3 100644
--- a/master/closure-library/closure/goog/graphics/vmlelement.js
+++ b/edit/closure-library/closure/goog/graphics/vmlelement.js
@@ -64,6 +64,9 @@ goog.graphics.vmlGetElement_ = function() {
* this element.
* @constructor
* @extends {goog.graphics.GroupElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlGroupElement = function(element, graphics) {
this.id_ = element.id;
@@ -105,10 +108,15 @@ goog.graphics.VmlGroupElement.prototype.setSize = function(width, height) {
var element = this.getElement();
var style = element.style;
- style.width = goog.graphics.VmlGraphics.toSizePx(width);
- style.height = goog.graphics.VmlGraphics.toSizePx(height);
+ style.width = /** @suppress {missingRequire} */ (
+ goog.graphics.VmlGraphics.toSizePx(width));
+ style.height = /** @suppress {missingRequire} */ (
+ goog.graphics.VmlGraphics.toSizePx(height));
- element.coordsize = goog.graphics.VmlGraphics.toSizeCoord(width) + ' ' +
+ element.coordsize = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizeCoord(width) +
+ ' ' +
+ /** @suppress {missingRequire} */
goog.graphics.VmlGraphics.toSizeCoord(height);
// Don't overwrite the root element's origin.
@@ -135,6 +143,9 @@ goog.graphics.VmlGroupElement.prototype.setSize = function(width, height) {
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.EllipseElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlEllipseElement = function(element, graphics,
cx, cy, rx, ry, stroke, fill) {
@@ -188,6 +199,7 @@ goog.graphics.VmlEllipseElement.prototype.getElement =
goog.graphics.VmlEllipseElement.prototype.setCenter = function(cx, cy) {
this.cx = cx;
this.cy = cy;
+ /** @suppress {missingRequire} */
goog.graphics.VmlGraphics.setPositionAndSize(this.getElement(),
cx - this.rx, cy - this.ry, this.rx * 2, this.ry * 2);
};
@@ -202,6 +214,7 @@ goog.graphics.VmlEllipseElement.prototype.setCenter = function(cx, cy) {
goog.graphics.VmlEllipseElement.prototype.setRadius = function(rx, ry) {
this.rx = rx;
this.ry = ry;
+ /** @suppress {missingRequire} */
goog.graphics.VmlGraphics.setPositionAndSize(this.getElement(),
this.cx - rx, this.cy - ry, rx * 2, ry * 2);
};
@@ -220,6 +233,9 @@ goog.graphics.VmlEllipseElement.prototype.setRadius = function(rx, ry) {
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.RectElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlRectElement = function(element, graphics, stroke, fill) {
this.id_ = element.id;
@@ -241,8 +257,11 @@ goog.graphics.VmlRectElement.prototype.getElement =
*/
goog.graphics.VmlRectElement.prototype.setPosition = function(x, y) {
var style = this.getElement().style;
- style.left = goog.graphics.VmlGraphics.toPosPx(x);
- style.top = goog.graphics.VmlGraphics.toPosPx(y);
+
+ style.left = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(x);
+ style.top = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(y);
};
@@ -254,8 +273,10 @@ goog.graphics.VmlRectElement.prototype.setPosition = function(x, y) {
*/
goog.graphics.VmlRectElement.prototype.setSize = function(width, height) {
var style = this.getElement().style;
- style.width = goog.graphics.VmlGraphics.toSizePx(width);
- style.height = goog.graphics.VmlGraphics.toSizePx(height);
+ style.width = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizePx(width);
+ style.height = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizePx(height);
};
@@ -272,6 +293,9 @@ goog.graphics.VmlRectElement.prototype.setSize = function(width, height) {
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.PathElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlPathElement = function(element, graphics, stroke, fill) {
this.id_ = element.id;
@@ -291,8 +315,11 @@ goog.graphics.VmlPathElement.prototype.getElement =
* @override
*/
goog.graphics.VmlPathElement.prototype.setPath = function(path) {
+ /** @suppress {missingRequire} */
goog.graphics.VmlGraphics.setAttribute(
- this.getElement(), 'path', goog.graphics.VmlGraphics.getVmlPath(path));
+ this.getElement(), 'path',
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.getVmlPath(path));
};
@@ -309,6 +336,9 @@ goog.graphics.VmlPathElement.prototype.setPath = function(path) {
* @param {goog.graphics.Fill?} fill The fill to use for this element.
* @constructor
* @extends {goog.graphics.TextElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlTextElement = function(element, graphics, stroke, fill) {
this.id_ = element.id;
@@ -328,6 +358,7 @@ goog.graphics.VmlTextElement.prototype.getElement =
* @override
*/
goog.graphics.VmlTextElement.prototype.setText = function(text) {
+ /** @suppress {missingRequire} */
goog.graphics.VmlGraphics.setAttribute(this.getElement().childNodes[1],
'string', text);
};
@@ -344,6 +375,9 @@ goog.graphics.VmlTextElement.prototype.setText = function(text) {
* this element.
* @constructor
* @extends {goog.graphics.ImageElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlImageElement = function(element, graphics) {
this.id_ = element.id;
@@ -365,8 +399,11 @@ goog.graphics.VmlImageElement.prototype.getElement =
*/
goog.graphics.VmlImageElement.prototype.setPosition = function(x, y) {
var style = this.getElement().style;
- style.left = goog.graphics.VmlGraphics.toPosPx(x);
- style.top = goog.graphics.VmlGraphics.toPosPx(y);
+
+ style.left = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(x);
+ style.top = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(y);
};
@@ -378,8 +415,10 @@ goog.graphics.VmlImageElement.prototype.setPosition = function(x, y) {
*/
goog.graphics.VmlImageElement.prototype.setSize = function(width, height) {
var style = this.getElement().style;
- style.width = goog.graphics.VmlGraphics.toPosPx(width);
- style.height = goog.graphics.VmlGraphics.toPosPx(height);
+ style.width = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(width);
+ style.height = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(height);
};
@@ -389,5 +428,6 @@ goog.graphics.VmlImageElement.prototype.setSize = function(width, height) {
* @override
*/
goog.graphics.VmlImageElement.prototype.setSource = function(src) {
+ /** @suppress {missingRequire} */
goog.graphics.VmlGraphics.setAttribute(this.getElement(), 'src', src);
};
diff --git a/master/closure-library/closure/goog/graphics/vmlgraphics.js b/edit/closure-library/closure/goog/graphics/vmlgraphics.js
similarity index 98%
rename from master/closure-library/closure/goog/graphics/vmlgraphics.js
rename to edit/closure-library/closure/goog/graphics/vmlgraphics.js
index 113246829a..58f407f9af 100644
--- a/master/closure-library/closure/goog/graphics/vmlgraphics.js
+++ b/edit/closure-library/closure/goog/graphics/vmlgraphics.js
@@ -24,20 +24,20 @@ goog.provide('goog.graphics.VmlGraphics');
goog.require('goog.array');
-goog.require('goog.dom');
+goog.require('goog.events');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventType');
goog.require('goog.graphics.AbstractGraphics');
-goog.require('goog.graphics.Font');
goog.require('goog.graphics.LinearGradient');
+goog.require('goog.graphics.Path');
goog.require('goog.graphics.SolidFill');
-goog.require('goog.graphics.Stroke');
goog.require('goog.graphics.VmlEllipseElement');
goog.require('goog.graphics.VmlGroupElement');
goog.require('goog.graphics.VmlImageElement');
goog.require('goog.graphics.VmlPathElement');
goog.require('goog.graphics.VmlRectElement');
goog.require('goog.graphics.VmlTextElement');
+goog.require('goog.math');
goog.require('goog.math.Size');
goog.require('goog.string');
goog.require('goog.style');
@@ -58,6 +58,9 @@ goog.require('goog.style');
* document we want to render in.
* @constructor
* @extends {goog.graphics.AbstractGraphics}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
*/
goog.graphics.VmlGraphics = function(width, height,
opt_coordWidth, opt_coordHeight,
@@ -790,6 +793,7 @@ goog.graphics.VmlGraphics.prototype.drawPath = function(path, stroke, fill,
*
* @param {goog.graphics.Path} path The logical path.
* @return {string} The VML path representation.
+ * @suppress {deprecated} goog.graphics is deprecated.
*/
goog.graphics.VmlGraphics.getVmlPath = function(path) {
var list = [];
diff --git a/master/closure-library/closure/goog/history/event.js b/edit/closure-library/closure/goog/history/event.js
similarity index 100%
rename from master/closure-library/closure/goog/history/event.js
rename to edit/closure-library/closure/goog/history/event.js
diff --git a/master/closure-library/closure/goog/history/eventtype.js b/edit/closure-library/closure/goog/history/eventtype.js
similarity index 100%
rename from master/closure-library/closure/goog/history/eventtype.js
rename to edit/closure-library/closure/goog/history/eventtype.js
diff --git a/master/closure-library/closure/goog/history/history.js b/edit/closure-library/closure/goog/history/history.js
similarity index 95%
rename from master/closure-library/closure/goog/history/history.js
rename to edit/closure-library/closure/goog/history/history.js
index 6b4d650372..6ff24b6aeb 100644
--- a/master/closure-library/closure/goog/history/history.js
+++ b/edit/closure-library/closure/goog/history/history.js
@@ -164,14 +164,12 @@ goog.provide('goog.History.EventType');
goog.require('goog.Timer');
goog.require('goog.dom');
-goog.require('goog.events');
-goog.require('goog.events.BrowserEvent');
-goog.require('goog.events.Event');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.history.Event');
goog.require('goog.history.EventType');
+goog.require('goog.memoize');
goog.require('goog.string');
goog.require('goog.userAgent');
@@ -246,7 +244,7 @@ goog.History = function(opt_invisible, opt_blankPageUrl, opt_input,
* @type {HTMLInputElement}
* @private
*/
- this.hiddenInput_ = (/** @type {HTMLInputElement} */ input);
+ this.hiddenInput_ = /** @type {HTMLInputElement} */ (input);
/**
* The window whose location contains the history token fragment. This is
@@ -258,15 +256,6 @@ goog.History = function(opt_invisible, opt_blankPageUrl, opt_input,
this.window_ = opt_input ?
goog.dom.getWindow(goog.dom.getOwnerDocument(opt_input)) : window;
- /**
- * The initial page location with an empty hash component. If the page uses
- * a BASE element, setting location.hash directly will navigate away from the
- * current document. To prevent this, the full path is always specified.
- * @type {string}
- * @private
- */
- this.baseUrl_ = this.window_.location.href.split('#')[0];
-
/**
* The base URL for the hidden iframe. Must refer to a document in the
* same domain as the main page.
@@ -286,6 +275,7 @@ goog.History = function(opt_invisible, opt_blankPageUrl, opt_input,
* @private
*/
this.timer_ = new goog.Timer(goog.History.PollingType.NORMAL);
+ this.registerDisposable(this.timer_);
/**
* True if the state tokens are displayed in the address bar, false for hidden
@@ -323,7 +313,7 @@ goog.History = function(opt_invisible, opt_blankPageUrl, opt_input,
* @type {HTMLIFrameElement}
* @private
*/
- this.iframe_ = (/** @type {HTMLIFrameElement} */ iframe);
+ this.iframe_ = /** @type {HTMLIFrameElement} */ (iframe);
/**
* Whether the hidden iframe has had a document written to it yet in this
@@ -402,14 +392,17 @@ goog.History.prototype.lastToken_ = null;
/**
- * Whether the browser supports HTML5 history management.
- * {@link http://www.w3.org/TR/html5/history.html}.
- * @type {boolean}
+ * Whether the browser supports HTML5 history management's onhashchange event.
+ * {@link http://www.w3.org/TR/html5/history.html}. IE 9 in compatibility mode
+ * indicates that onhashchange is in window, but testing reveals the event
+ * isn't actually fired.
+ * @return {boolean} Whether onhashchange is supported.
*/
-goog.History.HAS_ONHASHCHANGE =
- goog.userAgent.IE && goog.userAgent.isDocumentMode(8) ||
- goog.userAgent.GECKO && goog.userAgent.isVersion('1.9.2') ||
- goog.userAgent.WEBKIT && goog.userAgent.isVersion('532.1');
+goog.History.isOnHashChangeSupported = goog.memoize(function() {
+ return goog.userAgent.IE ?
+ document.documentMode >= 8 :
+ 'onhashchange' in goog.global;
+});
/**
@@ -418,7 +411,8 @@ goog.History.HAS_ONHASHCHANGE =
* current versions.
* @type {boolean}
*/
-goog.History.LEGACY_IE = goog.userAgent.IE && !goog.userAgent.isDocumentMode(8);
+goog.History.LEGACY_IE = goog.userAgent.IE &&
+ !goog.userAgent.isDocumentModeOrHigher(8);
/**
@@ -488,7 +482,8 @@ goog.History.prototype.setEnabled = function(enable) {
// TODO(user): make HTML5 and invisible history work by listening to the
// iframe # changes instead of the window.
- if (goog.History.HAS_ONHASHCHANGE && this.userVisible_) {
+ if (goog.History.isOnHashChangeSupported() &&
+ this.userVisible_) {
this.eventHandler_.listen(
this.window_, goog.events.EventType.HASHCHANGE, this.onHashChange_);
this.enabled_ = true;
@@ -563,8 +558,8 @@ goog.History.prototype.onShow_ = function(e) {
/**
* Handles HTML5 onhashchange events on browsers where it is supported.
* This is very similar to {@link #check_}, except that it is not executed
- * continuously. It is only used when {@code goog.History.HAS_ONHASHCHANGE} is
- * true.
+ * continuously. It is only used when
+ * {@code goog.History.isOnHashChangeSupported()} is true.
* @param {goog.events.BrowserEvent} e The browser event.
* @private
*/
@@ -651,7 +646,7 @@ goog.History.prototype.setHistoryState_ = function(token, replace, opt_title) {
if (this.userVisible_) {
this.setHash_(token, replace);
- if (!goog.History.HAS_ONHASHCHANGE) {
+ if (!goog.History.isOnHashChangeSupported()) {
if (goog.userAgent.IE) {
// IE must save state using the iframe.
this.setIframeToken_(token, replace, opt_title);
@@ -659,8 +654,8 @@ goog.History.prototype.setHistoryState_ = function(token, replace, opt_title) {
}
// This condition needs to be called even if
- // goog.History.HAS_ONHASHCHANGE is true so the NAVIGATE event fires
- // sychronously.
+ // goog.History.isOnHashChangeSupported() is true so the NAVIGATE event
+ // fires sychronously.
if (this.enabled_) {
this.check_(false);
}
@@ -698,8 +693,12 @@ goog.History.prototype.setHistoryState_ = function(token, replace, opt_title) {
* @private
*/
goog.History.prototype.setHash_ = function(token, opt_replace) {
+ // If the page uses a BASE element, setting location.hash directly will
+ // navigate away from the current document. Also, the original URL path may
+ // possibly change from HTML5 history pushState. To account for these, the
+ // full path is always specified.
var loc = this.window_.location;
- var url = this.baseUrl_;
+ var url = loc.href.split('#')[0];
// If a hash has already been set, then removing it programmatically will
// reload the page. Once there is a hash, we won't remove it.
@@ -832,7 +831,7 @@ goog.History.prototype.getIframeToken_ = function() {
/**
* Checks the state of the document fragment and the iframe title to detect
- * navigation changes. If {@code goog.History.HAS_ONHASHCHANGE} is
+ * navigation changes. If {@code goog.HistoryisOnHashChangeSupported()} is
* {@code false}, then this runs approximately twenty times per second.
* @param {boolean} isNavigation True if the event was initiated by a browser
* action, false if it was caused by a setToken call. See
diff --git a/edit/closure-library/closure/goog/history/history_test.js b/edit/closure-library/closure/goog/history/history_test.js
new file mode 100644
index 0000000000..4ee7f0eb37
--- /dev/null
+++ b/edit/closure-library/closure/goog/history/history_test.js
@@ -0,0 +1,54 @@
+// Copyright 2013 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.
+
+/**
+ * @fileoverview Unit tests for goog.history.History.
+ */
+
+/** @suppress {extraProvide} */
+goog.provide('goog.HistoryTest');
+
+goog.require('goog.History');
+goog.require('goog.testing.jsunit');
+goog.require('goog.userAgent');
+
+goog.setTestOnly('goog.HistoryTest');
+
+
+// Mimimal function to exercise construction.
+function testCreation() {
+
+ // Running goog.History in tests on older browsers simply hangs them in TAP.
+ if (goog.userAgent.GECKO ||
+ (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9))) {
+ return;
+ }
+
+ var history = new goog.History();
+
+}
+
+function testIsHashChangeSupported() {
+
+ // This is the policy currently implemented.
+ var supportsOnHashChange = (goog.userAgent.IE ?
+ document.documentMode >= 8 :
+ 'onhashchange' in window);
+
+ assertEquals(
+ supportsOnHashChange,
+ goog.History.isOnHashChangeSupported());
+}
+
+// TODO(nnaze): Test additional behavior.
diff --git a/master/closure-library/closure/goog/history/html5history.js b/edit/closure-library/closure/goog/history/html5history.js
similarity index 100%
rename from master/closure-library/closure/goog/history/html5history.js
rename to edit/closure-library/closure/goog/history/html5history.js
diff --git a/master/closure-library/closure/goog/i18n/bidi.js b/edit/closure-library/closure/goog/i18n/bidi.js
similarity index 99%
rename from master/closure-library/closure/goog/i18n/bidi.js
rename to edit/closure-library/closure/goog/i18n/bidi.js
index 1af4e859c0..22092f0867 100644
--- a/master/closure-library/closure/goog/i18n/bidi.js
+++ b/edit/closure-library/closure/goog/i18n/bidi.js
@@ -31,7 +31,7 @@ goog.provide('goog.i18n.bidi');
*
* {@see goog.i18n.bidi.IS_RTL}
*/
-goog.i18n.bidi.FORCE_RTL = false;
+goog.define('goog.i18n.bidi.FORCE_RTL', false);
/**
@@ -159,7 +159,7 @@ goog.i18n.bidi.toDir = function(givenDir) {
*/
goog.i18n.bidi.ltrChars_ =
'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' +
- '\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF';
+ '\u200E\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF';
/**
@@ -169,7 +169,7 @@ goog.i18n.bidi.ltrChars_ =
* @type {string}
* @private
*/
-goog.i18n.bidi.rtlChars_ = '\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC';
+goog.i18n.bidi.rtlChars_ = '\u0591-\u07FF\u200F\uFB1D-\uFDFF\uFE70-\uFEFC';
/**
diff --git a/master/closure-library/closure/goog/i18n/bidiformatter.js b/edit/closure-library/closure/goog/i18n/bidiformatter.js
similarity index 99%
rename from master/closure-library/closure/goog/i18n/bidiformatter.js
rename to edit/closure-library/closure/goog/i18n/bidiformatter.js
index bcc3e527b7..9d9364c572 100644
--- a/master/closure-library/closure/goog/i18n/bidiformatter.js
+++ b/edit/closure-library/closure/goog/i18n/bidiformatter.js
@@ -199,7 +199,9 @@ goog.i18n.BidiFormatter.prototype.dirResetIfNeeded_ = function(str, dir,
* is RTL, and "ltr" otherwise.
* Needed for GXP, which can't handle dirAttr.
* Example use case:
- *