diff --git a/master/apidoc/44f1750883.html b/master/apidoc/44f1750883.html index f136f3b183..07a97e6501 100644 --- a/master/apidoc/44f1750883.html +++ b/master/apidoc/44f1750883.html @@ -137,13 +137,13 @@ items from the cache is the responsibility of the user.
diff --git a/master/apidoc/global.html b/master/apidoc/global.html index 8196c49eb3..00ce1e8aaf 100644 --- a/master/apidoc/global.html +++ b/master/apidoc/global.html @@ -61,7 +61,7 @@
Source:
-
+
@@ -140,7 +140,7 @@
Source:
-
+
@@ -219,7 +219,7 @@
Source:
-
+
@@ -421,13 +421,13 @@
diff --git a/master/apidoc/index.html b/master/apidoc/index.html index 7e5503627e..3fb1c959c8 100644 --- a/master/apidoc/index.html +++ b/master/apidoc/index.html @@ -50,13 +50,13 @@
diff --git a/master/apidoc/ol.AnchoredElement.html b/master/apidoc/ol.AnchoredElement.html index 0235b1d394..f2a3228c26 100644 --- a/master/apidoc/ol.AnchoredElement.html +++ b/master/apidoc/ol.AnchoredElement.html @@ -2337,13 +2337,13 @@
diff --git a/master/apidoc/ol.Attribution.html b/master/apidoc/ol.Attribution.html index a1cb9b2954..78b5b7472d 100644 --- a/master/apidoc/ol.Attribution.html +++ b/master/apidoc/ol.Attribution.html @@ -428,13 +428,13 @@
diff --git a/master/apidoc/ol.Collection.html b/master/apidoc/ol.Collection.html index 0346db1b66..f363375756 100644 --- a/master/apidoc/ol.Collection.html +++ b/master/apidoc/ol.Collection.html @@ -2614,13 +2614,13 @@
diff --git a/master/apidoc/ol.CollectionEvent.html b/master/apidoc/ol.CollectionEvent.html index 4af017adbb..590e39e826 100644 --- a/master/apidoc/ol.CollectionEvent.html +++ b/master/apidoc/ol.CollectionEvent.html @@ -301,13 +301,13 @@
diff --git a/master/apidoc/ol.Color.html b/master/apidoc/ol.Color.html index a472860a82..68cc893eba 100644 --- a/master/apidoc/ol.Color.html +++ b/master/apidoc/ol.Color.html @@ -756,13 +756,13 @@
diff --git a/master/apidoc/ol.Constraints.html b/master/apidoc/ol.Constraints.html index ea7ba395fc..1961411736 100644 --- a/master/apidoc/ol.Constraints.html +++ b/master/apidoc/ol.Constraints.html @@ -294,13 +294,13 @@
diff --git a/master/apidoc/ol.Coordinate.html b/master/apidoc/ol.Coordinate.html index c3c8970b68..a5b636254c 100644 --- a/master/apidoc/ol.Coordinate.html +++ b/master/apidoc/ol.Coordinate.html @@ -860,13 +860,13 @@
diff --git a/master/apidoc/ol.Ellipsoid.html b/master/apidoc/ol.Ellipsoid.html index a032aeb69e..8742e399ce 100644 --- a/master/apidoc/ol.Ellipsoid.html +++ b/master/apidoc/ol.Ellipsoid.html @@ -1268,13 +1268,13 @@
diff --git a/master/apidoc/ol.Extent.html b/master/apidoc/ol.Extent.html index 67e64b16ea..34303d9104 100644 --- a/master/apidoc/ol.Extent.html +++ b/master/apidoc/ol.Extent.html @@ -2377,13 +2377,13 @@ extent.
diff --git a/master/apidoc/ol.Geolocation.html b/master/apidoc/ol.Geolocation.html index 3d322f7658..6d70f355e2 100644 --- a/master/apidoc/ol.Geolocation.html +++ b/master/apidoc/ol.Geolocation.html @@ -52,64 +52,6 @@ -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
positionOptions - - -GeolocationPositionOptions= - - - - - - <optional>
- - - -
(Optional) PositionOptions.
-
@@ -133,7 +75,7 @@
Source:
-
+
@@ -207,7 +149,7 @@
Source:
-
+
@@ -579,7 +521,7 @@
Source:
-
+
@@ -776,7 +718,7 @@
Source:
-
+
@@ -860,7 +802,7 @@
Source:
-
+
@@ -944,7 +886,7 @@
Source:
-
+
@@ -1028,7 +970,7 @@
Source:
-
+
@@ -1206,7 +1148,7 @@
Source:
-
+
@@ -1290,7 +1232,7 @@
Source:
-
+
@@ -1374,7 +1316,7 @@
Source:
-
+
@@ -1417,6 +1359,174 @@ + + + + +
+

getTracking

+ + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • geolocation.js, line 246
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ tracking. +
+ + + +
+
+ Type +
+
+ +boolean +| + +undefined + + +
+
+ + + + +
+ + + +
+

getTrackingOptions

+ + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • geolocation.js, line 259
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ tracking options. +
+ + + +
+
+ Type +
+
+ +GeolocationPositionOptions +| + +undefined + + +
+
+ + + +
@@ -1865,7 +1975,221 @@
Source:
-
+
+ + + + + + + +
+ + + + + + + + + + + + + +
+

setTracking

+ + +
+
+ + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
tracking + + +boolean + + + + Enable or disable tracking.
+ + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • geolocation.js, line 284
+ + + + + + + +
+ + + + + + + + + +
+ + + +
+

setTrackingOptions

+ + +
+
+ + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +GeolocationPositionOptions + + + + Tracking options.
+ + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • geolocation.js, line 296
@@ -2083,13 +2407,13 @@
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:18 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:32 GMT+0100 (CET)
diff --git a/master/apidoc/ol.Image.html b/master/apidoc/ol.Image.html index 0de248fd1f..06d960ece5 100644 --- a/master/apidoc/ol.Image.html +++ b/master/apidoc/ol.Image.html @@ -952,13 +952,13 @@
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:19 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:32 GMT+0100 (CET)
diff --git a/master/apidoc/ol.ImageTile.html b/master/apidoc/ol.ImageTile.html index 46c31aeaf2..1738f94105 100644 --- a/master/apidoc/ol.ImageTile.html +++ b/master/apidoc/ol.ImageTile.html @@ -106,6 +106,35 @@ + + + state + + + + + +ol.TileState + + + + + + + + + + + + + + + + State. + + + + src @@ -191,7 +220,7 @@
Source:
-
  • imagetile.js, line 19
+
  • imagetile.js, line 20
@@ -235,62 +264,6 @@
-
-

inQueue :number

- - -
-
- -
- A count incremented each time the tile is inQueue in a tile queue, -and decremented each time the tile is dequeued from a tile queue. -
- - - -
- - - - - - - -
Inherited From:
-
- - - - - - - - - - - - - -
Source:
-
  • tile.js, line 38
- - - - - - - -
- - - -
- - -

tileCoord :ol.TileCoord

@@ -326,7 +299,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 43
+
  • tile.js, line 38
@@ -390,7 +363,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 58
+
  • tile.js, line 53
@@ -449,7 +422,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • imagetile.js, line 59
+
  • imagetile.js, line 60
@@ -508,7 +481,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • imagetile.js, line 81
+
  • imagetile.js, line 82
@@ -572,7 +545,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 81
+
  • tile.js, line 76
@@ -657,7 +630,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • imagetile.js, line 113
+
  • imagetile.js, line 114
@@ -695,13 +668,13 @@ and decremented each time the tile is dequeued from a tile queue.
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:19 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:32 GMT+0100 (CET)
diff --git a/master/apidoc/ol.Kinetic.html b/master/apidoc/ol.Kinetic.html index cf8815f3e5..e0409a9324 100644 --- a/master/apidoc/ol.Kinetic.html +++ b/master/apidoc/ol.Kinetic.html @@ -791,13 +791,13 @@
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:22 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:35 GMT+0100 (CET)
diff --git a/master/apidoc/ol.Map.html b/master/apidoc/ol.Map.html index edb245498c..3cb7869779 100644 --- a/master/apidoc/ol.Map.html +++ b/master/apidoc/ol.Map.html @@ -406,7 +406,7 @@
Source:
-
  • map.js, line 819
+
  • map.js, line 860
@@ -446,6 +446,113 @@ +
+ + + +
+

addLayer

+ + +
+
+ + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
layer + + +ol.layer.Layer + + + + Layer.
+ + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • map.js, line 304
+ + + + + + + +
+ + + + + + + + +
@@ -535,7 +642,7 @@
Source:
-
+
@@ -642,7 +749,7 @@
Source:
-
+
@@ -912,7 +1019,7 @@
Source:
-
+
@@ -975,7 +1082,7 @@
Source:
-
+
@@ -1168,7 +1275,7 @@
Source:
-
+
@@ -1300,7 +1407,7 @@
Source:
-
+
@@ -1381,7 +1488,7 @@
Source:
-
+
@@ -1552,7 +1659,7 @@
Source:
-
+
@@ -1633,7 +1740,7 @@
Source:
-
+
@@ -1764,7 +1871,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -1845,7 +1952,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -1926,7 +2033,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2010,7 +2117,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2185,7 +2292,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2266,7 +2373,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2347,7 +2454,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2515,7 +2622,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2574,7 +2681,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2681,7 +2788,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2740,7 +2847,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2799,7 +2906,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -2951,6 +3058,139 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent. + + + + +
+

removeLayer

+ + +
+
+ + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
layer + + +ol.layer.Layer + + + + Layer.
+ + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • map.js, line 656
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ The removed layer or undefined if the + layer was not found. +
+ + + +
+
+ Type +
+
+ +ol.layer.Layer +| + +undefined + + +
+
+ + + +
@@ -3040,7 +3280,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -3125,7 +3365,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -3188,7 +3428,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -3430,7 +3670,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -3537,7 +3777,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -3756,7 +3996,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -3863,7 +4103,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -4106,7 +4346,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -4252,7 +4492,7 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
Source:
-
+
@@ -4290,13 +4530,13 @@ clicks and gestures on an overlay don't trigger any MapBrowserEvent.
diff --git a/master/apidoc/ol.MapBrowserEvent.html b/master/apidoc/ol.MapBrowserEvent.html index adb47c4393..e65c2793bc 100644 --- a/master/apidoc/ol.MapBrowserEvent.html +++ b/master/apidoc/ol.MapBrowserEvent.html @@ -1313,13 +1313,13 @@ FIXME: replace with goog.events.EventType enum once we use
diff --git a/master/apidoc/ol.MapBrowserEventHandler.html b/master/apidoc/ol.MapBrowserEventHandler.html index a0c52670b1..265e851933 100644 --- a/master/apidoc/ol.MapBrowserEventHandler.html +++ b/master/apidoc/ol.MapBrowserEventHandler.html @@ -248,13 +248,13 @@
diff --git a/master/apidoc/ol.MapEvent.html b/master/apidoc/ol.MapEvent.html index b8fa439d5b..9a34668f06 100644 --- a/master/apidoc/ol.MapEvent.html +++ b/master/apidoc/ol.MapEvent.html @@ -460,13 +460,13 @@
diff --git a/master/apidoc/ol.Object.html b/master/apidoc/ol.Object.html index 45890938e9..81839b3aed 100644 --- a/master/apidoc/ol.Object.html +++ b/master/apidoc/ol.Object.html @@ -1999,13 +1999,13 @@
diff --git a/master/apidoc/ol.Pixel.html b/master/apidoc/ol.Pixel.html index 691bf28008..88bd6d1ce2 100644 --- a/master/apidoc/ol.Pixel.html +++ b/master/apidoc/ol.Pixel.html @@ -204,13 +204,13 @@
diff --git a/master/apidoc/ol.PixelBounds.html b/master/apidoc/ol.PixelBounds.html index d9d461be94..89fec75667 100644 --- a/master/apidoc/ol.PixelBounds.html +++ b/master/apidoc/ol.PixelBounds.html @@ -1518,13 +1518,13 @@
diff --git a/master/apidoc/ol.Projection.html b/master/apidoc/ol.Projection.html index 0877a3dfd9..970cf57e8c 100644 --- a/master/apidoc/ol.Projection.html +++ b/master/apidoc/ol.Projection.html @@ -65,8 +65,6 @@ Type - Argument - @@ -79,118 +77,23 @@ - code + options -string +ol.ProjectionOptions - - - - - - - Code. - - - - - - - units - - - - - -ol.ProjectionUnits - - - - - - - - - - - - - - - - Units. - - - - - - - extent - - - - - -ol.Extent - - - - - - - - - - - - - - - - Extent. - - - - - - - axisOrientation - - - - - -string= - - - - - - - - - <optional>
- - - - - - - - - (Optional) Axis orientation. + Options object. @@ -220,7 +123,7 @@
Source:
-
+
@@ -288,7 +191,7 @@
Source:
-
+
@@ -347,7 +250,7 @@
Source:
-
+
@@ -428,7 +331,7 @@
Source:
-
+
@@ -509,7 +412,7 @@
Source:
-
+
@@ -590,7 +493,7 @@
Source:
-
+
@@ -671,7 +574,7 @@
Source:
-
+
@@ -752,7 +655,7 @@
Source:
-
+
@@ -792,6 +695,87 @@ + + + + +
+

isGlobal

+ + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • projection.js, line 152
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ Wether the projection is global. +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + +
@@ -881,7 +865,7 @@
Source:
-
+
@@ -919,13 +903,13 @@
diff --git a/master/apidoc/ol.Rectangle.html b/master/apidoc/ol.Rectangle.html index 01a33a45fc..fd557c18fc 100644 --- a/master/apidoc/ol.Rectangle.html +++ b/master/apidoc/ol.Rectangle.html @@ -1442,13 +1442,13 @@
diff --git a/master/apidoc/ol.Size.html b/master/apidoc/ol.Size.html index e8072194f1..253ca9b3ab 100644 --- a/master/apidoc/ol.Size.html +++ b/master/apidoc/ol.Size.html @@ -337,13 +337,13 @@
diff --git a/master/apidoc/ol.Sphere.html b/master/apidoc/ol.Sphere.html index 74d525bd25..0d7feb2c0e 100644 --- a/master/apidoc/ol.Sphere.html +++ b/master/apidoc/ol.Sphere.html @@ -1681,13 +1681,13 @@ latitude.
diff --git a/master/apidoc/ol.Tile.html b/master/apidoc/ol.Tile.html index b6e42977c9..7ebed340b8 100644 --- a/master/apidoc/ol.Tile.html +++ b/master/apidoc/ol.Tile.html @@ -97,6 +97,29 @@ + + + + state + + + + + +ol.TileState + + + + + + + + + + State. + + + @@ -123,7 +146,7 @@
Source:
-
+
@@ -197,58 +220,7 @@
Source:
-
- - - - - - - - - - - - - - - -
-

inQueue :number

- - -
-
- -
- A count incremented each time the tile is inQueue in a tile queue, -and decremented each time the tile is dequeued from a tile queue. -
- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • tile.js, line 38
+
  • tile.js, line 62
@@ -298,7 +270,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 89
+
  • tile.js, line 84
@@ -344,7 +316,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 49
+
  • tile.js, line 44
@@ -390,7 +362,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 43
+
  • tile.js, line 38
@@ -449,7 +421,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 58
+
  • tile.js, line 53
@@ -508,7 +480,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 73
+
  • tile.js, line 68
@@ -589,7 +561,7 @@ and decremented each time the tile is dequeued from a tile queue.
Source:
-
  • tile.js, line 81
+
  • tile.js, line 76
@@ -649,13 +621,13 @@ and decremented each time the tile is dequeued from a tile queue.
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:38 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:53 GMT+0100 (CET)
diff --git a/master/apidoc/ol.TileCache.html b/master/apidoc/ol.TileCache.html index ed5baa0c8b..879e048d69 100644 --- a/master/apidoc/ol.TileCache.html +++ b/master/apidoc/ol.TileCache.html @@ -1589,13 +1589,13 @@
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:39 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:53 GMT+0100 (CET)
diff --git a/master/apidoc/ol.TileCoord.html b/master/apidoc/ol.TileCoord.html index 28ffe02917..2b53c43400 100644 --- a/master/apidoc/ol.TileCoord.html +++ b/master/apidoc/ol.TileCoord.html @@ -783,13 +783,13 @@
- Documentation generated by JSDoc 3 on Wed Mar 06 2013 18:05:39 GMT+0100 (CET) + Documentation generated by JSDoc 3 on Mon Mar 11 2013 13:34:54 GMT+0100 (CET)
diff --git a/master/apidoc/ol.TileQueue.html b/master/apidoc/ol.TileQueue.html index 086cb98f23..b28512e794 100644 --- a/master/apidoc/ol.TileQueue.html +++ b/master/apidoc/ol.TileQueue.html @@ -298,7 +298,7 @@
Source:
-
  • tilequeue.js, line 104
+
  • tilequeue.js, line 102
@@ -357,7 +357,7 @@
Source:
-
  • tilequeue.js, line 125
+
  • tilequeue.js, line 121
@@ -387,10 +387,6 @@
-
- FIXME empty description for jsdoc -
- @@ -420,7 +416,7 @@
Source:
-
  • tilequeue.js, line 177
+
  • tilequeue.js, line 173
@@ -436,6 +432,28 @@ +
Returns:
+ + +
+ New loading tiles? +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ +
@@ -483,7 +501,7 @@
Source:
-
+
@@ -521,13 +539,13 @@
diff --git a/master/apidoc/ol.TileRange.html b/master/apidoc/ol.TileRange.html index d9182bd981..faa2892f20 100644 --- a/master/apidoc/ol.TileRange.html +++ b/master/apidoc/ol.TileRange.html @@ -1880,13 +1880,13 @@ by its min/max tile coordinates and is inclusive of coordinates.
diff --git a/master/apidoc/ol.View.html b/master/apidoc/ol.View.html index 4a363f8f14..b22084d6d3 100644 --- a/master/apidoc/ol.View.html +++ b/master/apidoc/ol.View.html @@ -1520,13 +1520,13 @@
diff --git a/master/apidoc/ol.View2D.html b/master/apidoc/ol.View2D.html index c340ef3758..095fc04244 100644 --- a/master/apidoc/ol.View2D.html +++ b/master/apidoc/ol.View2D.html @@ -1891,6 +1891,181 @@ + + + + +
+

pan

+ + +
+
+ + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeArgumentDescription
map + + +ol.Map + + + + + + + + Map.
delta + + +ol.Coordinate + + + + + + + + Delta.
duration + + +number= + + + + + + <optional>
+ + + +
(Optional) Duration.
+ + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • view2d.js, line 263
+ + + + + + + +
+ + + + + + + + +
@@ -2082,7 +2257,7 @@
Source:
-
+
@@ -2291,7 +2466,7 @@
Source:
-
+
@@ -3502,7 +3677,7 @@
Source:
-
+
@@ -3708,7 +3883,7 @@
Source:
-
+
@@ -3917,7 +4092,7 @@
Source:
-
+
@@ -3955,13 +4130,13 @@
diff --git a/master/apidoc/ol.control.Attribution.html b/master/apidoc/ol.control.Attribution.html index 2159bc88a4..c90ebd0855 100644 --- a/master/apidoc/ol.control.Attribution.html +++ b/master/apidoc/ol.control.Attribution.html @@ -735,13 +735,13 @@
diff --git a/master/apidoc/ol.control.Control.html b/master/apidoc/ol.control.Control.html index e000b560c2..7ee1eb585f 100644 --- a/master/apidoc/ol.control.Control.html +++ b/master/apidoc/ol.control.Control.html @@ -493,13 +493,13 @@ to the map here.
diff --git a/master/apidoc/ol.control.DragBox.html b/master/apidoc/ol.control.DragBox.html index a90d9c0f61..d6bfe3ce8e 100644 --- a/master/apidoc/ol.control.DragBox.html +++ b/master/apidoc/ol.control.DragBox.html @@ -449,13 +449,13 @@
diff --git a/master/apidoc/ol.control.MousePosition.html b/master/apidoc/ol.control.MousePosition.html index 9752886238..6ea339819c 100644 --- a/master/apidoc/ol.control.MousePosition.html +++ b/master/apidoc/ol.control.MousePosition.html @@ -780,13 +780,13 @@
diff --git a/master/apidoc/ol.control.ScaleLine.html b/master/apidoc/ol.control.ScaleLine.html index 4953d1b00d..c099f8f2f3 100644 --- a/master/apidoc/ol.control.ScaleLine.html +++ b/master/apidoc/ol.control.ScaleLine.html @@ -612,13 +612,13 @@
diff --git a/master/apidoc/ol.control.Zoom.html b/master/apidoc/ol.control.Zoom.html index e1324665c1..667f6a2822 100644 --- a/master/apidoc/ol.control.Zoom.html +++ b/master/apidoc/ol.control.Zoom.html @@ -518,13 +518,13 @@ to the map here.
diff --git a/master/apidoc/ol.interaction.DblClickZoom.html b/master/apidoc/ol.interaction.DblClickZoom.html index 26e947f767..a846b48575 100644 --- a/master/apidoc/ol.interaction.DblClickZoom.html +++ b/master/apidoc/ol.interaction.DblClickZoom.html @@ -244,13 +244,13 @@
diff --git a/master/apidoc/ol.interaction.Drag.html b/master/apidoc/ol.interaction.Drag.html index 576d48d763..a8af2ac8c8 100644 --- a/master/apidoc/ol.interaction.Drag.html +++ b/master/apidoc/ol.interaction.Drag.html @@ -660,13 +660,13 @@
diff --git a/master/apidoc/ol.interaction.DragPan.html b/master/apidoc/ol.interaction.DragPan.html index 27d51dad63..ffa36d7247 100644 --- a/master/apidoc/ol.interaction.DragPan.html +++ b/master/apidoc/ol.interaction.DragPan.html @@ -834,13 +834,13 @@
diff --git a/master/apidoc/ol.interaction.DragRotate.html b/master/apidoc/ol.interaction.DragRotate.html index 8f161ebc4d..d830cb892a 100644 --- a/master/apidoc/ol.interaction.DragRotate.html +++ b/master/apidoc/ol.interaction.DragRotate.html @@ -787,13 +787,13 @@
diff --git a/master/apidoc/ol.interaction.DragRotateAndZoom.html b/master/apidoc/ol.interaction.DragRotateAndZoom.html index 7f9d5cdeb4..258b3c1e9f 100644 --- a/master/apidoc/ol.interaction.DragRotateAndZoom.html +++ b/master/apidoc/ol.interaction.DragRotateAndZoom.html @@ -779,13 +779,13 @@
diff --git a/master/apidoc/ol.interaction.DragZoom.html b/master/apidoc/ol.interaction.DragZoom.html index 087c858d80..3610319827 100644 --- a/master/apidoc/ol.interaction.DragZoom.html +++ b/master/apidoc/ol.interaction.DragZoom.html @@ -779,13 +779,13 @@
diff --git a/master/apidoc/ol.interaction.Interaction.html b/master/apidoc/ol.interaction.Interaction.html index 6118f49fa6..66c9555356 100644 --- a/master/apidoc/ol.interaction.Interaction.html +++ b/master/apidoc/ol.interaction.Interaction.html @@ -177,13 +177,13 @@
diff --git a/master/apidoc/ol.interaction.Keyboard.html b/master/apidoc/ol.interaction.Keyboard.html index fe05bc8ed2..38c5f8c13a 100644 --- a/master/apidoc/ol.interaction.Keyboard.html +++ b/master/apidoc/ol.interaction.Keyboard.html @@ -326,13 +326,13 @@
diff --git a/master/apidoc/ol.interaction.KeyboardPan.html b/master/apidoc/ol.interaction.KeyboardPan.html index 9991da77b2..de8cdb5fbc 100644 --- a/master/apidoc/ol.interaction.KeyboardPan.html +++ b/master/apidoc/ol.interaction.KeyboardPan.html @@ -65,6 +65,8 @@ Type + Argument + @@ -77,23 +79,31 @@ - pixelDelta + options -number +ol.interaction.KeyboardPanOptions= + + + <optional>
+ + + + - Pixel delta. + + (Optional) Options. @@ -123,7 +133,7 @@
Source:
-
+
@@ -206,7 +216,7 @@
Source:
-
+
@@ -244,13 +254,13 @@
diff --git a/master/apidoc/ol.interaction.KeyboardZoom.html b/master/apidoc/ol.interaction.KeyboardZoom.html index c32cb3f9bd..88a80e1494 100644 --- a/master/apidoc/ol.interaction.KeyboardZoom.html +++ b/master/apidoc/ol.interaction.KeyboardZoom.html @@ -52,6 +52,64 @@ +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeArgumentDescription
options + + +ol.interaction.KeyboardZoomOptions= + + + + + + <optional>
+ + + +
(Optional) Options.
+
@@ -75,7 +133,7 @@
Source:
-
+
@@ -158,7 +216,7 @@
Source:
-
+
@@ -196,13 +254,13 @@
diff --git a/master/apidoc/ol.interaction.MouseWheelZoom.html b/master/apidoc/ol.interaction.MouseWheelZoom.html index 4680b4e9b2..a505decd12 100644 --- a/master/apidoc/ol.interaction.MouseWheelZoom.html +++ b/master/apidoc/ol.interaction.MouseWheelZoom.html @@ -196,13 +196,13 @@
diff --git a/master/apidoc/ol.interaction.Touch.html b/master/apidoc/ol.interaction.Touch.html index 57bd4f867f..3b290e8d06 100644 --- a/master/apidoc/ol.interaction.Touch.html +++ b/master/apidoc/ol.interaction.Touch.html @@ -513,13 +513,13 @@
diff --git a/master/apidoc/ol.interaction.TouchPan.html b/master/apidoc/ol.interaction.TouchPan.html index 9776d4a5aa..5ebffe37a7 100644 --- a/master/apidoc/ol.interaction.TouchPan.html +++ b/master/apidoc/ol.interaction.TouchPan.html @@ -537,13 +537,13 @@
diff --git a/master/apidoc/ol.interaction.TouchRotate.html b/master/apidoc/ol.interaction.TouchRotate.html index fb5e98144c..b3429e857c 100644 --- a/master/apidoc/ol.interaction.TouchRotate.html +++ b/master/apidoc/ol.interaction.TouchRotate.html @@ -496,13 +496,13 @@
diff --git a/master/apidoc/ol.interaction.TouchZoom.html b/master/apidoc/ol.interaction.TouchZoom.html index 5b4c0e2920..e462914064 100644 --- a/master/apidoc/ol.interaction.TouchZoom.html +++ b/master/apidoc/ol.interaction.TouchZoom.html @@ -433,13 +433,13 @@
diff --git a/master/apidoc/ol.layer.ImageLayer.html b/master/apidoc/ol.layer.ImageLayer.html index 8885df31ec..7121eba884 100644 --- a/master/apidoc/ol.layer.ImageLayer.html +++ b/master/apidoc/ol.layer.ImageLayer.html @@ -2829,13 +2829,13 @@ permitted).
diff --git a/master/apidoc/ol.layer.Layer.html b/master/apidoc/ol.layer.Layer.html index fa6c94c316..2cdc30aad6 100644 --- a/master/apidoc/ol.layer.Layer.html +++ b/master/apidoc/ol.layer.Layer.html @@ -2673,13 +2673,13 @@ permitted).
diff --git a/master/apidoc/ol.layer.TileLayer.html b/master/apidoc/ol.layer.TileLayer.html index 080c56e0ca..1ac6092cc1 100644 --- a/master/apidoc/ol.layer.TileLayer.html +++ b/master/apidoc/ol.layer.TileLayer.html @@ -2829,13 +2829,13 @@ permitted).
diff --git a/master/apidoc/ol.parser.XML.html b/master/apidoc/ol.parser.XML.html index 09aa7e0043..48f3e46d64 100644 --- a/master/apidoc/ol.parser.XML.html +++ b/master/apidoc/ol.parser.XML.html @@ -970,13 +970,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.ExceptionReport.html b/master/apidoc/ol.parser.ogc.ExceptionReport.html index 7c302dbc36..a5fc875423 100644 --- a/master/apidoc/ol.parser.ogc.ExceptionReport.html +++ b/master/apidoc/ol.parser.ogc.ExceptionReport.html @@ -1138,13 +1138,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.OWSCommon_v1.html b/master/apidoc/ol.parser.ogc.OWSCommon_v1.html index 25ad714e0d..40463f69ac 100644 --- a/master/apidoc/ol.parser.ogc.OWSCommon_v1.html +++ b/master/apidoc/ol.parser.ogc.OWSCommon_v1.html @@ -1001,13 +1001,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.OWSCommon_v1_1_0.html b/master/apidoc/ol.parser.ogc.OWSCommon_v1_1_0.html index 7485c9eebf..17557bf081 100644 --- a/master/apidoc/ol.parser.ogc.OWSCommon_v1_1_0.html +++ b/master/apidoc/ol.parser.ogc.OWSCommon_v1_1_0.html @@ -1001,13 +1001,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.Versioned.html b/master/apidoc/ol.parser.ogc.Versioned.html index f15f623d4a..a14bec751d 100644 --- a/master/apidoc/ol.parser.ogc.Versioned.html +++ b/master/apidoc/ol.parser.ogc.Versioned.html @@ -822,13 +822,13 @@
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities.html b/master/apidoc/ol.parser.ogc.WMSCapabilities.html index 7161bd7504..423d4e902e 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities.html @@ -133,7 +133,7 @@
Source:
-
+
@@ -858,13 +858,13 @@
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1.html index 249ae2ebe5..e12b9fb66e 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1.html @@ -1136,13 +1136,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_0_0.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_0_0.html new file mode 100644 index 0000000000..1e194097c3 --- /dev/null +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_0_0.html @@ -0,0 +1,1155 @@ + + + + + OpenLayers: Class: ol.parser.ogc.WMSCapabilities_v1_0_0 + + + + + + + + + + +
+ +

Class: ol.parser.ogc.WMSCapabilities_v1_0_0

+ + + + + +
+ +
+

+ ol.parser.ogc.WMSCapabilities_v1_0_0 +

+ +
+ +
+
+ + + + +
+

new WMSCapabilities_v1_0_0

+ + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
Source:
+
  • wmscapabilities_v1_0_0.js, line 11
+ + + + + + + +
+ + + + + + + + + +
+ + +
+ + +

Extends

+ + + + + + + + + + + + + + + +

Methods

+ +
+ +
+

getAttributeNodeNS

+ + +
+
+ + +
+ Get an attribute node given the namespace URI and local name. +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Element + + + + Node on which to search for attribute nodes.
uri + + +string + + + + Namespace URI.
name + + +string + + + + Local name of the attribute (without the prefix).
+ + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • xml.js, line 105
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ An attribute node or null if none found. +
+ + + +
+
+ Type +
+
+ +?Element + + +
+
+ + + + +
+ + + +
+

getAttributeNS

+ + +
+
+ + +
+ Get an attribute value given the namespace URI and local name. +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Element + + + + Node on which to search for an attribute.
uri + + +string + + + + Namespace URI.
name + + +string + + + + Local name of the attribute (without the prefix).
+ + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • xml.js, line 136
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ An attribute value or and empty string if none found. +
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + +
+ + + +
+

getChildValue

+ + +
+
+ + +
+ Get the textual value of the node if it exists, or return an +optional default string. Returns an empty string if no first child +exists and no default value is supplied. +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Element + + + + The element used to look for a first child value.
def + + +string + + + + Optional string to return in the event that no +first child value exists.
+ + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • xml.js, line 79
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ The value of the first child of the given node. +
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + +
+ + + +
+

read

+ + +
+
+ + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
data + + +string +| + +Document +| + +Element + + + + Data to read.
+ + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • wmscapabilities_v1.js, line 305
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ An object representing the document. +
+ + + +
+
+ Type +
+
+ +Object + + +
+
+ + + + +
+ + + +
+

readChildNodes

+ + +
+
+ + +
+ Shorthand for applying the named readers to all children of a node. +For each child of type 1 (element), is called. +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Element +| + +Document + + + + The node to be read (required).
obj + + +Object + + + + The object to be modified (optional).
+ + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • xml.js, line 53
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ The input object, modified. +
+ + + +
+
+ Type +
+
+ +Object + + +
+
+ + + + +
+ + + +
+

readNode

+ + +
+
+ + +
+ Shorthand for applying one of the named readers given the node +namespace and local name. Readers take two args (node, obj) and +generally extend or modify the second. +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Element +| + +Document + + + + The node to be read (required).
obj + + +Object + + + + The object to be modified (optional).
+ + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • xml.js, line 28
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ The input object, modified (or a new one if none was +provided). +
+ + + +
+
+ Type +
+
+ +Object + + +
+
+ + + + +
+ +
+ + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1.html index ba62cab042..30e9a4d7b5 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1.html @@ -1141,13 +1141,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_0.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_0.html index 12db118a67..8aca013751 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_0.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_0.html @@ -1141,13 +1141,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1.html index c238cc2453..5ccd95d9fc 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1.html @@ -1141,13 +1141,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC.html index d90e65d89e..775c070841 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC.html @@ -1141,13 +1141,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_3_0.html b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_3_0.html index f262cbbb48..bec214a4c9 100644 --- a/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_3_0.html +++ b/master/apidoc/ol.parser.ogc.WMSCapabilities_v1_3_0.html @@ -1141,13 +1141,13 @@ provided).
diff --git a/master/apidoc/ol.parser.ogc.WMTSCapabilities.html b/master/apidoc/ol.parser.ogc.WMTSCapabilities.html index e325ac5a17..68586048ae 100644 --- a/master/apidoc/ol.parser.ogc.WMTSCapabilities.html +++ b/master/apidoc/ol.parser.ogc.WMTSCapabilities.html @@ -858,13 +858,13 @@
diff --git a/master/apidoc/ol.parser.ogc.WMTSCapabilities_v1_0_0.html b/master/apidoc/ol.parser.ogc.WMTSCapabilities_v1_0_0.html index 6c93d9c101..e50c3c3b12 100644 --- a/master/apidoc/ol.parser.ogc.WMTSCapabilities_v1_0_0.html +++ b/master/apidoc/ol.parser.ogc.WMTSCapabilities_v1_0_0.html @@ -1136,13 +1136,13 @@ provided).
diff --git a/master/apidoc/ol.projection.EPSG3857.html b/master/apidoc/ol.projection.EPSG3857.html index 533146bedb..f70504db3a 100644 --- a/master/apidoc/ol.projection.EPSG3857.html +++ b/master/apidoc/ol.projection.EPSG3857.html @@ -201,7 +201,7 @@
Source:
-
+
@@ -247,7 +247,7 @@
Source:
-
+
@@ -293,7 +293,7 @@
Source:
-
+
@@ -343,7 +343,7 @@
Source:
-
+
@@ -389,7 +389,7 @@
Source:
-
+
@@ -453,7 +453,7 @@
Source:
-
+
@@ -539,7 +539,7 @@
Source:
-
+
@@ -625,7 +625,7 @@
Source:
-
+
@@ -711,7 +711,7 @@
Source:
-
+
@@ -797,7 +797,7 @@
Source:
-
+
@@ -878,7 +878,7 @@
Source:
-
+
@@ -942,7 +942,7 @@
Source:
-
+
@@ -982,6 +982,92 @@ + + + + +
+

isGlobal

+ + +
+
+ + + + + + + + + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • projection.js, line 152
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ Wether the projection is global. +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + +
@@ -1076,7 +1162,7 @@
Source:
-
+
@@ -1257,7 +1343,7 @@
Source:
-
+
@@ -1460,7 +1546,7 @@
Source:
-
+
@@ -1520,13 +1606,13 @@
diff --git a/master/apidoc/ol.projection.EPSG4326.html b/master/apidoc/ol.projection.EPSG4326.html index bd0cbe8bd9..99c6f89218 100644 --- a/master/apidoc/ol.projection.EPSG4326.html +++ b/master/apidoc/ol.projection.EPSG4326.html @@ -240,7 +240,7 @@
Source:
-
+
@@ -290,7 +290,7 @@
Source:
-
+
@@ -354,7 +354,7 @@
Source:
-
+
@@ -440,7 +440,7 @@
Source:
-
+
@@ -526,7 +526,7 @@
Source:
-
+
@@ -612,7 +612,7 @@
Source:
-
+
@@ -698,7 +698,7 @@
Source:
-
+
@@ -779,7 +779,7 @@
Source:
-
+
@@ -843,7 +843,7 @@
Source:
-
+
@@ -883,6 +883,92 @@ + + + + +
+

isGlobal

+ + +
+
+ + + + + + + + + + +
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + +
Source:
+
  • projection.js, line 152
+ + + + + + + +
+ + + + + + + +
Returns:
+ + +
+ Wether the projection is global. +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + +
@@ -977,7 +1063,7 @@
Source:
-
+
@@ -1015,13 +1101,13 @@
diff --git a/master/apidoc/ol.renderer.Layer.html b/master/apidoc/ol.renderer.Layer.html index f483ec2c1b..d745cce223 100644 --- a/master/apidoc/ol.renderer.Layer.html +++ b/master/apidoc/ol.renderer.Layer.html @@ -940,7 +940,7 @@
Source:
-
+
@@ -2863,7 +2863,7 @@
Source:
-
+
@@ -3016,7 +3016,7 @@
Source:
-
+
@@ -3054,13 +3054,13 @@
diff --git a/master/apidoc/ol.renderer.Map.html b/master/apidoc/ol.renderer.Map.html index 9f0e12c5ca..c7f195450e 100644 --- a/master/apidoc/ol.renderer.Map.html +++ b/master/apidoc/ol.renderer.Map.html @@ -1758,13 +1758,13 @@
diff --git a/master/apidoc/ol.renderer.canvas.ImageLayer.html b/master/apidoc/ol.renderer.canvas.ImageLayer.html index 474a3f326b..46d164e2b7 100644 --- a/master/apidoc/ol.renderer.canvas.ImageLayer.html +++ b/master/apidoc/ol.renderer.canvas.ImageLayer.html @@ -924,7 +924,7 @@
Source:
-
+
@@ -3165,7 +3165,7 @@
Source:
-
+
@@ -3323,7 +3323,7 @@
Source:
-
+
@@ -3361,13 +3361,13 @@
diff --git a/master/apidoc/ol.renderer.canvas.Layer.html b/master/apidoc/ol.renderer.canvas.Layer.html index fe14a32a78..c2ae069d63 100644 --- a/master/apidoc/ol.renderer.canvas.Layer.html +++ b/master/apidoc/ol.renderer.canvas.Layer.html @@ -1067,7 +1067,7 @@
Source:
-
+
@@ -3050,7 +3050,7 @@
Source:
-
+
@@ -3208,7 +3208,7 @@
Source:
-
+
@@ -3246,13 +3246,13 @@
diff --git a/master/apidoc/ol.renderer.canvas.Map.html b/master/apidoc/ol.renderer.canvas.Map.html index bd2f0305f5..96bb911b96 100644 --- a/master/apidoc/ol.renderer.canvas.Map.html +++ b/master/apidoc/ol.renderer.canvas.Map.html @@ -1780,13 +1780,13 @@
diff --git a/master/apidoc/ol.renderer.canvas.TileLayer.html b/master/apidoc/ol.renderer.canvas.TileLayer.html index e06546ec5b..f69a45e0ff 100644 --- a/master/apidoc/ol.renderer.canvas.TileLayer.html +++ b/master/apidoc/ol.renderer.canvas.TileLayer.html @@ -924,7 +924,7 @@
Source:
-
+
@@ -3165,7 +3165,7 @@
Source:
-
+
@@ -3323,7 +3323,7 @@
Source:
-
+
@@ -3361,13 +3361,13 @@
diff --git a/master/apidoc/ol.renderer.dom.ImageLayer.html b/master/apidoc/ol.renderer.dom.ImageLayer.html index 45cf340f0a..634d3adab4 100644 --- a/master/apidoc/ol.renderer.dom.ImageLayer.html +++ b/master/apidoc/ol.renderer.dom.ImageLayer.html @@ -975,7 +975,7 @@
Source:
-
+
@@ -3355,7 +3355,7 @@
Source:
-
+
@@ -3513,7 +3513,7 @@
Source:
-
+
@@ -3551,13 +3551,13 @@
diff --git a/master/apidoc/ol.renderer.dom.Layer.html b/master/apidoc/ol.renderer.dom.Layer.html index 8f7e953ddd..ac419defcd 100644 --- a/master/apidoc/ol.renderer.dom.Layer.html +++ b/master/apidoc/ol.renderer.dom.Layer.html @@ -1044,7 +1044,7 @@
Source:
-
+
@@ -3167,7 +3167,7 @@
Source:
-
+
@@ -3325,7 +3325,7 @@
Source:
-
+
@@ -3363,13 +3363,13 @@
diff --git a/master/apidoc/ol.renderer.dom.Map.html b/master/apidoc/ol.renderer.dom.Map.html index b96a4ae504..f4f61b6f73 100644 --- a/master/apidoc/ol.renderer.dom.Map.html +++ b/master/apidoc/ol.renderer.dom.Map.html @@ -1719,13 +1719,13 @@
diff --git a/master/apidoc/ol.renderer.dom.TileLayer.html b/master/apidoc/ol.renderer.dom.TileLayer.html index ca0f8936f1..e9ab3d02a7 100644 --- a/master/apidoc/ol.renderer.dom.TileLayer.html +++ b/master/apidoc/ol.renderer.dom.TileLayer.html @@ -975,7 +975,7 @@
Source:
-
+
@@ -3248,7 +3248,7 @@
Source:
-
+
@@ -3406,7 +3406,7 @@
Source:
-
+
@@ -3444,13 +3444,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.FragmentShader.html b/master/apidoc/ol.renderer.webgl.FragmentShader.html index 5ccdb7c4c5..ce43588f2f 100644 --- a/master/apidoc/ol.renderer.webgl.FragmentShader.html +++ b/master/apidoc/ol.renderer.webgl.FragmentShader.html @@ -385,13 +385,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.ImageLayer.html b/master/apidoc/ol.renderer.webgl.ImageLayer.html index 0cd834274f..f4b747a0d8 100644 --- a/master/apidoc/ol.renderer.webgl.ImageLayer.html +++ b/master/apidoc/ol.renderer.webgl.ImageLayer.html @@ -720,7 +720,7 @@
Source:
-
+
@@ -3480,7 +3480,7 @@
Source:
-
+
@@ -3638,7 +3638,7 @@
Source:
-
+
@@ -3676,13 +3676,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.Layer.html b/master/apidoc/ol.renderer.webgl.Layer.html index aede516c82..ff82654655 100644 --- a/master/apidoc/ol.renderer.webgl.Layer.html +++ b/master/apidoc/ol.renderer.webgl.Layer.html @@ -959,7 +959,7 @@
Source:
-
+
@@ -3254,7 +3254,7 @@
Source:
-
+
@@ -3412,7 +3412,7 @@
Source:
-
+
@@ -3450,13 +3450,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.Map.html b/master/apidoc/ol.renderer.webgl.Map.html index a2bb9c5dc8..2d0045244a 100644 --- a/master/apidoc/ol.renderer.webgl.Map.html +++ b/master/apidoc/ol.renderer.webgl.Map.html @@ -1935,7 +1935,7 @@
-

<protected> handleWebGLContextResourced

+

<protected> handleWebGLContextRestored

@@ -2525,13 +2525,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.Shader.html b/master/apidoc/ol.renderer.webgl.Shader.html index 94851e6062..d6e05f32e8 100644 --- a/master/apidoc/ol.renderer.webgl.Shader.html +++ b/master/apidoc/ol.renderer.webgl.Shader.html @@ -356,13 +356,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.TileLayer.html b/master/apidoc/ol.renderer.webgl.TileLayer.html index 0238a0238e..d3394a8f5b 100644 --- a/master/apidoc/ol.renderer.webgl.TileLayer.html +++ b/master/apidoc/ol.renderer.webgl.TileLayer.html @@ -720,7 +720,7 @@
Source:
-
+
@@ -3480,7 +3480,7 @@
Source:
-
+
@@ -3638,7 +3638,7 @@
Source:
-
+
@@ -3676,13 +3676,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.VertexShader.html b/master/apidoc/ol.renderer.webgl.VertexShader.html index db17999d3d..8314c35058 100644 --- a/master/apidoc/ol.renderer.webgl.VertexShader.html +++ b/master/apidoc/ol.renderer.webgl.VertexShader.html @@ -385,13 +385,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.map.shader.Fragment.html b/master/apidoc/ol.renderer.webgl.map.shader.Fragment.html index 4fc7c3e0f8..bac3a9bbb0 100644 --- a/master/apidoc/ol.renderer.webgl.map.shader.Fragment.html +++ b/master/apidoc/ol.renderer.webgl.map.shader.Fragment.html @@ -349,13 +349,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.map.shader.Vertex.html b/master/apidoc/ol.renderer.webgl.map.shader.Vertex.html index 276cbfeaa9..ce8503ad6c 100644 --- a/master/apidoc/ol.renderer.webgl.map.shader.Vertex.html +++ b/master/apidoc/ol.renderer.webgl.map.shader.Vertex.html @@ -342,13 +342,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Fragment.html b/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Fragment.html index 8b449ef4a5..bff85a080c 100644 --- a/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Fragment.html +++ b/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Fragment.html @@ -342,13 +342,13 @@
diff --git a/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Vertex.html b/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Vertex.html index 846441e9f3..e00d21bd60 100644 --- a/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Vertex.html +++ b/master/apidoc/ol.renderer.webgl.tilelayerrenderer.shader.Vertex.html @@ -342,13 +342,13 @@
diff --git a/master/apidoc/ol.source.BingMaps.html b/master/apidoc/ol.source.BingMaps.html index 1b2c302df6..61b363771d 100644 --- a/master/apidoc/ol.source.BingMaps.html +++ b/master/apidoc/ol.source.BingMaps.html @@ -211,7 +211,7 @@
Source:
-
+
@@ -275,7 +275,7 @@
Source:
-
+
@@ -339,7 +339,7 @@
Source:
-
+
@@ -528,7 +528,7 @@ loaded tiles.
Source:
-
+
@@ -614,7 +614,7 @@ loaded tiles.
Source:
-
+
@@ -700,7 +700,7 @@ loaded tiles.
Source:
-
+
@@ -786,7 +786,7 @@ loaded tiles.
Source:
-
+
@@ -872,7 +872,7 @@ loaded tiles.
Source:
-
+
@@ -958,7 +958,7 @@ loaded tiles.
Source:
-
+
@@ -1022,7 +1022,7 @@ loaded tiles.
Source:
-
+
@@ -1086,7 +1086,7 @@ loaded tiles.
Source:
-
+
@@ -1386,7 +1386,7 @@ loaded tiles.
Source:
-
+
@@ -1498,7 +1498,7 @@ loaded tiles.
Source:
-
+
@@ -1610,7 +1610,7 @@ loaded tiles.
Source:
-
+
@@ -1768,7 +1768,7 @@ loaded tiles.
Source:
-
+
@@ -1870,13 +1870,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.DebugTileSource.html b/master/apidoc/ol.source.DebugTileSource.html index edef017fd3..d0073c27f6 100644 --- a/master/apidoc/ol.source.DebugTileSource.html +++ b/master/apidoc/ol.source.DebugTileSource.html @@ -123,7 +123,7 @@
Source:
-
+
@@ -202,7 +202,7 @@
Source:
-
+
@@ -253,7 +253,7 @@
Source:
-
+
@@ -308,7 +308,7 @@
Source:
-
+
@@ -367,7 +367,7 @@
Source:
-
+
@@ -431,7 +431,7 @@
Source:
-
+
@@ -490,7 +490,7 @@
Source:
-
+
@@ -679,7 +679,7 @@ loaded tiles.
Source:
-
+
@@ -765,7 +765,7 @@ loaded tiles.
Source:
-
+
@@ -851,7 +851,7 @@ loaded tiles.
Source:
-
+
@@ -937,7 +937,7 @@ loaded tiles.
Source:
-
+
@@ -1023,7 +1023,7 @@ loaded tiles.
Source:
-
+
@@ -1109,7 +1109,7 @@ loaded tiles.
Source:
-
+
@@ -1168,7 +1168,7 @@ loaded tiles.
Source:
-
+
@@ -1232,7 +1232,7 @@ loaded tiles.
Source:
-
+
@@ -1366,7 +1366,7 @@ loaded tiles.
Source:
-
+
@@ -1478,7 +1478,7 @@ loaded tiles.
Source:
-
+
@@ -1590,7 +1590,7 @@ loaded tiles.
Source:
-
+
@@ -1748,7 +1748,7 @@ loaded tiles.
Source:
-
+
@@ -1786,13 +1786,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.ImageSource.html b/master/apidoc/ol.source.ImageSource.html index 88169e1cb6..c402dda495 100644 --- a/master/apidoc/ol.source.ImageSource.html +++ b/master/apidoc/ol.source.ImageSource.html @@ -249,7 +249,7 @@
Source:
-
+
@@ -346,7 +346,7 @@
Source:
-
+
@@ -608,7 +608,7 @@
Source:
-
+
@@ -801,7 +801,7 @@
Source:
-
+
@@ -887,7 +887,7 @@
Source:
-
+
@@ -973,7 +973,7 @@
Source:
-
+
@@ -1107,7 +1107,7 @@
Source:
-
+
@@ -1219,7 +1219,7 @@
Source:
-
+
@@ -1331,7 +1331,7 @@
Source:
-
+
@@ -1369,13 +1369,13 @@
diff --git a/master/apidoc/ol.source.ImageTileSource.html b/master/apidoc/ol.source.ImageTileSource.html index e10ef15c39..9d20d9f8d1 100644 --- a/master/apidoc/ol.source.ImageTileSource.html +++ b/master/apidoc/ol.source.ImageTileSource.html @@ -123,7 +123,7 @@
Source:
-
+
@@ -202,7 +202,7 @@
Source:
-
+
@@ -253,7 +253,7 @@
Source:
-
+
@@ -299,7 +299,7 @@
Source:
-
+
@@ -358,7 +358,7 @@
Source:
-
+
@@ -422,7 +422,7 @@
Source:
-
+
@@ -481,7 +481,7 @@
Source:
-
+
@@ -670,7 +670,7 @@ loaded tiles.
Source:
-
+
@@ -756,7 +756,7 @@ loaded tiles.
Source:
-
+
@@ -842,7 +842,7 @@ loaded tiles.
Source:
-
+
@@ -928,7 +928,7 @@ loaded tiles.
Source:
-
+
@@ -1014,7 +1014,7 @@ loaded tiles.
Source:
-
+
@@ -1100,7 +1100,7 @@ loaded tiles.
Source:
-
+
@@ -1159,7 +1159,7 @@ loaded tiles.
Source:
-
+
@@ -1223,7 +1223,7 @@ loaded tiles.
Source:
-
+
@@ -1357,7 +1357,7 @@ loaded tiles.
Source:
-
+
@@ -1469,7 +1469,7 @@ loaded tiles.
Source:
-
+
@@ -1581,7 +1581,7 @@ loaded tiles.
Source:
-
+
@@ -1739,7 +1739,7 @@ loaded tiles.
Source:
-
+
@@ -1836,13 +1836,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.MapQuestOSM.html b/master/apidoc/ol.source.MapQuestOSM.html index 1fb3387929..00478e7801 100644 --- a/master/apidoc/ol.source.MapQuestOSM.html +++ b/master/apidoc/ol.source.MapQuestOSM.html @@ -154,7 +154,7 @@
Source:
-
+
@@ -205,7 +205,7 @@
Source:
-
+
@@ -256,7 +256,7 @@
Source:
-
+
@@ -320,7 +320,7 @@
Source:
-
+
@@ -384,7 +384,7 @@
Source:
-
+
@@ -448,7 +448,7 @@
Source:
-
+
@@ -637,7 +637,7 @@ loaded tiles.
Source:
-
+
@@ -723,7 +723,7 @@ loaded tiles.
Source:
-
+
@@ -809,7 +809,7 @@ loaded tiles.
Source:
-
+
@@ -895,7 +895,7 @@ loaded tiles.
Source:
-
+
@@ -981,7 +981,7 @@ loaded tiles.
Source:
-
+
@@ -1067,7 +1067,7 @@ loaded tiles.
Source:
-
+
@@ -1131,7 +1131,7 @@ loaded tiles.
Source:
-
+
@@ -1195,7 +1195,7 @@ loaded tiles.
Source:
-
+
@@ -1329,7 +1329,7 @@ loaded tiles.
Source:
-
+
@@ -1441,7 +1441,7 @@ loaded tiles.
Source:
-
+
@@ -1553,7 +1553,7 @@ loaded tiles.
Source:
-
+
@@ -1711,7 +1711,7 @@ loaded tiles.
Source:
-
+
@@ -1813,13 +1813,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.MapQuestOpenAerial.html b/master/apidoc/ol.source.MapQuestOpenAerial.html index f2d6c4367b..1d899688b4 100644 --- a/master/apidoc/ol.source.MapQuestOpenAerial.html +++ b/master/apidoc/ol.source.MapQuestOpenAerial.html @@ -154,7 +154,7 @@
Source:
-
+
@@ -205,7 +205,7 @@
Source:
-
+
@@ -256,7 +256,7 @@
Source:
-
+
@@ -320,7 +320,7 @@
Source:
-
+
@@ -384,7 +384,7 @@
Source:
-
+
@@ -448,7 +448,7 @@
Source:
-
+
@@ -637,7 +637,7 @@ loaded tiles.
Source:
-
+
@@ -723,7 +723,7 @@ loaded tiles.
Source:
-
+
@@ -809,7 +809,7 @@ loaded tiles.
Source:
-
+
@@ -895,7 +895,7 @@ loaded tiles.
Source:
-
+
@@ -981,7 +981,7 @@ loaded tiles.
Source:
-
+
@@ -1067,7 +1067,7 @@ loaded tiles.
Source:
-
+
@@ -1131,7 +1131,7 @@ loaded tiles.
Source:
-
+
@@ -1195,7 +1195,7 @@ loaded tiles.
Source:
-
+
@@ -1329,7 +1329,7 @@ loaded tiles.
Source:
-
+
@@ -1441,7 +1441,7 @@ loaded tiles.
Source:
-
+
@@ -1553,7 +1553,7 @@ loaded tiles.
Source:
-
+
@@ -1711,7 +1711,7 @@ loaded tiles.
Source:
-
+
@@ -1813,13 +1813,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.OpenStreetMap.html b/master/apidoc/ol.source.OpenStreetMap.html index e692f8fffb..67c2fb9ec9 100644 --- a/master/apidoc/ol.source.OpenStreetMap.html +++ b/master/apidoc/ol.source.OpenStreetMap.html @@ -154,7 +154,7 @@
Source:
-
+
@@ -205,7 +205,7 @@
Source:
-
+
@@ -256,7 +256,7 @@
Source:
-
+
@@ -320,7 +320,7 @@
Source:
-
+
@@ -384,7 +384,7 @@
Source:
-
+
@@ -448,7 +448,7 @@
Source:
-
+
@@ -637,7 +637,7 @@ loaded tiles.
Source:
-
+
@@ -723,7 +723,7 @@ loaded tiles.
Source:
-
+
@@ -809,7 +809,7 @@ loaded tiles.
Source:
-
+
@@ -895,7 +895,7 @@ loaded tiles.
Source:
-
+
@@ -981,7 +981,7 @@ loaded tiles.
Source:
-
+
@@ -1067,7 +1067,7 @@ loaded tiles.
Source:
-
+
@@ -1131,7 +1131,7 @@ loaded tiles.
Source:
-
+
@@ -1195,7 +1195,7 @@ loaded tiles.
Source:
-
+
@@ -1329,7 +1329,7 @@ loaded tiles.
Source:
-
+
@@ -1441,7 +1441,7 @@ loaded tiles.
Source:
-
+
@@ -1553,7 +1553,7 @@ loaded tiles.
Source:
-
+
@@ -1711,7 +1711,7 @@ loaded tiles.
Source:
-
+
@@ -1813,13 +1813,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.SingleImageWMS.html b/master/apidoc/ol.source.SingleImageWMS.html index b30f4f8825..bcdb4afb95 100644 --- a/master/apidoc/ol.source.SingleImageWMS.html +++ b/master/apidoc/ol.source.SingleImageWMS.html @@ -202,7 +202,7 @@
Source:
-
+
@@ -304,7 +304,7 @@
Source:
-
+
@@ -571,7 +571,7 @@
Source:
-
+
@@ -769,7 +769,7 @@
Source:
-
+
@@ -855,7 +855,7 @@
Source:
-
+
@@ -1000,7 +1000,7 @@
Source:
-
+
@@ -1134,7 +1134,7 @@
Source:
-
+
@@ -1246,7 +1246,7 @@
Source:
-
+
@@ -1358,7 +1358,7 @@
Source:
-
+
@@ -1396,13 +1396,13 @@
diff --git a/master/apidoc/ol.source.Source.html b/master/apidoc/ol.source.Source.html index bdea294619..5a19d0003e 100644 --- a/master/apidoc/ol.source.Source.html +++ b/master/apidoc/ol.source.Source.html @@ -197,7 +197,7 @@
Source:
-
+
@@ -243,7 +243,7 @@
Source:
-
+
@@ -302,7 +302,7 @@
Source:
-
+
@@ -361,7 +361,7 @@
Source:
-
+
@@ -442,7 +442,7 @@
Source:
-
+
@@ -523,7 +523,7 @@
Source:
-
+
@@ -652,7 +652,7 @@
Source:
-
+
@@ -759,7 +759,7 @@
Source:
-
+
@@ -866,7 +866,7 @@
Source:
-
+
@@ -904,13 +904,13 @@
diff --git a/master/apidoc/ol.source.Stamen.html b/master/apidoc/ol.source.Stamen.html index e38622d41c..849f7077c6 100644 --- a/master/apidoc/ol.source.Stamen.html +++ b/master/apidoc/ol.source.Stamen.html @@ -123,7 +123,7 @@
Source:
-
+
@@ -202,7 +202,7 @@
Source:
-
+
@@ -253,7 +253,7 @@
Source:
-
+
@@ -304,7 +304,7 @@
Source:
-
+
@@ -368,7 +368,7 @@
Source:
-
+
@@ -432,7 +432,7 @@
Source:
-
+
@@ -496,7 +496,7 @@
Source:
-
+
@@ -685,7 +685,7 @@ loaded tiles.
Source:
-
+
@@ -771,7 +771,7 @@ loaded tiles.
Source:
-
+
@@ -857,7 +857,7 @@ loaded tiles.
Source:
-
+
@@ -943,7 +943,7 @@ loaded tiles.
Source:
-
+
@@ -1029,7 +1029,7 @@ loaded tiles.
Source:
-
+
@@ -1115,7 +1115,7 @@ loaded tiles.
Source:
-
+
@@ -1179,7 +1179,7 @@ loaded tiles.
Source:
-
+
@@ -1243,7 +1243,7 @@ loaded tiles.
Source:
-
+
@@ -1377,7 +1377,7 @@ loaded tiles.
Source:
-
+
@@ -1489,7 +1489,7 @@ loaded tiles.
Source:
-
+
@@ -1601,7 +1601,7 @@ loaded tiles.
Source:
-
+
@@ -1759,7 +1759,7 @@ loaded tiles.
Source:
-
+
@@ -1861,13 +1861,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.StaticImage.html b/master/apidoc/ol.source.StaticImage.html index de33c8cb14..5cd2065a51 100644 --- a/master/apidoc/ol.source.StaticImage.html +++ b/master/apidoc/ol.source.StaticImage.html @@ -123,7 +123,7 @@
Source:
-
+
@@ -202,7 +202,7 @@
Source:
-
+
@@ -304,7 +304,7 @@
Source:
-
+
@@ -414,7 +414,7 @@
Source:
-
+
@@ -703,7 +703,7 @@
Source:
-
+
@@ -901,7 +901,7 @@
Source:
-
+
@@ -987,7 +987,7 @@
Source:
-
+
@@ -1068,7 +1068,7 @@
Source:
-
+
@@ -1132,7 +1132,7 @@
Source:
-
+
@@ -1266,7 +1266,7 @@
Source:
-
+
@@ -1378,7 +1378,7 @@
Source:
-
+
@@ -1490,7 +1490,7 @@
Source:
-
+
@@ -1528,13 +1528,13 @@
diff --git a/master/apidoc/ol.source.TileJSON.html b/master/apidoc/ol.source.TileJSON.html index 84830d1efe..9381719196 100644 --- a/master/apidoc/ol.source.TileJSON.html +++ b/master/apidoc/ol.source.TileJSON.html @@ -123,7 +123,7 @@
Source:
-
+
@@ -211,7 +211,7 @@
Source:
-
+
@@ -275,7 +275,7 @@
Source:
-
+
@@ -339,7 +339,7 @@
Source:
-
+
@@ -528,7 +528,7 @@ loaded tiles.
Source:
-
+
@@ -614,7 +614,7 @@ loaded tiles.
Source:
-
+
@@ -700,7 +700,7 @@ loaded tiles.
Source:
-
+
@@ -786,7 +786,7 @@ loaded tiles.
Source:
-
+
@@ -872,7 +872,7 @@ loaded tiles.
Source:
-
+
@@ -958,7 +958,7 @@ loaded tiles.
Source:
-
+
@@ -1022,7 +1022,7 @@ loaded tiles.
Source:
-
+
@@ -1086,7 +1086,7 @@ loaded tiles.
Source:
-
+
@@ -1167,7 +1167,7 @@ loaded tiles.
Source:
-
+
@@ -1226,7 +1226,7 @@ loaded tiles.
Source:
-
+
@@ -1338,7 +1338,7 @@ loaded tiles.
Source:
-
+
@@ -1450,7 +1450,7 @@ loaded tiles.
Source:
-
+
@@ -1562,7 +1562,7 @@ loaded tiles.
Source:
-
+
@@ -1720,7 +1720,7 @@ loaded tiles.
Source:
-
+
@@ -1822,13 +1822,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.TileSource.html b/master/apidoc/ol.source.TileSource.html index 9099535cb9..def80623cd 100644 --- a/master/apidoc/ol.source.TileSource.html +++ b/master/apidoc/ol.source.TileSource.html @@ -123,7 +123,7 @@
Source:
-
+
@@ -197,7 +197,7 @@
Source:
-
+
@@ -243,7 +243,7 @@
Source:
-
+
@@ -289,7 +289,7 @@
Source:
-
+
@@ -340,7 +340,7 @@
Source:
-
+
@@ -386,7 +386,7 @@
Source:
-
+
@@ -436,7 +436,7 @@
Source:
-
+
@@ -500,7 +500,7 @@
Source:
-
+
@@ -684,7 +684,7 @@ loaded tiles.
Source:
-
+
@@ -770,7 +770,7 @@ loaded tiles.
Source:
-
+
@@ -856,7 +856,7 @@ loaded tiles.
Source:
-
+
@@ -937,7 +937,7 @@ loaded tiles.
Source:
-
+
@@ -1023,7 +1023,7 @@ loaded tiles.
Source:
-
+
@@ -1104,7 +1104,7 @@ loaded tiles.
Source:
-
+
@@ -1163,7 +1163,7 @@ loaded tiles.
Source:
-
+
@@ -1297,7 +1297,7 @@ loaded tiles.
Source:
-
+
@@ -1409,7 +1409,7 @@ loaded tiles.
Source:
-
+
@@ -1521,7 +1521,7 @@ loaded tiles.
Source:
-
+
@@ -1674,7 +1674,7 @@ loaded tiles.
Source:
-
+
@@ -1712,13 +1712,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.TiledWMS.html b/master/apidoc/ol.source.TiledWMS.html index bbc3da2f47..ed71cf3077 100644 --- a/master/apidoc/ol.source.TiledWMS.html +++ b/master/apidoc/ol.source.TiledWMS.html @@ -202,7 +202,7 @@
Source:
-
+
@@ -253,7 +253,7 @@
Source:
-
+
@@ -304,7 +304,7 @@
Source:
-
+
@@ -368,7 +368,7 @@
Source:
-
+
@@ -432,7 +432,7 @@
Source:
-
+
@@ -496,7 +496,7 @@
Source:
-
+
@@ -685,7 +685,7 @@ loaded tiles.
Source:
-
+
@@ -771,7 +771,7 @@ loaded tiles.
Source:
-
+
@@ -857,7 +857,7 @@ loaded tiles.
Source:
-
+
@@ -943,7 +943,7 @@ loaded tiles.
Source:
-
+
@@ -1029,7 +1029,7 @@ loaded tiles.
Source:
-
+
@@ -1115,7 +1115,7 @@ loaded tiles.
Source:
-
+
@@ -1179,7 +1179,7 @@ loaded tiles.
Source:
-
+
@@ -1243,7 +1243,7 @@ loaded tiles.
Source:
-
+
@@ -1377,7 +1377,7 @@ loaded tiles.
Source:
-
+
@@ -1489,7 +1489,7 @@ loaded tiles.
Source:
-
+
@@ -1601,7 +1601,7 @@ loaded tiles.
Source:
-
+
@@ -1759,7 +1759,7 @@ loaded tiles.
Source:
-
+
@@ -1861,13 +1861,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.source.XYZ.html b/master/apidoc/ol.source.XYZ.html index 2c5a44bd7d..bfe381ffbd 100644 --- a/master/apidoc/ol.source.XYZ.html +++ b/master/apidoc/ol.source.XYZ.html @@ -202,7 +202,7 @@
Source:
-
+
@@ -253,7 +253,7 @@
Source:
-
+
@@ -304,7 +304,7 @@
Source:
-
+
@@ -414,7 +414,7 @@
Source:
-
+
@@ -478,7 +478,7 @@
Source:
-
+
@@ -542,7 +542,7 @@
Source:
-
+
@@ -731,7 +731,7 @@ loaded tiles.
Source:
-
+
@@ -817,7 +817,7 @@ loaded tiles.
Source:
-
+
@@ -903,7 +903,7 @@ loaded tiles.
Source:
-
+
@@ -989,7 +989,7 @@ loaded tiles.
Source:
-
+
@@ -1075,7 +1075,7 @@ loaded tiles.
Source:
-
+
@@ -1161,7 +1161,7 @@ loaded tiles.
Source:
-
+
@@ -1225,7 +1225,7 @@ loaded tiles.
Source:
-
+
@@ -1289,7 +1289,7 @@ loaded tiles.
Source:
-
+
@@ -1423,7 +1423,7 @@ loaded tiles.
Source:
-
+
@@ -1535,7 +1535,7 @@ loaded tiles.
Source:
-
+
@@ -1647,7 +1647,7 @@ loaded tiles.
Source:
-
+
@@ -1805,7 +1805,7 @@ loaded tiles.
Source:
-
+
@@ -1907,13 +1907,13 @@ loaded tiles.
diff --git a/master/apidoc/ol.tilegrid.TileGrid.html b/master/apidoc/ol.tilegrid.TileGrid.html index 22814241df..9fe8191db2 100644 --- a/master/apidoc/ol.tilegrid.TileGrid.html +++ b/master/apidoc/ol.tilegrid.TileGrid.html @@ -2256,13 +2256,13 @@ assigned the higher tile coordinate.
diff --git a/master/apidoc/ol.tilegrid.XYZ.html b/master/apidoc/ol.tilegrid.XYZ.html index 74bf08d7c0..3d692d0c1d 100644 --- a/master/apidoc/ol.tilegrid.XYZ.html +++ b/master/apidoc/ol.tilegrid.XYZ.html @@ -2216,13 +2216,13 @@ assigned the higher tile coordinate.
diff --git a/master/build/ol-deps.js b/master/build/ol-deps.js new file mode 100644 index 0000000000..bf64b71b3b --- /dev/null +++ b/master/build/ol-deps.js @@ -0,0 +1,963 @@ +// This file was autogenerated by bin/closure/depswriter.py. +// Please do not edit. +goog.addDependency('../../../ol/ol/anchoredelement.js', ['ol.AnchoredElement', 'ol.AnchoredElementPositioning', 'ol.AnchoredElementProperty'], ['goog.dom', 'goog.events', 'goog.style', 'ol.Coordinate', 'ol.Map', 'ol.MapEventType', 'ol.Object']); +goog.addDependency('../../../ol/ol/animation.js', ['ol.animation'], ['ol.PreRenderFunction', 'ol.ViewHint', 'ol.easing']); +goog.addDependency('../../../ol/ol/array.js', ['ol.array'], ['goog.array']); +goog.addDependency('../../../ol/ol/attribution.js', ['ol.Attribution'], ['ol.TileRange']); +goog.addDependency('../../../ol/ol/browserfeature.js', ['ol.BrowserFeature'], []); +goog.addDependency('../../../ol/ol/canvas/canvas.js', ['ol.canvas'], ['goog.dom', 'goog.dom.TagName']); +goog.addDependency('../../../ol/ol/collection.js', ['ol.Collection', 'ol.CollectionEvent', 'ol.CollectionEventType'], ['goog.array', 'goog.events.Event', 'ol.Object']); +goog.addDependency('../../../ol/ol/color.js', ['ol.Color'], ['goog.color', 'goog.math']); +goog.addDependency('../../../ol/ol/constraints.js', ['ol.Constraints'], ['ol.ResolutionConstraintType', 'ol.RotationConstraintType']); +goog.addDependency('../../../ol/ol/control/attributioncontrol.js', ['ol.control.Attribution'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.object', 'goog.style', 'ol.Attribution', 'ol.FrameState', 'ol.MapEvent', 'ol.MapEventType', 'ol.TileRange', 'ol.control.Control', 'ol.source.Source']); +goog.addDependency('../../../ol/ol/control/control.js', ['ol.control.Control', 'ol.control.ControlOptions'], ['goog.Disposable']); +goog.addDependency('../../../ol/ol/control/defaults.js', ['ol.control.defaults'], ['goog.array', 'ol.control.Attribution', 'ol.control.Zoom']); +goog.addDependency('../../../ol/ol/control/dragboxcontrol.js', ['ol.control.DragBox'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.style', 'ol.Coordinate', 'ol.MapBrowserEvent', 'ol.MapBrowserEvent.EventType', 'ol.Pixel', 'ol.Size', 'ol.control.Control']); +goog.addDependency('../../../ol/ol/control/mousepositioncontrol.js', ['ol.control.MousePosition'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.style', 'ol.Coordinate', 'ol.CoordinateFormatType', 'ol.MapEvent', 'ol.MapEventType', 'ol.Pixel', 'ol.Projection', 'ol.TransformFunction', 'ol.control.Control', 'ol.projection']); +goog.addDependency('../../../ol/ol/control/scalelinecontrol.js', ['ol.control.ScaleLine', 'ol.control.ScaleLineUnits'], ['goog.dom', 'goog.style', 'ol.FrameState', 'ol.MapEvent', 'ol.MapEventType', 'ol.ProjectionUnits', 'ol.TransformFunction', 'ol.control.Control', 'ol.projection', 'ol.sphere.NORMAL']); +goog.addDependency('../../../ol/ol/control/zoomcontrol.js', ['ol.control.Zoom'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'ol.control.Control']); +goog.addDependency('../../../ol/ol/coordinate.js', ['ol.Coordinate', 'ol.CoordinateFormatType'], ['goog.math', 'goog.math.Vec2']); +goog.addDependency('../../../ol/ol/dom/dom.js', ['ol.dom', 'ol.dom.BrowserFeature'], ['goog.vec.Mat4']); +goog.addDependency('../../../ol/ol/easing.js', ['ol.easing'], ['goog.fx.easing']); +goog.addDependency('../../../ol/ol/ellipsoid.js', ['ol.Ellipsoid'], ['goog.math', 'ol.Coordinate']); +goog.addDependency('../../../ol/ol/ellipsoid/wgs84.js', ['ol.ellipsoid.WGS84'], ['ol.Ellipsoid']); +goog.addDependency('../../../ol/ol/extent.js', ['ol.Extent'], ['ol.Coordinate', 'ol.Rectangle', 'ol.TransformFunction']); +goog.addDependency('../../../ol/ol/framestate.js', ['ol.FrameState', 'ol.PostRenderFunction', 'ol.PreRenderFunction'], ['goog.vec.Mat4', 'ol.Attribution', 'ol.Color', 'ol.Extent', 'ol.Size', 'ol.TileQueue', 'ol.TileRange', 'ol.View2DState', 'ol.layer.Layer', 'ol.layer.LayerState']); +goog.addDependency('../../../ol/ol/geolocation.js', ['ol.Geolocation', 'ol.GeolocationProperty'], ['goog.functions', 'goog.math', 'ol.Coordinate', 'ol.Object', 'ol.Projection', 'ol.projection']); +goog.addDependency('../../../ol/ol/image.js', ['ol.Image', 'ol.ImageState'], ['goog.array', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'ol.Attribution', 'ol.Extent']); +goog.addDependency('../../../ol/ol/imagetile.js', ['ol.ImageTile'], ['goog.array', 'goog.events', 'goog.events.EventType', 'ol.Tile', 'ol.TileCoord', 'ol.TileState']); +goog.addDependency('../../../ol/ol/imageurlfunction.js', ['ol.ImageUrlFunction', 'ol.ImageUrlFunctionType'], ['ol.Extent', 'ol.Size', 'ol.source.wms']); +goog.addDependency('../../../ol/ol/interaction/condition.js', ['ol.interaction.ConditionType', 'ol.interaction.condition'], []); +goog.addDependency('../../../ol/ol/interaction/dblclickzoominteraction.js', ['ol.interaction.DblClickZoom'], ['ol.MapBrowserEvent', 'ol.MapBrowserEvent.EventType', 'ol.View2D', 'ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/defaults.js', ['ol.interaction.defaults'], ['ol.Collection', 'ol.Kinetic', 'ol.interaction.DblClickZoom', 'ol.interaction.DragPan', 'ol.interaction.DragRotate', 'ol.interaction.DragZoom', 'ol.interaction.Interaction', 'ol.interaction.KeyboardPan', 'ol.interaction.KeyboardZoom', 'ol.interaction.MouseWheelZoom', 'ol.interaction.TouchPan', 'ol.interaction.TouchRotate', 'ol.interaction.TouchZoom', 'ol.interaction.condition']); +goog.addDependency('../../../ol/ol/interaction/draginteraction.js', ['ol.interaction.Drag'], ['goog.asserts', 'goog.functions', 'ol.Coordinate', 'ol.MapBrowserEvent', 'ol.MapBrowserEvent.EventType', 'ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/dragpaninteraction.js', ['ol.interaction.DragPan'], ['goog.asserts', 'ol.Coordinate', 'ol.Kinetic', 'ol.Pixel', 'ol.PreRenderFunction', 'ol.View2D', 'ol.ViewHint', 'ol.interaction.ConditionType', 'ol.interaction.Drag']); +goog.addDependency('../../../ol/ol/interaction/dragrotateandzoominteraction.js', ['ol.interaction.DragRotateAndZoom'], ['goog.math.Vec2', 'ol.View2D', 'ol.interaction.ConditionType', 'ol.interaction.Drag']); +goog.addDependency('../../../ol/ol/interaction/dragrotateinteraction.js', ['ol.interaction.DragRotate'], ['ol.View2D', 'ol.ViewHint', 'ol.interaction.ConditionType', 'ol.interaction.Drag']); +goog.addDependency('../../../ol/ol/interaction/dragzoominteraction.js', ['ol.interaction.DragZoom'], ['ol.Extent', 'ol.Size', 'ol.View2D', 'ol.control.DragBox', 'ol.interaction.ConditionType', 'ol.interaction.Drag']); +goog.addDependency('../../../ol/ol/interaction/interaction.js', ['ol.interaction.Interaction'], ['ol.MapBrowserEvent']); +goog.addDependency('../../../ol/ol/interaction/keyboardinteraction.js', ['ol.interaction.Keyboard'], ['ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/keyboardpaninteraction.js', ['ol.interaction.KeyboardPan'], ['goog.events.KeyCodes', 'goog.events.KeyHandler.EventType', 'ol.Coordinate', 'ol.View2D', 'ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/keyboardzoominteraction.js', ['ol.interaction.KeyboardZoom'], ['goog.events.KeyHandler.EventType', 'ol.View2D', 'ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/mousewheelzoominteraction.js', ['ol.interaction.MouseWheelZoom'], ['goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler.EventType', 'goog.math', 'ol.Coordinate', 'ol.View2D', 'ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/touchinteraction.js', ['ol.interaction.Touch'], ['goog.functions', 'ol.MapBrowserEvent', 'ol.MapBrowserEvent.EventType', 'ol.Pixel', 'ol.interaction.Interaction']); +goog.addDependency('../../../ol/ol/interaction/touchpaninteraction.js', ['ol.interaction.TouchPan'], ['goog.asserts', 'ol.Coordinate', 'ol.Kinetic', 'ol.Pixel', 'ol.PreRenderFunction', 'ol.View', 'ol.ViewHint', 'ol.interaction.Touch']); +goog.addDependency('../../../ol/ol/interaction/touchrotateinteraction.js', ['ol.interaction.TouchRotate'], ['goog.asserts', 'ol.View', 'ol.ViewHint', 'ol.interaction.Touch']); +goog.addDependency('../../../ol/ol/interaction/touchzoominteraction.js', ['ol.interaction.TouchZoom'], ['goog.asserts', 'ol.View', 'ol.ViewHint', 'ol.interaction.Touch']); +goog.addDependency('../../../ol/ol/iview.js', ['ol.IView'], ['ol.IView2D', 'ol.IView3D']); +goog.addDependency('../../../ol/ol/iview2d.js', ['ol.IView2D', 'ol.View2DState'], ['ol.Coordinate', 'ol.Projection']); +goog.addDependency('../../../ol/ol/iview3d.js', ['ol.IView3D'], []); +goog.addDependency('../../../ol/ol/kinetic.js', ['ol.Kinetic'], ['ol.Coordinate', 'ol.PreRenderFunction', 'ol.animation']); +goog.addDependency('../../../ol/ol/layer/imagelayer.js', ['ol.layer.ImageLayer'], ['ol.layer.Layer', 'ol.source.ImageSource']); +goog.addDependency('../../../ol/ol/layer/layer.js', ['ol.layer.Layer', 'ol.layer.LayerProperty', 'ol.layer.LayerState'], ['goog.events', 'goog.events.EventType', 'goog.math', 'ol.Object', 'ol.source.Source']); +goog.addDependency('../../../ol/ol/layer/tilelayer.js', ['ol.layer.TileLayer'], ['ol.layer.Layer', 'ol.source.TileSource']); +goog.addDependency('../../../ol/ol/map.js', ['ol.Map', 'ol.MapProperty', 'ol.RendererHint', 'ol.RendererHints'], ['goog.Uri.QueryData', 'goog.async.AnimationDelay', 'goog.debug.Logger', 'goog.dom', 'goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.events.MouseWheelHandler', 'goog.events.MouseWheelHandler.EventType', 'goog.style', 'ol.BrowserFeature', 'ol.Collection', 'ol.Color', 'ol.Coordinate', 'ol.Extent', 'ol.FrameState', 'ol.IView', 'ol.MapBrowserEvent', 'ol.MapBrowserEvent.EventType', 'ol.MapBrowserEventHandler', 'ol.MapEvent', 'ol.MapEventType', 'ol.Object', 'ol.ObjectEventType', 'ol.Pixel', 'ol.PostRenderFunction', 'ol.PreRenderFunction', 'ol.Size', 'ol.Tile', 'ol.TileQueue', 'ol.View', 'ol.View2D', 'ol.control.defaults', 'ol.interaction.defaults', 'ol.layer.Layer', 'ol.projection', 'ol.projection.addCommonProjections', 'ol.renderer.Map', 'ol.renderer.canvas.Map', 'ol.renderer.canvas.SUPPORTED', 'ol.renderer.dom.Map', 'ol.renderer.dom.SUPPORTED', 'ol.renderer.webgl.Map', 'ol.renderer.webgl.SUPPORTED']); +goog.addDependency('../../../ol/ol/mapbrowserevent.js', ['ol.MapBrowserEvent', 'ol.MapBrowserEvent.EventType', 'ol.MapBrowserEventHandler'], ['goog.array', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.style', 'ol.BrowserFeature', 'ol.Coordinate', 'ol.FrameState', 'ol.MapEvent', 'ol.Pixel']); +goog.addDependency('../../../ol/ol/mapevent.js', ['ol.MapEvent', 'ol.MapEventType'], ['goog.events.Event', 'ol.FrameState']); +goog.addDependency('../../../ol/ol/math.js', ['ol.math'], []); +goog.addDependency('../../../ol/ol/object.js', ['ol.Object', 'ol.ObjectEventType'], ['goog.array', 'goog.events', 'goog.events.EventTarget', 'goog.object']); +goog.addDependency('../../../ol/ol/ol.js', ['ol'], ['goog.debug.Logger']); +goog.addDependency('../../../ol/ol/parser/ogc/exceptionreport.js', ['ol.parser.ogc.ExceptionReport'], ['goog.dom.xml', 'ol.parser.XML']); +goog.addDependency('../../../ol/ol/parser/ogc/owscommon_v1.js', ['ol.parser.ogc.OWSCommon_v1'], ['ol.Extent', 'ol.parser.XML']); +goog.addDependency('../../../ol/ol/parser/ogc/owscommon_v1_1_0.js', ['ol.parser.ogc.OWSCommon_v1_1_0'], ['goog.object', 'ol.parser.ogc.OWSCommon_v1']); +goog.addDependency('../../../ol/ol/parser/ogc/versioned.js', ['ol.parser.ogc.Versioned'], ['goog.dom.xml', 'ol.parser.ogc.ExceptionReport']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities.js', ['ol.parser.ogc.WMSCapabilities'], ['ol.parser.ogc.Versioned', 'ol.parser.ogc.WMSCapabilities_v1_0_0', 'ol.parser.ogc.WMSCapabilities_v1_1_0', 'ol.parser.ogc.WMSCapabilities_v1_1_1', 'ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC', 'ol.parser.ogc.WMSCapabilities_v1_3_0']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1.js', ['ol.parser.ogc.WMSCapabilities_v1'], ['goog.dom.xml', 'goog.object', 'ol.parser.XML']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1_0_0.js', ['ol.parser.ogc.WMSCapabilities_v1_0_0'], ['goog.string', 'ol.parser.ogc.WMSCapabilities_v1_1_0']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1_1.js', ['ol.parser.ogc.WMSCapabilities_v1_1'], ['ol.parser.ogc.WMSCapabilities_v1']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1_1_0.js', ['ol.parser.ogc.WMSCapabilities_v1_1_0'], ['ol.parser.ogc.WMSCapabilities_v1_1']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1_1_1.js', ['ol.parser.ogc.WMSCapabilities_v1_1_1'], ['ol.parser.ogc.WMSCapabilities_v1_1']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js', ['ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC'], ['ol.parser.ogc.WMSCapabilities_v1_1_1']); +goog.addDependency('../../../ol/ol/parser/ogc/wmscapabilities_v1_3_0.js', ['ol.parser.ogc.WMSCapabilities_v1_3_0'], ['ol.parser.ogc.WMSCapabilities_v1']); +goog.addDependency('../../../ol/ol/parser/ogc/wmtscapabilities.js', ['ol.parser.ogc.WMTSCapabilities'], ['ol.parser.ogc.Versioned', 'ol.parser.ogc.WMTSCapabilities_v1_0_0']); +goog.addDependency('../../../ol/ol/parser/ogc/wmtscapabilities_v1_0_0.js', ['ol.parser.ogc.WMTSCapabilities_v1_0_0'], ['goog.dom.xml', 'ol.Coordinate', 'ol.parser.XML', 'ol.parser.ogc.OWSCommon_v1_1_0', 'ol.projection']); +goog.addDependency('../../../ol/ol/parser/xml.js', ['ol.parser.XML'], []); +goog.addDependency('../../../ol/ol/pixel.js', ['ol.Pixel'], ['goog.math.Coordinate']); +goog.addDependency('../../../ol/ol/pixelbounds.js', ['ol.PixelBounds'], ['ol.Rectangle']); +goog.addDependency('../../../ol/ol/projection.js', ['ol.Projection', 'ol.ProjectionLike', 'ol.ProjectionUnits', 'ol.projection'], ['goog.array', 'goog.asserts', 'goog.object', 'ol.Coordinate', 'ol.Extent', 'ol.TransformFunction', 'ol.sphere.NORMAL']); +goog.addDependency('../../../ol/ol/projection/common.js', ['ol.projection.addCommonProjections'], ['ol.projection', 'ol.projection.EPSG3857', 'ol.projection.EPSG4326']); +goog.addDependency('../../../ol/ol/projection/epsg3857.js', ['ol.projection.EPSG3857'], ['goog.array', 'ol.Extent', 'ol.Projection', 'ol.ProjectionUnits', 'ol.math', 'ol.projection']); +goog.addDependency('../../../ol/ol/projection/epsg4326.js', ['ol.projection.EPSG4326'], ['ol.Extent', 'ol.Projection', 'ol.ProjectionUnits', 'ol.projection']); +goog.addDependency('../../../ol/ol/rectangle.js', ['ol.Rectangle'], ['goog.asserts', 'ol.Coordinate', 'ol.Size']); +goog.addDependency('../../../ol/ol/renderer/canvas/canvasimagelayerrenderer.js', ['ol.renderer.canvas.ImageLayer'], ['goog.vec.Mat4', 'ol.Image', 'ol.ImageState', 'ol.ViewHint', 'ol.layer.ImageLayer', 'ol.renderer.Map', 'ol.renderer.canvas.Layer']); +goog.addDependency('../../../ol/ol/renderer/canvas/canvaslayerrenderer.js', ['ol.renderer.canvas.Layer'], ['ol.layer.Layer', 'ol.renderer.Layer']); +goog.addDependency('../../../ol/ol/renderer/canvas/canvasmaprenderer.js', ['ol.renderer.canvas.Map'], ['goog.array', 'goog.dom', 'goog.style', 'goog.vec.Mat4', 'ol.Size', 'ol.layer.ImageLayer', 'ol.layer.TileLayer', 'ol.renderer.Map', 'ol.renderer.canvas.ImageLayer', 'ol.renderer.canvas.TileLayer']); +goog.addDependency('../../../ol/ol/renderer/canvas/canvasrenderer.js', ['ol.renderer.canvas.SUPPORTED'], ['ol.canvas']); +goog.addDependency('../../../ol/ol/renderer/canvas/canvastilelayerrenderer.js', ['ol.renderer.canvas.TileLayer'], ['goog.array', 'goog.dom', 'goog.vec.Mat4', 'ol.Size', 'ol.Tile', 'ol.TileCoord', 'ol.TileState', 'ol.layer.TileLayer', 'ol.renderer.Map', 'ol.renderer.canvas.Layer']); +goog.addDependency('../../../ol/ol/renderer/dom/domimagelayerrenderer.js', ['ol.renderer.dom.ImageLayer'], ['goog.dom', 'goog.vec.Mat4', 'ol.Image', 'ol.ImageState', 'ol.ViewHint', 'ol.dom', 'ol.layer.ImageLayer', 'ol.renderer.dom.Layer']); +goog.addDependency('../../../ol/ol/renderer/dom/domlayerrenderer.js', ['ol.renderer.dom.Layer'], ['ol.layer.Layer', 'ol.renderer.Layer']); +goog.addDependency('../../../ol/ol/renderer/dom/dommaprenderer.js', ['ol.renderer.dom.Map'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.style', 'ol.layer.ImageLayer', 'ol.layer.TileLayer', 'ol.renderer.Map', 'ol.renderer.dom.ImageLayer', 'ol.renderer.dom.TileLayer']); +goog.addDependency('../../../ol/ol/renderer/dom/domrenderer.js', ['ol.renderer.dom.SUPPORTED'], []); +goog.addDependency('../../../ol/ol/renderer/dom/domtilelayerrenderer.js', ['ol.renderer.dom.TileLayer'], ['goog.asserts', 'goog.dom', 'goog.style', 'goog.vec.Mat4', 'ol.Coordinate', 'ol.Extent', 'ol.Tile', 'ol.TileCoord', 'ol.TileState', 'ol.ViewHint', 'ol.dom', 'ol.layer.TileLayer', 'ol.renderer.dom.Layer', 'ol.tilegrid.TileGrid']); +goog.addDependency('../../../ol/ol/renderer/layerrenderer.js', ['ol.renderer.Layer'], ['goog.events', 'goog.events.EventType', 'ol.Attribution', 'ol.FrameState', 'ol.Image', 'ol.ImageState', 'ol.Object', 'ol.Tile', 'ol.TileCoord', 'ol.TileRange', 'ol.TileState', 'ol.layer.Layer', 'ol.layer.LayerProperty', 'ol.layer.LayerState', 'ol.source.TileSource']); +goog.addDependency('../../../ol/ol/renderer/maprenderer.js', ['ol.renderer.Map'], ['goog.Disposable', 'goog.array', 'goog.asserts', 'goog.events', 'goog.functions', 'goog.vec.Mat4', 'ol.CollectionEvent', 'ol.CollectionEventType', 'ol.FrameState', 'ol.Object', 'ol.layer.Layer', 'ol.renderer.Layer']); +goog.addDependency('../../../ol/ol/renderer/webgl/shader.js', ['ol.renderer.webgl.FragmentShader', 'ol.renderer.webgl.VertexShader'], ['goog.functions', 'goog.webgl']); +goog.addDependency('../../../ol/ol/renderer/webgl/webglimagelayerrenderer.js', ['ol.renderer.webgl.ImageLayer'], ['goog.vec.Mat4', 'ol.Coordinate', 'ol.Extent', 'ol.Image', 'ol.ImageState', 'ol.ViewHint', 'ol.layer.ImageLayer', 'ol.renderer.webgl.Layer']); +goog.addDependency('../../../ol/ol/renderer/webgl/webgllayerrenderer.js', ['ol.renderer.webgl.Layer'], ['goog.vec.Mat4', 'ol.layer.Layer', 'ol.renderer.Layer', 'ol.vec.Mat4']); +goog.addDependency('../../../ol/ol/renderer/webgl/webglmaprenderer.js', ['ol.renderer.webgl.Map', 'ol.renderer.webgl.map.shader'], ['goog.array', 'goog.debug.Logger', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.style', 'goog.webgl', 'ol.FrameState', 'ol.Size', 'ol.Tile', 'ol.layer.ImageLayer', 'ol.layer.TileLayer', 'ol.renderer.Map', 'ol.renderer.webgl.FragmentShader', 'ol.renderer.webgl.ImageLayer', 'ol.renderer.webgl.TileLayer', 'ol.renderer.webgl.VertexShader', 'ol.structs.LRUCache', 'ol.webgl', 'ol.webgl.WebGLContextEventType']); +goog.addDependency('../../../ol/ol/renderer/webgl/webglrenderer.js', ['ol.renderer.webgl.SUPPORTED'], ['ol.webgl']); +goog.addDependency('../../../ol/ol/renderer/webgl/webgltilelayerrenderer.js', ['ol.renderer.webgl.TileLayer', 'ol.renderer.webgl.tilelayerrenderer', 'ol.renderer.webgl.tilelayerrenderer.shader.Fragment', 'ol.renderer.webgl.tilelayerrenderer.shader.Vertex'], ['goog.array', 'goog.object', 'goog.structs.PriorityQueue', 'goog.vec.Mat4', 'goog.vec.Vec4', 'goog.webgl', 'ol.Extent', 'ol.FrameState', 'ol.Size', 'ol.Tile', 'ol.TileCoord', 'ol.TileRange', 'ol.TileState', 'ol.layer.TileLayer', 'ol.renderer.webgl.FragmentShader', 'ol.renderer.webgl.Layer', 'ol.renderer.webgl.VertexShader']); +goog.addDependency('../../../ol/ol/resolutionconstraint.js', ['ol.ResolutionConstraint', 'ol.ResolutionConstraintType'], ['goog.math', 'ol.array']); +goog.addDependency('../../../ol/ol/rotationconstraint.js', ['ol.RotationConstraint', 'ol.RotationConstraintType'], []); +goog.addDependency('../../../ol/ol/size.js', ['ol.Size'], ['goog.math.Size']); +goog.addDependency('../../../ol/ol/source/bingmapssource.js', ['ol.source.BingMaps'], ['goog.Uri', 'goog.array', 'goog.net.Jsonp', 'ol.Attribution', 'ol.Extent', 'ol.Size', 'ol.TileCoord', 'ol.TileRange', 'ol.TileUrlFunction', 'ol.projection', 'ol.source.ImageTileSource', 'ol.tilegrid.XYZ']); +goog.addDependency('../../../ol/ol/source/debugtilesource.js', ['ol.source.DebugTileSource'], ['ol.Size', 'ol.Tile', 'ol.TileCache', 'ol.TileCoord', 'ol.TileState', 'ol.source.TileSource', 'ol.tilegrid.TileGrid']); +goog.addDependency('../../../ol/ol/source/imagesource.js', ['ol.source.ImageSource'], ['goog.array', 'ol.Attribution', 'ol.Extent', 'ol.Image', 'ol.ImageUrlFunction', 'ol.ImageUrlFunctionType', 'ol.Projection', 'ol.Size', 'ol.array', 'ol.source.Source']); +goog.addDependency('../../../ol/ol/source/imagetilesource.js', ['ol.source.ImageTileSource', 'ol.source.ImageTileSourceOptions'], ['ol.Attribution', 'ol.Extent', 'ol.ImageTile', 'ol.Projection', 'ol.Tile', 'ol.TileCache', 'ol.TileState', 'ol.TileUrlFunction', 'ol.TileUrlFunctionType', 'ol.source.TileSource', 'ol.tilegrid.TileGrid']); +goog.addDependency('../../../ol/ol/source/mapquestsource.js', ['ol.source.MapQuestOSM', 'ol.source.MapQuestOpenAerial'], ['ol.Attribution', 'ol.source.XYZ']); +goog.addDependency('../../../ol/ol/source/openstreetmapsource.js', ['ol.source.OpenStreetMap'], ['ol.Attribution', 'ol.source.XYZ']); +goog.addDependency('../../../ol/ol/source/singleimagewmssource.js', ['ol.source.SingleImageWMS'], ['ol.Extent', 'ol.Image', 'ol.ImageUrlFunction', 'ol.Size', 'ol.source.ImageSource']); +goog.addDependency('../../../ol/ol/source/source.js', ['ol.source.Source'], ['goog.events.EventTarget', 'goog.events.EventType', 'goog.functions', 'ol.Attribution', 'ol.Extent', 'ol.projection']); +goog.addDependency('../../../ol/ol/source/stamensource.js', ['ol.source.Stamen'], ['ol.Attribution', 'ol.source.XYZ']); +goog.addDependency('../../../ol/ol/source/staticimagesource.js', ['ol.source.StaticImage'], ['ol.Image', 'ol.ImageUrlFunctionType', 'ol.projection', 'ol.source.ImageSource']); +goog.addDependency('../../../ol/ol/source/tiledwmssource.js', ['ol.source.TiledWMS'], ['goog.array', 'ol.Extent', 'ol.TileCoord', 'ol.TileUrlFunction', 'ol.source.ImageTileSource']); +goog.addDependency('../../../ol/ol/source/tilejsonsource.js', ['ol.source.TileJSON', 'ol.tilejson'], ['goog.asserts', 'goog.net.jsloader', 'ol.Attribution', 'ol.Extent', 'ol.TileCoord', 'ol.TileRange', 'ol.TileUrlFunction', 'ol.projection', 'ol.source.ImageTileSource', 'ol.tilegrid.XYZ']); +goog.addDependency('../../../ol/ol/source/tilesource.js', ['ol.source.TileSource', 'ol.source.TileSourceOptions'], ['goog.functions', 'ol.Attribution', 'ol.Extent', 'ol.Tile', 'ol.TileCoord', 'ol.TileRange', 'ol.source.Source', 'ol.tilegrid.TileGrid']); +goog.addDependency('../../../ol/ol/source/wms.js', ['ol.source.wms'], []); +goog.addDependency('../../../ol/ol/source/xyzsource.js', ['ol.source.XYZ', 'ol.source.XYZOptions'], ['goog.math', 'ol.Attribution', 'ol.Extent', 'ol.Projection', 'ol.TileCoord', 'ol.TileUrlFunction', 'ol.TileUrlFunctionType', 'ol.projection', 'ol.source.ImageTileSource', 'ol.tilegrid.XYZ']); +goog.addDependency('../../../ol/ol/sphere.js', ['ol.Sphere'], ['goog.math', 'ol.Coordinate']); +goog.addDependency('../../../ol/ol/sphere/normal.js', ['ol.sphere.NORMAL'], ['ol.Sphere']); +goog.addDependency('../../../ol/ol/sphere/wgs84.js', ['ol.sphere.WGS84'], ['ol.Sphere']); +goog.addDependency('../../../ol/ol/structs/lrucache.js', ['ol.structs.LRUCache'], ['goog.asserts', 'goog.object']); +goog.addDependency('../../../ol/ol/tile.js', ['ol.Tile', 'ol.TileState'], ['goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'ol.TileCoord']); +goog.addDependency('../../../ol/ol/tilecache.js', ['ol.TileCache'], ['ol.Tile', 'ol.TileRange', 'ol.structs.LRUCache']); +goog.addDependency('../../../ol/ol/tilecoord.js', ['ol.TileCoord'], ['goog.array', 'ol.Coordinate']); +goog.addDependency('../../../ol/ol/tilegrid/tilegrid.js', ['ol.tilegrid.TileGrid'], ['goog.array', 'goog.asserts', 'ol.Coordinate', 'ol.Extent', 'ol.PixelBounds', 'ol.Projection', 'ol.Size', 'ol.TileCoord', 'ol.TileRange', 'ol.array']); +goog.addDependency('../../../ol/ol/tilegrid/xyztilegrid.js', ['ol.tilegrid.XYZ'], ['ol.Coordinate', 'ol.Size', 'ol.TileRange', 'ol.projection', 'ol.projection.EPSG3857', 'ol.tilegrid.TileGrid']); +goog.addDependency('../../../ol/ol/tilequeue.js', ['ol.TilePriorityFunction', 'ol.TileQueue'], ['goog.events', 'goog.events.EventType', 'ol.Coordinate', 'ol.Tile', 'ol.TileState']); +goog.addDependency('../../../ol/ol/tilerange.js', ['ol.TileRange'], ['goog.asserts', 'ol.Rectangle', 'ol.TileCoord']); +goog.addDependency('../../../ol/ol/tileurlfunction.js', ['ol.TileUrlFunction', 'ol.TileUrlFunctionType'], ['goog.array', 'goog.math', 'ol.TileCoord', 'ol.source.wms', 'ol.tilegrid.TileGrid']); +goog.addDependency('../../../ol/ol/transformfunction.js', ['ol.TransformFunction'], []); +goog.addDependency('../../../ol/ol/vec/mat4.js', ['ol.vec.Mat4'], ['goog.vec.Mat4']); +goog.addDependency('../../../ol/ol/view.js', ['ol.View', 'ol.ViewHint'], ['goog.array', 'ol.IView', 'ol.Object']); +goog.addDependency('../../../ol/ol/view2d.js', ['ol.View2D', 'ol.View2DProperty'], ['ol.Constraints', 'ol.Coordinate', 'ol.Extent', 'ol.IView2D', 'ol.IView3D', 'ol.Projection', 'ol.ResolutionConstraint', 'ol.RotationConstraint', 'ol.Size', 'ol.View', 'ol.animation', 'ol.easing', 'ol.projection']); +goog.addDependency('../../../ol/ol/webgl/webgl.js', ['ol.webgl', 'ol.webgl.WebGLContextEventType'], []); +goog.addDependency('../../third_party/closure/goog/caja/string/html/htmlparser.js', ['goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlParser.Entities', 'goog.string.html.HtmlSaxHandler'], []); +goog.addDependency('../../third_party/closure/goog/caja/string/html/htmlsanitizer.js', ['goog.string.html.HtmlSanitizer', 'goog.string.html.HtmlSanitizer.AttributeType', 'goog.string.html.HtmlSanitizer.Attributes', 'goog.string.html.htmlSanitize'], ['goog.string.StringBuffer', 'goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlSaxHandler']); +goog.addDependency('../../third_party/closure/goog/dojo/dom/query.js', ['goog.dom.query'], ['goog.array', 'goog.dom', 'goog.functions', 'goog.string', 'goog.userAgent']); +goog.addDependency('../../third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js', ['goog.crypt.JpegEncoder'], ['goog.crypt.base64']); +goog.addDependency('../../third_party/closure/goog/loremipsum/text/loremipsum.js', ['goog.text.LoremIpsum'], ['goog.array', 'goog.math', 'goog.string', 'goog.structs.Map', 'goog.structs.Set']); +goog.addDependency('../../third_party/closure/goog/mochikit/async/deferred.js', ['goog.async.Deferred', 'goog.async.Deferred.AlreadyCalledError', 'goog.async.Deferred.CancelledError'], ['goog.array', 'goog.asserts', 'goog.debug.Error']); +goog.addDependency('../../third_party/closure/goog/mochikit/async/deferredlist.js', ['goog.async.DeferredList'], ['goog.array', 'goog.async.Deferred']); +goog.addDependency('../../third_party/closure/goog/osapi/osapi.js', ['goog.osapi'], []); +goog.addDependency('../../third_party/closure/goog/silverlight/clipboardbutton.js', ['goog.silverlight.ClipboardButton', 'goog.silverlight.ClipboardButtonType', 'goog.silverlight.ClipboardEvent', 'goog.silverlight.CopyButton', 'goog.silverlight.PasteButton', 'goog.silverlight.PasteButtonEvent'], ['goog.asserts', 'goog.events.Event', 'goog.math.Size', 'goog.silverlight', 'goog.ui.Component']); +goog.addDependency('../../third_party/closure/goog/silverlight/silverlight.js', ['goog.silverlight'], []); +goog.addDependency('../../third_party/closure/goog/silverlight/supporteduseragent.js', ['goog.silverlight.supportedUserAgent'], []); +goog.addDependency('array/array.js', ['goog.array', 'goog.array.ArrayLike'], ['goog.asserts']); +goog.addDependency('asserts/asserts.js', ['goog.asserts', 'goog.asserts.AssertionError'], ['goog.debug.Error', 'goog.string']); +goog.addDependency('async/animationdelay.js', ['goog.async.AnimationDelay'], ['goog.async.Delay', 'goog.functions']); +goog.addDependency('async/conditionaldelay.js', ['goog.async.ConditionalDelay'], ['goog.Disposable', 'goog.async.Delay']); +goog.addDependency('async/delay.js', ['goog.Delay', 'goog.async.Delay'], ['goog.Disposable', 'goog.Timer']); +goog.addDependency('async/throttle.js', ['goog.Throttle', 'goog.async.Throttle'], ['goog.Disposable', 'goog.Timer']); +goog.addDependency('base.js', ['goog'], []); +goog.addDependency('color/alpha.js', ['goog.color.alpha'], ['goog.color']); +goog.addDependency('color/color.js', ['goog.color'], ['goog.color.names', 'goog.math']); +goog.addDependency('color/names.js', ['goog.color.names'], []); +goog.addDependency('crypt/arc4.js', ['goog.crypt.Arc4'], ['goog.asserts']); +goog.addDependency('crypt/base64.js', ['goog.crypt.base64'], ['goog.crypt', 'goog.userAgent']); +goog.addDependency('crypt/basen.js', ['goog.crypt.baseN'], []); +goog.addDependency('crypt/blobhasher.js', ['goog.crypt.BlobHasher', 'goog.crypt.BlobHasher.EventType'], ['goog.asserts', 'goog.crypt', 'goog.crypt.Hash', 'goog.debug.Logger', 'goog.events.EventTarget', 'goog.fs']); +goog.addDependency('crypt/crypt.js', ['goog.crypt'], ['goog.array']); +goog.addDependency('crypt/hash.js', ['goog.crypt.Hash'], []); +goog.addDependency('crypt/hash32.js', ['goog.crypt.hash32'], ['goog.crypt']); +goog.addDependency('crypt/hash_test.js', ['goog.crypt.hash_test'], ['goog.testing.asserts']); +goog.addDependency('crypt/hmac.js', ['goog.crypt.Hmac'], ['goog.asserts', 'goog.crypt.Hash']); +goog.addDependency('crypt/md5.js', ['goog.crypt.Md5'], ['goog.crypt.Hash']); +goog.addDependency('crypt/sha1.js', ['goog.crypt.Sha1'], ['goog.crypt.Hash']); +goog.addDependency('cssom/cssom.js', ['goog.cssom', 'goog.cssom.CssRuleType'], ['goog.array', 'goog.dom']); +goog.addDependency('cssom/iframe/style.js', ['goog.cssom.iframe.style'], ['goog.cssom', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classes', 'goog.string', 'goog.style', 'goog.userAgent']); +goog.addDependency('datasource/datamanager.js', ['goog.ds.DataManager'], ['goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.Expr', 'goog.string', 'goog.structs', 'goog.structs.Map']); +goog.addDependency('datasource/datasource.js', ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState', 'goog.ds.SortedNodeList', 'goog.ds.Util', 'goog.ds.logger'], ['goog.array', 'goog.debug.Logger']); +goog.addDependency('datasource/expr.js', ['goog.ds.Expr'], ['goog.ds.BasicNodeList', 'goog.ds.EmptyNodeList', 'goog.string']); +goog.addDependency('datasource/fastdatanode.js', ['goog.ds.AbstractFastDataNode', 'goog.ds.FastDataNode', 'goog.ds.FastListNode', 'goog.ds.PrimitiveFastDataNode'], ['goog.ds.DataManager', 'goog.ds.EmptyNodeList', 'goog.string']); +goog.addDependency('datasource/jsdatasource.js', ['goog.ds.JsDataSource', 'goog.ds.JsPropertyDataSource'], ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState']); +goog.addDependency('datasource/jsondatasource.js', ['goog.ds.JsonDataSource'], ['goog.Uri', 'goog.dom', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.LoadState', 'goog.ds.logger']); +goog.addDependency('datasource/jsxmlhttpdatasource.js', ['goog.ds.JsXmlHttpDataSource'], ['goog.Uri', 'goog.ds.DataManager', 'goog.ds.FastDataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.events', 'goog.net.EventType', 'goog.net.XhrIo']); +goog.addDependency('datasource/xmldatasource.js', ['goog.ds.XmlDataSource', 'goog.ds.XmlHttpDataSource'], ['goog.Uri', 'goog.dom.NodeType', 'goog.dom.xml', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.net.XhrIo', 'goog.string']); +goog.addDependency('date/date.js', ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay'], ['goog.asserts', 'goog.date.DateLike', 'goog.i18n.DateTimeSymbols', 'goog.string']); +goog.addDependency('date/datelike.js', ['goog.date.DateLike'], []); +goog.addDependency('date/daterange.js', ['goog.date.DateRange', 'goog.date.DateRange.Iterator', 'goog.date.DateRange.StandardDateRangeKeys'], ['goog.date.Date', 'goog.date.Interval', 'goog.iter.Iterator', 'goog.iter.StopIteration']); +goog.addDependency('date/relative.js', ['goog.date.relative'], ['goog.i18n.DateTimeFormat']); +goog.addDependency('date/utcdatetime.js', ['goog.date.UtcDateTime'], ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval']); +goog.addDependency('db/cursor.js', ['goog.db.Cursor'], ['goog.async.Deferred', 'goog.db.Error', 'goog.debug', 'goog.events.EventTarget']); +goog.addDependency('db/db.js', ['goog.db'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.IndexedDb']); +goog.addDependency('db/error.js', ['goog.db.Error', 'goog.db.Error.ErrorCode', 'goog.db.Error.VersionChangeBlockedError'], ['goog.debug.Error']); +goog.addDependency('db/index.js', ['goog.db.Index'], ['goog.async.Deferred', 'goog.db.Error', 'goog.debug']); +goog.addDependency('db/indexeddb.js', ['goog.db.IndexedDb'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.Error.VersionChangeBlockedError', 'goog.db.ObjectStore', 'goog.db.Transaction', 'goog.db.Transaction.TransactionMode']); +goog.addDependency('db/keyrange.js', ['goog.db.KeyRange'], []); +goog.addDependency('db/objectstore.js', ['goog.db.ObjectStore'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.Index', 'goog.debug', 'goog.events']); +goog.addDependency('db/transaction.js', ['goog.db.Transaction', 'goog.db.Transaction.TransactionMode'], ['goog.db.Error', 'goog.db.ObjectStore', 'goog.events.EventHandler', 'goog.events.EventTarget']); +goog.addDependency('debug/console.js', ['goog.debug.Console'], ['goog.debug.LogManager', 'goog.debug.Logger.Level', 'goog.debug.TextFormatter']); +goog.addDependency('debug/debug.js', ['goog.debug'], ['goog.array', 'goog.string', 'goog.structs.Set', 'goog.userAgent']); +goog.addDependency('debug/debugwindow.js', ['goog.debug.DebugWindow'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.structs.CircularBuffer', 'goog.userAgent']); +goog.addDependency('debug/devcss/devcss.js', ['goog.debug.DevCss', 'goog.debug.DevCss.UserAgent'], ['goog.cssom', 'goog.dom.classes', 'goog.events', 'goog.events.EventType', 'goog.string', 'goog.userAgent']); +goog.addDependency('debug/devcss/devcssrunner.js', ['goog.debug.devCssRunner'], ['goog.debug.DevCss']); +goog.addDependency('debug/divconsole.js', ['goog.debug.DivConsole'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.style']); +goog.addDependency('debug/entrypointregistry.js', ['goog.debug.EntryPointMonitor', 'goog.debug.entryPointRegistry'], ['goog.asserts']); +goog.addDependency('debug/error.js', ['goog.debug.Error'], []); +goog.addDependency('debug/errorhandler.js', ['goog.debug.ErrorHandler', 'goog.debug.ErrorHandler.ProtectedFunctionError'], ['goog.asserts', 'goog.debug', 'goog.debug.EntryPointMonitor', 'goog.debug.Trace']); +goog.addDependency('debug/errorhandlerweakdep.js', ['goog.debug.errorHandlerWeakDep'], []); +goog.addDependency('debug/errorreporter.js', ['goog.debug.ErrorReporter', 'goog.debug.ErrorReporter.ExceptionEvent'], ['goog.debug', 'goog.debug.ErrorHandler', 'goog.debug.Logger', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.uri.utils', 'goog.userAgent']); +goog.addDependency('debug/fancywindow.js', ['goog.debug.FancyWindow'], ['goog.debug.DebugWindow', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.debug.Logger.Level', 'goog.dom.DomHelper', 'goog.object', 'goog.string', 'goog.userAgent']); +goog.addDependency('debug/formatter.js', ['goog.debug.Formatter', 'goog.debug.HtmlFormatter', 'goog.debug.TextFormatter'], ['goog.debug.RelativeTimeProvider', 'goog.string']); +goog.addDependency('debug/fpsdisplay.js', ['goog.debug.FpsDisplay'], ['goog.asserts', 'goog.async.AnimationDelay', 'goog.ui.Component']); +goog.addDependency('debug/gcdiagnostics.js', ['goog.debug.GcDiagnostics'], ['goog.debug.Logger', 'goog.debug.Trace', 'goog.userAgent']); +goog.addDependency('debug/logbuffer.js', ['goog.debug.LogBuffer'], ['goog.asserts', 'goog.debug.LogRecord']); +goog.addDependency('debug/logger.js', ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.debug.Logger.Level'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.LogBuffer', 'goog.debug.LogRecord']); +goog.addDependency('debug/logrecord.js', ['goog.debug.LogRecord'], []); +goog.addDependency('debug/logrecordserializer.js', ['goog.debug.logRecordSerializer'], ['goog.debug.LogRecord', 'goog.debug.Logger.Level', 'goog.json', 'goog.object']); +goog.addDependency('debug/reflect.js', ['goog.debug.reflect'], []); +goog.addDependency('debug/relativetimeprovider.js', ['goog.debug.RelativeTimeProvider'], []); +goog.addDependency('debug/tracer.js', ['goog.debug.Trace'], ['goog.array', 'goog.debug.Logger', 'goog.iter', 'goog.structs.Map', 'goog.structs.SimplePool']); +goog.addDependency('demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'], ['goog.ui.equation.EquationEditorDialog']); +goog.addDependency('demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']); +goog.addDependency('demos/editor/helloworlddialog.js', ['goog.demos.editor.HelloWorldDialog', 'goog.demos.editor.HelloWorldDialog.OkEvent'], ['goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType']); +goog.addDependency('demos/editor/helloworlddialogplugin.js', ['goog.demos.editor.HelloWorldDialogPlugin', 'goog.demos.editor.HelloWorldDialogPlugin.Command'], ['goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType']); +goog.addDependency('demos/samplecomponent.js', ['goog.demos.SampleComponent'], ['goog.dom', 'goog.dom.classes', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.ui.Component']); +goog.addDependency('disposable/disposable.js', ['goog.Disposable', 'goog.dispose'], ['goog.disposable.IDisposable']); +goog.addDependency('disposable/idisposable.js', ['goog.disposable.IDisposable'], []); +goog.addDependency('dom/a11y.js', ['goog.dom.a11y', 'goog.dom.a11y.Announcer', 'goog.dom.a11y.LivePriority', 'goog.dom.a11y.Role', 'goog.dom.a11y.State'], ['goog.Disposable', 'goog.dom', 'goog.object']); +goog.addDependency('dom/abstractmultirange.js', ['goog.dom.AbstractMultiRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange']); +goog.addDependency('dom/abstractrange.js', ['goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.SavedCaretRange', 'goog.dom.TagIterator', 'goog.userAgent']); +goog.addDependency('dom/annotate.js', ['goog.dom.annotate'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.string']); +goog.addDependency('dom/browserfeature.js', ['goog.dom.BrowserFeature'], ['goog.userAgent']); +goog.addDependency('dom/browserrange/abstractrange.js', ['goog.dom.browserrange.AbstractRange'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter', 'goog.string', 'goog.string.StringBuffer', 'goog.userAgent']); +goog.addDependency('dom/browserrange/browserrange.js', ['goog.dom.browserrange', 'goog.dom.browserrange.Error'], ['goog.dom', 'goog.dom.browserrange.GeckoRange', 'goog.dom.browserrange.IeRange', 'goog.dom.browserrange.OperaRange', 'goog.dom.browserrange.W3cRange', 'goog.dom.browserrange.WebKitRange', 'goog.userAgent']); +goog.addDependency('dom/browserrange/geckorange.js', ['goog.dom.browserrange.GeckoRange'], ['goog.dom.browserrange.W3cRange']); +goog.addDependency('dom/browserrange/ierange.js', ['goog.dom.browserrange.IeRange'], ['goog.array', 'goog.debug.Logger', 'goog.dom', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange.AbstractRange', 'goog.iter', 'goog.iter.StopIteration', 'goog.string']); +goog.addDependency('dom/browserrange/operarange.js', ['goog.dom.browserrange.OperaRange'], ['goog.dom.browserrange.W3cRange']); +goog.addDependency('dom/browserrange/w3crange.js', ['goog.dom.browserrange.W3cRange'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.browserrange.AbstractRange', 'goog.string']); +goog.addDependency('dom/browserrange/webkitrange.js', ['goog.dom.browserrange.WebKitRange'], ['goog.dom.RangeEndpoint', 'goog.dom.browserrange.W3cRange', 'goog.userAgent']); +goog.addDependency('dom/classes.js', ['goog.dom.classes'], ['goog.array']); +goog.addDependency('dom/classes_test.js', ['goog.dom.classes_test'], ['goog.dom', 'goog.dom.classes', 'goog.testing.jsunit']); +goog.addDependency('dom/controlrange.js', ['goog.dom.ControlRange', 'goog.dom.ControlRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagWalkType', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.userAgent']); +goog.addDependency('dom/dataset.js', ['goog.dom.dataset'], ['goog.string']); +goog.addDependency('dom/dom.js', ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType'], ['goog.array', 'goog.dom.BrowserFeature', 'goog.dom.TagName', 'goog.dom.classes', 'goog.math.Coordinate', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.userAgent']); +goog.addDependency('dom/dom_test.js', ['goog.dom.dom_test'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.object', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']); +goog.addDependency('dom/fontsizemonitor.js', ['goog.dom.FontSizeMonitor', 'goog.dom.FontSizeMonitor.EventType'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent']); +goog.addDependency('dom/forms.js', ['goog.dom.forms'], ['goog.structs.Map']); +goog.addDependency('dom/fullscreen.js', ['goog.dom.fullscreen', 'goog.dom.fullscreen.EventType'], ['goog.dom', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('dom/iframe.js', ['goog.dom.iframe'], ['goog.dom']); +goog.addDependency('dom/iter.js', ['goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator'], ['goog.iter.Iterator', 'goog.iter.StopIteration']); +goog.addDependency('dom/multirange.js', ['goog.dom.MultiRange', 'goog.dom.MultiRangeIterator'], ['goog.array', 'goog.debug.Logger', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TextRange', 'goog.iter.StopIteration']); +goog.addDependency('dom/nodeiterator.js', ['goog.dom.NodeIterator'], ['goog.dom.TagIterator']); +goog.addDependency('dom/nodeoffset.js', ['goog.dom.NodeOffset'], ['goog.Disposable', 'goog.dom.TagName']); +goog.addDependency('dom/pattern/abstractpattern.js', ['goog.dom.pattern.AbstractPattern'], ['goog.dom.pattern.MatchType']); +goog.addDependency('dom/pattern/allchildren.js', ['goog.dom.pattern.AllChildren'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']); +goog.addDependency('dom/pattern/callback/callback.js', ['goog.dom.pattern.callback'], ['goog.dom', 'goog.dom.TagWalkType', 'goog.iter']); +goog.addDependency('dom/pattern/callback/counter.js', ['goog.dom.pattern.callback.Counter'], []); +goog.addDependency('dom/pattern/callback/test.js', ['goog.dom.pattern.callback.Test'], ['goog.iter.StopIteration']); +goog.addDependency('dom/pattern/childmatches.js', ['goog.dom.pattern.ChildMatches'], ['goog.dom.pattern.AllChildren', 'goog.dom.pattern.MatchType']); +goog.addDependency('dom/pattern/endtag.js', ['goog.dom.pattern.EndTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag']); +goog.addDependency('dom/pattern/fulltag.js', ['goog.dom.pattern.FullTag'], ['goog.dom.pattern.MatchType', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Tag']); +goog.addDependency('dom/pattern/matcher.js', ['goog.dom.pattern.Matcher'], ['goog.dom.TagIterator', 'goog.dom.pattern.MatchType', 'goog.iter']); +goog.addDependency('dom/pattern/nodetype.js', ['goog.dom.pattern.NodeType'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']); +goog.addDependency('dom/pattern/pattern.js', ['goog.dom.pattern', 'goog.dom.pattern.MatchType'], []); +goog.addDependency('dom/pattern/repeat.js', ['goog.dom.pattern.Repeat'], ['goog.dom.NodeType', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']); +goog.addDependency('dom/pattern/sequence.js', ['goog.dom.pattern.Sequence'], ['goog.dom.NodeType', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']); +goog.addDependency('dom/pattern/starttag.js', ['goog.dom.pattern.StartTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag']); +goog.addDependency('dom/pattern/tag.js', ['goog.dom.pattern.Tag'], ['goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType', 'goog.object']); +goog.addDependency('dom/pattern/text.js', ['goog.dom.pattern.Text'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']); +goog.addDependency('dom/range.js', ['goog.dom.Range'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.ControlRange', 'goog.dom.MultiRange', 'goog.dom.NodeType', 'goog.dom.TextRange', 'goog.userAgent']); +goog.addDependency('dom/rangeendpoint.js', ['goog.dom.RangeEndpoint'], []); +goog.addDependency('dom/savedcaretrange.js', ['goog.dom.SavedCaretRange'], ['goog.array', 'goog.dom', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.string']); +goog.addDependency('dom/savedrange.js', ['goog.dom.SavedRange'], ['goog.Disposable', 'goog.debug.Logger']); +goog.addDependency('dom/selection.js', ['goog.dom.selection'], ['goog.string', 'goog.userAgent']); +goog.addDependency('dom/tagiterator.js', ['goog.dom.TagIterator', 'goog.dom.TagWalkType'], ['goog.dom.NodeType', 'goog.iter.Iterator', 'goog.iter.StopIteration']); +goog.addDependency('dom/tagname.js', ['goog.dom.TagName'], []); +goog.addDependency('dom/textrange.js', ['goog.dom.TextRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.dom.browserrange', 'goog.string', 'goog.userAgent']); +goog.addDependency('dom/textrangeiterator.js', ['goog.dom.TextRangeIterator'], ['goog.array', 'goog.dom.NodeType', 'goog.dom.RangeIterator', 'goog.dom.TagName', 'goog.iter.StopIteration']); +goog.addDependency('dom/viewportsizemonitor.js', ['goog.dom.ViewportSizeMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size', 'goog.userAgent']); +goog.addDependency('dom/xml.js', ['goog.dom.xml'], ['goog.dom', 'goog.dom.NodeType']); +goog.addDependency('editor/browserfeature.js', ['goog.editor.BrowserFeature'], ['goog.editor.defines', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']); +goog.addDependency('editor/clicktoeditwrapper.js', ['goog.editor.ClickToEditWrapper'], ['goog.Disposable', 'goog.asserts', 'goog.debug.Logger', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field.EventType', 'goog.editor.range', 'goog.events.BrowserEvent.MouseButton', 'goog.events.EventHandler', 'goog.events.EventType']); +goog.addDependency('editor/command.js', ['goog.editor.Command'], []); +goog.addDependency('editor/contenteditablefield.js', ['goog.editor.ContentEditableField'], ['goog.asserts', 'goog.debug.Logger', 'goog.editor.Field']); +goog.addDependency('editor/defines.js', ['goog.editor.defines'], []); +goog.addDependency('editor/field.js', ['goog.editor.Field', 'goog.editor.Field.EventType'], ['goog.array', 'goog.async.Delay', 'goog.debug.Logger', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classes', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.editor.range', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('editor/field_test.js', ['goog.editor.field_test'], ['goog.dom.Range', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.events', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.LooseMock', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.recordFunction', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('editor/focus.js', ['goog.editor.focus'], ['goog.dom.selection']); +goog.addDependency('editor/icontent.js', ['goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo'], ['goog.editor.BrowserFeature', 'goog.style', 'goog.userAgent']); +goog.addDependency('editor/link.js', ['goog.editor.Link'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.string.Unicode', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex']); +goog.addDependency('editor/node.js', ['goog.editor.node'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.iter', 'goog.object', 'goog.string', 'goog.string.Unicode']); +goog.addDependency('editor/plugin.js', ['goog.editor.Plugin'], ['goog.debug.Logger', 'goog.editor.Command', 'goog.events.EventTarget', 'goog.functions', 'goog.object', 'goog.reflect']); +goog.addDependency('editor/plugins/abstractbubbleplugin.js', ['goog.editor.plugins.AbstractBubblePlugin'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.style', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.functions', 'goog.string.Unicode', 'goog.ui.Component.EventType', 'goog.ui.editor.Bubble', 'goog.userAgent']); +goog.addDependency('editor/plugins/abstractdialogplugin.js', ['goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.plugins.AbstractDialogPlugin.EventType'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field.EventType', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.ui.editor.AbstractDialog.EventType']); +goog.addDependency('editor/plugins/abstracttabhandler.js', ['goog.editor.plugins.AbstractTabHandler'], ['goog.editor.Plugin', 'goog.events.KeyCodes']); +goog.addDependency('editor/plugins/basictextformatter.js', ['goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.BasicTextFormatter.COMMAND'], ['goog.array', 'goog.debug.Logger', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.editor.style', 'goog.iter', 'goog.iter.StopIteration', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.editor.messages', 'goog.userAgent']); +goog.addDependency('editor/plugins/blockquote.js', ['goog.editor.plugins.Blockquote'], ['goog.debug.Logger', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classes', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions']); +goog.addDependency('editor/plugins/emoticons.js', ['goog.editor.plugins.Emoticons'], ['goog.dom.TagName', 'goog.editor.Plugin', 'goog.functions', 'goog.ui.emoji.Emoji']); +goog.addDependency('editor/plugins/enterhandler.js', ['goog.editor.plugins.EnterHandler'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.Blockquote', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.string', 'goog.userAgent']); +goog.addDependency('editor/plugins/equationeditorbubble.js', ['goog.editor.plugins.equation.EquationBubble'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.string.Unicode', 'goog.ui.editor.Bubble', 'goog.ui.equation.ImageRenderer']); +goog.addDependency('editor/plugins/equationeditorplugin.js', ['goog.editor.plugins.EquationEditorPlugin'], ['goog.editor.Command', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.EquationEditorDialog', 'goog.ui.editor.EquationEditorOkEvent', 'goog.ui.equation.EquationEditor', 'goog.ui.equation.ImageRenderer', 'goog.ui.equation.TexEditor']); +goog.addDependency('editor/plugins/headerformatter.js', ['goog.editor.plugins.HeaderFormatter'], ['goog.editor.Command', 'goog.editor.Plugin', 'goog.userAgent']); +goog.addDependency('editor/plugins/linkbubble.js', ['goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkBubble.Action'], ['goog.array', 'goog.dom', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.editor.range', 'goog.string', 'goog.style', 'goog.ui.editor.messages', 'goog.uri.utils', 'goog.window']); +goog.addDependency('editor/plugins/linkdialogplugin.js', ['goog.editor.plugins.LinkDialogPlugin'], ['goog.array', 'goog.dom', 'goog.editor.Command', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.EventHandler', 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType', 'goog.ui.editor.LinkDialog', 'goog.ui.editor.LinkDialog.EventType', 'goog.ui.editor.LinkDialog.OkEvent', 'goog.uri.utils']); +goog.addDependency('editor/plugins/linkshortcutplugin.js', ['goog.editor.plugins.LinkShortcutPlugin'], ['goog.editor.Command', 'goog.editor.Link', 'goog.editor.Plugin', 'goog.string']); +goog.addDependency('editor/plugins/listtabhandler.js', ['goog.editor.plugins.ListTabHandler'], ['goog.dom.TagName', 'goog.editor.Command', 'goog.editor.plugins.AbstractTabHandler']); +goog.addDependency('editor/plugins/loremipsum.js', ['goog.editor.plugins.LoremIpsum'], ['goog.asserts', 'goog.dom', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions']); +goog.addDependency('editor/plugins/removeformatting.js', ['goog.editor.plugins.RemoveFormatting'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.string']); +goog.addDependency('editor/plugins/spacestabhandler.js', ['goog.editor.plugins.SpacesTabHandler'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.plugins.AbstractTabHandler', 'goog.editor.range']); +goog.addDependency('editor/plugins/tableeditor.js', ['goog.editor.plugins.TableEditor'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.Table', 'goog.editor.node', 'goog.editor.range', 'goog.object']); +goog.addDependency('editor/plugins/tagonenterhandler.js', ['goog.editor.plugins.TagOnEnterHandler'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.string', 'goog.style', 'goog.userAgent']); +goog.addDependency('editor/plugins/undoredo.js', ['goog.editor.plugins.UndoRedo'], ['goog.debug.Logger', 'goog.dom', 'goog.dom.NodeOffset', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field.EventType', 'goog.editor.Plugin', 'goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventHandler']); +goog.addDependency('editor/plugins/undoredomanager.js', ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoManager.EventType'], ['goog.editor.plugins.UndoRedoState', 'goog.events.EventTarget']); +goog.addDependency('editor/plugins/undoredostate.js', ['goog.editor.plugins.UndoRedoState'], ['goog.events.EventTarget']); +goog.addDependency('editor/range.js', ['goog.editor.range', 'goog.editor.range.Point'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.SavedCaretRange', 'goog.editor.BrowserFeature', 'goog.editor.node', 'goog.editor.style', 'goog.iter']); +goog.addDependency('editor/seamlessfield.js', ['goog.editor.SeamlessField'], ['goog.cssom.iframe.style', 'goog.debug.Logger', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.events', 'goog.events.EventType', 'goog.style']); +goog.addDependency('editor/seamlessfield_test.js', ['goog.editor.seamlessfield_test'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.SeamlessField', 'goog.events', 'goog.functions', 'goog.style', 'goog.testing.MockClock', 'goog.testing.MockRange', 'goog.testing.jsunit']); +goog.addDependency('editor/style.js', ['goog.editor.style'], ['goog.dom', 'goog.dom.NodeType', 'goog.editor.BrowserFeature', 'goog.events.EventType', 'goog.object', 'goog.style', 'goog.userAgent']); +goog.addDependency('editor/table.js', ['goog.editor.Table', 'goog.editor.TableCell', 'goog.editor.TableRow'], ['goog.debug.Logger', 'goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.string.Unicode', 'goog.style']); +goog.addDependency('events/actioneventwrapper.js', ['goog.events.actionEventWrapper'], ['goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.EventWrapper', 'goog.events.KeyCodes']); +goog.addDependency('events/actionhandler.js', ['goog.events.ActionEvent', 'goog.events.ActionHandler', 'goog.events.ActionHandler.EventType', 'goog.events.BeforeActionEvent'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent']); +goog.addDependency('events/browserevent.js', ['goog.events.BrowserEvent', 'goog.events.BrowserEvent.MouseButton'], ['goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.reflect', 'goog.userAgent']); +goog.addDependency('events/browserfeature.js', ['goog.events.BrowserFeature'], ['goog.userAgent']); +goog.addDependency('events/event.js', ['goog.events.Event'], ['goog.Disposable']); +goog.addDependency('events/eventhandler.js', ['goog.events.EventHandler'], ['goog.Disposable', 'goog.array', 'goog.events', 'goog.events.EventWrapper']); +goog.addDependency('events/events.js', ['goog.events'], ['goog.array', 'goog.debug.entryPointRegistry', 'goog.debug.errorHandlerWeakDep', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventWrapper', 'goog.events.Listener', 'goog.object', 'goog.userAgent']); +goog.addDependency('events/eventtarget.js', ['goog.events.EventTarget'], ['goog.Disposable', 'goog.events']); +goog.addDependency('events/eventtype.js', ['goog.events.EventType'], ['goog.userAgent']); +goog.addDependency('events/eventwrapper.js', ['goog.events.EventWrapper'], []); +goog.addDependency('events/filedrophandler.js', ['goog.events.FileDropHandler', 'goog.events.FileDropHandler.EventType'], ['goog.array', 'goog.debug.Logger', 'goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType']); +goog.addDependency('events/focushandler.js', ['goog.events.FocusHandler', 'goog.events.FocusHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.userAgent']); +goog.addDependency('events/imehandler.js', ['goog.events.ImeHandler', 'goog.events.ImeHandler.Event', 'goog.events.ImeHandler.EventType'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('events/inputhandler.js', ['goog.events.InputHandler', 'goog.events.InputHandler.EventType'], ['goog.Timer', 'goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.userAgent']); +goog.addDependency('events/keycodes.js', ['goog.events.KeyCodes'], ['goog.userAgent']); +goog.addDependency('events/keyhandler.js', ['goog.events.KeyEvent', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent']); +goog.addDependency('events/keynames.js', ['goog.events.KeyNames'], []); +goog.addDependency('events/listener.js', ['goog.events.Listener'], []); +goog.addDependency('events/mousewheelhandler.js', ['goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.events.MouseWheelHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.math', 'goog.style', 'goog.userAgent']); +goog.addDependency('events/onlinehandler.js', ['goog.events.OnlineHandler', 'goog.events.OnlineHandler.EventType'], ['goog.Timer', 'goog.events.BrowserFeature', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.userAgent']); +goog.addDependency('events/pastehandler.js', ['goog.events.PasteHandler', 'goog.events.PasteHandler.EventType', 'goog.events.PasteHandler.State'], ['goog.Timer', 'goog.async.ConditionalDelay', 'goog.debug.Logger', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes']); +goog.addDependency('format/emailaddress.js', ['goog.format.EmailAddress'], ['goog.string']); +goog.addDependency('format/format.js', ['goog.format'], ['goog.i18n.GraphemeBreak', 'goog.string', 'goog.userAgent']); +goog.addDependency('format/htmlprettyprinter.js', ['goog.format.HtmlPrettyPrinter', 'goog.format.HtmlPrettyPrinter.Buffer'], ['goog.object', 'goog.string.StringBuffer']); +goog.addDependency('format/jsonprettyprinter.js', ['goog.format.JsonPrettyPrinter', 'goog.format.JsonPrettyPrinter.HtmlDelimiters', 'goog.format.JsonPrettyPrinter.TextDelimiters'], ['goog.json', 'goog.json.Serializer', 'goog.string', 'goog.string.StringBuffer', 'goog.string.format']); +goog.addDependency('fs/entry.js', ['goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntry.Behavior', 'goog.fs.Entry', 'goog.fs.FileEntry'], ['goog.array', 'goog.async.Deferred', 'goog.fs.Error', 'goog.fs.FileWriter', 'goog.functions', 'goog.string']); +goog.addDependency('fs/error.js', ['goog.fs.Error', 'goog.fs.Error.ErrorCode'], ['goog.debug.Error', 'goog.string']); +goog.addDependency('fs/filereader.js', ['goog.fs.FileReader', 'goog.fs.FileReader.EventType', 'goog.fs.FileReader.ReadyState'], ['goog.async.Deferred', 'goog.events.Event', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent']); +goog.addDependency('fs/filesaver.js', ['goog.fs.FileSaver', 'goog.fs.FileSaver.EventType', 'goog.fs.FileSaver.ProgressEvent', 'goog.fs.FileSaver.ReadyState'], ['goog.events.Event', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent']); +goog.addDependency('fs/filesystem.js', ['goog.fs.FileSystem'], ['goog.fs.DirectoryEntry']); +goog.addDependency('fs/filewriter.js', ['goog.fs.FileWriter'], ['goog.fs.Error', 'goog.fs.FileSaver']); +goog.addDependency('fs/fs.js', ['goog.fs'], ['goog.async.Deferred', 'goog.events', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSystem', 'goog.userAgent']); +goog.addDependency('fs/progressevent.js', ['goog.fs.ProgressEvent'], ['goog.events.Event']); +goog.addDependency('functions/functions.js', ['goog.functions'], []); +goog.addDependency('fx/abstractdragdrop.js', ['goog.fx.AbstractDragDrop', 'goog.fx.AbstractDragDrop.EventType', 'goog.fx.DragDropEvent', 'goog.fx.DragDropItem'], ['goog.dom', 'goog.dom.classes', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style']); +goog.addDependency('fx/anim/anim.js', ['goog.fx.anim', 'goog.fx.anim.Animated'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.object']); +goog.addDependency('fx/animation.js', ['goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent'], ['goog.array', 'goog.events.Event', 'goog.fx.Transition', 'goog.fx.Transition.EventType', 'goog.fx.TransitionBase.State', 'goog.fx.anim', 'goog.fx.anim.Animated']); +goog.addDependency('fx/animationqueue.js', ['goog.fx.AnimationParallelQueue', 'goog.fx.AnimationQueue', 'goog.fx.AnimationSerialQueue'], ['goog.array', 'goog.asserts', 'goog.events.EventHandler', 'goog.fx.Transition.EventType', 'goog.fx.TransitionBase', 'goog.fx.TransitionBase.State']); +goog.addDependency('fx/css3/fx.js', ['goog.fx.css3'], ['goog.fx.css3.Transition']); +goog.addDependency('fx/css3/transition.js', ['goog.fx.css3.Transition'], ['goog.Timer', 'goog.fx.TransitionBase', 'goog.style', 'goog.style.transition']); +goog.addDependency('fx/cssspriteanimation.js', ['goog.fx.CssSpriteAnimation'], ['goog.fx.Animation']); +goog.addDependency('fx/dom.js', ['goog.fx.dom', 'goog.fx.dom.BgColorTransform', 'goog.fx.dom.ColorTransform', 'goog.fx.dom.Fade', 'goog.fx.dom.FadeIn', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOut', 'goog.fx.dom.FadeOutAndHide', 'goog.fx.dom.PredefinedEffect', 'goog.fx.dom.Resize', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Scroll', 'goog.fx.dom.Slide', 'goog.fx.dom.SlideFrom', 'goog.fx.dom.Swipe'], ['goog.color', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition.EventType', 'goog.style', 'goog.style.bidi']); +goog.addDependency('fx/dragdrop.js', ['goog.fx.DragDrop'], ['goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem']); +goog.addDependency('fx/dragdropgroup.js', ['goog.fx.DragDropGroup'], ['goog.dom', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem']); +goog.addDependency('fx/dragger.js', ['goog.fx.DragEvent', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent.MouseButton', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.style', 'goog.style.bidi', 'goog.userAgent']); +goog.addDependency('fx/draglistgroup.js', ['goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.DragListGroup.EventType', 'goog.fx.DragListGroupEvent'], ['goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classes', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType', 'goog.math.Coordinate', 'goog.style']); +goog.addDependency('fx/dragscrollsupport.js', ['goog.fx.DragScrollSupport'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.style']); +goog.addDependency('fx/easing.js', ['goog.fx.easing'], []); +goog.addDependency('fx/fx.js', ['goog.fx'], ['goog.asserts', 'goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent', 'goog.fx.Transition.EventType', 'goog.fx.easing']); +goog.addDependency('fx/transition.js', ['goog.fx.Transition', 'goog.fx.Transition.EventType'], []); +goog.addDependency('fx/transitionbase.js', ['goog.fx.TransitionBase', 'goog.fx.TransitionBase.State'], ['goog.events.EventTarget', 'goog.fx.Transition', 'goog.fx.Transition.EventType']); +goog.addDependency('gears/basestore.js', ['goog.gears.BaseStore', 'goog.gears.BaseStore.SchemaType'], ['goog.Disposable']); +goog.addDependency('gears/database.js', ['goog.gears.Database', 'goog.gears.Database.EventType', 'goog.gears.Database.TransactionEvent'], ['goog.array', 'goog.debug', 'goog.debug.Logger', 'goog.events.Event', 'goog.events.EventTarget', 'goog.gears', 'goog.json']); +goog.addDependency('gears/gears.js', ['goog.gears'], ['goog.string']); +goog.addDependency('gears/httprequest.js', ['goog.gears.HttpRequest'], ['goog.Timer', 'goog.gears', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttp']); +goog.addDependency('gears/loggerclient.js', ['goog.gears.LoggerClient'], ['goog.Disposable', 'goog.debug', 'goog.debug.Logger']); +goog.addDependency('gears/loggerserver.js', ['goog.gears.LoggerServer'], ['goog.Disposable', 'goog.debug.Logger', 'goog.debug.Logger.Level', 'goog.gears.Worker.EventType']); +goog.addDependency('gears/logstore.js', ['goog.gears.LogStore', 'goog.gears.LogStore.Query'], ['goog.async.Delay', 'goog.debug.LogManager', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.debug.Logger.Level', 'goog.gears.BaseStore', 'goog.gears.BaseStore.SchemaType', 'goog.json']); +goog.addDependency('gears/managedresourcestore.js', ['goog.gears.ManagedResourceStore', 'goog.gears.ManagedResourceStore.EventType', 'goog.gears.ManagedResourceStore.UpdateStatus', 'goog.gears.ManagedResourceStoreEvent'], ['goog.debug.Logger', 'goog.events.Event', 'goog.events.EventTarget', 'goog.gears', 'goog.string']); +goog.addDependency('gears/multipartformdata.js', ['goog.gears.MultipartFormData'], ['goog.asserts', 'goog.gears', 'goog.string']); +goog.addDependency('gears/statustype.js', ['goog.gears.StatusType'], []); +goog.addDependency('gears/urlcapture.js', ['goog.gears.UrlCapture', 'goog.gears.UrlCapture.Event', 'goog.gears.UrlCapture.EventType'], ['goog.Uri', 'goog.debug.Logger', 'goog.events.Event', 'goog.events.EventTarget', 'goog.gears']); +goog.addDependency('gears/worker.js', ['goog.gears.Worker', 'goog.gears.Worker.EventType', 'goog.gears.WorkerEvent'], ['goog.events.Event', 'goog.events.EventTarget']); +goog.addDependency('gears/workerchannel.js', ['goog.gears.WorkerChannel'], ['goog.Disposable', 'goog.debug', 'goog.debug.Logger', 'goog.events', 'goog.gears.Worker', 'goog.gears.Worker.EventType', 'goog.gears.WorkerEvent', 'goog.json', 'goog.messaging.AbstractChannel']); +goog.addDependency('gears/workerpool.js', ['goog.gears.WorkerPool', 'goog.gears.WorkerPool.Event', 'goog.gears.WorkerPool.EventType'], ['goog.events.Event', 'goog.events.EventTarget', 'goog.gears', 'goog.gears.Worker']); +goog.addDependency('graphics/abstractgraphics.js', ['goog.graphics.AbstractGraphics'], ['goog.graphics.Path', 'goog.math.Coordinate', 'goog.math.Size', 'goog.style', 'goog.ui.Component']); +goog.addDependency('graphics/affinetransform.js', ['goog.graphics.AffineTransform'], ['goog.math']); +goog.addDependency('graphics/canvaselement.js', ['goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.Path', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement']); +goog.addDependency('graphics/canvasgraphics.js', ['goog.graphics.CanvasGraphics'], ['goog.dom', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement', 'goog.graphics.Font', 'goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.math.Size']); +goog.addDependency('graphics/element.js', ['goog.graphics.Element'], ['goog.events', 'goog.events.EventTarget', 'goog.graphics.AffineTransform', 'goog.math']); +goog.addDependency('graphics/ellipseelement.js', ['goog.graphics.EllipseElement'], ['goog.graphics.StrokeAndFillElement']); +goog.addDependency('graphics/ext/coordinates.js', ['goog.graphics.ext.coordinates'], ['goog.string']); +goog.addDependency('graphics/ext/element.js', ['goog.graphics.ext.Element'], ['goog.events', 'goog.events.EventTarget', 'goog.functions', 'goog.graphics', 'goog.graphics.ext.coordinates']); +goog.addDependency('graphics/ext/ellipse.js', ['goog.graphics.ext.Ellipse'], ['goog.graphics.ext.StrokeAndFillElement']); +goog.addDependency('graphics/ext/ext.js', ['goog.graphics.ext'], ['goog.graphics.ext.Ellipse', 'goog.graphics.ext.Graphics', 'goog.graphics.ext.Group', 'goog.graphics.ext.Image', 'goog.graphics.ext.Rectangle', 'goog.graphics.ext.Shape', 'goog.graphics.ext.coordinates']); +goog.addDependency('graphics/ext/graphics.js', ['goog.graphics.ext.Graphics'], ['goog.events.EventType', 'goog.graphics.ext.Group']); +goog.addDependency('graphics/ext/group.js', ['goog.graphics.ext.Group'], ['goog.graphics.ext.Element']); +goog.addDependency('graphics/ext/image.js', ['goog.graphics.ext.Image'], ['goog.graphics.ext.Element']); +goog.addDependency('graphics/ext/path.js', ['goog.graphics.ext.Path'], ['goog.graphics.AffineTransform', 'goog.graphics.Path', 'goog.math', 'goog.math.Rect']); +goog.addDependency('graphics/ext/rectangle.js', ['goog.graphics.ext.Rectangle'], ['goog.graphics.ext.StrokeAndFillElement']); +goog.addDependency('graphics/ext/shape.js', ['goog.graphics.ext.Shape'], ['goog.graphics.ext.Path', 'goog.graphics.ext.StrokeAndFillElement', 'goog.math.Rect']); +goog.addDependency('graphics/ext/strokeandfillelement.js', ['goog.graphics.ext.StrokeAndFillElement'], ['goog.graphics.ext.Element']); +goog.addDependency('graphics/fill.js', ['goog.graphics.Fill'], []); +goog.addDependency('graphics/font.js', ['goog.graphics.Font'], []); +goog.addDependency('graphics/graphics.js', ['goog.graphics'], ['goog.graphics.CanvasGraphics', 'goog.graphics.SvgGraphics', 'goog.graphics.VmlGraphics', 'goog.userAgent']); +goog.addDependency('graphics/groupelement.js', ['goog.graphics.GroupElement'], ['goog.graphics.Element']); +goog.addDependency('graphics/imageelement.js', ['goog.graphics.ImageElement'], ['goog.graphics.Element']); +goog.addDependency('graphics/lineargradient.js', ['goog.graphics.LinearGradient'], ['goog.asserts', 'goog.graphics.Fill']); +goog.addDependency('graphics/path.js', ['goog.graphics.Path', 'goog.graphics.Path.Segment'], ['goog.array', 'goog.math']); +goog.addDependency('graphics/pathelement.js', ['goog.graphics.PathElement'], ['goog.graphics.StrokeAndFillElement']); +goog.addDependency('graphics/paths.js', ['goog.graphics.paths'], ['goog.graphics.Path', 'goog.math.Coordinate']); +goog.addDependency('graphics/rectelement.js', ['goog.graphics.RectElement'], ['goog.graphics.StrokeAndFillElement']); +goog.addDependency('graphics/solidfill.js', ['goog.graphics.SolidFill'], ['goog.graphics.Fill']); +goog.addDependency('graphics/stroke.js', ['goog.graphics.Stroke'], []); +goog.addDependency('graphics/strokeandfillelement.js', ['goog.graphics.StrokeAndFillElement'], ['goog.graphics.Element']); +goog.addDependency('graphics/svgelement.js', ['goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement']); +goog.addDependency('graphics/svggraphics.js', ['goog.graphics.SvgGraphics'], ['goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.Font', 'goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement', 'goog.math.Size', 'goog.style', 'goog.userAgent']); +goog.addDependency('graphics/textelement.js', ['goog.graphics.TextElement'], ['goog.graphics.StrokeAndFillElement']); +goog.addDependency('graphics/vmlelement.js', ['goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement']); +goog.addDependency('graphics/vmlgraphics.js', ['goog.graphics.VmlGraphics'], ['goog.array', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.Font', 'goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement', 'goog.math.Size', 'goog.string', 'goog.style']); +goog.addDependency('history/event.js', ['goog.history.Event'], ['goog.events.Event', 'goog.history.EventType']); +goog.addDependency('history/eventtype.js', ['goog.history.EventType'], []); +goog.addDependency('history/history.js', ['goog.History', 'goog.History.Event', 'goog.History.EventType'], ['goog.Timer', 'goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event', 'goog.history.EventType', 'goog.string', 'goog.userAgent']); +goog.addDependency('history/html5history.js', ['goog.history.Html5History', 'goog.history.Html5History.TokenTransformer'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event', 'goog.history.EventType']); +goog.addDependency('i18n/bidi.js', ['goog.i18n.bidi'], []); +goog.addDependency('i18n/bidiformatter.js', ['goog.i18n.BidiFormatter'], ['goog.i18n.bidi', 'goog.string']); +goog.addDependency('i18n/charlistdecompressor.js', ['goog.i18n.CharListDecompressor'], ['goog.array', 'goog.i18n.uChar']); +goog.addDependency('i18n/charpickerdata.js', ['goog.i18n.CharPickerData'], []); +goog.addDependency('i18n/currency.js', ['goog.i18n.currency'], []); +goog.addDependency('i18n/currencycodemap.js', ['goog.i18n.currencyCodeMap', 'goog.i18n.currencyCodeMapTier2'], []); +goog.addDependency('i18n/datetimeformat.js', ['goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeFormat.Format'], ['goog.asserts', 'goog.date.DateLike', 'goog.i18n.DateTimeSymbols', 'goog.i18n.TimeZone', 'goog.string']); +goog.addDependency('i18n/datetimeparse.js', ['goog.i18n.DateTimeParse'], ['goog.date.DateLike', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols']); +goog.addDependency('i18n/datetimepatterns.js', ['goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_af', 'goog.i18n.DateTimePatterns_am', 'goog.i18n.DateTimePatterns_ar', 'goog.i18n.DateTimePatterns_bg', 'goog.i18n.DateTimePatterns_bn', 'goog.i18n.DateTimePatterns_ca', 'goog.i18n.DateTimePatterns_chr', 'goog.i18n.DateTimePatterns_cs', 'goog.i18n.DateTimePatterns_cy', 'goog.i18n.DateTimePatterns_da', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_de_AT', 'goog.i18n.DateTimePatterns_de_CH', 'goog.i18n.DateTimePatterns_el', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_en_AU', 'goog.i18n.DateTimePatterns_en_GB', 'goog.i18n.DateTimePatterns_en_IE', 'goog.i18n.DateTimePatterns_en_IN', 'goog.i18n.DateTimePatterns_en_SG', 'goog.i18n.DateTimePatterns_en_US', 'goog.i18n.DateTimePatterns_en_ZA', 'goog.i18n.DateTimePatterns_es', 'goog.i18n.DateTimePatterns_es_419', 'goog.i18n.DateTimePatterns_et', 'goog.i18n.DateTimePatterns_eu', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fi', 'goog.i18n.DateTimePatterns_fil', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_fr_CA', 'goog.i18n.DateTimePatterns_gl', 'goog.i18n.DateTimePatterns_gsw', 'goog.i18n.DateTimePatterns_gu', 'goog.i18n.DateTimePatterns_haw', 'goog.i18n.DateTimePatterns_he', 'goog.i18n.DateTimePatterns_hi', 'goog.i18n.DateTimePatterns_hr', 'goog.i18n.DateTimePatterns_hu', 'goog.i18n.DateTimePatterns_id', 'goog.i18n.DateTimePatterns_in', 'goog.i18n.DateTimePatterns_is', 'goog.i18n.DateTimePatterns_it', 'goog.i18n.DateTimePatterns_iw', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_kn', 'goog.i18n.DateTimePatterns_ko', 'goog.i18n.DateTimePatterns_ln', 'goog.i18n.DateTimePatterns_lt', 'goog.i18n.DateTimePatterns_lv', 'goog.i18n.DateTimePatterns_ml', 'goog.i18n.DateTimePatterns_mo', 'goog.i18n.DateTimePatterns_mr', 'goog.i18n.DateTimePatterns_ms', 'goog.i18n.DateTimePatterns_mt', 'goog.i18n.DateTimePatterns_nl', 'goog.i18n.DateTimePatterns_no', 'goog.i18n.DateTimePatterns_or', 'goog.i18n.DateTimePatterns_pl', 'goog.i18n.DateTimePatterns_pt', 'goog.i18n.DateTimePatterns_pt_BR', 'goog.i18n.DateTimePatterns_pt_PT', 'goog.i18n.DateTimePatterns_ro', 'goog.i18n.DateTimePatterns_ru', 'goog.i18n.DateTimePatterns_sk', 'goog.i18n.DateTimePatterns_sl', 'goog.i18n.DateTimePatterns_sq', 'goog.i18n.DateTimePatterns_sr', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimePatterns_sw', 'goog.i18n.DateTimePatterns_ta', 'goog.i18n.DateTimePatterns_te', 'goog.i18n.DateTimePatterns_th', 'goog.i18n.DateTimePatterns_tl', 'goog.i18n.DateTimePatterns_tr', 'goog.i18n.DateTimePatterns_uk', 'goog.i18n.DateTimePatterns_ur', 'goog.i18n.DateTimePatterns_vi', 'goog.i18n.DateTimePatterns_zh', 'goog.i18n.DateTimePatterns_zh_CN', 'goog.i18n.DateTimePatterns_zh_HK', 'goog.i18n.DateTimePatterns_zh_TW', 'goog.i18n.DateTimePatterns_zu'], []); +goog.addDependency('i18n/datetimepatternsext.js', ['goog.i18n.DateTimePatternsExt', 'goog.i18n.DateTimePatterns_af_NA', 'goog.i18n.DateTimePatterns_af_ZA', 'goog.i18n.DateTimePatterns_agq', 'goog.i18n.DateTimePatterns_agq_CM', 'goog.i18n.DateTimePatterns_ak', 'goog.i18n.DateTimePatterns_ak_GH', 'goog.i18n.DateTimePatterns_am_ET', 'goog.i18n.DateTimePatterns_ar_AE', 'goog.i18n.DateTimePatterns_ar_BH', 'goog.i18n.DateTimePatterns_ar_DZ', 'goog.i18n.DateTimePatterns_ar_EG', 'goog.i18n.DateTimePatterns_ar_IQ', 'goog.i18n.DateTimePatterns_ar_JO', 'goog.i18n.DateTimePatterns_ar_KW', 'goog.i18n.DateTimePatterns_ar_LB', 'goog.i18n.DateTimePatterns_ar_LY', 'goog.i18n.DateTimePatterns_ar_MA', 'goog.i18n.DateTimePatterns_ar_OM', 'goog.i18n.DateTimePatterns_ar_QA', 'goog.i18n.DateTimePatterns_ar_SA', 'goog.i18n.DateTimePatterns_ar_SD', 'goog.i18n.DateTimePatterns_ar_SY', 'goog.i18n.DateTimePatterns_ar_TN', 'goog.i18n.DateTimePatterns_ar_YE', 'goog.i18n.DateTimePatterns_as', 'goog.i18n.DateTimePatterns_as_IN', 'goog.i18n.DateTimePatterns_asa', 'goog.i18n.DateTimePatterns_asa_TZ', 'goog.i18n.DateTimePatterns_az', 'goog.i18n.DateTimePatterns_az_Cyrl', 'goog.i18n.DateTimePatterns_az_Cyrl_AZ', 'goog.i18n.DateTimePatterns_az_Latn', 'goog.i18n.DateTimePatterns_az_Latn_AZ', 'goog.i18n.DateTimePatterns_bas', 'goog.i18n.DateTimePatterns_bas_CM', 'goog.i18n.DateTimePatterns_be', 'goog.i18n.DateTimePatterns_be_BY', 'goog.i18n.DateTimePatterns_bem', 'goog.i18n.DateTimePatterns_bem_ZM', 'goog.i18n.DateTimePatterns_bez', 'goog.i18n.DateTimePatterns_bez_TZ', 'goog.i18n.DateTimePatterns_bg_BG', 'goog.i18n.DateTimePatterns_bm', 'goog.i18n.DateTimePatterns_bm_ML', 'goog.i18n.DateTimePatterns_bn_BD', 'goog.i18n.DateTimePatterns_bn_IN', 'goog.i18n.DateTimePatterns_bo', 'goog.i18n.DateTimePatterns_bo_CN', 'goog.i18n.DateTimePatterns_bo_IN', 'goog.i18n.DateTimePatterns_br', 'goog.i18n.DateTimePatterns_br_FR', 'goog.i18n.DateTimePatterns_brx', 'goog.i18n.DateTimePatterns_brx_IN', 'goog.i18n.DateTimePatterns_bs', 'goog.i18n.DateTimePatterns_bs_BA', 'goog.i18n.DateTimePatterns_ca_ES', 'goog.i18n.DateTimePatterns_cgg', 'goog.i18n.DateTimePatterns_cgg_UG', 'goog.i18n.DateTimePatterns_chr_US', 'goog.i18n.DateTimePatterns_cs_CZ', 'goog.i18n.DateTimePatterns_cy_GB', 'goog.i18n.DateTimePatterns_da_DK', 'goog.i18n.DateTimePatterns_dav', 'goog.i18n.DateTimePatterns_dav_KE', 'goog.i18n.DateTimePatterns_de_BE', 'goog.i18n.DateTimePatterns_de_DE', 'goog.i18n.DateTimePatterns_de_LI', 'goog.i18n.DateTimePatterns_de_LU', 'goog.i18n.DateTimePatterns_dje', 'goog.i18n.DateTimePatterns_dje_NE', 'goog.i18n.DateTimePatterns_dua', 'goog.i18n.DateTimePatterns_dua_CM', 'goog.i18n.DateTimePatterns_dyo', 'goog.i18n.DateTimePatterns_dyo_SN', 'goog.i18n.DateTimePatterns_ebu', 'goog.i18n.DateTimePatterns_ebu_KE', 'goog.i18n.DateTimePatterns_ee', 'goog.i18n.DateTimePatterns_ee_GH', 'goog.i18n.DateTimePatterns_ee_TG', 'goog.i18n.DateTimePatterns_el_CY', 'goog.i18n.DateTimePatterns_el_GR', 'goog.i18n.DateTimePatterns_en_AS', 'goog.i18n.DateTimePatterns_en_BB', 'goog.i18n.DateTimePatterns_en_BE', 'goog.i18n.DateTimePatterns_en_BM', 'goog.i18n.DateTimePatterns_en_BW', 'goog.i18n.DateTimePatterns_en_BZ', 'goog.i18n.DateTimePatterns_en_CA', 'goog.i18n.DateTimePatterns_en_GU', 'goog.i18n.DateTimePatterns_en_GY', 'goog.i18n.DateTimePatterns_en_HK', 'goog.i18n.DateTimePatterns_en_JM', 'goog.i18n.DateTimePatterns_en_MH', 'goog.i18n.DateTimePatterns_en_MP', 'goog.i18n.DateTimePatterns_en_MT', 'goog.i18n.DateTimePatterns_en_MU', 'goog.i18n.DateTimePatterns_en_NA', 'goog.i18n.DateTimePatterns_en_NZ', 'goog.i18n.DateTimePatterns_en_PH', 'goog.i18n.DateTimePatterns_en_PK', 'goog.i18n.DateTimePatterns_en_TT', 'goog.i18n.DateTimePatterns_en_UM', 'goog.i18n.DateTimePatterns_en_US_POSIX', 'goog.i18n.DateTimePatterns_en_VI', 'goog.i18n.DateTimePatterns_en_ZW', 'goog.i18n.DateTimePatterns_eo', 'goog.i18n.DateTimePatterns_es_AR', 'goog.i18n.DateTimePatterns_es_BO', 'goog.i18n.DateTimePatterns_es_CL', 'goog.i18n.DateTimePatterns_es_CO', 'goog.i18n.DateTimePatterns_es_CR', 'goog.i18n.DateTimePatterns_es_DO', 'goog.i18n.DateTimePatterns_es_EC', 'goog.i18n.DateTimePatterns_es_ES', 'goog.i18n.DateTimePatterns_es_GQ', 'goog.i18n.DateTimePatterns_es_GT', 'goog.i18n.DateTimePatterns_es_HN', 'goog.i18n.DateTimePatterns_es_MX', 'goog.i18n.DateTimePatterns_es_NI', 'goog.i18n.DateTimePatterns_es_PA', 'goog.i18n.DateTimePatterns_es_PE', 'goog.i18n.DateTimePatterns_es_PR', 'goog.i18n.DateTimePatterns_es_PY', 'goog.i18n.DateTimePatterns_es_SV', 'goog.i18n.DateTimePatterns_es_US', 'goog.i18n.DateTimePatterns_es_UY', 'goog.i18n.DateTimePatterns_es_VE', 'goog.i18n.DateTimePatterns_et_EE', 'goog.i18n.DateTimePatterns_eu_ES', 'goog.i18n.DateTimePatterns_ewo', 'goog.i18n.DateTimePatterns_ewo_CM', 'goog.i18n.DateTimePatterns_fa_AF', 'goog.i18n.DateTimePatterns_fa_IR', 'goog.i18n.DateTimePatterns_ff', 'goog.i18n.DateTimePatterns_ff_SN', 'goog.i18n.DateTimePatterns_fi_FI', 'goog.i18n.DateTimePatterns_fil_PH', 'goog.i18n.DateTimePatterns_fo', 'goog.i18n.DateTimePatterns_fo_FO', 'goog.i18n.DateTimePatterns_fr_BE', 'goog.i18n.DateTimePatterns_fr_BF', 'goog.i18n.DateTimePatterns_fr_BI', 'goog.i18n.DateTimePatterns_fr_BJ', 'goog.i18n.DateTimePatterns_fr_BL', 'goog.i18n.DateTimePatterns_fr_CD', 'goog.i18n.DateTimePatterns_fr_CF', 'goog.i18n.DateTimePatterns_fr_CG', 'goog.i18n.DateTimePatterns_fr_CH', 'goog.i18n.DateTimePatterns_fr_CI', 'goog.i18n.DateTimePatterns_fr_CM', 'goog.i18n.DateTimePatterns_fr_DJ', 'goog.i18n.DateTimePatterns_fr_FR', 'goog.i18n.DateTimePatterns_fr_GA', 'goog.i18n.DateTimePatterns_fr_GF', 'goog.i18n.DateTimePatterns_fr_GN', 'goog.i18n.DateTimePatterns_fr_GP', 'goog.i18n.DateTimePatterns_fr_GQ', 'goog.i18n.DateTimePatterns_fr_KM', 'goog.i18n.DateTimePatterns_fr_LU', 'goog.i18n.DateTimePatterns_fr_MC', 'goog.i18n.DateTimePatterns_fr_MF', 'goog.i18n.DateTimePatterns_fr_MG', 'goog.i18n.DateTimePatterns_fr_ML', 'goog.i18n.DateTimePatterns_fr_MQ', 'goog.i18n.DateTimePatterns_fr_NE', 'goog.i18n.DateTimePatterns_fr_RE', 'goog.i18n.DateTimePatterns_fr_RW', 'goog.i18n.DateTimePatterns_fr_SN', 'goog.i18n.DateTimePatterns_fr_TD', 'goog.i18n.DateTimePatterns_fr_TG', 'goog.i18n.DateTimePatterns_fr_YT', 'goog.i18n.DateTimePatterns_ga', 'goog.i18n.DateTimePatterns_ga_IE', 'goog.i18n.DateTimePatterns_gl_ES', 'goog.i18n.DateTimePatterns_gsw_CH', 'goog.i18n.DateTimePatterns_gu_IN', 'goog.i18n.DateTimePatterns_guz', 'goog.i18n.DateTimePatterns_guz_KE', 'goog.i18n.DateTimePatterns_gv', 'goog.i18n.DateTimePatterns_gv_GB', 'goog.i18n.DateTimePatterns_ha', 'goog.i18n.DateTimePatterns_ha_Latn', 'goog.i18n.DateTimePatterns_ha_Latn_GH', 'goog.i18n.DateTimePatterns_ha_Latn_NE', 'goog.i18n.DateTimePatterns_ha_Latn_NG', 'goog.i18n.DateTimePatterns_haw_US', 'goog.i18n.DateTimePatterns_he_IL', 'goog.i18n.DateTimePatterns_hi_IN', 'goog.i18n.DateTimePatterns_hr_HR', 'goog.i18n.DateTimePatterns_hu_HU', 'goog.i18n.DateTimePatterns_hy', 'goog.i18n.DateTimePatterns_hy_AM', 'goog.i18n.DateTimePatterns_id_ID', 'goog.i18n.DateTimePatterns_ig', 'goog.i18n.DateTimePatterns_ig_NG', 'goog.i18n.DateTimePatterns_ii', 'goog.i18n.DateTimePatterns_ii_CN', 'goog.i18n.DateTimePatterns_is_IS', 'goog.i18n.DateTimePatterns_it_CH', 'goog.i18n.DateTimePatterns_it_IT', 'goog.i18n.DateTimePatterns_ja_JP', 'goog.i18n.DateTimePatterns_jmc', 'goog.i18n.DateTimePatterns_jmc_TZ', 'goog.i18n.DateTimePatterns_ka', 'goog.i18n.DateTimePatterns_ka_GE', 'goog.i18n.DateTimePatterns_kab', 'goog.i18n.DateTimePatterns_kab_DZ', 'goog.i18n.DateTimePatterns_kam', 'goog.i18n.DateTimePatterns_kam_KE', 'goog.i18n.DateTimePatterns_kde', 'goog.i18n.DateTimePatterns_kde_TZ', 'goog.i18n.DateTimePatterns_kea', 'goog.i18n.DateTimePatterns_kea_CV', 'goog.i18n.DateTimePatterns_khq', 'goog.i18n.DateTimePatterns_khq_ML', 'goog.i18n.DateTimePatterns_ki', 'goog.i18n.DateTimePatterns_ki_KE', 'goog.i18n.DateTimePatterns_kk', 'goog.i18n.DateTimePatterns_kk_Cyrl', 'goog.i18n.DateTimePatterns_kk_Cyrl_KZ', 'goog.i18n.DateTimePatterns_kl', 'goog.i18n.DateTimePatterns_kl_GL', 'goog.i18n.DateTimePatterns_kln', 'goog.i18n.DateTimePatterns_kln_KE', 'goog.i18n.DateTimePatterns_km', 'goog.i18n.DateTimePatterns_km_KH', 'goog.i18n.DateTimePatterns_kn_IN', 'goog.i18n.DateTimePatterns_ko_KR', 'goog.i18n.DateTimePatterns_kok', 'goog.i18n.DateTimePatterns_kok_IN', 'goog.i18n.DateTimePatterns_ksb', 'goog.i18n.DateTimePatterns_ksb_TZ', 'goog.i18n.DateTimePatterns_ksf', 'goog.i18n.DateTimePatterns_ksf_CM', 'goog.i18n.DateTimePatterns_kw', 'goog.i18n.DateTimePatterns_kw_GB', 'goog.i18n.DateTimePatterns_lag', 'goog.i18n.DateTimePatterns_lag_TZ', 'goog.i18n.DateTimePatterns_lg', 'goog.i18n.DateTimePatterns_lg_UG', 'goog.i18n.DateTimePatterns_ln_CD', 'goog.i18n.DateTimePatterns_ln_CG', 'goog.i18n.DateTimePatterns_lt_LT', 'goog.i18n.DateTimePatterns_lu', 'goog.i18n.DateTimePatterns_lu_CD', 'goog.i18n.DateTimePatterns_luo', 'goog.i18n.DateTimePatterns_luo_KE', 'goog.i18n.DateTimePatterns_luy', 'goog.i18n.DateTimePatterns_luy_KE', 'goog.i18n.DateTimePatterns_lv_LV', 'goog.i18n.DateTimePatterns_mas', 'goog.i18n.DateTimePatterns_mas_KE', 'goog.i18n.DateTimePatterns_mas_TZ', 'goog.i18n.DateTimePatterns_mer', 'goog.i18n.DateTimePatterns_mer_KE', 'goog.i18n.DateTimePatterns_mfe', 'goog.i18n.DateTimePatterns_mfe_MU', 'goog.i18n.DateTimePatterns_mg', 'goog.i18n.DateTimePatterns_mg_MG', 'goog.i18n.DateTimePatterns_mgh', 'goog.i18n.DateTimePatterns_mgh_MZ', 'goog.i18n.DateTimePatterns_mk', 'goog.i18n.DateTimePatterns_mk_MK', 'goog.i18n.DateTimePatterns_ml_IN', 'goog.i18n.DateTimePatterns_mr_IN', 'goog.i18n.DateTimePatterns_ms_BN', 'goog.i18n.DateTimePatterns_ms_MY', 'goog.i18n.DateTimePatterns_mt_MT', 'goog.i18n.DateTimePatterns_mua', 'goog.i18n.DateTimePatterns_mua_CM', 'goog.i18n.DateTimePatterns_my', 'goog.i18n.DateTimePatterns_my_MM', 'goog.i18n.DateTimePatterns_naq', 'goog.i18n.DateTimePatterns_naq_NA', 'goog.i18n.DateTimePatterns_nb', 'goog.i18n.DateTimePatterns_nb_NO', 'goog.i18n.DateTimePatterns_nd', 'goog.i18n.DateTimePatterns_nd_ZW', 'goog.i18n.DateTimePatterns_ne', 'goog.i18n.DateTimePatterns_ne_IN', 'goog.i18n.DateTimePatterns_ne_NP', 'goog.i18n.DateTimePatterns_nl_AW', 'goog.i18n.DateTimePatterns_nl_BE', 'goog.i18n.DateTimePatterns_nl_NL', 'goog.i18n.DateTimePatterns_nmg', 'goog.i18n.DateTimePatterns_nmg_CM', 'goog.i18n.DateTimePatterns_nn', 'goog.i18n.DateTimePatterns_nn_NO', 'goog.i18n.DateTimePatterns_nus', 'goog.i18n.DateTimePatterns_nus_SD', 'goog.i18n.DateTimePatterns_nyn', 'goog.i18n.DateTimePatterns_nyn_UG', 'goog.i18n.DateTimePatterns_om', 'goog.i18n.DateTimePatterns_om_ET', 'goog.i18n.DateTimePatterns_om_KE', 'goog.i18n.DateTimePatterns_or_IN', 'goog.i18n.DateTimePatterns_pa', 'goog.i18n.DateTimePatterns_pa_Arab', 'goog.i18n.DateTimePatterns_pa_Arab_PK', 'goog.i18n.DateTimePatterns_pa_Guru', 'goog.i18n.DateTimePatterns_pa_Guru_IN', 'goog.i18n.DateTimePatterns_pl_PL', 'goog.i18n.DateTimePatterns_ps', 'goog.i18n.DateTimePatterns_ps_AF', 'goog.i18n.DateTimePatterns_pt_AO', 'goog.i18n.DateTimePatterns_pt_GW', 'goog.i18n.DateTimePatterns_pt_MZ', 'goog.i18n.DateTimePatterns_pt_ST', 'goog.i18n.DateTimePatterns_rm', 'goog.i18n.DateTimePatterns_rm_CH', 'goog.i18n.DateTimePatterns_rn', 'goog.i18n.DateTimePatterns_rn_BI', 'goog.i18n.DateTimePatterns_ro_MD', 'goog.i18n.DateTimePatterns_ro_RO', 'goog.i18n.DateTimePatterns_rof', 'goog.i18n.DateTimePatterns_rof_TZ', 'goog.i18n.DateTimePatterns_ru_MD', 'goog.i18n.DateTimePatterns_ru_RU', 'goog.i18n.DateTimePatterns_ru_UA', 'goog.i18n.DateTimePatterns_rw', 'goog.i18n.DateTimePatterns_rw_RW', 'goog.i18n.DateTimePatterns_rwk', 'goog.i18n.DateTimePatterns_rwk_TZ', 'goog.i18n.DateTimePatterns_saq', 'goog.i18n.DateTimePatterns_saq_KE', 'goog.i18n.DateTimePatterns_sbp', 'goog.i18n.DateTimePatterns_sbp_TZ', 'goog.i18n.DateTimePatterns_seh', 'goog.i18n.DateTimePatterns_seh_MZ', 'goog.i18n.DateTimePatterns_ses', 'goog.i18n.DateTimePatterns_ses_ML', 'goog.i18n.DateTimePatterns_sg', 'goog.i18n.DateTimePatterns_sg_CF', 'goog.i18n.DateTimePatterns_shi', 'goog.i18n.DateTimePatterns_shi_Latn', 'goog.i18n.DateTimePatterns_shi_Latn_MA', 'goog.i18n.DateTimePatterns_shi_Tfng', 'goog.i18n.DateTimePatterns_shi_Tfng_MA', 'goog.i18n.DateTimePatterns_si', 'goog.i18n.DateTimePatterns_si_LK', 'goog.i18n.DateTimePatterns_sk_SK', 'goog.i18n.DateTimePatterns_sl_SI', 'goog.i18n.DateTimePatterns_sn', 'goog.i18n.DateTimePatterns_sn_ZW', 'goog.i18n.DateTimePatterns_so', 'goog.i18n.DateTimePatterns_so_DJ', 'goog.i18n.DateTimePatterns_so_ET', 'goog.i18n.DateTimePatterns_so_KE', 'goog.i18n.DateTimePatterns_so_SO', 'goog.i18n.DateTimePatterns_sq_AL', 'goog.i18n.DateTimePatterns_sr_Cyrl', 'goog.i18n.DateTimePatterns_sr_Cyrl_BA', 'goog.i18n.DateTimePatterns_sr_Cyrl_ME', 'goog.i18n.DateTimePatterns_sr_Cyrl_RS', 'goog.i18n.DateTimePatterns_sr_Latn', 'goog.i18n.DateTimePatterns_sr_Latn_BA', 'goog.i18n.DateTimePatterns_sr_Latn_ME', 'goog.i18n.DateTimePatterns_sr_Latn_RS', 'goog.i18n.DateTimePatterns_sv_FI', 'goog.i18n.DateTimePatterns_sv_SE', 'goog.i18n.DateTimePatterns_sw_KE', 'goog.i18n.DateTimePatterns_sw_TZ', 'goog.i18n.DateTimePatterns_swc', 'goog.i18n.DateTimePatterns_swc_CD', 'goog.i18n.DateTimePatterns_ta_IN', 'goog.i18n.DateTimePatterns_ta_LK', 'goog.i18n.DateTimePatterns_te_IN', 'goog.i18n.DateTimePatterns_teo', 'goog.i18n.DateTimePatterns_teo_KE', 'goog.i18n.DateTimePatterns_teo_UG', 'goog.i18n.DateTimePatterns_th_TH', 'goog.i18n.DateTimePatterns_ti', 'goog.i18n.DateTimePatterns_ti_ER', 'goog.i18n.DateTimePatterns_ti_ET', 'goog.i18n.DateTimePatterns_to', 'goog.i18n.DateTimePatterns_to_TO', 'goog.i18n.DateTimePatterns_tr_TR', 'goog.i18n.DateTimePatterns_twq', 'goog.i18n.DateTimePatterns_twq_NE', 'goog.i18n.DateTimePatterns_tzm', 'goog.i18n.DateTimePatterns_tzm_Latn', 'goog.i18n.DateTimePatterns_tzm_Latn_MA', 'goog.i18n.DateTimePatterns_uk_UA', 'goog.i18n.DateTimePatterns_ur_IN', 'goog.i18n.DateTimePatterns_ur_PK', 'goog.i18n.DateTimePatterns_uz', 'goog.i18n.DateTimePatterns_uz_Arab', 'goog.i18n.DateTimePatterns_uz_Arab_AF', 'goog.i18n.DateTimePatterns_uz_Cyrl', 'goog.i18n.DateTimePatterns_uz_Cyrl_UZ', 'goog.i18n.DateTimePatterns_uz_Latn', 'goog.i18n.DateTimePatterns_uz_Latn_UZ', 'goog.i18n.DateTimePatterns_vai', 'goog.i18n.DateTimePatterns_vai_Latn', 'goog.i18n.DateTimePatterns_vai_Latn_LR', 'goog.i18n.DateTimePatterns_vai_Vaii', 'goog.i18n.DateTimePatterns_vai_Vaii_LR', 'goog.i18n.DateTimePatterns_vi_VN', 'goog.i18n.DateTimePatterns_vun', 'goog.i18n.DateTimePatterns_vun_TZ', 'goog.i18n.DateTimePatterns_xog', 'goog.i18n.DateTimePatterns_xog_UG', 'goog.i18n.DateTimePatterns_yav', 'goog.i18n.DateTimePatterns_yav_CM', 'goog.i18n.DateTimePatterns_yo', 'goog.i18n.DateTimePatterns_yo_NG', 'goog.i18n.DateTimePatterns_zh_Hans', 'goog.i18n.DateTimePatterns_zh_Hans_CN', 'goog.i18n.DateTimePatterns_zh_Hans_HK', 'goog.i18n.DateTimePatterns_zh_Hans_MO', 'goog.i18n.DateTimePatterns_zh_Hans_SG', 'goog.i18n.DateTimePatterns_zh_Hant', 'goog.i18n.DateTimePatterns_zh_Hant_HK', 'goog.i18n.DateTimePatterns_zh_Hant_MO', 'goog.i18n.DateTimePatterns_zh_Hant_TW', 'goog.i18n.DateTimePatterns_zu_ZA'], ['goog.i18n.DateTimePatterns']); +goog.addDependency('i18n/datetimesymbols.js', ['goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_af', 'goog.i18n.DateTimeSymbols_am', 'goog.i18n.DateTimeSymbols_ar', 'goog.i18n.DateTimeSymbols_bg', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_ca', 'goog.i18n.DateTimeSymbols_chr', 'goog.i18n.DateTimeSymbols_cs', 'goog.i18n.DateTimeSymbols_cy', 'goog.i18n.DateTimeSymbols_da', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_de_AT', 'goog.i18n.DateTimeSymbols_de_CH', 'goog.i18n.DateTimeSymbols_el', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_AU', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_ISO', 'goog.i18n.DateTimeSymbols_en_SG', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_en_ZA', 'goog.i18n.DateTimeSymbols_es', 'goog.i18n.DateTimeSymbols_es_419', 'goog.i18n.DateTimeSymbols_et', 'goog.i18n.DateTimeSymbols_eu', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fi', 'goog.i18n.DateTimeSymbols_fil', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_CA', 'goog.i18n.DateTimeSymbols_gl', 'goog.i18n.DateTimeSymbols_gsw', 'goog.i18n.DateTimeSymbols_gu', 'goog.i18n.DateTimeSymbols_haw', 'goog.i18n.DateTimeSymbols_he', 'goog.i18n.DateTimeSymbols_hi', 'goog.i18n.DateTimeSymbols_hr', 'goog.i18n.DateTimeSymbols_hu', 'goog.i18n.DateTimeSymbols_id', 'goog.i18n.DateTimeSymbols_in', 'goog.i18n.DateTimeSymbols_is', 'goog.i18n.DateTimeSymbols_it', 'goog.i18n.DateTimeSymbols_iw', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_kn', 'goog.i18n.DateTimeSymbols_ko', 'goog.i18n.DateTimeSymbols_ln', 'goog.i18n.DateTimeSymbols_lt', 'goog.i18n.DateTimeSymbols_lv', 'goog.i18n.DateTimeSymbols_ml', 'goog.i18n.DateTimeSymbols_mr', 'goog.i18n.DateTimeSymbols_ms', 'goog.i18n.DateTimeSymbols_mt', 'goog.i18n.DateTimeSymbols_nl', 'goog.i18n.DateTimeSymbols_no', 'goog.i18n.DateTimeSymbols_or', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_pt', 'goog.i18n.DateTimeSymbols_pt_BR', 'goog.i18n.DateTimeSymbols_pt_PT', 'goog.i18n.DateTimeSymbols_ro', 'goog.i18n.DateTimeSymbols_ru', 'goog.i18n.DateTimeSymbols_sk', 'goog.i18n.DateTimeSymbols_sl', 'goog.i18n.DateTimeSymbols_sq', 'goog.i18n.DateTimeSymbols_sr', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.DateTimeSymbols_sw', 'goog.i18n.DateTimeSymbols_ta', 'goog.i18n.DateTimeSymbols_te', 'goog.i18n.DateTimeSymbols_th', 'goog.i18n.DateTimeSymbols_tl', 'goog.i18n.DateTimeSymbols_tr', 'goog.i18n.DateTimeSymbols_uk', 'goog.i18n.DateTimeSymbols_ur', 'goog.i18n.DateTimeSymbols_vi', 'goog.i18n.DateTimeSymbols_zh', 'goog.i18n.DateTimeSymbols_zh_CN', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.i18n.DateTimeSymbols_zh_TW', 'goog.i18n.DateTimeSymbols_zu'], []); +goog.addDependency('i18n/datetimesymbolsext.js', ['goog.i18n.DateTimeSymbolsExt', 'goog.i18n.DateTimeSymbols_aa', 'goog.i18n.DateTimeSymbols_aa_DJ', 'goog.i18n.DateTimeSymbols_aa_ER', 'goog.i18n.DateTimeSymbols_aa_ET', 'goog.i18n.DateTimeSymbols_af_NA', 'goog.i18n.DateTimeSymbols_af_ZA', 'goog.i18n.DateTimeSymbols_agq', 'goog.i18n.DateTimeSymbols_agq_CM', 'goog.i18n.DateTimeSymbols_ak', 'goog.i18n.DateTimeSymbols_ak_GH', 'goog.i18n.DateTimeSymbols_am_ET', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_BH', 'goog.i18n.DateTimeSymbols_ar_DZ', 'goog.i18n.DateTimeSymbols_ar_EG', 'goog.i18n.DateTimeSymbols_ar_IQ', 'goog.i18n.DateTimeSymbols_ar_JO', 'goog.i18n.DateTimeSymbols_ar_KW', 'goog.i18n.DateTimeSymbols_ar_LB', 'goog.i18n.DateTimeSymbols_ar_LY', 'goog.i18n.DateTimeSymbols_ar_MA', 'goog.i18n.DateTimeSymbols_ar_OM', 'goog.i18n.DateTimeSymbols_ar_QA', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_ar_SD', 'goog.i18n.DateTimeSymbols_ar_SY', 'goog.i18n.DateTimeSymbols_ar_TN', 'goog.i18n.DateTimeSymbols_ar_YE', 'goog.i18n.DateTimeSymbols_as', 'goog.i18n.DateTimeSymbols_as_IN', 'goog.i18n.DateTimeSymbols_asa', 'goog.i18n.DateTimeSymbols_asa_TZ', 'goog.i18n.DateTimeSymbols_az', 'goog.i18n.DateTimeSymbols_az_Cyrl', 'goog.i18n.DateTimeSymbols_az_Cyrl_AZ', 'goog.i18n.DateTimeSymbols_az_Latn', 'goog.i18n.DateTimeSymbols_az_Latn_AZ', 'goog.i18n.DateTimeSymbols_bas', 'goog.i18n.DateTimeSymbols_bas_CM', 'goog.i18n.DateTimeSymbols_be', 'goog.i18n.DateTimeSymbols_be_BY', 'goog.i18n.DateTimeSymbols_bem', 'goog.i18n.DateTimeSymbols_bem_ZM', 'goog.i18n.DateTimeSymbols_bez', 'goog.i18n.DateTimeSymbols_bez_TZ', 'goog.i18n.DateTimeSymbols_bg_BG', 'goog.i18n.DateTimeSymbols_bm', 'goog.i18n.DateTimeSymbols_bm_ML', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_bn_IN', 'goog.i18n.DateTimeSymbols_bo', 'goog.i18n.DateTimeSymbols_bo_CN', 'goog.i18n.DateTimeSymbols_bo_IN', 'goog.i18n.DateTimeSymbols_br', 'goog.i18n.DateTimeSymbols_br_FR', 'goog.i18n.DateTimeSymbols_brx', 'goog.i18n.DateTimeSymbols_brx_IN', 'goog.i18n.DateTimeSymbols_bs', 'goog.i18n.DateTimeSymbols_bs_BA', 'goog.i18n.DateTimeSymbols_byn', 'goog.i18n.DateTimeSymbols_byn_ER', 'goog.i18n.DateTimeSymbols_ca_ES', 'goog.i18n.DateTimeSymbols_cgg', 'goog.i18n.DateTimeSymbols_cgg_UG', 'goog.i18n.DateTimeSymbols_chr_US', 'goog.i18n.DateTimeSymbols_ckb', 'goog.i18n.DateTimeSymbols_ckb_Arab', 'goog.i18n.DateTimeSymbols_ckb_Arab_IQ', 'goog.i18n.DateTimeSymbols_ckb_Arab_IR', 'goog.i18n.DateTimeSymbols_ckb_IQ', 'goog.i18n.DateTimeSymbols_ckb_IR', 'goog.i18n.DateTimeSymbols_ckb_Latn', 'goog.i18n.DateTimeSymbols_ckb_Latn_IQ', 'goog.i18n.DateTimeSymbols_cs_CZ', 'goog.i18n.DateTimeSymbols_cy_GB', 'goog.i18n.DateTimeSymbols_da_DK', 'goog.i18n.DateTimeSymbols_dav', 'goog.i18n.DateTimeSymbols_dav_KE', 'goog.i18n.DateTimeSymbols_de_BE', 'goog.i18n.DateTimeSymbols_de_DE', 'goog.i18n.DateTimeSymbols_de_LI', 'goog.i18n.DateTimeSymbols_de_LU', 'goog.i18n.DateTimeSymbols_dje', 'goog.i18n.DateTimeSymbols_dje_NE', 'goog.i18n.DateTimeSymbols_dua', 'goog.i18n.DateTimeSymbols_dua_CM', 'goog.i18n.DateTimeSymbols_dyo', 'goog.i18n.DateTimeSymbols_dyo_SN', 'goog.i18n.DateTimeSymbols_dz', 'goog.i18n.DateTimeSymbols_dz_BT', 'goog.i18n.DateTimeSymbols_ebu', 'goog.i18n.DateTimeSymbols_ebu_KE', 'goog.i18n.DateTimeSymbols_ee', 'goog.i18n.DateTimeSymbols_ee_GH', 'goog.i18n.DateTimeSymbols_ee_TG', 'goog.i18n.DateTimeSymbols_el_CY', 'goog.i18n.DateTimeSymbols_el_GR', 'goog.i18n.DateTimeSymbols_en_AS', 'goog.i18n.DateTimeSymbols_en_BB', 'goog.i18n.DateTimeSymbols_en_BE', 'goog.i18n.DateTimeSymbols_en_BM', 'goog.i18n.DateTimeSymbols_en_BW', 'goog.i18n.DateTimeSymbols_en_BZ', 'goog.i18n.DateTimeSymbols_en_CA', 'goog.i18n.DateTimeSymbols_en_Dsrt', 'goog.i18n.DateTimeSymbols_en_Dsrt_US', 'goog.i18n.DateTimeSymbols_en_GU', 'goog.i18n.DateTimeSymbols_en_GY', 'goog.i18n.DateTimeSymbols_en_HK', 'goog.i18n.DateTimeSymbols_en_JM', 'goog.i18n.DateTimeSymbols_en_MH', 'goog.i18n.DateTimeSymbols_en_MP', 'goog.i18n.DateTimeSymbols_en_MT', 'goog.i18n.DateTimeSymbols_en_MU', 'goog.i18n.DateTimeSymbols_en_NA', 'goog.i18n.DateTimeSymbols_en_NZ', 'goog.i18n.DateTimeSymbols_en_PH', 'goog.i18n.DateTimeSymbols_en_PK', 'goog.i18n.DateTimeSymbols_en_TT', 'goog.i18n.DateTimeSymbols_en_UM', 'goog.i18n.DateTimeSymbols_en_VI', 'goog.i18n.DateTimeSymbols_en_ZW', 'goog.i18n.DateTimeSymbols_eo', 'goog.i18n.DateTimeSymbols_es_AR', 'goog.i18n.DateTimeSymbols_es_BO', 'goog.i18n.DateTimeSymbols_es_CL', 'goog.i18n.DateTimeSymbols_es_CO', 'goog.i18n.DateTimeSymbols_es_CR', 'goog.i18n.DateTimeSymbols_es_DO', 'goog.i18n.DateTimeSymbols_es_EC', 'goog.i18n.DateTimeSymbols_es_ES', 'goog.i18n.DateTimeSymbols_es_GQ', 'goog.i18n.DateTimeSymbols_es_GT', 'goog.i18n.DateTimeSymbols_es_HN', 'goog.i18n.DateTimeSymbols_es_MX', 'goog.i18n.DateTimeSymbols_es_NI', 'goog.i18n.DateTimeSymbols_es_PA', 'goog.i18n.DateTimeSymbols_es_PE', 'goog.i18n.DateTimeSymbols_es_PR', 'goog.i18n.DateTimeSymbols_es_PY', 'goog.i18n.DateTimeSymbols_es_SV', 'goog.i18n.DateTimeSymbols_es_US', 'goog.i18n.DateTimeSymbols_es_UY', 'goog.i18n.DateTimeSymbols_es_VE', 'goog.i18n.DateTimeSymbols_et_EE', 'goog.i18n.DateTimeSymbols_eu_ES', 'goog.i18n.DateTimeSymbols_ewo', 'goog.i18n.DateTimeSymbols_ewo_CM', 'goog.i18n.DateTimeSymbols_fa_AF', 'goog.i18n.DateTimeSymbols_fa_IR', 'goog.i18n.DateTimeSymbols_ff', 'goog.i18n.DateTimeSymbols_ff_SN', 'goog.i18n.DateTimeSymbols_fi_FI', 'goog.i18n.DateTimeSymbols_fil_PH', 'goog.i18n.DateTimeSymbols_fo', 'goog.i18n.DateTimeSymbols_fo_FO', 'goog.i18n.DateTimeSymbols_fr_BE', 'goog.i18n.DateTimeSymbols_fr_BF', 'goog.i18n.DateTimeSymbols_fr_BI', 'goog.i18n.DateTimeSymbols_fr_BJ', 'goog.i18n.DateTimeSymbols_fr_BL', 'goog.i18n.DateTimeSymbols_fr_CD', 'goog.i18n.DateTimeSymbols_fr_CF', 'goog.i18n.DateTimeSymbols_fr_CG', 'goog.i18n.DateTimeSymbols_fr_CH', 'goog.i18n.DateTimeSymbols_fr_CI', 'goog.i18n.DateTimeSymbols_fr_CM', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_fr_FR', 'goog.i18n.DateTimeSymbols_fr_GA', 'goog.i18n.DateTimeSymbols_fr_GF', 'goog.i18n.DateTimeSymbols_fr_GN', 'goog.i18n.DateTimeSymbols_fr_GP', 'goog.i18n.DateTimeSymbols_fr_GQ', 'goog.i18n.DateTimeSymbols_fr_KM', 'goog.i18n.DateTimeSymbols_fr_LU', 'goog.i18n.DateTimeSymbols_fr_MC', 'goog.i18n.DateTimeSymbols_fr_MF', 'goog.i18n.DateTimeSymbols_fr_MG', 'goog.i18n.DateTimeSymbols_fr_ML', 'goog.i18n.DateTimeSymbols_fr_MQ', 'goog.i18n.DateTimeSymbols_fr_NE', 'goog.i18n.DateTimeSymbols_fr_RE', 'goog.i18n.DateTimeSymbols_fr_RW', 'goog.i18n.DateTimeSymbols_fr_SN', 'goog.i18n.DateTimeSymbols_fr_TD', 'goog.i18n.DateTimeSymbols_fr_TG', 'goog.i18n.DateTimeSymbols_fr_YT', 'goog.i18n.DateTimeSymbols_fur', 'goog.i18n.DateTimeSymbols_fur_IT', 'goog.i18n.DateTimeSymbols_ga', 'goog.i18n.DateTimeSymbols_ga_IE', 'goog.i18n.DateTimeSymbols_gl_ES', 'goog.i18n.DateTimeSymbols_gsw_CH', 'goog.i18n.DateTimeSymbols_gu_IN', 'goog.i18n.DateTimeSymbols_guz', 'goog.i18n.DateTimeSymbols_guz_KE', 'goog.i18n.DateTimeSymbols_gv', 'goog.i18n.DateTimeSymbols_gv_GB', 'goog.i18n.DateTimeSymbols_ha', 'goog.i18n.DateTimeSymbols_ha_Latn', 'goog.i18n.DateTimeSymbols_ha_Latn_GH', 'goog.i18n.DateTimeSymbols_ha_Latn_NE', 'goog.i18n.DateTimeSymbols_ha_Latn_NG', 'goog.i18n.DateTimeSymbols_haw_US', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_hi_IN', 'goog.i18n.DateTimeSymbols_hr_HR', 'goog.i18n.DateTimeSymbols_hu_HU', 'goog.i18n.DateTimeSymbols_hy', 'goog.i18n.DateTimeSymbols_hy_AM', 'goog.i18n.DateTimeSymbols_ia', 'goog.i18n.DateTimeSymbols_id_ID', 'goog.i18n.DateTimeSymbols_ig', 'goog.i18n.DateTimeSymbols_ig_NG', 'goog.i18n.DateTimeSymbols_ii', 'goog.i18n.DateTimeSymbols_ii_CN', 'goog.i18n.DateTimeSymbols_is_IS', 'goog.i18n.DateTimeSymbols_it_CH', 'goog.i18n.DateTimeSymbols_it_IT', 'goog.i18n.DateTimeSymbols_ja_JP', 'goog.i18n.DateTimeSymbols_jmc', 'goog.i18n.DateTimeSymbols_jmc_TZ', 'goog.i18n.DateTimeSymbols_ka', 'goog.i18n.DateTimeSymbols_ka_GE', 'goog.i18n.DateTimeSymbols_kab', 'goog.i18n.DateTimeSymbols_kab_DZ', 'goog.i18n.DateTimeSymbols_kam', 'goog.i18n.DateTimeSymbols_kam_KE', 'goog.i18n.DateTimeSymbols_kde', 'goog.i18n.DateTimeSymbols_kde_TZ', 'goog.i18n.DateTimeSymbols_kea', 'goog.i18n.DateTimeSymbols_kea_CV', 'goog.i18n.DateTimeSymbols_khq', 'goog.i18n.DateTimeSymbols_khq_ML', 'goog.i18n.DateTimeSymbols_ki', 'goog.i18n.DateTimeSymbols_ki_KE', 'goog.i18n.DateTimeSymbols_kk', 'goog.i18n.DateTimeSymbols_kk_Cyrl', 'goog.i18n.DateTimeSymbols_kk_Cyrl_KZ', 'goog.i18n.DateTimeSymbols_kl', 'goog.i18n.DateTimeSymbols_kl_GL', 'goog.i18n.DateTimeSymbols_kln', 'goog.i18n.DateTimeSymbols_kln_KE', 'goog.i18n.DateTimeSymbols_km', 'goog.i18n.DateTimeSymbols_km_KH', 'goog.i18n.DateTimeSymbols_kn_IN', 'goog.i18n.DateTimeSymbols_ko_KR', 'goog.i18n.DateTimeSymbols_kok', 'goog.i18n.DateTimeSymbols_kok_IN', 'goog.i18n.DateTimeSymbols_ksb', 'goog.i18n.DateTimeSymbols_ksb_TZ', 'goog.i18n.DateTimeSymbols_ksf', 'goog.i18n.DateTimeSymbols_ksf_CM', 'goog.i18n.DateTimeSymbols_ksh', 'goog.i18n.DateTimeSymbols_ksh_DE', 'goog.i18n.DateTimeSymbols_ku', 'goog.i18n.DateTimeSymbols_kw', 'goog.i18n.DateTimeSymbols_kw_GB', 'goog.i18n.DateTimeSymbols_lag', 'goog.i18n.DateTimeSymbols_lag_TZ', 'goog.i18n.DateTimeSymbols_lg', 'goog.i18n.DateTimeSymbols_lg_UG', 'goog.i18n.DateTimeSymbols_ln_CD', 'goog.i18n.DateTimeSymbols_ln_CG', 'goog.i18n.DateTimeSymbols_lo', 'goog.i18n.DateTimeSymbols_lo_LA', 'goog.i18n.DateTimeSymbols_lt_LT', 'goog.i18n.DateTimeSymbols_lu', 'goog.i18n.DateTimeSymbols_lu_CD', 'goog.i18n.DateTimeSymbols_luo', 'goog.i18n.DateTimeSymbols_luo_KE', 'goog.i18n.DateTimeSymbols_luy', 'goog.i18n.DateTimeSymbols_luy_KE', 'goog.i18n.DateTimeSymbols_lv_LV', 'goog.i18n.DateTimeSymbols_mas', 'goog.i18n.DateTimeSymbols_mas_KE', 'goog.i18n.DateTimeSymbols_mas_TZ', 'goog.i18n.DateTimeSymbols_mer', 'goog.i18n.DateTimeSymbols_mer_KE', 'goog.i18n.DateTimeSymbols_mfe', 'goog.i18n.DateTimeSymbols_mfe_MU', 'goog.i18n.DateTimeSymbols_mg', 'goog.i18n.DateTimeSymbols_mg_MG', 'goog.i18n.DateTimeSymbols_mgh', 'goog.i18n.DateTimeSymbols_mgh_MZ', 'goog.i18n.DateTimeSymbols_mk', 'goog.i18n.DateTimeSymbols_mk_MK', 'goog.i18n.DateTimeSymbols_ml_IN', 'goog.i18n.DateTimeSymbols_mr_IN', 'goog.i18n.DateTimeSymbols_ms_BN', 'goog.i18n.DateTimeSymbols_ms_MY', 'goog.i18n.DateTimeSymbols_mt_MT', 'goog.i18n.DateTimeSymbols_mua', 'goog.i18n.DateTimeSymbols_mua_CM', 'goog.i18n.DateTimeSymbols_my', 'goog.i18n.DateTimeSymbols_my_MM', 'goog.i18n.DateTimeSymbols_naq', 'goog.i18n.DateTimeSymbols_naq_NA', 'goog.i18n.DateTimeSymbols_nb', 'goog.i18n.DateTimeSymbols_nb_NO', 'goog.i18n.DateTimeSymbols_nd', 'goog.i18n.DateTimeSymbols_nd_ZW', 'goog.i18n.DateTimeSymbols_ne', 'goog.i18n.DateTimeSymbols_ne_IN', 'goog.i18n.DateTimeSymbols_ne_NP', 'goog.i18n.DateTimeSymbols_nl_AW', 'goog.i18n.DateTimeSymbols_nl_BE', 'goog.i18n.DateTimeSymbols_nl_NL', 'goog.i18n.DateTimeSymbols_nmg', 'goog.i18n.DateTimeSymbols_nmg_CM', 'goog.i18n.DateTimeSymbols_nn', 'goog.i18n.DateTimeSymbols_nn_NO', 'goog.i18n.DateTimeSymbols_nr', 'goog.i18n.DateTimeSymbols_nr_ZA', 'goog.i18n.DateTimeSymbols_nso', 'goog.i18n.DateTimeSymbols_nso_ZA', 'goog.i18n.DateTimeSymbols_nus', 'goog.i18n.DateTimeSymbols_nus_SD', 'goog.i18n.DateTimeSymbols_nyn', 'goog.i18n.DateTimeSymbols_nyn_UG', 'goog.i18n.DateTimeSymbols_om', 'goog.i18n.DateTimeSymbols_om_ET', 'goog.i18n.DateTimeSymbols_om_KE', 'goog.i18n.DateTimeSymbols_or_IN', 'goog.i18n.DateTimeSymbols_pa', 'goog.i18n.DateTimeSymbols_pa_Arab', 'goog.i18n.DateTimeSymbols_pa_Arab_PK', 'goog.i18n.DateTimeSymbols_pa_Guru', 'goog.i18n.DateTimeSymbols_pa_Guru_IN', 'goog.i18n.DateTimeSymbols_pl_PL', 'goog.i18n.DateTimeSymbols_ps', 'goog.i18n.DateTimeSymbols_ps_AF', 'goog.i18n.DateTimeSymbols_pt_AO', 'goog.i18n.DateTimeSymbols_pt_GW', 'goog.i18n.DateTimeSymbols_pt_MZ', 'goog.i18n.DateTimeSymbols_pt_ST', 'goog.i18n.DateTimeSymbols_rm', 'goog.i18n.DateTimeSymbols_rm_CH', 'goog.i18n.DateTimeSymbols_rn', 'goog.i18n.DateTimeSymbols_rn_BI', 'goog.i18n.DateTimeSymbols_ro_MD', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_rof', 'goog.i18n.DateTimeSymbols_rof_TZ', 'goog.i18n.DateTimeSymbols_ru_MD', 'goog.i18n.DateTimeSymbols_ru_RU', 'goog.i18n.DateTimeSymbols_ru_UA', 'goog.i18n.DateTimeSymbols_rw', 'goog.i18n.DateTimeSymbols_rw_RW', 'goog.i18n.DateTimeSymbols_rwk', 'goog.i18n.DateTimeSymbols_rwk_TZ', 'goog.i18n.DateTimeSymbols_sah', 'goog.i18n.DateTimeSymbols_sah_RU', 'goog.i18n.DateTimeSymbols_saq', 'goog.i18n.DateTimeSymbols_saq_KE', 'goog.i18n.DateTimeSymbols_sbp', 'goog.i18n.DateTimeSymbols_sbp_TZ', 'goog.i18n.DateTimeSymbols_se', 'goog.i18n.DateTimeSymbols_se_FI', 'goog.i18n.DateTimeSymbols_se_NO', 'goog.i18n.DateTimeSymbols_seh', 'goog.i18n.DateTimeSymbols_seh_MZ', 'goog.i18n.DateTimeSymbols_ses', 'goog.i18n.DateTimeSymbols_ses_ML', 'goog.i18n.DateTimeSymbols_sg', 'goog.i18n.DateTimeSymbols_sg_CF', 'goog.i18n.DateTimeSymbols_shi', 'goog.i18n.DateTimeSymbols_shi_Latn', 'goog.i18n.DateTimeSymbols_shi_Latn_MA', 'goog.i18n.DateTimeSymbols_shi_Tfng', 'goog.i18n.DateTimeSymbols_shi_Tfng_MA', 'goog.i18n.DateTimeSymbols_si', 'goog.i18n.DateTimeSymbols_si_LK', 'goog.i18n.DateTimeSymbols_sk_SK', 'goog.i18n.DateTimeSymbols_sl_SI', 'goog.i18n.DateTimeSymbols_sn', 'goog.i18n.DateTimeSymbols_sn_ZW', 'goog.i18n.DateTimeSymbols_so', 'goog.i18n.DateTimeSymbols_so_DJ', 'goog.i18n.DateTimeSymbols_so_ET', 'goog.i18n.DateTimeSymbols_so_KE', 'goog.i18n.DateTimeSymbols_so_SO', 'goog.i18n.DateTimeSymbols_sq_AL', 'goog.i18n.DateTimeSymbols_sr_Cyrl', 'goog.i18n.DateTimeSymbols_sr_Cyrl_BA', 'goog.i18n.DateTimeSymbols_sr_Cyrl_ME', 'goog.i18n.DateTimeSymbols_sr_Cyrl_RS', 'goog.i18n.DateTimeSymbols_sr_Latn', 'goog.i18n.DateTimeSymbols_sr_Latn_BA', 'goog.i18n.DateTimeSymbols_sr_Latn_ME', 'goog.i18n.DateTimeSymbols_sr_Latn_RS', 'goog.i18n.DateTimeSymbols_ss', 'goog.i18n.DateTimeSymbols_ss_SZ', 'goog.i18n.DateTimeSymbols_ss_ZA', 'goog.i18n.DateTimeSymbols_ssy', 'goog.i18n.DateTimeSymbols_ssy_ER', 'goog.i18n.DateTimeSymbols_st', 'goog.i18n.DateTimeSymbols_st_LS', 'goog.i18n.DateTimeSymbols_st_ZA', 'goog.i18n.DateTimeSymbols_sv_FI', 'goog.i18n.DateTimeSymbols_sv_SE', 'goog.i18n.DateTimeSymbols_sw_KE', 'goog.i18n.DateTimeSymbols_sw_TZ', 'goog.i18n.DateTimeSymbols_swc', 'goog.i18n.DateTimeSymbols_swc_CD', 'goog.i18n.DateTimeSymbols_ta_IN', 'goog.i18n.DateTimeSymbols_ta_LK', 'goog.i18n.DateTimeSymbols_te_IN', 'goog.i18n.DateTimeSymbols_teo', 'goog.i18n.DateTimeSymbols_teo_KE', 'goog.i18n.DateTimeSymbols_teo_UG', 'goog.i18n.DateTimeSymbols_tg', 'goog.i18n.DateTimeSymbols_tg_Cyrl', 'goog.i18n.DateTimeSymbols_tg_Cyrl_TJ', 'goog.i18n.DateTimeSymbols_th_TH', 'goog.i18n.DateTimeSymbols_ti', 'goog.i18n.DateTimeSymbols_ti_ER', 'goog.i18n.DateTimeSymbols_ti_ET', 'goog.i18n.DateTimeSymbols_tig', 'goog.i18n.DateTimeSymbols_tig_ER', 'goog.i18n.DateTimeSymbols_tn', 'goog.i18n.DateTimeSymbols_tn_ZA', 'goog.i18n.DateTimeSymbols_to', 'goog.i18n.DateTimeSymbols_to_TO', 'goog.i18n.DateTimeSymbols_tr_TR', 'goog.i18n.DateTimeSymbols_ts', 'goog.i18n.DateTimeSymbols_ts_ZA', 'goog.i18n.DateTimeSymbols_twq', 'goog.i18n.DateTimeSymbols_twq_NE', 'goog.i18n.DateTimeSymbols_tzm', 'goog.i18n.DateTimeSymbols_tzm_Latn', 'goog.i18n.DateTimeSymbols_tzm_Latn_MA', 'goog.i18n.DateTimeSymbols_uk_UA', 'goog.i18n.DateTimeSymbols_ur_IN', 'goog.i18n.DateTimeSymbols_ur_PK', 'goog.i18n.DateTimeSymbols_uz', 'goog.i18n.DateTimeSymbols_uz_Arab', 'goog.i18n.DateTimeSymbols_uz_Arab_AF', 'goog.i18n.DateTimeSymbols_uz_Cyrl', 'goog.i18n.DateTimeSymbols_uz_Cyrl_UZ', 'goog.i18n.DateTimeSymbols_uz_Latn', 'goog.i18n.DateTimeSymbols_uz_Latn_UZ', 'goog.i18n.DateTimeSymbols_vai', 'goog.i18n.DateTimeSymbols_vai_Latn', 'goog.i18n.DateTimeSymbols_vai_Latn_LR', 'goog.i18n.DateTimeSymbols_vai_Vaii', 'goog.i18n.DateTimeSymbols_vai_Vaii_LR', 'goog.i18n.DateTimeSymbols_ve', 'goog.i18n.DateTimeSymbols_ve_ZA', 'goog.i18n.DateTimeSymbols_vi_VN', 'goog.i18n.DateTimeSymbols_vun', 'goog.i18n.DateTimeSymbols_vun_TZ', 'goog.i18n.DateTimeSymbols_wae', 'goog.i18n.DateTimeSymbols_wae_CH', 'goog.i18n.DateTimeSymbols_wal', 'goog.i18n.DateTimeSymbols_wal_ET', 'goog.i18n.DateTimeSymbols_xh', 'goog.i18n.DateTimeSymbols_xh_ZA', 'goog.i18n.DateTimeSymbols_xog', 'goog.i18n.DateTimeSymbols_xog_UG', 'goog.i18n.DateTimeSymbols_yav', 'goog.i18n.DateTimeSymbols_yav_CM', 'goog.i18n.DateTimeSymbols_yo', 'goog.i18n.DateTimeSymbols_yo_NG', 'goog.i18n.DateTimeSymbols_zh_Hans', 'goog.i18n.DateTimeSymbols_zh_Hans_CN', 'goog.i18n.DateTimeSymbols_zh_Hans_HK', 'goog.i18n.DateTimeSymbols_zh_Hans_MO', 'goog.i18n.DateTimeSymbols_zh_Hans_SG', 'goog.i18n.DateTimeSymbols_zh_Hant', 'goog.i18n.DateTimeSymbols_zh_Hant_HK', 'goog.i18n.DateTimeSymbols_zh_Hant_MO', 'goog.i18n.DateTimeSymbols_zh_Hant_TW', 'goog.i18n.DateTimeSymbols_zu_ZA'], ['goog.i18n.DateTimeSymbols']); +goog.addDependency('i18n/graphemebreak.js', ['goog.i18n.GraphemeBreak'], ['goog.structs.InversionMap']); +goog.addDependency('i18n/messageformat.js', ['goog.i18n.MessageFormat'], ['goog.asserts', 'goog.i18n.NumberFormat', 'goog.i18n.ordinalRules', 'goog.i18n.pluralRules']); +goog.addDependency('i18n/mime.js', ['goog.i18n.mime', 'goog.i18n.mime.encode'], []); +goog.addDependency('i18n/numberformat.js', ['goog.i18n.NumberFormat', 'goog.i18n.NumberFormat.CurrencyStyle', 'goog.i18n.NumberFormat.Format'], ['goog.i18n.NumberFormatSymbols', 'goog.i18n.currency']); +goog.addDependency('i18n/numberformatsymbols.js', ['goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_af', 'goog.i18n.NumberFormatSymbols_af_ZA', 'goog.i18n.NumberFormatSymbols_am', 'goog.i18n.NumberFormatSymbols_am_ET', 'goog.i18n.NumberFormatSymbols_ar', 'goog.i18n.NumberFormatSymbols_ar_001', 'goog.i18n.NumberFormatSymbols_ar_EG', 'goog.i18n.NumberFormatSymbols_bg', 'goog.i18n.NumberFormatSymbols_bg_BG', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_bn_BD', 'goog.i18n.NumberFormatSymbols_ca', 'goog.i18n.NumberFormatSymbols_ca_ES', 'goog.i18n.NumberFormatSymbols_chr', 'goog.i18n.NumberFormatSymbols_chr_US', 'goog.i18n.NumberFormatSymbols_cs', 'goog.i18n.NumberFormatSymbols_cs_CZ', 'goog.i18n.NumberFormatSymbols_cy', 'goog.i18n.NumberFormatSymbols_cy_GB', 'goog.i18n.NumberFormatSymbols_da', 'goog.i18n.NumberFormatSymbols_da_DK', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_de_AT', 'goog.i18n.NumberFormatSymbols_de_BE', 'goog.i18n.NumberFormatSymbols_de_CH', 'goog.i18n.NumberFormatSymbols_de_DE', 'goog.i18n.NumberFormatSymbols_de_LU', 'goog.i18n.NumberFormatSymbols_el', 'goog.i18n.NumberFormatSymbols_el_GR', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_en_AS', 'goog.i18n.NumberFormatSymbols_en_AU', 'goog.i18n.NumberFormatSymbols_en_Dsrt', 'goog.i18n.NumberFormatSymbols_en_Dsrt_US', 'goog.i18n.NumberFormatSymbols_en_GB', 'goog.i18n.NumberFormatSymbols_en_GU', 'goog.i18n.NumberFormatSymbols_en_IE', 'goog.i18n.NumberFormatSymbols_en_IN', 'goog.i18n.NumberFormatSymbols_en_MH', 'goog.i18n.NumberFormatSymbols_en_MP', 'goog.i18n.NumberFormatSymbols_en_SG', 'goog.i18n.NumberFormatSymbols_en_UM', 'goog.i18n.NumberFormatSymbols_en_US', 'goog.i18n.NumberFormatSymbols_en_VI', 'goog.i18n.NumberFormatSymbols_en_ZA', 'goog.i18n.NumberFormatSymbols_es', 'goog.i18n.NumberFormatSymbols_es_419', 'goog.i18n.NumberFormatSymbols_es_ES', 'goog.i18n.NumberFormatSymbols_et', 'goog.i18n.NumberFormatSymbols_et_EE', 'goog.i18n.NumberFormatSymbols_eu', 'goog.i18n.NumberFormatSymbols_eu_ES', 'goog.i18n.NumberFormatSymbols_fa', 'goog.i18n.NumberFormatSymbols_fa_IR', 'goog.i18n.NumberFormatSymbols_fi', 'goog.i18n.NumberFormatSymbols_fi_FI', 'goog.i18n.NumberFormatSymbols_fil', 'goog.i18n.NumberFormatSymbols_fil_PH', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_fr_BL', 'goog.i18n.NumberFormatSymbols_fr_CA', 'goog.i18n.NumberFormatSymbols_fr_FR', 'goog.i18n.NumberFormatSymbols_fr_GF', 'goog.i18n.NumberFormatSymbols_fr_GP', 'goog.i18n.NumberFormatSymbols_fr_MC', 'goog.i18n.NumberFormatSymbols_fr_MF', 'goog.i18n.NumberFormatSymbols_fr_MQ', 'goog.i18n.NumberFormatSymbols_fr_RE', 'goog.i18n.NumberFormatSymbols_fr_YT', 'goog.i18n.NumberFormatSymbols_gl', 'goog.i18n.NumberFormatSymbols_gl_ES', 'goog.i18n.NumberFormatSymbols_gsw', 'goog.i18n.NumberFormatSymbols_gsw_CH', 'goog.i18n.NumberFormatSymbols_gu', 'goog.i18n.NumberFormatSymbols_gu_IN', 'goog.i18n.NumberFormatSymbols_haw', 'goog.i18n.NumberFormatSymbols_haw_US', 'goog.i18n.NumberFormatSymbols_he', 'goog.i18n.NumberFormatSymbols_he_IL', 'goog.i18n.NumberFormatSymbols_hi', 'goog.i18n.NumberFormatSymbols_hi_IN', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.NumberFormatSymbols_hr_HR', 'goog.i18n.NumberFormatSymbols_hu', 'goog.i18n.NumberFormatSymbols_hu_HU', 'goog.i18n.NumberFormatSymbols_id', 'goog.i18n.NumberFormatSymbols_id_ID', 'goog.i18n.NumberFormatSymbols_in', 'goog.i18n.NumberFormatSymbols_is', 'goog.i18n.NumberFormatSymbols_is_IS', 'goog.i18n.NumberFormatSymbols_it', 'goog.i18n.NumberFormatSymbols_it_IT', 'goog.i18n.NumberFormatSymbols_iw', 'goog.i18n.NumberFormatSymbols_ja', 'goog.i18n.NumberFormatSymbols_ja_JP', 'goog.i18n.NumberFormatSymbols_kn', 'goog.i18n.NumberFormatSymbols_kn_IN', 'goog.i18n.NumberFormatSymbols_ko', 'goog.i18n.NumberFormatSymbols_ko_KR', 'goog.i18n.NumberFormatSymbols_ln', 'goog.i18n.NumberFormatSymbols_ln_CD', 'goog.i18n.NumberFormatSymbols_lt', 'goog.i18n.NumberFormatSymbols_lt_LT', 'goog.i18n.NumberFormatSymbols_lv', 'goog.i18n.NumberFormatSymbols_lv_LV', 'goog.i18n.NumberFormatSymbols_ml', 'goog.i18n.NumberFormatSymbols_ml_IN', 'goog.i18n.NumberFormatSymbols_mr', 'goog.i18n.NumberFormatSymbols_mr_IN', 'goog.i18n.NumberFormatSymbols_ms', 'goog.i18n.NumberFormatSymbols_ms_MY', 'goog.i18n.NumberFormatSymbols_mt', 'goog.i18n.NumberFormatSymbols_mt_MT', 'goog.i18n.NumberFormatSymbols_nl', 'goog.i18n.NumberFormatSymbols_nl_NL', 'goog.i18n.NumberFormatSymbols_no', 'goog.i18n.NumberFormatSymbols_or', 'goog.i18n.NumberFormatSymbols_or_IN', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_pl_PL', 'goog.i18n.NumberFormatSymbols_pt', 'goog.i18n.NumberFormatSymbols_pt_BR', 'goog.i18n.NumberFormatSymbols_pt_PT', 'goog.i18n.NumberFormatSymbols_ro', 'goog.i18n.NumberFormatSymbols_ro_RO', 'goog.i18n.NumberFormatSymbols_ru', 'goog.i18n.NumberFormatSymbols_ru_RU', 'goog.i18n.NumberFormatSymbols_sk', 'goog.i18n.NumberFormatSymbols_sk_SK', 'goog.i18n.NumberFormatSymbols_sl', 'goog.i18n.NumberFormatSymbols_sl_SI', 'goog.i18n.NumberFormatSymbols_sq', 'goog.i18n.NumberFormatSymbols_sq_AL', 'goog.i18n.NumberFormatSymbols_sr', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.NumberFormatSymbols_sr_Latn_RS', 'goog.i18n.NumberFormatSymbols_sv', 'goog.i18n.NumberFormatSymbols_sv_SE', 'goog.i18n.NumberFormatSymbols_sw', 'goog.i18n.NumberFormatSymbols_sw_TZ', 'goog.i18n.NumberFormatSymbols_ta', 'goog.i18n.NumberFormatSymbols_ta_IN', 'goog.i18n.NumberFormatSymbols_te', 'goog.i18n.NumberFormatSymbols_te_IN', 'goog.i18n.NumberFormatSymbols_th', 'goog.i18n.NumberFormatSymbols_th_TH', 'goog.i18n.NumberFormatSymbols_tl', 'goog.i18n.NumberFormatSymbols_tr', 'goog.i18n.NumberFormatSymbols_tr_TR', 'goog.i18n.NumberFormatSymbols_uk', 'goog.i18n.NumberFormatSymbols_uk_UA', 'goog.i18n.NumberFormatSymbols_ur', 'goog.i18n.NumberFormatSymbols_ur_PK', 'goog.i18n.NumberFormatSymbols_vi', 'goog.i18n.NumberFormatSymbols_vi_VN', 'goog.i18n.NumberFormatSymbols_zh', 'goog.i18n.NumberFormatSymbols_zh_CN', 'goog.i18n.NumberFormatSymbols_zh_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans', 'goog.i18n.NumberFormatSymbols_zh_Hans_CN', 'goog.i18n.NumberFormatSymbols_zh_TW', 'goog.i18n.NumberFormatSymbols_zu', 'goog.i18n.NumberFormatSymbols_zu_ZA'], []); +goog.addDependency('i18n/numberformatsymbolsext.js', ['goog.i18n.NumberFormatSymbolsExt', 'goog.i18n.NumberFormatSymbols_aa', 'goog.i18n.NumberFormatSymbols_aa_DJ', 'goog.i18n.NumberFormatSymbols_aa_ER', 'goog.i18n.NumberFormatSymbols_aa_ET', 'goog.i18n.NumberFormatSymbols_af_NA', 'goog.i18n.NumberFormatSymbols_agq', 'goog.i18n.NumberFormatSymbols_agq_CM', 'goog.i18n.NumberFormatSymbols_ak', 'goog.i18n.NumberFormatSymbols_ak_GH', 'goog.i18n.NumberFormatSymbols_ar_AE', 'goog.i18n.NumberFormatSymbols_ar_BH', 'goog.i18n.NumberFormatSymbols_ar_DZ', 'goog.i18n.NumberFormatSymbols_ar_IQ', 'goog.i18n.NumberFormatSymbols_ar_JO', 'goog.i18n.NumberFormatSymbols_ar_KW', 'goog.i18n.NumberFormatSymbols_ar_LB', 'goog.i18n.NumberFormatSymbols_ar_LY', 'goog.i18n.NumberFormatSymbols_ar_MA', 'goog.i18n.NumberFormatSymbols_ar_OM', 'goog.i18n.NumberFormatSymbols_ar_QA', 'goog.i18n.NumberFormatSymbols_ar_SA', 'goog.i18n.NumberFormatSymbols_ar_SD', 'goog.i18n.NumberFormatSymbols_ar_SY', 'goog.i18n.NumberFormatSymbols_ar_TN', 'goog.i18n.NumberFormatSymbols_ar_YE', 'goog.i18n.NumberFormatSymbols_as', 'goog.i18n.NumberFormatSymbols_as_IN', 'goog.i18n.NumberFormatSymbols_asa', 'goog.i18n.NumberFormatSymbols_asa_TZ', 'goog.i18n.NumberFormatSymbols_az', 'goog.i18n.NumberFormatSymbols_az_Cyrl', 'goog.i18n.NumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.NumberFormatSymbols_az_Latn', 'goog.i18n.NumberFormatSymbols_az_Latn_AZ', 'goog.i18n.NumberFormatSymbols_bas', 'goog.i18n.NumberFormatSymbols_bas_CM', 'goog.i18n.NumberFormatSymbols_be', 'goog.i18n.NumberFormatSymbols_be_BY', 'goog.i18n.NumberFormatSymbols_bem', 'goog.i18n.NumberFormatSymbols_bem_ZM', 'goog.i18n.NumberFormatSymbols_bez', 'goog.i18n.NumberFormatSymbols_bez_TZ', 'goog.i18n.NumberFormatSymbols_bm', 'goog.i18n.NumberFormatSymbols_bm_ML', 'goog.i18n.NumberFormatSymbols_bn_IN', 'goog.i18n.NumberFormatSymbols_bo', 'goog.i18n.NumberFormatSymbols_bo_CN', 'goog.i18n.NumberFormatSymbols_bo_IN', 'goog.i18n.NumberFormatSymbols_br', 'goog.i18n.NumberFormatSymbols_br_FR', 'goog.i18n.NumberFormatSymbols_brx', 'goog.i18n.NumberFormatSymbols_brx_IN', 'goog.i18n.NumberFormatSymbols_bs', 'goog.i18n.NumberFormatSymbols_bs_BA', 'goog.i18n.NumberFormatSymbols_byn', 'goog.i18n.NumberFormatSymbols_byn_ER', 'goog.i18n.NumberFormatSymbols_cgg', 'goog.i18n.NumberFormatSymbols_cgg_UG', 'goog.i18n.NumberFormatSymbols_ckb', 'goog.i18n.NumberFormatSymbols_ckb_Arab', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.NumberFormatSymbols_ckb_IQ', 'goog.i18n.NumberFormatSymbols_ckb_IR', 'goog.i18n.NumberFormatSymbols_ckb_Latn', 'goog.i18n.NumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.NumberFormatSymbols_dav', 'goog.i18n.NumberFormatSymbols_dav_KE', 'goog.i18n.NumberFormatSymbols_de_LI', 'goog.i18n.NumberFormatSymbols_dje', 'goog.i18n.NumberFormatSymbols_dje_NE', 'goog.i18n.NumberFormatSymbols_dua', 'goog.i18n.NumberFormatSymbols_dua_CM', 'goog.i18n.NumberFormatSymbols_dyo', 'goog.i18n.NumberFormatSymbols_dyo_SN', 'goog.i18n.NumberFormatSymbols_dz', 'goog.i18n.NumberFormatSymbols_dz_BT', 'goog.i18n.NumberFormatSymbols_ebu', 'goog.i18n.NumberFormatSymbols_ebu_KE', 'goog.i18n.NumberFormatSymbols_ee', 'goog.i18n.NumberFormatSymbols_ee_GH', 'goog.i18n.NumberFormatSymbols_ee_TG', 'goog.i18n.NumberFormatSymbols_el_CY', 'goog.i18n.NumberFormatSymbols_en_BB', 'goog.i18n.NumberFormatSymbols_en_BE', 'goog.i18n.NumberFormatSymbols_en_BM', 'goog.i18n.NumberFormatSymbols_en_BW', 'goog.i18n.NumberFormatSymbols_en_BZ', 'goog.i18n.NumberFormatSymbols_en_CA', 'goog.i18n.NumberFormatSymbols_en_GY', 'goog.i18n.NumberFormatSymbols_en_HK', 'goog.i18n.NumberFormatSymbols_en_JM', 'goog.i18n.NumberFormatSymbols_en_MT', 'goog.i18n.NumberFormatSymbols_en_MU', 'goog.i18n.NumberFormatSymbols_en_NA', 'goog.i18n.NumberFormatSymbols_en_NZ', 'goog.i18n.NumberFormatSymbols_en_PH', 'goog.i18n.NumberFormatSymbols_en_PK', 'goog.i18n.NumberFormatSymbols_en_TT', 'goog.i18n.NumberFormatSymbols_en_ZW', 'goog.i18n.NumberFormatSymbols_eo', 'goog.i18n.NumberFormatSymbols_es_AR', 'goog.i18n.NumberFormatSymbols_es_BO', 'goog.i18n.NumberFormatSymbols_es_CL', 'goog.i18n.NumberFormatSymbols_es_CO', 'goog.i18n.NumberFormatSymbols_es_CR', 'goog.i18n.NumberFormatSymbols_es_DO', 'goog.i18n.NumberFormatSymbols_es_EC', 'goog.i18n.NumberFormatSymbols_es_GQ', 'goog.i18n.NumberFormatSymbols_es_GT', 'goog.i18n.NumberFormatSymbols_es_HN', 'goog.i18n.NumberFormatSymbols_es_MX', 'goog.i18n.NumberFormatSymbols_es_NI', 'goog.i18n.NumberFormatSymbols_es_PA', 'goog.i18n.NumberFormatSymbols_es_PE', 'goog.i18n.NumberFormatSymbols_es_PR', 'goog.i18n.NumberFormatSymbols_es_PY', 'goog.i18n.NumberFormatSymbols_es_SV', 'goog.i18n.NumberFormatSymbols_es_US', 'goog.i18n.NumberFormatSymbols_es_UY', 'goog.i18n.NumberFormatSymbols_es_VE', 'goog.i18n.NumberFormatSymbols_ewo', 'goog.i18n.NumberFormatSymbols_ewo_CM', 'goog.i18n.NumberFormatSymbols_fa_AF', 'goog.i18n.NumberFormatSymbols_ff', 'goog.i18n.NumberFormatSymbols_ff_SN', 'goog.i18n.NumberFormatSymbols_fo', 'goog.i18n.NumberFormatSymbols_fo_FO', 'goog.i18n.NumberFormatSymbols_fr_BE', 'goog.i18n.NumberFormatSymbols_fr_BF', 'goog.i18n.NumberFormatSymbols_fr_BI', 'goog.i18n.NumberFormatSymbols_fr_BJ', 'goog.i18n.NumberFormatSymbols_fr_CD', 'goog.i18n.NumberFormatSymbols_fr_CF', 'goog.i18n.NumberFormatSymbols_fr_CG', 'goog.i18n.NumberFormatSymbols_fr_CH', 'goog.i18n.NumberFormatSymbols_fr_CI', 'goog.i18n.NumberFormatSymbols_fr_CM', 'goog.i18n.NumberFormatSymbols_fr_DJ', 'goog.i18n.NumberFormatSymbols_fr_GA', 'goog.i18n.NumberFormatSymbols_fr_GN', 'goog.i18n.NumberFormatSymbols_fr_GQ', 'goog.i18n.NumberFormatSymbols_fr_KM', 'goog.i18n.NumberFormatSymbols_fr_LU', 'goog.i18n.NumberFormatSymbols_fr_MG', 'goog.i18n.NumberFormatSymbols_fr_ML', 'goog.i18n.NumberFormatSymbols_fr_NE', 'goog.i18n.NumberFormatSymbols_fr_RW', 'goog.i18n.NumberFormatSymbols_fr_SN', 'goog.i18n.NumberFormatSymbols_fr_TD', 'goog.i18n.NumberFormatSymbols_fr_TG', 'goog.i18n.NumberFormatSymbols_fur', 'goog.i18n.NumberFormatSymbols_fur_IT', 'goog.i18n.NumberFormatSymbols_ga', 'goog.i18n.NumberFormatSymbols_ga_IE', 'goog.i18n.NumberFormatSymbols_gd', 'goog.i18n.NumberFormatSymbols_gd_GB', 'goog.i18n.NumberFormatSymbols_guz', 'goog.i18n.NumberFormatSymbols_guz_KE', 'goog.i18n.NumberFormatSymbols_gv', 'goog.i18n.NumberFormatSymbols_gv_GB', 'goog.i18n.NumberFormatSymbols_ha', 'goog.i18n.NumberFormatSymbols_ha_Latn', 'goog.i18n.NumberFormatSymbols_ha_Latn_GH', 'goog.i18n.NumberFormatSymbols_ha_Latn_NE', 'goog.i18n.NumberFormatSymbols_ha_Latn_NG', 'goog.i18n.NumberFormatSymbols_hy', 'goog.i18n.NumberFormatSymbols_hy_AM', 'goog.i18n.NumberFormatSymbols_ia', 'goog.i18n.NumberFormatSymbols_ig', 'goog.i18n.NumberFormatSymbols_ig_NG', 'goog.i18n.NumberFormatSymbols_ii', 'goog.i18n.NumberFormatSymbols_ii_CN', 'goog.i18n.NumberFormatSymbols_it_CH', 'goog.i18n.NumberFormatSymbols_jmc', 'goog.i18n.NumberFormatSymbols_jmc_TZ', 'goog.i18n.NumberFormatSymbols_ka', 'goog.i18n.NumberFormatSymbols_ka_GE', 'goog.i18n.NumberFormatSymbols_kab', 'goog.i18n.NumberFormatSymbols_kab_DZ', 'goog.i18n.NumberFormatSymbols_kam', 'goog.i18n.NumberFormatSymbols_kam_KE', 'goog.i18n.NumberFormatSymbols_kde', 'goog.i18n.NumberFormatSymbols_kde_TZ', 'goog.i18n.NumberFormatSymbols_kea', 'goog.i18n.NumberFormatSymbols_kea_CV', 'goog.i18n.NumberFormatSymbols_khq', 'goog.i18n.NumberFormatSymbols_khq_ML', 'goog.i18n.NumberFormatSymbols_ki', 'goog.i18n.NumberFormatSymbols_ki_KE', 'goog.i18n.NumberFormatSymbols_kk', 'goog.i18n.NumberFormatSymbols_kk_Cyrl', 'goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ', 'goog.i18n.NumberFormatSymbols_kl', 'goog.i18n.NumberFormatSymbols_kl_GL', 'goog.i18n.NumberFormatSymbols_kln', 'goog.i18n.NumberFormatSymbols_kln_KE', 'goog.i18n.NumberFormatSymbols_km', 'goog.i18n.NumberFormatSymbols_km_KH', 'goog.i18n.NumberFormatSymbols_kok', 'goog.i18n.NumberFormatSymbols_kok_IN', 'goog.i18n.NumberFormatSymbols_ksb', 'goog.i18n.NumberFormatSymbols_ksb_TZ', 'goog.i18n.NumberFormatSymbols_ksf', 'goog.i18n.NumberFormatSymbols_ksf_CM', 'goog.i18n.NumberFormatSymbols_ksh', 'goog.i18n.NumberFormatSymbols_ksh_DE', 'goog.i18n.NumberFormatSymbols_ku', 'goog.i18n.NumberFormatSymbols_kw', 'goog.i18n.NumberFormatSymbols_kw_GB', 'goog.i18n.NumberFormatSymbols_lag', 'goog.i18n.NumberFormatSymbols_lag_TZ', 'goog.i18n.NumberFormatSymbols_lg', 'goog.i18n.NumberFormatSymbols_lg_UG', 'goog.i18n.NumberFormatSymbols_ln_CG', 'goog.i18n.NumberFormatSymbols_lo', 'goog.i18n.NumberFormatSymbols_lo_LA', 'goog.i18n.NumberFormatSymbols_lu', 'goog.i18n.NumberFormatSymbols_lu_CD', 'goog.i18n.NumberFormatSymbols_luo', 'goog.i18n.NumberFormatSymbols_luo_KE', 'goog.i18n.NumberFormatSymbols_luy', 'goog.i18n.NumberFormatSymbols_luy_KE', 'goog.i18n.NumberFormatSymbols_mas', 'goog.i18n.NumberFormatSymbols_mas_KE', 'goog.i18n.NumberFormatSymbols_mas_TZ', 'goog.i18n.NumberFormatSymbols_mer', 'goog.i18n.NumberFormatSymbols_mer_KE', 'goog.i18n.NumberFormatSymbols_mfe', 'goog.i18n.NumberFormatSymbols_mfe_MU', 'goog.i18n.NumberFormatSymbols_mg', 'goog.i18n.NumberFormatSymbols_mg_MG', 'goog.i18n.NumberFormatSymbols_mgh', 'goog.i18n.NumberFormatSymbols_mgh_MZ', 'goog.i18n.NumberFormatSymbols_mk', 'goog.i18n.NumberFormatSymbols_mk_MK', 'goog.i18n.NumberFormatSymbols_ms_BN', 'goog.i18n.NumberFormatSymbols_mua', 'goog.i18n.NumberFormatSymbols_mua_CM', 'goog.i18n.NumberFormatSymbols_my', 'goog.i18n.NumberFormatSymbols_my_MM', 'goog.i18n.NumberFormatSymbols_naq', 'goog.i18n.NumberFormatSymbols_naq_NA', 'goog.i18n.NumberFormatSymbols_nb', 'goog.i18n.NumberFormatSymbols_nb_NO', 'goog.i18n.NumberFormatSymbols_nd', 'goog.i18n.NumberFormatSymbols_nd_ZW', 'goog.i18n.NumberFormatSymbols_ne', 'goog.i18n.NumberFormatSymbols_ne_IN', 'goog.i18n.NumberFormatSymbols_ne_NP', 'goog.i18n.NumberFormatSymbols_nl_AW', 'goog.i18n.NumberFormatSymbols_nl_BE', 'goog.i18n.NumberFormatSymbols_nl_CW', 'goog.i18n.NumberFormatSymbols_nl_SX', 'goog.i18n.NumberFormatSymbols_nmg', 'goog.i18n.NumberFormatSymbols_nmg_CM', 'goog.i18n.NumberFormatSymbols_nn', 'goog.i18n.NumberFormatSymbols_nn_NO', 'goog.i18n.NumberFormatSymbols_nr', 'goog.i18n.NumberFormatSymbols_nr_ZA', 'goog.i18n.NumberFormatSymbols_nso', 'goog.i18n.NumberFormatSymbols_nso_ZA', 'goog.i18n.NumberFormatSymbols_nus', 'goog.i18n.NumberFormatSymbols_nus_SD', 'goog.i18n.NumberFormatSymbols_nyn', 'goog.i18n.NumberFormatSymbols_nyn_UG', 'goog.i18n.NumberFormatSymbols_om', 'goog.i18n.NumberFormatSymbols_om_ET', 'goog.i18n.NumberFormatSymbols_om_KE', 'goog.i18n.NumberFormatSymbols_pa', 'goog.i18n.NumberFormatSymbols_pa_Arab', 'goog.i18n.NumberFormatSymbols_pa_Arab_PK', 'goog.i18n.NumberFormatSymbols_pa_Guru', 'goog.i18n.NumberFormatSymbols_pa_Guru_IN', 'goog.i18n.NumberFormatSymbols_ps', 'goog.i18n.NumberFormatSymbols_ps_AF', 'goog.i18n.NumberFormatSymbols_pt_AO', 'goog.i18n.NumberFormatSymbols_pt_GW', 'goog.i18n.NumberFormatSymbols_pt_MZ', 'goog.i18n.NumberFormatSymbols_pt_ST', 'goog.i18n.NumberFormatSymbols_rm', 'goog.i18n.NumberFormatSymbols_rm_CH', 'goog.i18n.NumberFormatSymbols_rn', 'goog.i18n.NumberFormatSymbols_rn_BI', 'goog.i18n.NumberFormatSymbols_ro_MD', 'goog.i18n.NumberFormatSymbols_rof', 'goog.i18n.NumberFormatSymbols_rof_TZ', 'goog.i18n.NumberFormatSymbols_ru_MD', 'goog.i18n.NumberFormatSymbols_ru_UA', 'goog.i18n.NumberFormatSymbols_rw', 'goog.i18n.NumberFormatSymbols_rw_RW', 'goog.i18n.NumberFormatSymbols_rwk', 'goog.i18n.NumberFormatSymbols_rwk_TZ', 'goog.i18n.NumberFormatSymbols_sah', 'goog.i18n.NumberFormatSymbols_sah_RU', 'goog.i18n.NumberFormatSymbols_saq', 'goog.i18n.NumberFormatSymbols_saq_KE', 'goog.i18n.NumberFormatSymbols_sbp', 'goog.i18n.NumberFormatSymbols_sbp_TZ', 'goog.i18n.NumberFormatSymbols_se', 'goog.i18n.NumberFormatSymbols_se_FI', 'goog.i18n.NumberFormatSymbols_se_NO', 'goog.i18n.NumberFormatSymbols_seh', 'goog.i18n.NumberFormatSymbols_seh_MZ', 'goog.i18n.NumberFormatSymbols_ses', 'goog.i18n.NumberFormatSymbols_ses_ML', 'goog.i18n.NumberFormatSymbols_sg', 'goog.i18n.NumberFormatSymbols_sg_CF', 'goog.i18n.NumberFormatSymbols_shi', 'goog.i18n.NumberFormatSymbols_shi_Latn', 'goog.i18n.NumberFormatSymbols_shi_Latn_MA', 'goog.i18n.NumberFormatSymbols_shi_Tfng', 'goog.i18n.NumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.NumberFormatSymbols_si', 'goog.i18n.NumberFormatSymbols_si_LK', 'goog.i18n.NumberFormatSymbols_sn', 'goog.i18n.NumberFormatSymbols_sn_ZW', 'goog.i18n.NumberFormatSymbols_so', 'goog.i18n.NumberFormatSymbols_so_DJ', 'goog.i18n.NumberFormatSymbols_so_ET', 'goog.i18n.NumberFormatSymbols_so_KE', 'goog.i18n.NumberFormatSymbols_so_SO', 'goog.i18n.NumberFormatSymbols_sr_Cyrl', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.NumberFormatSymbols_sr_Latn', 'goog.i18n.NumberFormatSymbols_sr_Latn_BA', 'goog.i18n.NumberFormatSymbols_sr_Latn_ME', 'goog.i18n.NumberFormatSymbols_ss', 'goog.i18n.NumberFormatSymbols_ss_SZ', 'goog.i18n.NumberFormatSymbols_ss_ZA', 'goog.i18n.NumberFormatSymbols_ssy', 'goog.i18n.NumberFormatSymbols_ssy_ER', 'goog.i18n.NumberFormatSymbols_st', 'goog.i18n.NumberFormatSymbols_st_LS', 'goog.i18n.NumberFormatSymbols_st_ZA', 'goog.i18n.NumberFormatSymbols_sv_FI', 'goog.i18n.NumberFormatSymbols_sw_KE', 'goog.i18n.NumberFormatSymbols_swc', 'goog.i18n.NumberFormatSymbols_swc_CD', 'goog.i18n.NumberFormatSymbols_ta_LK', 'goog.i18n.NumberFormatSymbols_teo', 'goog.i18n.NumberFormatSymbols_teo_KE', 'goog.i18n.NumberFormatSymbols_teo_UG', 'goog.i18n.NumberFormatSymbols_tg', 'goog.i18n.NumberFormatSymbols_tg_Cyrl', 'goog.i18n.NumberFormatSymbols_tg_Cyrl_TJ', 'goog.i18n.NumberFormatSymbols_ti', 'goog.i18n.NumberFormatSymbols_ti_ER', 'goog.i18n.NumberFormatSymbols_ti_ET', 'goog.i18n.NumberFormatSymbols_tig', 'goog.i18n.NumberFormatSymbols_tig_ER', 'goog.i18n.NumberFormatSymbols_tn', 'goog.i18n.NumberFormatSymbols_tn_ZA', 'goog.i18n.NumberFormatSymbols_to', 'goog.i18n.NumberFormatSymbols_to_TO', 'goog.i18n.NumberFormatSymbols_ts', 'goog.i18n.NumberFormatSymbols_ts_ZA', 'goog.i18n.NumberFormatSymbols_twq', 'goog.i18n.NumberFormatSymbols_twq_NE', 'goog.i18n.NumberFormatSymbols_tzm', 'goog.i18n.NumberFormatSymbols_tzm_Latn', 'goog.i18n.NumberFormatSymbols_tzm_Latn_MA', 'goog.i18n.NumberFormatSymbols_ur_IN', 'goog.i18n.NumberFormatSymbols_uz', 'goog.i18n.NumberFormatSymbols_uz_Arab', 'goog.i18n.NumberFormatSymbols_uz_Arab_AF', 'goog.i18n.NumberFormatSymbols_uz_Cyrl', 'goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.NumberFormatSymbols_uz_Latn', 'goog.i18n.NumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.NumberFormatSymbols_vai', 'goog.i18n.NumberFormatSymbols_vai_Latn', 'goog.i18n.NumberFormatSymbols_vai_Latn_LR', 'goog.i18n.NumberFormatSymbols_vai_Vaii', 'goog.i18n.NumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.NumberFormatSymbols_ve', 'goog.i18n.NumberFormatSymbols_ve_ZA', 'goog.i18n.NumberFormatSymbols_vun', 'goog.i18n.NumberFormatSymbols_vun_TZ', 'goog.i18n.NumberFormatSymbols_wae', 'goog.i18n.NumberFormatSymbols_wae_CH', 'goog.i18n.NumberFormatSymbols_wal', 'goog.i18n.NumberFormatSymbols_wal_ET', 'goog.i18n.NumberFormatSymbols_xh', 'goog.i18n.NumberFormatSymbols_xh_ZA', 'goog.i18n.NumberFormatSymbols_xog', 'goog.i18n.NumberFormatSymbols_xog_UG', 'goog.i18n.NumberFormatSymbols_yav', 'goog.i18n.NumberFormatSymbols_yav_CM', 'goog.i18n.NumberFormatSymbols_yo', 'goog.i18n.NumberFormatSymbols_yo_NG', 'goog.i18n.NumberFormatSymbols_zh_Hans_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans_MO', 'goog.i18n.NumberFormatSymbols_zh_Hans_SG', 'goog.i18n.NumberFormatSymbols_zh_Hant', 'goog.i18n.NumberFormatSymbols_zh_Hant_HK', 'goog.i18n.NumberFormatSymbols_zh_Hant_MO', 'goog.i18n.NumberFormatSymbols_zh_Hant_TW'], ['goog.i18n.NumberFormatSymbols']); +goog.addDependency('i18n/ordinalrules.js', ['goog.i18n.ordinalRules'], []); +goog.addDependency('i18n/pluralrules.js', ['goog.i18n.pluralRules'], []); +goog.addDependency('i18n/timezone.js', ['goog.i18n.TimeZone'], ['goog.array', 'goog.date.DateLike', 'goog.string']); +goog.addDependency('i18n/uchar.js', ['goog.i18n.uChar'], []); +goog.addDependency('i18n/uchar/localnamefetcher.js', ['goog.i18n.uChar.LocalNameFetcher'], ['goog.debug.Logger', 'goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher']); +goog.addDependency('i18n/uchar/namefetcher.js', ['goog.i18n.uChar.NameFetcher'], []); +goog.addDependency('i18n/uchar/remotenamefetcher.js', ['goog.i18n.uChar.RemoteNameFetcher'], ['goog.Disposable', 'goog.Uri', 'goog.debug.Logger', 'goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.net.XhrIo', 'goog.structs.Map']); +goog.addDependency('iter/iter.js', ['goog.iter', 'goog.iter.Iterator', 'goog.iter.StopIteration'], ['goog.array', 'goog.asserts']); +goog.addDependency('json/evaljsonprocessor.js', ['goog.json.EvalJsonProcessor'], ['goog.json', 'goog.json.Processor', 'goog.json.Serializer']); +goog.addDependency('json/json.js', ['goog.json', 'goog.json.Serializer'], []); +goog.addDependency('json/nativejsonprocessor.js', ['goog.json.NativeJsonProcessor'], ['goog.asserts', 'goog.json', 'goog.json.Processor']); +goog.addDependency('json/processor.js', ['goog.json.Processor'], ['goog.string.Parser', 'goog.string.Stringifier']); +goog.addDependency('labs/net/image.js', ['goog.labs.net.image'], ['goog.events.EventHandler', 'goog.events.EventType', 'goog.labs.result.SimpleResult', 'goog.net.EventType', 'goog.userAgent']); +goog.addDependency('labs/net/image_test.js', ['goog.labs.net.imageTest'], ['goog.events', 'goog.labs.net.image', 'goog.labs.result', 'goog.labs.result.Result', 'goog.net.EventType', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction']); +goog.addDependency('labs/net/xhr.js', ['goog.labs.net.xhr', 'goog.labs.net.xhr.Error', 'goog.labs.net.xhr.HttpError', 'goog.labs.net.xhr.TimeoutError'], ['goog.debug.Error', 'goog.json', 'goog.labs.result', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.string', 'goog.uri.utils']); +goog.addDependency('labs/object/object.js', ['goog.labs.object'], []); +goog.addDependency('labs/observe/notice.js', ['goog.labs.observe.Notice'], []); +goog.addDependency('labs/observe/observable.js', ['goog.labs.observe.Observable'], ['goog.disposable.IDisposable']); +goog.addDependency('labs/observe/observableset.js', ['goog.labs.observe.ObservableSet'], ['goog.array', 'goog.labs.observe.Observer']); +goog.addDependency('labs/observe/observationset.js', ['goog.labs.observe.ObservationSet'], ['goog.array', 'goog.labs.observe.Observer']); +goog.addDependency('labs/observe/observer.js', ['goog.labs.observe.Observer'], []); +goog.addDependency('labs/observe/simpleobservable.js', ['goog.labs.observe.SimpleObservable'], ['goog.Disposable', 'goog.array', 'goog.asserts', 'goog.labs.observe.Notice', 'goog.labs.observe.Observable', 'goog.labs.observe.Observer', 'goog.object']); +goog.addDependency('labs/result/deferredadaptor.js', ['goog.labs.result.DeferredAdaptor'], ['goog.async.Deferred', 'goog.labs.result', 'goog.labs.result.Result']); +goog.addDependency('labs/result/result_interface.js', ['goog.labs.result.Result'], ['goog.debug.Error']); +goog.addDependency('labs/result/resultutil.js', ['goog.labs.result'], ['goog.array', 'goog.labs.result.Result', 'goog.labs.result.SimpleResult']); +goog.addDependency('labs/result/simpleresult.js', ['goog.labs.result.SimpleResult', 'goog.labs.result.SimpleResult.StateError'], ['goog.debug.Error', 'goog.labs.result.Result']); +goog.addDependency('labs/structs/map.js', ['goog.labs.structs.Map'], ['goog.array', 'goog.asserts', 'goog.labs.object', 'goog.object']); +goog.addDependency('labs/structs/map_perf.js', ['goog.labs.structs.mapPerf'], ['goog.dom', 'goog.labs.structs.Map', 'goog.structs.Map', 'goog.testing.PerformanceTable', 'goog.testing.jsunit']); +goog.addDependency('labs/structs/multimap.js', ['goog.labs.structs.Multimap'], ['goog.array', 'goog.labs.object', 'goog.labs.structs.Map']); +goog.addDependency('labs/testing/assertthat.js', ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat'], ['goog.asserts', 'goog.debug.Error', 'goog.labs.testing.Matcher']); +goog.addDependency('labs/testing/dictionarymatcher.js', ['goog.labs.testing.HasEntriesMatcher', 'goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.HasKeyMatcher', 'goog.labs.testing.HasValueMatcher'], ['goog.array', 'goog.asserts', 'goog.labs.testing.Matcher', 'goog.string']); +goog.addDependency('labs/testing/logicmatcher.js', ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.AnyOfMatcher', 'goog.labs.testing.IsNotMatcher'], ['goog.array', 'goog.labs.testing.Matcher']); +goog.addDependency('labs/testing/matcher.js', ['goog.labs.testing.Matcher'], []); +goog.addDependency('labs/testing/numbermatcher.js', ['goog.labs.testing.CloseToMatcher', 'goog.labs.testing.EqualToMatcher', 'goog.labs.testing.GreaterThanEqualToMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.LessThanEqualToMatcher', 'goog.labs.testing.LessThanMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher']); +goog.addDependency('labs/testing/objectmatcher.js', ['goog.labs.testing.HasPropertyMatcher', 'goog.labs.testing.InstanceOfMatcher', 'goog.labs.testing.IsNullMatcher', 'goog.labs.testing.IsNullOrUndefinedMatcher', 'goog.labs.testing.IsUndefinedMatcher', 'goog.labs.testing.ObjectEqualsMatcher'], ['goog.labs.testing.Matcher', 'goog.string']); +goog.addDependency('labs/testing/stringmatcher.js', ['goog.labs.testing.ContainsStringMatcher', 'goog.labs.testing.EndsWithMatcher', 'goog.labs.testing.EqualToIgnoringCaseMatcher', 'goog.labs.testing.EqualToIgnoringWhitespaceMatcher', 'goog.labs.testing.EqualsMatcher', 'goog.labs.testing.StartsWithMatcher', 'goog.labs.testing.StringContainsInOrderMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.string']); +goog.addDependency('locale/countries.js', ['goog.locale.countries'], []); +goog.addDependency('locale/defaultlocalenameconstants.js', ['goog.locale.defaultLocaleNameConstants'], []); +goog.addDependency('locale/genericfontnames.js', ['goog.locale.genericFontNames'], []); +goog.addDependency('locale/genericfontnamesdata.js', ['goog.locale.genericFontNamesData'], ['goog.locale']); +goog.addDependency('locale/locale.js', ['goog.locale'], ['goog.locale.nativeNameConstants']); +goog.addDependency('locale/nativenameconstants.js', ['goog.locale.nativeNameConstants'], []); +goog.addDependency('locale/scriptToLanguages.js', ['goog.locale.scriptToLanguages'], ['goog.locale']); +goog.addDependency('locale/timezonedetection.js', ['goog.locale.timeZoneDetection'], ['goog.locale', 'goog.locale.TimeZoneFingerprint']); +goog.addDependency('locale/timezonefingerprint.js', ['goog.locale.TimeZoneFingerprint'], ['goog.locale']); +goog.addDependency('locale/timezonelist.js', ['goog.locale.TimeZoneList'], ['goog.locale']); +goog.addDependency('math/bezier.js', ['goog.math.Bezier'], ['goog.math', 'goog.math.Coordinate']); +goog.addDependency('math/box.js', ['goog.math.Box'], ['goog.math.Coordinate']); +goog.addDependency('math/coordinate.js', ['goog.math.Coordinate'], ['goog.math']); +goog.addDependency('math/coordinate3.js', ['goog.math.Coordinate3'], []); +goog.addDependency('math/exponentialbackoff.js', ['goog.math.ExponentialBackoff'], ['goog.asserts']); +goog.addDependency('math/integer.js', ['goog.math.Integer'], []); +goog.addDependency('math/interpolator/interpolator1.js', ['goog.math.interpolator.Interpolator1'], []); +goog.addDependency('math/interpolator/linear1.js', ['goog.math.interpolator.Linear1'], ['goog.array', 'goog.math', 'goog.math.interpolator.Interpolator1']); +goog.addDependency('math/interpolator/pchip1.js', ['goog.math.interpolator.Pchip1'], ['goog.math', 'goog.math.interpolator.Spline1']); +goog.addDependency('math/interpolator/spline1.js', ['goog.math.interpolator.Spline1'], ['goog.array', 'goog.math', 'goog.math.interpolator.Interpolator1', 'goog.math.tdma']); +goog.addDependency('math/line.js', ['goog.math.Line'], ['goog.math', 'goog.math.Coordinate']); +goog.addDependency('math/long.js', ['goog.math.Long'], []); +goog.addDependency('math/math.js', ['goog.math'], ['goog.array']); +goog.addDependency('math/matrix.js', ['goog.math.Matrix'], ['goog.array', 'goog.math', 'goog.math.Size']); +goog.addDependency('math/range.js', ['goog.math.Range'], []); +goog.addDependency('math/rangeset.js', ['goog.math.RangeSet'], ['goog.array', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.math.Range']); +goog.addDependency('math/rect.js', ['goog.math.Rect'], ['goog.math.Box', 'goog.math.Size']); +goog.addDependency('math/size.js', ['goog.math.Size'], []); +goog.addDependency('math/tdma.js', ['goog.math.tdma'], []); +goog.addDependency('math/vec2.js', ['goog.math.Vec2'], ['goog.math', 'goog.math.Coordinate']); +goog.addDependency('math/vec3.js', ['goog.math.Vec3'], ['goog.math', 'goog.math.Coordinate3']); +goog.addDependency('memoize/memoize.js', ['goog.memoize'], []); +goog.addDependency('messaging/abstractchannel.js', ['goog.messaging.AbstractChannel'], ['goog.Disposable', 'goog.debug', 'goog.debug.Logger', 'goog.json', 'goog.messaging.MessageChannel']); +goog.addDependency('messaging/bufferedchannel.js', ['goog.messaging.BufferedChannel'], ['goog.Timer', 'goog.Uri', 'goog.debug.Error', 'goog.debug.Logger', 'goog.events', 'goog.messaging.MessageChannel', 'goog.messaging.MultiChannel']); +goog.addDependency('messaging/deferredchannel.js', ['goog.messaging.DeferredChannel'], ['goog.Disposable', 'goog.async.Deferred', 'goog.messaging.MessageChannel']); +goog.addDependency('messaging/loggerclient.js', ['goog.messaging.LoggerClient'], ['goog.Disposable', 'goog.debug', 'goog.debug.LogManager', 'goog.debug.Logger']); +goog.addDependency('messaging/loggerserver.js', ['goog.messaging.LoggerServer'], ['goog.Disposable', 'goog.debug.Logger']); +goog.addDependency('messaging/messagechannel.js', ['goog.messaging.MessageChannel'], []); +goog.addDependency('messaging/messaging.js', ['goog.messaging'], ['goog.messaging.MessageChannel']); +goog.addDependency('messaging/multichannel.js', ['goog.messaging.MultiChannel', 'goog.messaging.MultiChannel.VirtualChannel'], ['goog.Disposable', 'goog.debug.Logger', 'goog.events.EventHandler', 'goog.messaging.MessageChannel', 'goog.object']); +goog.addDependency('messaging/portcaller.js', ['goog.messaging.PortCaller'], ['goog.Disposable', 'goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object']); +goog.addDependency('messaging/portchannel.js', ['goog.messaging.PortChannel'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.debug', 'goog.debug.Logger', 'goog.dom', 'goog.dom.DomHelper', 'goog.events', 'goog.events.EventType', 'goog.json', 'goog.messaging.AbstractChannel', 'goog.messaging.DeferredChannel', 'goog.object', 'goog.string']); +goog.addDependency('messaging/portnetwork.js', ['goog.messaging.PortNetwork'], []); +goog.addDependency('messaging/portoperator.js', ['goog.messaging.PortOperator'], ['goog.Disposable', 'goog.asserts', 'goog.debug.Logger', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object']); +goog.addDependency('messaging/respondingchannel.js', ['goog.messaging.RespondingChannel'], ['goog.Disposable', 'goog.debug.Logger', 'goog.messaging.MessageChannel', 'goog.messaging.MultiChannel', 'goog.messaging.MultiChannel.VirtualChannel']); +goog.addDependency('messaging/testdata/portchannel_worker.js', ['goog.messaging.testdata.portchannel_worker'], ['goog.messaging.PortChannel']); +goog.addDependency('messaging/testdata/portnetwork_worker1.js', ['goog.messaging.testdata.portnetwork_worker1'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel']); +goog.addDependency('messaging/testdata/portnetwork_worker2.js', ['goog.messaging.testdata.portnetwork_worker2'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel']); +goog.addDependency('module/abstractmoduleloader.js', ['goog.module.AbstractModuleLoader'], []); +goog.addDependency('module/basemodule.js', ['goog.module.BaseModule'], ['goog.Disposable']); +goog.addDependency('module/loader.js', ['goog.module.Loader'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.object']); +goog.addDependency('module/module.js', ['goog.module'], ['goog.array', 'goog.module.Loader']); +goog.addDependency('module/moduleinfo.js', ['goog.module.ModuleInfo'], ['goog.Disposable', 'goog.functions', 'goog.module.BaseModule', 'goog.module.ModuleLoadCallback']); +goog.addDependency('module/moduleloadcallback.js', ['goog.module.ModuleLoadCallback'], ['goog.debug.entryPointRegistry', 'goog.debug.errorHandlerWeakDep']); +goog.addDependency('module/moduleloader.js', ['goog.module.ModuleLoader'], ['goog.Timer', 'goog.array', 'goog.debug.Logger', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.module.AbstractModuleLoader', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.net.jsloader']); +goog.addDependency('module/modulemanager.js', ['goog.module.ModuleManager', 'goog.module.ModuleManager.CallbackType', 'goog.module.ModuleManager.FailureType'], ['goog.Disposable', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.debug.Logger', 'goog.debug.Trace', 'goog.module.ModuleInfo', 'goog.module.ModuleLoadCallback', 'goog.object']); +goog.addDependency('module/testdata/modA_1.js', ['goog.module.testdata.modA_1'], []); +goog.addDependency('module/testdata/modA_2.js', ['goog.module.testdata.modA_2'], ['goog.module.ModuleManager']); +goog.addDependency('module/testdata/modB_1.js', ['goog.module.testdata.modB_1'], ['goog.module.ModuleManager']); +goog.addDependency('net/browserchannel.js', ['goog.net.BrowserChannel', 'goog.net.BrowserChannel.Error', 'goog.net.BrowserChannel.Event', 'goog.net.BrowserChannel.Handler', 'goog.net.BrowserChannel.LogSaver', 'goog.net.BrowserChannel.QueuedMap', 'goog.net.BrowserChannel.ServerReachability', 'goog.net.BrowserChannel.ServerReachabilityEvent', 'goog.net.BrowserChannel.Stat', 'goog.net.BrowserChannel.StatEvent', 'goog.net.BrowserChannel.State', 'goog.net.BrowserChannel.TimingEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.Logger', 'goog.debug.TextFormatter', 'goog.events.Event', 'goog.events.EventTarget', 'goog.json', 'goog.json.EvalJsonProcessor', 'goog.net.BrowserTestChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error', 'goog.net.XhrIo', 'goog.net.tmpnetwork', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer', 'goog.userAgent']); +goog.addDependency('net/browsertestchannel.js', ['goog.net.BrowserTestChannel'], ['goog.json.EvalJsonProcessor', 'goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error', 'goog.net.tmpnetwork', 'goog.string.Parser', 'goog.userAgent']); +goog.addDependency('net/bulkloader.js', ['goog.net.BulkLoader'], ['goog.debug.Logger', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.net.BulkLoaderHelper', 'goog.net.EventType', 'goog.net.XhrIo']); +goog.addDependency('net/bulkloaderhelper.js', ['goog.net.BulkLoaderHelper'], ['goog.Disposable', 'goog.debug.Logger']); +goog.addDependency('net/channeldebug.js', ['goog.net.ChannelDebug'], ['goog.debug.Logger', 'goog.json']); +goog.addDependency('net/channelrequest.js', ['goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error'], ['goog.Timer', 'goog.events', 'goog.events.EventHandler', 'goog.net.EventType', 'goog.net.XmlHttp.ReadyState', 'goog.object', 'goog.userAgent']); +goog.addDependency('net/cookies.js', ['goog.net.Cookies', 'goog.net.cookies'], ['goog.userAgent']); +goog.addDependency('net/crossdomainrpc.js', ['goog.net.CrossDomainRpc'], ['goog.Uri.QueryData', 'goog.debug.Logger', 'goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.json', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.userAgent']); +goog.addDependency('net/errorcode.js', ['goog.net.ErrorCode'], []); +goog.addDependency('net/eventtype.js', ['goog.net.EventType'], []); +goog.addDependency('net/filedownloader.js', ['goog.net.FileDownloader', 'goog.net.FileDownloader.Error'], ['goog.Disposable', 'goog.asserts', 'goog.async.Deferred', 'goog.crypt.hash32', 'goog.debug.Error', 'goog.events.EventHandler', 'goog.fs', 'goog.fs.DirectoryEntry.Behavior', 'goog.fs.Error.ErrorCode', 'goog.fs.FileSaver.EventType', 'goog.net.EventType', 'goog.net.XhrIo.ResponseType', 'goog.net.XhrIoPool']); +goog.addDependency('net/httpstatus.js', ['goog.net.HttpStatus'], []); +goog.addDependency('net/iframeio.js', ['goog.net.IframeIo', 'goog.net.IframeIo.IncrementalDataEvent'], ['goog.Timer', 'goog.Uri', 'goog.debug', 'goog.debug.Logger', 'goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.reflect', 'goog.string', 'goog.structs', 'goog.userAgent']); +goog.addDependency('net/iframeloadmonitor.js', ['goog.net.IframeLoadMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent']); +goog.addDependency('net/imageloader.js', ['goog.net.ImageLoader'], ['goog.array', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.EventType', 'goog.object', 'goog.userAgent']); +goog.addDependency('net/ipaddress.js', ['goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address'], ['goog.array', 'goog.math.Integer', 'goog.object', 'goog.string']); +goog.addDependency('net/jsloader.js', ['goog.net.jsloader', 'goog.net.jsloader.Error'], ['goog.array', 'goog.async.Deferred', 'goog.debug.Error', 'goog.dom', 'goog.userAgent']); +goog.addDependency('net/jsonp.js', ['goog.net.Jsonp'], ['goog.Uri', 'goog.dom', 'goog.net.jsloader']); +goog.addDependency('net/mockiframeio.js', ['goog.net.MockIFrameIo'], ['goog.events.EventTarget', 'goog.net.ErrorCode', 'goog.net.IframeIo', 'goog.net.IframeIo.IncrementalDataEvent']); +goog.addDependency('net/mockxhrlite.js', ['goog.net.MockXhrLite'], ['goog.testing.net.XhrIo']); +goog.addDependency('net/multiiframeloadmonitor.js', ['goog.net.MultiIframeLoadMonitor'], ['goog.net.IframeLoadMonitor']); +goog.addDependency('net/networktester.js', ['goog.net.NetworkTester'], ['goog.Timer', 'goog.Uri', 'goog.debug.Logger']); +goog.addDependency('net/testdata/jsloader_test1.js', ['goog.net.testdata.jsloader_test1'], []); +goog.addDependency('net/testdata/jsloader_test2.js', ['goog.net.testdata.jsloader_test2'], []); +goog.addDependency('net/testdata/jsloader_test3.js', ['goog.net.testdata.jsloader_test3'], []); +goog.addDependency('net/testdata/jsloader_test4.js', ['goog.net.testdata.jsloader_test4'], []); +goog.addDependency('net/tmpnetwork.js', ['goog.net.tmpnetwork'], ['goog.Uri', 'goog.net.ChannelDebug']); +goog.addDependency('net/websocket.js', ['goog.net.WebSocket', 'goog.net.WebSocket.ErrorEvent', 'goog.net.WebSocket.EventType', 'goog.net.WebSocket.MessageEvent'], ['goog.Timer', 'goog.asserts', 'goog.debug.Logger', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget']); +goog.addDependency('net/wrapperxmlhttpfactory.js', ['goog.net.WrapperXmlHttpFactory'], ['goog.net.XmlHttpFactory']); +goog.addDependency('net/xhrio.js', ['goog.net.XhrIo', 'goog.net.XhrIo.ResponseType'], ['goog.Timer', 'goog.debug.Logger', 'goog.debug.entryPointRegistry', 'goog.debug.errorHandlerWeakDep', 'goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.object', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils']); +goog.addDependency('net/xhriopool.js', ['goog.net.XhrIoPool'], ['goog.net.XhrIo', 'goog.structs', 'goog.structs.PriorityPool']); +goog.addDependency('net/xhrlite.js', ['goog.net.XhrLite'], ['goog.net.XhrIo']); +goog.addDependency('net/xhrlitepool.js', ['goog.net.XhrLitePool'], ['goog.net.XhrIoPool']); +goog.addDependency('net/xhrmanager.js', ['goog.net.XhrManager', 'goog.net.XhrManager.Event', 'goog.net.XhrManager.Request'], ['goog.Disposable', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.structs.Map']); +goog.addDependency('net/xmlhttp.js', ['goog.net.DefaultXmlHttpFactory', 'goog.net.XmlHttp', 'goog.net.XmlHttp.OptionType', 'goog.net.XmlHttp.ReadyState'], ['goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttpFactory']); +goog.addDependency('net/xmlhttpfactory.js', ['goog.net.XmlHttpFactory'], []); +goog.addDependency('net/xpc/crosspagechannel.js', ['goog.net.xpc.CrossPageChannel'], ['goog.Disposable', 'goog.Uri', 'goog.async.Deferred', 'goog.async.Delay', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.json', 'goog.messaging.AbstractChannel', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.FrameElementMethodTransport', 'goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframeRelayTransport', 'goog.net.xpc.NativeMessagingTransport', 'goog.net.xpc.NixTransport', 'goog.net.xpc.Transport', 'goog.userAgent']); +goog.addDependency('net/xpc/crosspagechannelrole.js', ['goog.net.xpc.CrossPageChannelRole'], []); +goog.addDependency('net/xpc/frameelementmethodtransport.js', ['goog.net.xpc.FrameElementMethodTransport'], ['goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport']); +goog.addDependency('net/xpc/iframepollingtransport.js', ['goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframePollingTransport.Receiver', 'goog.net.xpc.IframePollingTransport.Sender'], ['goog.array', 'goog.dom', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.userAgent']); +goog.addDependency('net/xpc/iframerelaytransport.js', ['goog.net.xpc.IframeRelayTransport'], ['goog.dom', 'goog.events', 'goog.net.xpc', 'goog.net.xpc.Transport', 'goog.userAgent']); +goog.addDependency('net/xpc/nativemessagingtransport.js', ['goog.net.xpc.NativeMessagingTransport'], ['goog.Timer', 'goog.asserts', 'goog.async.Deferred', 'goog.events', 'goog.events.EventHandler', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport']); +goog.addDependency('net/xpc/nixtransport.js', ['goog.net.xpc.NixTransport'], ['goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.reflect']); +goog.addDependency('net/xpc/relay.js', ['goog.net.xpc.relay'], []); +goog.addDependency('net/xpc/transport.js', ['goog.net.xpc.Transport'], ['goog.Disposable', 'goog.dom', 'goog.net.xpc']); +goog.addDependency('net/xpc/xpc.js', ['goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.TransportNames', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields'], ['goog.debug.Logger']); +goog.addDependency('object/object.js', ['goog.object'], []); +goog.addDependency('positioning/absoluteposition.js', ['goog.positioning.AbsolutePosition'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning', 'goog.positioning.AbstractPosition']); +goog.addDependency('positioning/abstractposition.js', ['goog.positioning.AbstractPosition'], ['goog.math.Box', 'goog.math.Size', 'goog.positioning.Corner']); +goog.addDependency('positioning/anchoredposition.js', ['goog.positioning.AnchoredPosition'], ['goog.math.Box', 'goog.positioning', 'goog.positioning.AbstractPosition']); +goog.addDependency('positioning/anchoredviewportposition.js', ['goog.positioning.AnchoredViewportPosition'], ['goog.math.Box', 'goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus']); +goog.addDependency('positioning/clientposition.js', ['goog.positioning.ClientPosition'], ['goog.asserts', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.style']); +goog.addDependency('positioning/clientposition_test.js', ['goog.positioning.clientPositionTest'], ['goog.dom', 'goog.positioning.ClientPosition', 'goog.style', 'goog.testing.jsunit']); +goog.addDependency('positioning/menuanchoredposition.js', ['goog.positioning.MenuAnchoredPosition'], ['goog.math.Box', 'goog.math.Size', 'goog.positioning', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow']); +goog.addDependency('positioning/positioning.js', ['goog.positioning', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.style', 'goog.style.bidi']); +goog.addDependency('positioning/viewportclientposition.js', ['goog.positioning.ViewportClientPosition'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning.ClientPosition']); +goog.addDependency('positioning/viewportposition.js', ['goog.positioning.ViewportPosition'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning.AbstractPosition']); +goog.addDependency('proto/proto.js', ['goog.proto'], ['goog.proto.Serializer']); +goog.addDependency('proto/serializer.js', ['goog.proto.Serializer'], ['goog.json.Serializer', 'goog.string']); +goog.addDependency('proto2/descriptor.js', ['goog.proto2.Descriptor', 'goog.proto2.Metadata'], ['goog.array', 'goog.object', 'goog.proto2.Util']); +goog.addDependency('proto2/fielddescriptor.js', ['goog.proto2.FieldDescriptor'], ['goog.proto2.Util', 'goog.string']); +goog.addDependency('proto2/lazydeserializer.js', ['goog.proto2.LazyDeserializer'], ['goog.proto2.Serializer', 'goog.proto2.Util']); +goog.addDependency('proto2/message.js', ['goog.proto2.Message'], ['goog.proto2.Descriptor', 'goog.proto2.FieldDescriptor', 'goog.proto2.Util', 'goog.string']); +goog.addDependency('proto2/objectserializer.js', ['goog.proto2.ObjectSerializer'], ['goog.proto2.Serializer', 'goog.proto2.Util', 'goog.string']); +goog.addDependency('proto2/package_test.pb.js', ['someprotopackage.TestPackageTypes'], ['goog.proto2.Message', 'proto2.TestAllTypes']); +goog.addDependency('proto2/pbliteserializer.js', ['goog.proto2.PbLiteSerializer'], ['goog.proto2.LazyDeserializer', 'goog.proto2.Util']); +goog.addDependency('proto2/serializer.js', ['goog.proto2.Serializer'], ['goog.proto2.Descriptor', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.proto2.Util']); +goog.addDependency('proto2/test.pb.js', ['proto2.TestAllTypes', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup'], ['goog.proto2.Message']); +goog.addDependency('proto2/textformatserializer.js', ['goog.proto2.TextFormatSerializer', 'goog.proto2.TextFormatSerializer.Parser'], ['goog.array', 'goog.asserts', 'goog.json', 'goog.proto2.Serializer', 'goog.proto2.Util', 'goog.string']); +goog.addDependency('proto2/textformatserializer_test.js', ['goog.proto2.TextFormatSerializerTest'], ['goog.proto2.TextFormatSerializer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'proto2.TestAllTypes']); +goog.addDependency('proto2/util.js', ['goog.proto2.Util'], ['goog.asserts']); +goog.addDependency('pubsub/pubsub.js', ['goog.pubsub.PubSub'], ['goog.Disposable', 'goog.array']); +goog.addDependency('reflect/reflect.js', ['goog.reflect'], []); +goog.addDependency('soy/renderer.js', ['goog.soy.InjectedDataSupplier', 'goog.soy.Renderer'], ['goog.dom', 'goog.soy']); +goog.addDependency('soy/soy.js', ['goog.soy'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName']); +goog.addDependency('soy/soy_test.js', ['goog.soy.testHelper'], ['goog.dom', 'goog.string', 'goog.userAgent']); +goog.addDependency('spell/spellcheck.js', ['goog.spell.SpellCheck', 'goog.spell.SpellCheck.WordChangedEvent'], ['goog.Timer', 'goog.events.EventTarget', 'goog.structs.Set']); +goog.addDependency('stats/basicstat.js', ['goog.stats.BasicStat'], ['goog.array', 'goog.debug.Logger', 'goog.iter', 'goog.object', 'goog.string.format', 'goog.structs.CircularBuffer']); +goog.addDependency('storage/collectablestorage.js', ['goog.storage.CollectableStorage'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage', 'goog.storage.RichStorage.Wrapper', 'goog.storage.mechanism.IterableMechanism']); +goog.addDependency('storage/encryptedstorage.js', ['goog.storage.EncryptedStorage'], ['goog.crypt', 'goog.crypt.Arc4', 'goog.crypt.Sha1', 'goog.crypt.base64', 'goog.json', 'goog.json.Serializer', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.RichStorage.Wrapper', 'goog.storage.mechanism.IterableMechanism']); +goog.addDependency('storage/errorcode.js', ['goog.storage.ErrorCode'], []); +goog.addDependency('storage/expiringstorage.js', ['goog.storage.ExpiringStorage'], ['goog.storage.RichStorage', 'goog.storage.RichStorage.Wrapper', 'goog.storage.mechanism.Mechanism']); +goog.addDependency('storage/mechanism/errorcode.js', ['goog.storage.mechanism.ErrorCode'], []); +goog.addDependency('storage/mechanism/html5localstorage.js', ['goog.storage.mechanism.HTML5LocalStorage'], ['goog.storage.mechanism.HTML5WebStorage']); +goog.addDependency('storage/mechanism/html5sessionstorage.js', ['goog.storage.mechanism.HTML5SessionStorage'], ['goog.storage.mechanism.HTML5WebStorage']); +goog.addDependency('storage/mechanism/html5webstorage.js', ['goog.storage.mechanism.HTML5WebStorage'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism']); +goog.addDependency('storage/mechanism/ieuserdata.js', ['goog.storage.mechanism.IEUserData'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism', 'goog.structs.Map', 'goog.userAgent']); +goog.addDependency('storage/mechanism/iterablemechanism.js', ['goog.storage.mechanism.IterableMechanism'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.iter.Iterator', 'goog.storage.mechanism.Mechanism']); +goog.addDependency('storage/mechanism/iterablemechanism_test.js', ['goog.storage.mechanism.iterablemechanism_test'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism', 'goog.testing.asserts']); +goog.addDependency('storage/mechanism/mechanism.js', ['goog.storage.mechanism.Mechanism'], []); +goog.addDependency('storage/mechanism/mechanism_separation_test.js', ['goog.storage.mechanism.mechanism_separation_test'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism', 'goog.testing.asserts']); +goog.addDependency('storage/mechanism/mechanism_sharing_test.js', ['goog.storage.mechanism.mechanism_sharing_test'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism', 'goog.testing.asserts']); +goog.addDependency('storage/mechanism/mechanism_test.js', ['goog.storage.mechanism.mechanism_test'], ['goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.Mechanism', 'goog.testing.asserts', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']); +goog.addDependency('storage/mechanism/mechanismfactory.js', ['goog.storage.mechanism.mechanismfactory'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.IterableMechanism', 'goog.storage.mechanism.PrefixedMechanism']); +goog.addDependency('storage/mechanism/prefixedmechanism.js', ['goog.storage.mechanism.PrefixedMechanism'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism']); +goog.addDependency('storage/richstorage.js', ['goog.storage.RichStorage', 'goog.storage.RichStorage.Wrapper'], ['goog.storage.ErrorCode', 'goog.storage.Storage', 'goog.storage.mechanism.Mechanism']); +goog.addDependency('storage/storage.js', ['goog.storage.Storage'], ['goog.json', 'goog.json.Serializer', 'goog.storage.ErrorCode', 'goog.storage.mechanism.Mechanism']); +goog.addDependency('storage/storage_test.js', ['goog.storage.storage_test'], ['goog.storage.Storage', 'goog.structs.Map', 'goog.testing.asserts']); +goog.addDependency('string/linkify.js', ['goog.string.linkify'], ['goog.string']); +goog.addDependency('string/parser.js', ['goog.string.Parser'], []); +goog.addDependency('string/path.js', ['goog.string.path'], ['goog.array', 'goog.string']); +goog.addDependency('string/string.js', ['goog.string', 'goog.string.Unicode'], []); +goog.addDependency('string/stringbuffer.js', ['goog.string.StringBuffer'], []); +goog.addDependency('string/stringformat.js', ['goog.string.format'], ['goog.string']); +goog.addDependency('string/stringifier.js', ['goog.string.Stringifier'], []); +goog.addDependency('structs/avltree.js', ['goog.structs.AvlTree', 'goog.structs.AvlTree.Node'], ['goog.structs', 'goog.structs.Collection']); +goog.addDependency('structs/circularbuffer.js', ['goog.structs.CircularBuffer'], []); +goog.addDependency('structs/collection.js', ['goog.structs.Collection'], []); +goog.addDependency('structs/heap.js', ['goog.structs.Heap'], ['goog.array', 'goog.object', 'goog.structs.Node']); +goog.addDependency('structs/inversionmap.js', ['goog.structs.InversionMap'], ['goog.array']); +goog.addDependency('structs/linkedmap.js', ['goog.structs.LinkedMap'], ['goog.structs.Map']); +goog.addDependency('structs/map.js', ['goog.structs.Map'], ['goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.object', 'goog.structs']); +goog.addDependency('structs/node.js', ['goog.structs.Node'], []); +goog.addDependency('structs/pool.js', ['goog.structs.Pool'], ['goog.Disposable', 'goog.structs.Queue', 'goog.structs.Set']); +goog.addDependency('structs/prioritypool.js', ['goog.structs.PriorityPool'], ['goog.structs.Pool', 'goog.structs.PriorityQueue']); +goog.addDependency('structs/priorityqueue.js', ['goog.structs.PriorityQueue'], ['goog.structs', 'goog.structs.Heap']); +goog.addDependency('structs/quadtree.js', ['goog.structs.QuadTree', 'goog.structs.QuadTree.Node', 'goog.structs.QuadTree.Point'], ['goog.math.Coordinate']); +goog.addDependency('structs/queue.js', ['goog.structs.Queue'], ['goog.array']); +goog.addDependency('structs/set.js', ['goog.structs.Set'], ['goog.structs', 'goog.structs.Collection', 'goog.structs.Map']); +goog.addDependency('structs/simplepool.js', ['goog.structs.SimplePool'], ['goog.Disposable']); +goog.addDependency('structs/stringset.js', ['goog.structs.StringSet'], ['goog.iter']); +goog.addDependency('structs/structs.js', ['goog.structs'], ['goog.array', 'goog.object']); +goog.addDependency('structs/treenode.js', ['goog.structs.TreeNode'], ['goog.array', 'goog.asserts', 'goog.structs.Node']); +goog.addDependency('structs/trie.js', ['goog.structs.Trie'], ['goog.object', 'goog.structs']); +goog.addDependency('style/bidi.js', ['goog.style.bidi'], ['goog.dom', 'goog.style', 'goog.userAgent']); +goog.addDependency('style/cursor.js', ['goog.style.cursor'], ['goog.userAgent']); +goog.addDependency('style/style.js', ['goog.style'], ['goog.array', 'goog.dom', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.userAgent']); +goog.addDependency('style/style_test.js', ['goog.style_test'], ['goog.dom', 'goog.style', 'goog.testing.asserts']); +goog.addDependency('style/transition.js', ['goog.style.transition', 'goog.style.transition.Css3Property'], ['goog.array', 'goog.asserts', 'goog.userAgent']); +goog.addDependency('testing/asserts.js', ['goog.testing.JsUnitException', 'goog.testing.asserts'], ['goog.testing.stacktrace']); +goog.addDependency('testing/async/mockcontrol.js', ['goog.testing.async.MockControl'], ['goog.asserts', 'goog.async.Deferred', 'goog.debug', 'goog.testing.asserts', 'goog.testing.mockmatchers.IgnoreArgument']); +goog.addDependency('testing/asynctestcase.js', ['goog.testing.AsyncTestCase', 'goog.testing.AsyncTestCase.ControlBreakingException'], ['goog.testing.TestCase', 'goog.testing.TestCase.Test', 'goog.testing.asserts']); +goog.addDependency('testing/benchmark.js', ['goog.testing.benchmark'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTable', 'goog.testing.PerformanceTimer', 'goog.testing.TestCase']); +goog.addDependency('testing/benchmarks/jsbinarysizebutton.js', ['goog.ui.benchmarks.jsbinarysizebutton'], ['goog.array', 'goog.dom', 'goog.events', 'goog.ui.Button', 'goog.ui.ButtonSide', 'goog.ui.Component.EventType', 'goog.ui.CustomButton']); +goog.addDependency('testing/benchmarks/jsbinarysizetoolbar.js', ['goog.ui.benchmarks.jsbinarysizetoolbar'], ['goog.array', 'goog.dom', 'goog.events', 'goog.object', 'goog.ui.Component.EventType', 'goog.ui.Option', 'goog.ui.Toolbar', 'goog.ui.ToolbarButton', 'goog.ui.ToolbarSelect', 'goog.ui.ToolbarSeparator']); +goog.addDependency('testing/continuationtestcase.js', ['goog.testing.ContinuationTestCase', 'goog.testing.ContinuationTestCase.Step', 'goog.testing.ContinuationTestCase.Test'], ['goog.array', 'goog.events.EventHandler', 'goog.testing.TestCase', 'goog.testing.TestCase.Test', 'goog.testing.asserts']); +goog.addDependency('testing/deferredtestcase.js', ['goog.testing.DeferredTestCase'], ['goog.async.Deferred', 'goog.testing.AsyncTestCase', 'goog.testing.TestCase']); +goog.addDependency('testing/dom.js', ['goog.testing.dom'], ['goog.dom', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.dom.classes', 'goog.iter', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.asserts', 'goog.userAgent']); +goog.addDependency('testing/editor/dom.js', ['goog.testing.editor.dom'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagWalkType', 'goog.iter', 'goog.string', 'goog.testing.asserts']); +goog.addDependency('testing/editor/fieldmock.js', ['goog.testing.editor.FieldMock'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.testing.LooseMock']); +goog.addDependency('testing/editor/testhelper.js', ['goog.testing.editor.TestHelper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.node', 'goog.testing.dom']); +goog.addDependency('testing/events/eventobserver.js', ['goog.testing.events.EventObserver'], ['goog.array']); +goog.addDependency('testing/events/events.js', ['goog.testing.events', 'goog.testing.events.Event'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserEvent.MouseButton', 'goog.events.BrowserFeature', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.object', 'goog.style', 'goog.userAgent']); +goog.addDependency('testing/events/matchers.js', ['goog.testing.events.EventMatcher'], ['goog.events.Event', 'goog.testing.mockmatchers.ArgumentMatcher']); +goog.addDependency('testing/events/onlinehandler.js', ['goog.testing.events.OnlineHandler'], ['goog.events.EventTarget', 'goog.events.OnlineHandler.EventType']); +goog.addDependency('testing/expectedfailures.js', ['goog.testing.ExpectedFailures'], ['goog.debug.DivConsole', 'goog.debug.Logger', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.style', 'goog.testing.JsUnitException', 'goog.testing.TestCase', 'goog.testing.asserts']); +goog.addDependency('testing/fs/blob.js', ['goog.testing.fs.Blob'], ['goog.crypt.base64']); +goog.addDependency('testing/fs/entry.js', ['goog.testing.fs.DirectoryEntry', 'goog.testing.fs.Entry', 'goog.testing.fs.FileEntry'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntry.Behavior', 'goog.fs.Error', 'goog.functions', 'goog.object', 'goog.string', 'goog.testing.fs.File', 'goog.testing.fs.FileWriter']); +goog.addDependency('testing/fs/file.js', ['goog.testing.fs.File'], ['goog.testing.fs.Blob']); +goog.addDependency('testing/fs/filereader.js', ['goog.testing.fs.FileReader'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileReader.EventType', 'goog.fs.FileReader.ReadyState', 'goog.testing.fs.File', 'goog.testing.fs.ProgressEvent']); +goog.addDependency('testing/fs/filesystem.js', ['goog.testing.fs.FileSystem'], ['goog.testing.fs.DirectoryEntry']); +goog.addDependency('testing/fs/filewriter.js', ['goog.testing.fs.FileWriter'], ['goog.Timer', 'goog.events.Event', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileSaver.EventType', 'goog.fs.FileSaver.ReadyState', 'goog.string', 'goog.testing.fs.File', 'goog.testing.fs.ProgressEvent']); +goog.addDependency('testing/fs/fs.js', ['goog.testing.fs'], ['goog.Timer', 'goog.array', 'goog.fs', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem']); +goog.addDependency('testing/fs/progressevent.js', ['goog.testing.fs.ProgressEvent'], ['goog.events.Event']); +goog.addDependency('testing/functionmock.js', ['goog.testing', 'goog.testing.FunctionMock', 'goog.testing.GlobalFunctionMock', 'goog.testing.MethodMock'], ['goog.object', 'goog.testing.LooseMock', 'goog.testing.Mock', 'goog.testing.MockInterface', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock']); +goog.addDependency('testing/graphics.js', ['goog.testing.graphics'], ['goog.graphics.Path.Segment', 'goog.testing.asserts']); +goog.addDependency('testing/jsunit.js', ['goog.testing.jsunit'], ['goog.testing.TestCase', 'goog.testing.TestRunner']); +goog.addDependency('testing/loosemock.js', ['goog.testing.LooseExpectationCollection', 'goog.testing.LooseMock'], ['goog.array', 'goog.structs.Map', 'goog.testing.Mock']); +goog.addDependency('testing/messaging/mockmessagechannel.js', ['goog.testing.messaging.MockMessageChannel'], ['goog.messaging.AbstractChannel', 'goog.testing.asserts']); +goog.addDependency('testing/messaging/mockmessageevent.js', ['goog.testing.messaging.MockMessageEvent'], ['goog.events.BrowserEvent', 'goog.events.EventType', 'goog.testing.events']); +goog.addDependency('testing/messaging/mockmessageport.js', ['goog.testing.messaging.MockMessagePort'], ['goog.events.EventTarget']); +goog.addDependency('testing/messaging/mockportnetwork.js', ['goog.testing.messaging.MockPortNetwork'], ['goog.messaging.PortNetwork', 'goog.testing.messaging.MockMessageChannel']); +goog.addDependency('testing/mock.js', ['goog.testing.Mock', 'goog.testing.MockExpectation'], ['goog.array', 'goog.object', 'goog.testing.JsUnitException', 'goog.testing.MockInterface', 'goog.testing.mockmatchers']); +goog.addDependency('testing/mockclassfactory.js', ['goog.testing.MockClassFactory', 'goog.testing.MockClassRecord'], ['goog.array', 'goog.object', 'goog.testing.LooseMock', 'goog.testing.StrictMock', 'goog.testing.TestCase', 'goog.testing.mockmatchers']); +goog.addDependency('testing/mockclock.js', ['goog.testing.MockClock'], ['goog.Disposable', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event']); +goog.addDependency('testing/mockcontrol.js', ['goog.testing.MockControl'], ['goog.array', 'goog.testing', 'goog.testing.LooseMock', 'goog.testing.MockInterface', 'goog.testing.StrictMock']); +goog.addDependency('testing/mockinterface.js', ['goog.testing.MockInterface'], []); +goog.addDependency('testing/mockmatchers.js', ['goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.mockmatchers.IgnoreArgument', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.mockmatchers.ObjectEquals', 'goog.testing.mockmatchers.RegexpMatch', 'goog.testing.mockmatchers.SaveArgument', 'goog.testing.mockmatchers.TypeOf'], ['goog.array', 'goog.dom', 'goog.testing.asserts']); +goog.addDependency('testing/mockrandom.js', ['goog.testing.MockRandom'], ['goog.Disposable']); +goog.addDependency('testing/mockrange.js', ['goog.testing.MockRange'], ['goog.dom.AbstractRange', 'goog.testing.LooseMock']); +goog.addDependency('testing/mockstorage.js', ['goog.testing.MockStorage'], ['goog.structs.Map']); +goog.addDependency('testing/mockuseragent.js', ['goog.testing.MockUserAgent'], ['goog.Disposable', 'goog.userAgent']); +goog.addDependency('testing/multitestrunner.js', ['goog.testing.MultiTestRunner', 'goog.testing.MultiTestRunner.TestFrame'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.dom.classes', 'goog.events.EventHandler', 'goog.functions', 'goog.string', 'goog.ui.Component', 'goog.ui.ServerChart', 'goog.ui.ServerChart.ChartType', 'goog.ui.TableSorter']); +goog.addDependency('testing/net/xhrio.js', ['goog.testing.net.XhrIo'], ['goog.array', 'goog.dom.xml', 'goog.events', 'goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XhrIo.ResponseType', 'goog.net.XmlHttp', 'goog.object', 'goog.structs.Map', 'goog.uri.utils']); +goog.addDependency('testing/net/xhriopool.js', ['goog.testing.net.XhrIoPool'], ['goog.net.XhrIoPool', 'goog.testing.net.XhrIo']); +goog.addDependency('testing/objectpropertystring.js', ['goog.testing.ObjectPropertyString'], []); +goog.addDependency('testing/performancetable.js', ['goog.testing.PerformanceTable'], ['goog.dom', 'goog.testing.PerformanceTimer']); +goog.addDependency('testing/performancetimer.js', ['goog.testing.PerformanceTimer', 'goog.testing.PerformanceTimer.Task'], ['goog.array', 'goog.math']); +goog.addDependency('testing/propertyreplacer.js', ['goog.testing.PropertyReplacer'], ['goog.userAgent']); +goog.addDependency('testing/pseudorandom.js', ['goog.testing.PseudoRandom'], ['goog.Disposable']); +goog.addDependency('testing/recordfunction.js', ['goog.testing.FunctionCall', 'goog.testing.recordConstructor', 'goog.testing.recordFunction'], []); +goog.addDependency('testing/shardingtestcase.js', ['goog.testing.ShardingTestCase'], ['goog.asserts', 'goog.testing.TestCase']); +goog.addDependency('testing/singleton.js', ['goog.testing.singleton'], []); +goog.addDependency('testing/stacktrace.js', ['goog.testing.stacktrace', 'goog.testing.stacktrace.Frame'], []); +goog.addDependency('testing/storage/fakemechanism.js', ['goog.testing.storage.FakeMechanism'], ['goog.storage.mechanism.IterableMechanism', 'goog.structs.Map']); +goog.addDependency('testing/strictmock.js', ['goog.testing.StrictMock'], ['goog.array', 'goog.testing.Mock']); +goog.addDependency('testing/style/layoutasserts.js', ['goog.testing.style.layoutasserts'], ['goog.style', 'goog.testing.asserts', 'goog.testing.style']); +goog.addDependency('testing/style/style.js', ['goog.testing.style'], ['goog.dom', 'goog.math.Rect', 'goog.style']); +goog.addDependency('testing/testcase.js', ['goog.testing.TestCase', 'goog.testing.TestCase.Error', 'goog.testing.TestCase.Order', 'goog.testing.TestCase.Result', 'goog.testing.TestCase.Test'], ['goog.object', 'goog.testing.asserts', 'goog.testing.stacktrace']); +goog.addDependency('testing/testqueue.js', ['goog.testing.TestQueue'], []); +goog.addDependency('testing/testrunner.js', ['goog.testing.TestRunner'], ['goog.testing.TestCase']); +goog.addDependency('testing/ui/rendererasserts.js', ['goog.testing.ui.rendererasserts'], ['goog.testing.asserts']); +goog.addDependency('testing/ui/rendererharness.js', ['goog.testing.ui.RendererHarness'], ['goog.Disposable', 'goog.dom.NodeType', 'goog.testing.asserts']); +goog.addDependency('testing/ui/style.js', ['goog.testing.ui.style'], ['goog.array', 'goog.dom', 'goog.dom.classes', 'goog.testing.asserts']); +goog.addDependency('timer/timer.js', ['goog.Timer'], ['goog.events.EventTarget']); +goog.addDependency('tweak/entries.js', ['goog.tweak.BaseEntry', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting'], ['goog.array', 'goog.asserts', 'goog.debug.Logger', 'goog.object']); +goog.addDependency('tweak/registry.js', ['goog.tweak.Registry'], ['goog.asserts', 'goog.debug.Logger', 'goog.object', 'goog.string', 'goog.tweak.BaseEntry', 'goog.uri.utils']); +goog.addDependency('tweak/testhelpers.js', ['goog.tweak.testhelpers'], ['goog.tweak']); +goog.addDependency('tweak/tweak.js', ['goog.tweak', 'goog.tweak.ConfigParams'], ['goog.asserts', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting']); +goog.addDependency('tweak/tweakui.js', ['goog.tweak.EntriesPanel', 'goog.tweak.TweakUi'], ['goog.array', 'goog.asserts', 'goog.dom.DomHelper', 'goog.object', 'goog.style', 'goog.tweak', 'goog.ui.Zippy', 'goog.userAgent']); +goog.addDependency('ui/abstractspellchecker.js', ['goog.ui.AbstractSpellChecker', 'goog.ui.AbstractSpellChecker.AsyncResult'], ['goog.asserts', 'goog.dom', 'goog.dom.classes', 'goog.dom.selection', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.structs.Set', 'goog.style', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.PopupMenu']); +goog.addDependency('ui/ac/ac.js', ['goog.ui.ac'], ['goog.ui.ac.ArrayMatcher', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.Renderer']); +goog.addDependency('ui/ac/arraymatcher.js', ['goog.ui.ac.ArrayMatcher'], ['goog.iter', 'goog.string']); +goog.addDependency('ui/ac/autocomplete.js', ['goog.ui.ac.AutoComplete', 'goog.ui.ac.AutoComplete.EventType'], ['goog.events', 'goog.events.EventTarget']); +goog.addDependency('ui/ac/inputhandler.js', ['goog.ui.ac.InputHandler'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.dom.a11y', 'goog.dom.selection', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.string', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('ui/ac/remote.js', ['goog.ui.ac.Remote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RemoteArrayMatcher', 'goog.ui.ac.Renderer']); +goog.addDependency('ui/ac/remotearraymatcher.js', ['goog.ui.ac.RemoteArrayMatcher'], ['goog.Disposable', 'goog.Uri', 'goog.events', 'goog.json', 'goog.net.XhrIo']); +goog.addDependency('ui/ac/renderer.js', ['goog.ui.ac.Renderer', 'goog.ui.ac.Renderer.CustomRenderer'], ['goog.dispose', 'goog.dom', 'goog.dom.a11y', 'goog.dom.classes', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.iter', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.string', 'goog.style', 'goog.ui.IdGenerator', 'goog.ui.ac.AutoComplete.EventType', 'goog.userAgent']); +goog.addDependency('ui/ac/renderoptions.js', ['goog.ui.ac.RenderOptions'], []); +goog.addDependency('ui/ac/richinputhandler.js', ['goog.ui.ac.RichInputHandler'], ['goog.ui.ac.InputHandler']); +goog.addDependency('ui/ac/richremote.js', ['goog.ui.ac.RichRemote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.Remote', 'goog.ui.ac.Renderer', 'goog.ui.ac.RichInputHandler', 'goog.ui.ac.RichRemoteArrayMatcher']); +goog.addDependency('ui/ac/richremotearraymatcher.js', ['goog.ui.ac.RichRemoteArrayMatcher'], ['goog.ui.ac.RemoteArrayMatcher']); +goog.addDependency('ui/activitymonitor.js', ['goog.ui.ActivityMonitor'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType']); +goog.addDependency('ui/advancedtooltip.js', ['goog.ui.AdvancedTooltip'], ['goog.events.EventType', 'goog.math.Coordinate', 'goog.ui.Tooltip', 'goog.userAgent']); +goog.addDependency('ui/animatedzippy.js', ['goog.ui.AnimatedZippy'], ['goog.dom', 'goog.events', 'goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Transition.EventType', 'goog.fx.easing', 'goog.ui.Zippy', 'goog.ui.ZippyEvent']); +goog.addDependency('ui/attachablemenu.js', ['goog.ui.AttachableMenu'], ['goog.dom.a11y', 'goog.dom.a11y.State', 'goog.events.KeyCodes', 'goog.ui.ItemEvent', 'goog.ui.MenuBase']); +goog.addDependency('ui/autocomplete/arraymatcher.js', ['goog.ui.AutoComplete.ArrayMatcher'], ['goog.ui.AutoComplete', 'goog.ui.ac.ArrayMatcher']); +goog.addDependency('ui/autocomplete/autocomplete.js', ['goog.ui.AutoComplete', 'goog.ui.AutoComplete.EventType'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.AutoComplete.EventType']); +goog.addDependency('ui/autocomplete/basic.js', ['goog.ui.AutoComplete.Basic'], ['goog.ui.AutoComplete', 'goog.ui.AutoComplete.ArrayMatcher', 'goog.ui.AutoComplete.InputHandler', 'goog.ui.AutoComplete.Renderer', 'goog.ui.ac']); +goog.addDependency('ui/autocomplete/inputhandler.js', ['goog.ui.AutoComplete.InputHandler'], ['goog.ui.AutoComplete', 'goog.ui.ac.InputHandler']); +goog.addDependency('ui/autocomplete/remote.js', ['goog.ui.AutoComplete.Remote'], ['goog.ui.AutoComplete', 'goog.ui.AutoComplete.InputHandler', 'goog.ui.AutoComplete.RemoteArrayMatcher', 'goog.ui.AutoComplete.Renderer', 'goog.ui.ac.Remote']); +goog.addDependency('ui/autocomplete/remotearraymatcher.js', ['goog.ui.AutoComplete.RemoteArrayMatcher'], ['goog.ui.AutoComplete', 'goog.ui.ac.RemoteArrayMatcher']); +goog.addDependency('ui/autocomplete/renderer.js', ['goog.ui.AutoComplete.Renderer', 'goog.ui.AutoComplete.Renderer.CustomRenderer'], ['goog.ui.AutoComplete', 'goog.ui.ac.Renderer', 'goog.ui.ac.Renderer.CustomRenderer']); +goog.addDependency('ui/autocomplete/renderoptions.js', ['goog.ui.AutoComplete.RenderOptions'], ['goog.ui.AutoComplete', 'goog.ui.ac.RenderOptions']); +goog.addDependency('ui/autocomplete/richinputhandler.js', ['goog.ui.AutoComplete.RichInputHandler'], ['goog.ui.AutoComplete', 'goog.ui.AutoComplete.InputHandler', 'goog.ui.ac.RichInputHandler']); +goog.addDependency('ui/autocomplete/richremote.js', ['goog.ui.AutoComplete.RichRemote'], ['goog.ui.AutoComplete', 'goog.ui.AutoComplete.Remote', 'goog.ui.AutoComplete.Renderer', 'goog.ui.AutoComplete.RichInputHandler', 'goog.ui.AutoComplete.RichRemoteArrayMatcher', 'goog.ui.ac.RichRemote']); +goog.addDependency('ui/autocomplete/richremotearraymatcher.js', ['goog.ui.AutoComplete.RichRemoteArrayMatcher'], ['goog.ui.AutoComplete', 'goog.ui.AutoComplete.RemoteArrayMatcher', 'goog.ui.ac.RichRemoteArrayMatcher']); +goog.addDependency('ui/bidiinput.js', ['goog.ui.BidiInput'], ['goog.events', 'goog.events.InputHandler', 'goog.i18n.bidi', 'goog.ui.Component']); +goog.addDependency('ui/bubble.js', ['goog.ui.Bubble'], ['goog.Timer', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Box', 'goog.positioning', 'goog.positioning.AbsolutePosition', 'goog.positioning.AbstractPosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.style', 'goog.ui.Component', 'goog.ui.Popup', 'goog.ui.Popup.AnchoredPosition']); +goog.addDependency('ui/button.js', ['goog.ui.Button', 'goog.ui.Button.Side'], ['goog.events.KeyCodes', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Control', 'goog.ui.ControlContent', 'goog.ui.NativeButtonRenderer']); +goog.addDependency('ui/buttonrenderer.js', ['goog.ui.ButtonRenderer'], ['goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.a11y.State', 'goog.ui.ButtonSide', 'goog.ui.Component.State', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/buttonside.js', ['goog.ui.ButtonSide'], []); +goog.addDependency('ui/charcounter.js', ['goog.ui.CharCounter', 'goog.ui.CharCounter.Display'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.InputHandler']); +goog.addDependency('ui/charpicker.js', ['goog.ui.CharPicker'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyHandler', 'goog.i18n.CharListDecompressor', 'goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.structs.Set', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.ContainerScroller', 'goog.ui.FlatButtonRenderer', 'goog.ui.HoverCard', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.Tooltip.ElementTooltipPosition']); +goog.addDependency('ui/checkbox.js', ['goog.ui.Checkbox', 'goog.ui.Checkbox.State'], ['goog.dom.a11y', 'goog.dom.a11y.State', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.ui.CheckboxRenderer', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.Control', 'goog.ui.registry']); +goog.addDependency('ui/checkboxmenuitem.js', ['goog.ui.CheckBoxMenuItem'], ['goog.ui.ControlContent', 'goog.ui.MenuItem', 'goog.ui.registry']); +goog.addDependency('ui/checkboxrenderer.js', ['goog.ui.CheckboxRenderer'], ['goog.array', 'goog.asserts', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.a11y.State', 'goog.dom.classes', 'goog.object', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/colorbutton.js', ['goog.ui.ColorButton'], ['goog.ui.Button', 'goog.ui.ColorButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/colorbuttonrenderer.js', ['goog.ui.ColorButtonRenderer'], ['goog.dom.classes', 'goog.functions', 'goog.ui.ColorMenuButtonRenderer']); +goog.addDependency('ui/colormenubutton.js', ['goog.ui.ColorMenuButton'], ['goog.array', 'goog.object', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.ColorPalette', 'goog.ui.Component.EventType', 'goog.ui.ControlContent', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.registry']); +goog.addDependency('ui/colormenubuttonrenderer.js', ['goog.ui.ColorMenuButtonRenderer'], ['goog.color', 'goog.dom.classes', 'goog.ui.ControlContent', 'goog.ui.MenuButtonRenderer', 'goog.userAgent']); +goog.addDependency('ui/colorpalette.js', ['goog.ui.ColorPalette'], ['goog.array', 'goog.color', 'goog.dom', 'goog.style', 'goog.ui.Palette', 'goog.ui.PaletteRenderer']); +goog.addDependency('ui/colorpicker.js', ['goog.ui.ColorPicker', 'goog.ui.ColorPicker.EventType'], ['goog.ui.ColorPalette', 'goog.ui.Component', 'goog.ui.Component.State']); +goog.addDependency('ui/colorsplitbehavior.js', ['goog.ui.ColorSplitBehavior'], ['goog.ui.ColorButton', 'goog.ui.ColorMenuButton', 'goog.ui.SplitBehavior']); +goog.addDependency('ui/combobox.js', ['goog.ui.ComboBox', 'goog.ui.ComboBoxItem'], ['goog.Timer', 'goog.debug.Logger', 'goog.dom.classes', 'goog.events', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.ItemEvent', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.registry', 'goog.userAgent']); +goog.addDependency('ui/component.js', ['goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Component.State'], ['goog.array', 'goog.array.ArrayLike', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.object', 'goog.style', 'goog.ui.IdGenerator']); +goog.addDependency('ui/container.js', ['goog.ui.Container', 'goog.ui.Container.EventType', 'goog.ui.Container.Orientation'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.State', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.ContainerRenderer']); +goog.addDependency('ui/containerrenderer.js', ['goog.ui.ContainerRenderer'], ['goog.array', 'goog.dom', 'goog.dom.a11y', 'goog.dom.classes', 'goog.string', 'goog.style', 'goog.ui.Separator', 'goog.ui.registry', 'goog.userAgent']); +goog.addDependency('ui/containerscroller.js', ['goog.ui.ContainerScroller'], ['goog.Timer', 'goog.events.EventHandler', 'goog.style', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.ui.Container.EventType']); +goog.addDependency('ui/control.js', ['goog.ui.Control'], ['goog.array', 'goog.dom', 'goog.events.BrowserEvent.MouseButton', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.string', 'goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.ControlContent', 'goog.ui.ControlRenderer', 'goog.ui.decorate', 'goog.ui.registry', 'goog.userAgent']); +goog.addDependency('ui/controlcontent.js', ['goog.ui.ControlContent'], []); +goog.addDependency('ui/controlrenderer.js', ['goog.ui.ControlRenderer'], ['goog.array', 'goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.State', 'goog.dom.classes', 'goog.object', 'goog.style', 'goog.ui.Component.State', 'goog.ui.ControlContent', 'goog.userAgent']); +goog.addDependency('ui/cookieeditor.js', ['goog.ui.CookieEditor'], ['goog.dom', 'goog.dom.TagName', 'goog.events.EventType', 'goog.net.cookies', 'goog.string', 'goog.style', 'goog.ui.Component']); +goog.addDependency('ui/css3buttonrenderer.js', ['goog.ui.Css3ButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ControlContent', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']); +goog.addDependency('ui/css3menubuttonrenderer.js', ['goog.ui.Css3MenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.ControlContent', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/cssnames.js', ['goog.ui.INLINE_BLOCK_CLASSNAME'], []); +goog.addDependency('ui/custombutton.js', ['goog.ui.CustomButton'], ['goog.ui.Button', 'goog.ui.ControlContent', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/custombuttonrenderer.js', ['goog.ui.CustomButtonRenderer'], ['goog.dom', 'goog.dom.classes', 'goog.string', 'goog.ui.ButtonRenderer', 'goog.ui.ControlContent', 'goog.ui.INLINE_BLOCK_CLASSNAME']); +goog.addDependency('ui/customcolorpalette.js', ['goog.ui.CustomColorPalette'], ['goog.color', 'goog.dom', 'goog.ui.ColorPalette']); +goog.addDependency('ui/datepicker.js', ['goog.ui.DatePicker', 'goog.ui.DatePicker.Events', 'goog.ui.DatePickerEvent'], ['goog.date', 'goog.date.Date', 'goog.date.Interval', 'goog.dom', 'goog.dom.a11y', 'goog.dom.classes', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.style', 'goog.ui.Component', 'goog.ui.IdGenerator']); +goog.addDependency('ui/decorate.js', ['goog.ui.decorate'], ['goog.ui.registry']); +goog.addDependency('ui/dialog.js', ['goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.ButtonSet.DefaultButtons', 'goog.ui.Dialog.DefaultButtonCaptions', 'goog.ui.Dialog.DefaultButtonKeys', 'goog.ui.Dialog.Event', 'goog.ui.Dialog.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.a11y', 'goog.dom.classes', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.structs', 'goog.structs.Map', 'goog.style', 'goog.ui.ModalPopup', 'goog.userAgent']); +goog.addDependency('ui/dimensionpicker.js', ['goog.ui.DimensionPicker'], ['goog.events.EventType', 'goog.math.Size', 'goog.ui.Control', 'goog.ui.DimensionPickerRenderer', 'goog.ui.registry']); +goog.addDependency('ui/dimensionpickerrenderer.js', ['goog.ui.DimensionPickerRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent']); +goog.addDependency('ui/dragdropdetector.js', ['goog.ui.DragDropDetector', 'goog.ui.DragDropDetector.EventType', 'goog.ui.DragDropDetector.ImageDropEvent', 'goog.ui.DragDropDetector.LinkDropEvent'], ['goog.dom', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.userAgent']); +goog.addDependency('ui/drilldownrow.js', ['goog.ui.DrilldownRow'], ['goog.dom', 'goog.dom.classes', 'goog.events', 'goog.ui.Component']); +goog.addDependency('ui/editor/abstractdialog.js', ['goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType'], ['goog.dom', 'goog.dom.classes', 'goog.events.EventTarget', 'goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.DefaultButtonKeys', 'goog.ui.Dialog.Event', 'goog.ui.Dialog.EventType']); +goog.addDependency('ui/editor/bubble.js', ['goog.ui.editor.Bubble'], ['goog.debug.Logger', 'goog.dom', 'goog.dom.ViewportSizeMonitor', 'goog.editor.style', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Box', 'goog.positioning', 'goog.string', 'goog.style', 'goog.ui.Component.EventType', 'goog.ui.PopupBase', 'goog.ui.PopupBase.EventType', 'goog.userAgent']); +goog.addDependency('ui/editor/defaulttoolbar.js', ['goog.ui.editor.DefaultToolbar'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.editor.Command', 'goog.style', 'goog.ui.ControlContent', 'goog.ui.editor.ToolbarFactory', 'goog.ui.editor.messages']); +goog.addDependency('ui/editor/equationeditordialog.js', ['goog.ui.editor.EquationEditorDialog'], ['goog.editor.Command', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.EquationEditorOkEvent', 'goog.ui.equation.ChangeEvent', 'goog.ui.equation.TexEditor']); +goog.addDependency('ui/editor/equationeditorokevent.js', ['goog.ui.editor.EquationEditorOkEvent'], ['goog.events.Event', 'goog.ui.editor.AbstractDialog']); +goog.addDependency('ui/editor/linkdialog.js', ['goog.ui.editor.LinkDialog', 'goog.ui.editor.LinkDialog.BeforeTestLinkEvent', 'goog.ui.editor.LinkDialog.EventType', 'goog.ui.editor.LinkDialog.OkEvent'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.dom.classes', 'goog.dom.selection', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.editor.focus', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.InputHandler.EventType', 'goog.string', 'goog.style', 'goog.ui.Button', 'goog.ui.LinkButtonRenderer', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType', 'goog.ui.editor.TabPane', 'goog.ui.editor.messages', 'goog.userAgent', 'goog.window']); +goog.addDependency('ui/editor/messages.js', ['goog.ui.editor.messages'], []); +goog.addDependency('ui/editor/tabpane.js', ['goog.ui.editor.TabPane'], ['goog.dom.TagName', 'goog.events.EventHandler', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.Tab', 'goog.ui.TabBar']); +goog.addDependency('ui/editor/toolbarcontroller.js', ['goog.ui.editor.ToolbarController'], ['goog.editor.Field.EventType', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.ui.Component.EventType']); +goog.addDependency('ui/editor/toolbarfactory.js', ['goog.ui.editor.ToolbarFactory'], ['goog.array', 'goog.dom', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Component.State', 'goog.ui.Container.Orientation', 'goog.ui.ControlContent', 'goog.ui.Option', 'goog.ui.Toolbar', 'goog.ui.ToolbarButton', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarMenuButton', 'goog.ui.ToolbarRenderer', 'goog.ui.ToolbarSelect', 'goog.userAgent']); +goog.addDependency('ui/emoji/emoji.js', ['goog.ui.emoji.Emoji'], []); +goog.addDependency('ui/emoji/emojipalette.js', ['goog.ui.emoji.EmojiPalette'], ['goog.events.Event', 'goog.events.EventType', 'goog.net.ImageLoader', 'goog.ui.Palette', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPaletteRenderer']); +goog.addDependency('ui/emoji/emojipaletterenderer.js', ['goog.ui.emoji.EmojiPaletteRenderer'], ['goog.dom', 'goog.dom.a11y', 'goog.ui.PaletteRenderer', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.SpriteInfo']); +goog.addDependency('ui/emoji/emojipicker.js', ['goog.ui.emoji.EmojiPicker'], ['goog.debug.Logger', 'goog.dom', 'goog.ui.Component', 'goog.ui.TabPane', 'goog.ui.TabPane.TabPage', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPalette', 'goog.ui.emoji.EmojiPaletteRenderer', 'goog.ui.emoji.ProgressiveEmojiPaletteRenderer']); +goog.addDependency('ui/emoji/popupemojipicker.js', ['goog.ui.emoji.PopupEmojiPicker'], ['goog.dom', 'goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.ui.Component', 'goog.ui.Popup', 'goog.ui.emoji.EmojiPicker']); +goog.addDependency('ui/emoji/progressiveemojipaletterenderer.js', ['goog.ui.emoji.ProgressiveEmojiPaletteRenderer'], ['goog.ui.emoji.EmojiPaletteRenderer']); +goog.addDependency('ui/emoji/spriteinfo.js', ['goog.ui.emoji.SpriteInfo'], []); +goog.addDependency('ui/equation/arrowpalette.js', ['goog.ui.equation.ArrowPalette'], ['goog.math.Size', 'goog.ui.equation.Palette']); +goog.addDependency('ui/equation/changeevent.js', ['goog.ui.equation.ChangeEvent'], ['goog.events.Event', 'goog.events.EventType']); +goog.addDependency('ui/equation/comparisonpalette.js', ['goog.ui.equation.ComparisonPalette'], ['goog.math.Size', 'goog.ui.equation.Palette']); +goog.addDependency('ui/equation/editorpane.js', ['goog.ui.equation.EditorPane'], ['goog.dom', 'goog.style', 'goog.ui.Component']); +goog.addDependency('ui/equation/equationeditor.js', ['goog.ui.equation.EquationEditor'], ['goog.dom', 'goog.events', 'goog.ui.Component', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.equation.EditorPane', 'goog.ui.equation.ImageRenderer', 'goog.ui.equation.TexPane']); +goog.addDependency('ui/equation/equationeditordialog.js', ['goog.ui.equation.EquationEditorDialog'], ['goog.dom', 'goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.equation.EquationEditor', 'goog.ui.equation.ImageRenderer', 'goog.ui.equation.TexEditor']); +goog.addDependency('ui/equation/greekpalette.js', ['goog.ui.equation.GreekPalette'], ['goog.math.Size', 'goog.ui.equation.Palette']); +goog.addDependency('ui/equation/imagerenderer.js', ['goog.ui.equation.ImageRenderer'], ['goog.dom.TagName', 'goog.dom.classes', 'goog.string', 'goog.uri.utils']); +goog.addDependency('ui/equation/mathpalette.js', ['goog.ui.equation.MathPalette'], ['goog.math.Size', 'goog.ui.equation.Palette']); +goog.addDependency('ui/equation/menupalette.js', ['goog.ui.equation.MenuPalette', 'goog.ui.equation.MenuPaletteRenderer'], ['goog.math.Size', 'goog.style', 'goog.ui.equation.Palette', 'goog.ui.equation.PaletteRenderer']); +goog.addDependency('ui/equation/palette.js', ['goog.ui.equation.Palette', 'goog.ui.equation.PaletteEvent', 'goog.ui.equation.PaletteRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.Palette', 'goog.ui.equation.ImageRenderer']); +goog.addDependency('ui/equation/palettemanager.js', ['goog.ui.equation.PaletteManager'], ['goog.Timer', 'goog.events.EventTarget', 'goog.ui.equation.ArrowPalette', 'goog.ui.equation.ComparisonPalette', 'goog.ui.equation.GreekPalette', 'goog.ui.equation.MathPalette', 'goog.ui.equation.MenuPalette', 'goog.ui.equation.Palette', 'goog.ui.equation.SymbolPalette']); +goog.addDependency('ui/equation/symbolpalette.js', ['goog.ui.equation.SymbolPalette'], ['goog.math.Size', 'goog.ui.equation.Palette']); +goog.addDependency('ui/equation/texeditor.js', ['goog.ui.equation.TexEditor'], ['goog.dom', 'goog.ui.Component', 'goog.ui.equation.ImageRenderer', 'goog.ui.equation.TexPane']); +goog.addDependency('ui/equation/texpane.js', ['goog.ui.equation.TexPane'], ['goog.Timer', 'goog.dom', 'goog.dom.TagName', 'goog.dom.selection', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.equation.ChangeEvent', 'goog.ui.equation.EditorPane', 'goog.ui.equation.ImageRenderer', 'goog.ui.equation.PaletteManager']); +goog.addDependency('ui/filteredmenu.js', ['goog.ui.FilteredMenu'], ['goog.dom', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.string', 'goog.ui.FilterObservingMenuItem', 'goog.ui.Menu']); +goog.addDependency('ui/filterobservingmenuitem.js', ['goog.ui.FilterObservingMenuItem'], ['goog.ui.ControlContent', 'goog.ui.FilterObservingMenuItemRenderer', 'goog.ui.MenuItem', 'goog.ui.registry']); +goog.addDependency('ui/filterobservingmenuitemrenderer.js', ['goog.ui.FilterObservingMenuItemRenderer'], ['goog.ui.MenuItemRenderer']); +goog.addDependency('ui/flatbuttonrenderer.js', ['goog.ui.FlatButtonRenderer'], ['goog.dom.classes', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']); +goog.addDependency('ui/flatmenubuttonrenderer.js', ['goog.ui.FlatMenuButtonRenderer'], ['goog.style', 'goog.ui.ControlContent', 'goog.ui.FlatButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuRenderer', 'goog.ui.registry']); +goog.addDependency('ui/formpost.js', ['goog.ui.FormPost'], ['goog.array', 'goog.dom.TagName', 'goog.string', 'goog.string.StringBuffer', 'goog.ui.Component']); +goog.addDependency('ui/gauge.js', ['goog.ui.Gauge', 'goog.ui.GaugeColoredRange'], ['goog.dom', 'goog.dom.a11y', 'goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Transition.EventType', 'goog.fx.easing', 'goog.graphics', 'goog.graphics.Font', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.ui.Component', 'goog.ui.GaugeTheme']); +goog.addDependency('ui/gaugetheme.js', ['goog.ui.GaugeTheme'], ['goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke']); +goog.addDependency('ui/hovercard.js', ['goog.ui.HoverCard', 'goog.ui.HoverCard.EventType', 'goog.ui.HoverCard.TriggerEvent'], ['goog.dom', 'goog.events', 'goog.events.EventType', 'goog.ui.AdvancedTooltip']); +goog.addDependency('ui/hsvapalette.js', ['goog.ui.HsvaPalette'], ['goog.array', 'goog.color', 'goog.color.alpha', 'goog.events.EventType', 'goog.ui.Component.EventType', 'goog.ui.HsvPalette']); +goog.addDependency('ui/hsvpalette.js', ['goog.ui.HsvPalette'], ['goog.color', 'goog.dom', 'goog.dom.DomHelper', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.userAgent']); +goog.addDependency('ui/idgenerator.js', ['goog.ui.IdGenerator'], []); +goog.addDependency('ui/idletimer.js', ['goog.ui.IdleTimer'], ['goog.Timer', 'goog.events', 'goog.events.EventTarget', 'goog.structs.Set', 'goog.ui.ActivityMonitor']); +goog.addDependency('ui/iframemask.js', ['goog.ui.IframeMask'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.dom.DomHelper', 'goog.dom.iframe', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.style']); +goog.addDependency('ui/imagelessbuttonrenderer.js', ['goog.ui.ImagelessButtonRenderer'], ['goog.dom.classes', 'goog.ui.Button', 'goog.ui.ControlContent', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']); +goog.addDependency('ui/imagelessmenubuttonrenderer.js', ['goog.ui.ImagelessMenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.ui.ControlContent', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/inputdatepicker.js', ['goog.ui.InputDatePicker'], ['goog.date.DateTime', 'goog.dom', 'goog.string', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker']); +goog.addDependency('ui/itemevent.js', ['goog.ui.ItemEvent'], ['goog.events.Event']); +goog.addDependency('ui/keyboardshortcuthandler.js', ['goog.ui.KeyboardShortcutEvent', 'goog.ui.KeyboardShortcutHandler', 'goog.ui.KeyboardShortcutHandler.EventType'], ['goog.Timer', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyNames', 'goog.object']); +goog.addDependency('ui/labelinput.js', ['goog.ui.LabelInput'], ['goog.Timer', 'goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.State', 'goog.dom.classes', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.ui.Component', 'goog.userAgent']); +goog.addDependency('ui/linkbuttonrenderer.js', ['goog.ui.LinkButtonRenderer'], ['goog.ui.Button', 'goog.ui.FlatButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/media/flashobject.js', ['goog.ui.media.FlashObject', 'goog.ui.media.FlashObject.ScriptAccessLevel', 'goog.ui.media.FlashObject.Wmodes'], ['goog.asserts', 'goog.debug.Logger', 'goog.events.EventHandler', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.ui.Component.Error', 'goog.userAgent', 'goog.userAgent.flash']); +goog.addDependency('ui/media/flickr.js', ['goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel'], ['goog.object', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/media/googlevideo.js', ['goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/media/media.js', ['goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], ['goog.style', 'goog.ui.Component.State', 'goog.ui.Control', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/media/mediamodel.js', ['goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Category', 'goog.ui.media.MediaModel.Credit', 'goog.ui.media.MediaModel.Credit.Role', 'goog.ui.media.MediaModel.Credit.Scheme', 'goog.ui.media.MediaModel.Medium', 'goog.ui.media.MediaModel.MimeType', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaModel.SubTitle', 'goog.ui.media.MediaModel.Thumbnail'], ['goog.array']); +goog.addDependency('ui/media/mp3.js', ['goog.ui.media.Mp3'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/media/photo.js', ['goog.ui.media.Photo'], ['goog.ui.media.Media', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/media/picasa.js', ['goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel'], ['goog.object', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/media/vimeo.js', ['goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/media/youtube.js', ['goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel'], ['goog.string', 'goog.ui.Component.Error', 'goog.ui.Component.State', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaModel.Thumbnail', 'goog.ui.media.MediaRenderer']); +goog.addDependency('ui/menu.js', ['goog.ui.Menu', 'goog.ui.Menu.EventType'], ['goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.MenuHeader', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.MenuSeparator']); +goog.addDependency('ui/menubar.js', ['goog.ui.menuBar'], ['goog.ui.MenuBarRenderer']); +goog.addDependency('ui/menubardecorator.js', ['goog.ui.menuBarDecorator'], ['goog.ui.Container', 'goog.ui.menuBar']); +goog.addDependency('ui/menubarrenderer.js', ['goog.ui.MenuBarRenderer'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.a11y.State', 'goog.ui.ContainerRenderer']); +goog.addDependency('ui/menubase.js', ['goog.ui.MenuBase'], ['goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.ui.Popup']); +goog.addDependency('ui/menubutton.js', ['goog.ui.MenuButton'], ['goog.Timer', 'goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.State', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler.EventType', 'goog.math.Box', 'goog.math.Rect', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.style', 'goog.ui.Button', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.Menu', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('ui/menubuttonrenderer.js', ['goog.ui.MenuButtonRenderer'], ['goog.dom', 'goog.style', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuRenderer', 'goog.userAgent']); +goog.addDependency('ui/menuheader.js', ['goog.ui.MenuHeader'], ['goog.ui.Component.State', 'goog.ui.Control', 'goog.ui.MenuHeaderRenderer', 'goog.ui.registry']); +goog.addDependency('ui/menuheaderrenderer.js', ['goog.ui.MenuHeaderRenderer'], ['goog.dom', 'goog.dom.classes', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/menuitem.js', ['goog.ui.MenuItem'], ['goog.array', 'goog.dom', 'goog.dom.classes', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.string', 'goog.ui.Component.State', 'goog.ui.Control', 'goog.ui.ControlContent', 'goog.ui.MenuItemRenderer', 'goog.ui.registry']); +goog.addDependency('ui/menuitemrenderer.js', ['goog.ui.MenuItemRenderer'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.classes', 'goog.ui.Component.State', 'goog.ui.ControlContent', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/menurenderer.js', ['goog.ui.MenuRenderer'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.a11y.State', 'goog.ui.ContainerRenderer', 'goog.ui.Separator']); +goog.addDependency('ui/menuseparator.js', ['goog.ui.MenuSeparator'], ['goog.ui.MenuSeparatorRenderer', 'goog.ui.Separator', 'goog.ui.registry']); +goog.addDependency('ui/menuseparatorrenderer.js', ['goog.ui.MenuSeparatorRenderer'], ['goog.dom', 'goog.dom.classes', 'goog.ui.ControlContent', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/mockactivitymonitor.js', ['goog.ui.MockActivityMonitor'], ['goog.events.EventType', 'goog.ui.ActivityMonitor']); +goog.addDependency('ui/modalpopup.js', ['goog.ui.ModalPopup'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.dom.iframe', 'goog.events', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.fx.Transition', 'goog.style', 'goog.ui.Component', 'goog.ui.PopupBase.EventType', 'goog.userAgent']); +goog.addDependency('ui/nativebuttonrenderer.js', ['goog.ui.NativeButtonRenderer'], ['goog.dom.classes', 'goog.events.EventType', 'goog.ui.ButtonRenderer', 'goog.ui.Component.State']); +goog.addDependency('ui/offlineinstalldialog.js', ['goog.ui.OfflineInstallDialog', 'goog.ui.OfflineInstallDialog.ButtonKeyType', 'goog.ui.OfflineInstallDialog.EnableScreen', 'goog.ui.OfflineInstallDialog.InstallScreen', 'goog.ui.OfflineInstallDialog.InstallingGearsScreen', 'goog.ui.OfflineInstallDialog.ScreenType', 'goog.ui.OfflineInstallDialog.UpgradeScreen', 'goog.ui.OfflineInstallDialogScreen'], ['goog.Disposable', 'goog.dom.classes', 'goog.gears', 'goog.string', 'goog.string.StringBuffer', 'goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.EventType', 'goog.window']); +goog.addDependency('ui/offlinestatuscard.js', ['goog.ui.OfflineStatusCard', 'goog.ui.OfflineStatusCard.EventType'], ['goog.dom', 'goog.events.EventType', 'goog.gears.StatusType', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.ui.ProgressBar']); +goog.addDependency('ui/offlinestatuscomponent.js', ['goog.ui.OfflineStatusComponent', 'goog.ui.OfflineStatusComponent.StatusClassNames'], ['goog.dom.classes', 'goog.events.EventType', 'goog.gears.StatusType', 'goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.ui.Component', 'goog.ui.OfflineStatusCard.EventType', 'goog.ui.Popup']); +goog.addDependency('ui/option.js', ['goog.ui.Option'], ['goog.ui.Component.EventType', 'goog.ui.ControlContent', 'goog.ui.MenuItem', 'goog.ui.registry']); +goog.addDependency('ui/palette.js', ['goog.ui.Palette'], ['goog.array', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Control', 'goog.ui.PaletteRenderer', 'goog.ui.SelectionModel']); +goog.addDependency('ui/paletterenderer.js', ['goog.ui.PaletteRenderer'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.a11y', 'goog.dom.classes', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent']); +goog.addDependency('ui/plaintextspellchecker.js', ['goog.ui.PlainTextSpellChecker'], ['goog.Timer', 'goog.dom', 'goog.dom.a11y', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.AbstractSpellChecker.AsyncResult', 'goog.ui.Component.EventType', 'goog.userAgent']); +goog.addDependency('ui/popup.js', ['goog.ui.Popup', 'goog.ui.Popup.AbsolutePosition', 'goog.ui.Popup.AnchoredPosition', 'goog.ui.Popup.AnchoredViewPortPosition', 'goog.ui.Popup.ClientPosition', 'goog.ui.Popup.Corner', 'goog.ui.Popup.Overflow', 'goog.ui.Popup.ViewPortClientPosition', 'goog.ui.Popup.ViewPortPosition'], ['goog.math.Box', 'goog.positioning', 'goog.positioning.AbsolutePosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.ClientPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.positioning.ViewportClientPosition', 'goog.positioning.ViewportPosition', 'goog.style', 'goog.ui.PopupBase']); +goog.addDependency('ui/popupbase.js', ['goog.ui.PopupBase', 'goog.ui.PopupBase.EventType', 'goog.ui.PopupBase.Type'], ['goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.fx.Transition.EventType', 'goog.style', 'goog.userAgent']); +goog.addDependency('ui/popupcolorpicker.js', ['goog.ui.PopupColorPicker'], ['goog.dom.classes', 'goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.ColorPicker', 'goog.ui.ColorPicker.EventType', 'goog.ui.Component', 'goog.ui.Popup']); +goog.addDependency('ui/popupdatepicker.js', ['goog.ui.PopupDatePicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.style', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.DatePicker.Events', 'goog.ui.Popup', 'goog.ui.PopupBase.EventType']); +goog.addDependency('ui/popupmenu.js', ['goog.ui.PopupMenu'], ['goog.events.EventType', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.ViewportClientPosition', 'goog.structs', 'goog.structs.Map', 'goog.style', 'goog.ui.Component.EventType', 'goog.ui.Menu', 'goog.ui.PopupBase', 'goog.userAgent']); +goog.addDependency('ui/progressbar.js', ['goog.ui.ProgressBar', 'goog.ui.ProgressBar.Orientation'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.classes', 'goog.events', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.ui.RangeModel', 'goog.userAgent']); +goog.addDependency('ui/prompt.js', ['goog.ui.Prompt'], ['goog.Timer', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.functions', 'goog.ui.Component.Error', 'goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.DefaultButtonKeys', 'goog.ui.Dialog.EventType', 'goog.userAgent']); +goog.addDependency('ui/rangemodel.js', ['goog.ui.RangeModel'], ['goog.events.EventTarget', 'goog.ui.Component.EventType']); +goog.addDependency('ui/ratings.js', ['goog.ui.Ratings', 'goog.ui.Ratings.EventType'], ['goog.dom.a11y', 'goog.dom.classes', 'goog.events.EventType', 'goog.ui.Component']); +goog.addDependency('ui/registry.js', ['goog.ui.registry'], ['goog.dom.classes']); +goog.addDependency('ui/richtextspellchecker.js', ['goog.ui.RichTextSpellChecker'], ['goog.Timer', 'goog.dom', 'goog.dom.NodeType', 'goog.events', 'goog.events.EventType', 'goog.string.StringBuffer', 'goog.ui.AbstractSpellChecker', 'goog.ui.AbstractSpellChecker.AsyncResult']); +goog.addDependency('ui/roundedpanel.js', ['goog.ui.BaseRoundedPanel', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.ui.RoundedPanel.Corner'], ['goog.dom', 'goog.dom.classes', 'goog.graphics', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Component', 'goog.userAgent']); +goog.addDependency('ui/roundedtabrenderer.js', ['goog.ui.RoundedTabRenderer'], ['goog.dom', 'goog.ui.Tab', 'goog.ui.TabBar.Location', 'goog.ui.TabRenderer', 'goog.ui.registry']); +goog.addDependency('ui/scrollfloater.js', ['goog.ui.ScrollFloater', 'goog.ui.ScrollFloater.EventType'], ['goog.dom', 'goog.dom.classes', 'goog.events.EventType', 'goog.object', 'goog.style', 'goog.ui.Component', 'goog.userAgent']); +goog.addDependency('ui/select.js', ['goog.ui.Select'], ['goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.a11y.State', 'goog.events.EventType', 'goog.ui.Component.EventType', 'goog.ui.ControlContent', 'goog.ui.MenuButton', 'goog.ui.SelectionModel', 'goog.ui.registry']); +goog.addDependency('ui/selectionmenubutton.js', ['goog.ui.SelectionMenuButton', 'goog.ui.SelectionMenuButton.SelectionState'], ['goog.events.EventType', 'goog.ui.Component.EventType', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem']); +goog.addDependency('ui/selectionmodel.js', ['goog.ui.SelectionModel'], ['goog.array', 'goog.events.EventTarget', 'goog.events.EventType']); +goog.addDependency('ui/separator.js', ['goog.ui.Separator'], ['goog.dom.a11y', 'goog.ui.Component.State', 'goog.ui.Control', 'goog.ui.MenuSeparatorRenderer', 'goog.ui.registry']); +goog.addDependency('ui/serverchart.js', ['goog.ui.ServerChart', 'goog.ui.ServerChart.AxisDisplayType', 'goog.ui.ServerChart.ChartType', 'goog.ui.ServerChart.EncodingType', 'goog.ui.ServerChart.Event', 'goog.ui.ServerChart.LegendPosition', 'goog.ui.ServerChart.MaximumValue', 'goog.ui.ServerChart.MultiAxisAlignment', 'goog.ui.ServerChart.MultiAxisType', 'goog.ui.ServerChart.UriParam', 'goog.ui.ServerChart.UriTooLongEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.events.Event', 'goog.string', 'goog.ui.Component']); +goog.addDependency('ui/slider.js', ['goog.ui.Slider', 'goog.ui.Slider.Orientation'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.ui.SliderBase', 'goog.ui.SliderBase.Orientation']); +goog.addDependency('ui/sliderbase.js', ['goog.ui.SliderBase', 'goog.ui.SliderBase.Orientation'], ['goog.Timer', 'goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.dom.a11y.State', 'goog.dom.classes', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.events.MouseWheelHandler', 'goog.events.MouseWheelHandler.EventType', 'goog.fx.AnimationParallelQueue', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType', 'goog.fx.Transition.EventType', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Slide', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.ui.RangeModel']); +goog.addDependency('ui/splitbehavior.js', ['goog.ui.SplitBehavior', 'goog.ui.SplitBehavior.DefaultHandlers'], ['goog.Disposable', 'goog.array', 'goog.dispose', 'goog.dom', 'goog.dom.DomHelper', 'goog.dom.classes', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.string', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.decorate', 'goog.ui.registry']); +goog.addDependency('ui/splitpane.js', ['goog.ui.SplitPane', 'goog.ui.SplitPane.Orientation'], ['goog.dom', 'goog.dom.classes', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.userAgent']); +goog.addDependency('ui/style/app/buttonrenderer.js', ['goog.ui.style.app.ButtonRenderer'], ['goog.dom.classes', 'goog.ui.Button', 'goog.ui.ControlContent', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']); +goog.addDependency('ui/style/app/menubuttonrenderer.js', ['goog.ui.style.app.MenuButtonRenderer'], ['goog.array', 'goog.dom', 'goog.dom.a11y.Role', 'goog.style', 'goog.ui.ControlContent', 'goog.ui.Menu', 'goog.ui.MenuRenderer', 'goog.ui.style.app.ButtonRenderer']); +goog.addDependency('ui/style/app/primaryactionbuttonrenderer.js', ['goog.ui.style.app.PrimaryActionButtonRenderer'], ['goog.ui.Button', 'goog.ui.registry', 'goog.ui.style.app.ButtonRenderer']); +goog.addDependency('ui/submenu.js', ['goog.ui.SubMenu'], ['goog.Timer', 'goog.dom', 'goog.dom.classes', 'goog.events.KeyCodes', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.style', 'goog.ui.Component', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.ControlContent', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenuRenderer', 'goog.ui.registry']); +goog.addDependency('ui/submenurenderer.js', ['goog.ui.SubMenuRenderer'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.State', 'goog.dom.classes', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuItemRenderer']); +goog.addDependency('ui/tab.js', ['goog.ui.Tab'], ['goog.ui.Component.State', 'goog.ui.Control', 'goog.ui.ControlContent', 'goog.ui.TabRenderer', 'goog.ui.registry']); +goog.addDependency('ui/tabbar.js', ['goog.ui.TabBar', 'goog.ui.TabBar.Location'], ['goog.ui.Component.EventType', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.Tab', 'goog.ui.TabBarRenderer', 'goog.ui.registry']); +goog.addDependency('ui/tabbarrenderer.js', ['goog.ui.TabBarRenderer'], ['goog.dom.a11y.Role', 'goog.object', 'goog.ui.ContainerRenderer']); +goog.addDependency('ui/tablesorter.js', ['goog.ui.TableSorter', 'goog.ui.TableSorter.EventType'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.events', 'goog.events.EventType', 'goog.functions', 'goog.ui.Component']); +goog.addDependency('ui/tabpane.js', ['goog.ui.TabPane', 'goog.ui.TabPane.Events', 'goog.ui.TabPane.TabLocation', 'goog.ui.TabPane.TabPage', 'goog.ui.TabPaneEvent'], ['goog.dom', 'goog.dom.classes', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style']); +goog.addDependency('ui/tabrenderer.js', ['goog.ui.TabRenderer'], ['goog.dom.a11y.Role', 'goog.ui.Component.State', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/textarea.js', ['goog.ui.Textarea', 'goog.ui.Textarea.EventType'], ['goog.Timer', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.ui.Control', 'goog.ui.TextareaRenderer', 'goog.userAgent', 'goog.userAgent.product']); +goog.addDependency('ui/textarearenderer.js', ['goog.ui.TextareaRenderer'], ['goog.ui.Component.State', 'goog.ui.ControlRenderer']); +goog.addDependency('ui/togglebutton.js', ['goog.ui.ToggleButton'], ['goog.ui.Button', 'goog.ui.Component.State', 'goog.ui.ControlContent', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/toolbar.js', ['goog.ui.Toolbar'], ['goog.ui.Container', 'goog.ui.ToolbarRenderer']); +goog.addDependency('ui/toolbarbutton.js', ['goog.ui.ToolbarButton'], ['goog.ui.Button', 'goog.ui.ControlContent', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/toolbarbuttonrenderer.js', ['goog.ui.ToolbarButtonRenderer'], ['goog.ui.CustomButtonRenderer']); +goog.addDependency('ui/toolbarcolormenubutton.js', ['goog.ui.ToolbarColorMenuButton'], ['goog.ui.ColorMenuButton', 'goog.ui.ControlContent', 'goog.ui.ToolbarColorMenuButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/toolbarcolormenubuttonrenderer.js', ['goog.ui.ToolbarColorMenuButtonRenderer'], ['goog.dom.classes', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.ControlContent', 'goog.ui.MenuButtonRenderer', 'goog.ui.ToolbarMenuButtonRenderer']); +goog.addDependency('ui/toolbarmenubutton.js', ['goog.ui.ToolbarMenuButton'], ['goog.ui.ControlContent', 'goog.ui.MenuButton', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/toolbarmenubuttonrenderer.js', ['goog.ui.ToolbarMenuButtonRenderer'], ['goog.ui.MenuButtonRenderer']); +goog.addDependency('ui/toolbarrenderer.js', ['goog.ui.ToolbarRenderer'], ['goog.dom.a11y.Role', 'goog.ui.Container.Orientation', 'goog.ui.ContainerRenderer', 'goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer']); +goog.addDependency('ui/toolbarselect.js', ['goog.ui.ToolbarSelect'], ['goog.ui.ControlContent', 'goog.ui.Select', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/toolbarseparator.js', ['goog.ui.ToolbarSeparator'], ['goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer', 'goog.ui.registry']); +goog.addDependency('ui/toolbarseparatorrenderer.js', ['goog.ui.ToolbarSeparatorRenderer'], ['goog.dom.classes', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuSeparatorRenderer']); +goog.addDependency('ui/toolbartogglebutton.js', ['goog.ui.ToolbarToggleButton'], ['goog.ui.ControlContent', 'goog.ui.ToggleButton', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry']); +goog.addDependency('ui/tooltip.js', ['goog.ui.Tooltip', 'goog.ui.Tooltip.CursorTooltipPosition', 'goog.ui.Tooltip.ElementTooltipPosition', 'goog.ui.Tooltip.State'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.positioning.ViewportPosition', 'goog.structs.Set', 'goog.style', 'goog.ui.Popup', 'goog.ui.PopupBase']); +goog.addDependency('ui/tree/basenode.js', ['goog.ui.tree.BaseNode', 'goog.ui.tree.BaseNode.EventType'], ['goog.Timer', 'goog.asserts', 'goog.dom.a11y', 'goog.events.KeyCodes', 'goog.string', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.Component', 'goog.userAgent']); +goog.addDependency('ui/tree/treecontrol.js', ['goog.ui.tree.TreeControl'], ['goog.debug.Logger', 'goog.dom.a11y', 'goog.dom.classes', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeNode', 'goog.ui.tree.TypeAhead', 'goog.userAgent']); +goog.addDependency('ui/tree/treenode.js', ['goog.ui.tree.TreeNode'], ['goog.ui.tree.BaseNode']); +goog.addDependency('ui/tree/typeahead.js', ['goog.ui.tree.TypeAhead', 'goog.ui.tree.TypeAhead.Offset'], ['goog.array', 'goog.events.KeyCodes', 'goog.string', 'goog.structs.Trie']); +goog.addDependency('ui/tristatemenuitem.js', ['goog.ui.TriStateMenuItem', 'goog.ui.TriStateMenuItem.State'], ['goog.dom.classes', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.ControlContent', 'goog.ui.MenuItem', 'goog.ui.TriStateMenuItemRenderer', 'goog.ui.registry']); +goog.addDependency('ui/tristatemenuitemrenderer.js', ['goog.ui.TriStateMenuItemRenderer'], ['goog.dom.classes', 'goog.ui.MenuItemRenderer']); +goog.addDependency('ui/twothumbslider.js', ['goog.ui.TwoThumbSlider'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.a11y.Role', 'goog.ui.SliderBase']); +goog.addDependency('ui/zippy.js', ['goog.ui.Zippy', 'goog.ui.Zippy.Events', 'goog.ui.ZippyEvent'], ['goog.dom', 'goog.dom.a11y', 'goog.dom.classes', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style']); +goog.addDependency('uri/uri.js', ['goog.Uri', 'goog.Uri.QueryData'], ['goog.array', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex']); +goog.addDependency('uri/utils.js', ['goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.QueryArray', 'goog.uri.utils.QueryValue', 'goog.uri.utils.StandardQueryParam'], ['goog.asserts', 'goog.string', 'goog.userAgent']); +goog.addDependency('useragent/adobereader.js', ['goog.userAgent.adobeReader'], ['goog.string', 'goog.userAgent']); +goog.addDependency('useragent/flash.js', ['goog.userAgent.flash'], ['goog.string']); +goog.addDependency('useragent/iphoto.js', ['goog.userAgent.iphoto'], ['goog.string', 'goog.userAgent']); +goog.addDependency('useragent/jscript.js', ['goog.userAgent.jscript'], ['goog.string']); +goog.addDependency('useragent/picasa.js', ['goog.userAgent.picasa'], ['goog.string', 'goog.userAgent']); +goog.addDependency('useragent/platform.js', ['goog.userAgent.platform'], ['goog.userAgent']); +goog.addDependency('useragent/product.js', ['goog.userAgent.product'], ['goog.userAgent']); +goog.addDependency('useragent/product_isversion.js', ['goog.userAgent.product.isVersion'], ['goog.userAgent.product']); +goog.addDependency('useragent/useragent.js', ['goog.userAgent'], ['goog.string']); +goog.addDependency('vec/float32array.js', ['goog.vec.Float32Array'], []); +goog.addDependency('vec/float64array.js', ['goog.vec.Float64Array'], []); +goog.addDependency('vec/mat3.js', ['goog.vec.Mat3'], ['goog.vec', 'goog.vec.Vec3']); +goog.addDependency('vec/mat4.js', ['goog.vec.Mat4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4']); +goog.addDependency('vec/matrix3.js', ['goog.vec.Matrix3'], ['goog.vec']); +goog.addDependency('vec/matrix4.js', ['goog.vec.Matrix4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4']); +goog.addDependency('vec/quaternion.js', ['goog.vec.Quaternion'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4']); +goog.addDependency('vec/ray.js', ['goog.vec.Ray'], ['goog.vec.Vec3']); +goog.addDependency('vec/vec.js', ['goog.vec'], ['goog.vec.Float32Array', 'goog.vec.Float64Array']); +goog.addDependency('vec/vec2.js', ['goog.vec.Vec2'], ['goog.vec']); +goog.addDependency('vec/vec3.js', ['goog.vec.Vec3'], ['goog.vec']); +goog.addDependency('vec/vec4.js', ['goog.vec.Vec4'], ['goog.vec']); +goog.addDependency('webgl/webgl.js', ['goog.webgl'], []); +goog.addDependency('window/window.js', ['goog.window'], ['goog.string', 'goog.userAgent']); diff --git a/master/build/ol-simple.js b/master/build/ol-simple.js index 63162f207e..f71b01b2d8 100644 --- a/master/build/ol-simple.js +++ b/master/build/ol-simple.js @@ -445,12 +445,12 @@ goog.vec.Mat4.getRows=function(a,b,c,d,e){goog.vec.Mat4.getRow(a,0,b);goog.vec.M goog.vec.Mat4.addMat=function(a,b,c){c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];c[3]=a[3]+b[3];c[4]=a[4]+b[4];c[5]=a[5]+b[5];c[6]=a[6]+b[6];c[7]=a[7]+b[7];c[8]=a[8]+b[8];c[9]=a[9]+b[9];c[10]=a[10]+b[10];c[11]=a[11]+b[11];c[12]=a[12]+b[12];c[13]=a[13]+b[13];c[14]=a[14]+b[14];c[15]=a[15]+b[15];return c}; goog.vec.Mat4.subMat=function(a,b,c){c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];c[3]=a[3]-b[3];c[4]=a[4]-b[4];c[5]=a[5]-b[5];c[6]=a[6]-b[6];c[7]=a[7]-b[7];c[8]=a[8]-b[8];c[9]=a[9]-b[9];c[10]=a[10]-b[10];c[11]=a[11]-b[11];c[12]=a[12]-b[12];c[13]=a[13]-b[13];c[14]=a[14]-b[14];c[15]=a[15]-b[15];return c}; goog.vec.Mat4.multScalar=function(a,b,c){c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;c[3]=a[3]*b;c[4]=a[4]*b;c[5]=a[5]*b;c[6]=a[6]*b;c[7]=a[7]*b;c[8]=a[8]*b;c[9]=a[9]*b;c[10]=a[10]*b;c[11]=a[11]*b;c[12]=a[12]*b;c[13]=a[13]*b;c[14]=a[14]*b;c[15]=a[15]*b;return c}; -goog.vec.Mat4.multMat=function(a,b,c){var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],l=a[6],j=a[7],k=a[8],m=a[9],n=a[10],p=a[11],q=a[12],r=a[13],s=a[14],a=a[15],z=b[0],w=b[1],t=b[2],v=b[3],u=b[4],x=b[5],A=b[6],B=b[7],C=b[8],D=b[9],E=b[10],F=b[11],y=b[12],G=b[13],H=b[14],b=b[15];c[0]=d*z+h*w+k*t+q*v;c[1]=e*z+i*w+m*t+r*v;c[2]=f*z+l*w+n*t+s*v;c[3]=g*z+j*w+p*t+a*v;c[4]=d*u+h*x+k*A+q*B;c[5]=e*u+i*x+m*A+r*B;c[6]=f*u+l*x+n*A+s*B;c[7]=g*u+j*x+p*A+a*B;c[8]=d*C+h*D+k*E+q*F;c[9]=e*C+i*D+m*E+r*F;c[10]=f*C+l*D+ -n*E+s*F;c[11]=g*C+j*D+p*E+a*F;c[12]=d*y+h*G+k*H+q*b;c[13]=e*y+i*G+m*H+r*b;c[14]=f*y+l*G+n*H+s*b;c[15]=g*y+j*G+p*H+a*b;return c}; +goog.vec.Mat4.multMat=function(a,b,c){var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],l=a[6],j=a[7],k=a[8],m=a[9],n=a[10],p=a[11],q=a[12],r=a[13],s=a[14],a=a[15],t=b[0],x=b[1],u=b[2],v=b[3],w=b[4],y=b[5],A=b[6],B=b[7],C=b[8],D=b[9],E=b[10],F=b[11],z=b[12],G=b[13],H=b[14],b=b[15];c[0]=d*t+h*x+k*u+q*v;c[1]=e*t+i*x+m*u+r*v;c[2]=f*t+l*x+n*u+s*v;c[3]=g*t+j*x+p*u+a*v;c[4]=d*w+h*y+k*A+q*B;c[5]=e*w+i*y+m*A+r*B;c[6]=f*w+l*y+n*A+s*B;c[7]=g*w+j*y+p*A+a*B;c[8]=d*C+h*D+k*E+q*F;c[9]=e*C+i*D+m*E+r*F;c[10]=f*C+l*D+ +n*E+s*F;c[11]=g*C+j*D+p*E+a*F;c[12]=d*z+h*G+k*H+q*b;c[13]=e*z+i*G+m*H+r*b;c[14]=f*z+l*G+n*H+s*b;c[15]=g*z+j*G+p*H+a*b;return c}; goog.vec.Mat4.transpose=function(a,b){if(b==a){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];b[1]=a[4];b[2]=a[8];b[3]=a[12];b[4]=c;b[6]=a[9];b[7]=a[13];b[8]=d;b[9]=f;b[11]=a[14];b[12]=e;b[13]=g;b[14]=h}else b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15];return b}; goog.vec.Mat4.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],l=a[8],j=a[9],k=a[10],m=a[11],n=a[12],p=a[13],q=a[14],a=a[15];return(b*g-c*f)*(k*a-m*q)-(b*h-d*f)*(j*a-m*p)+(b*i-e*f)*(j*q-k*p)+(c*h-d*g)*(l*a-m*n)-(c*i-e*g)*(l*q-k*n)+(d*i-e*h)*(l*p-j*n)}; -goog.vec.Mat4.invert=function(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],i=a[6],l=a[7],j=a[8],k=a[9],m=a[10],n=a[11],p=a[12],q=a[13],r=a[14],s=a[15],z=c*h-d*g,w=c*i-e*g,t=c*l-f*g,v=d*i-e*h,u=d*l-f*h,x=e*l-f*i,A=j*q-k*p,B=j*r-m*p,C=j*s-n*p,D=k*r-m*q,E=k*s-n*q,F=m*s-n*r,y=z*F-w*E+t*D+v*C-u*B+x*A;if(0==y)return!1;y=1/y;b[0]=(h*F-i*E+l*D)*y;b[1]=(-d*F+e*E-f*D)*y;b[2]=(q*x-r*u+s*v)*y;b[3]=(-k*x+m*u-n*v)*y;b[4]=(-g*F+i*C-l*B)*y;b[5]=(c*F-e*C+f*B)*y;b[6]=(-p*x+r*t-s*w)*y;b[7]=(j*x-m*t+n*w)*y;b[8]= -(g*E-h*C+l*A)*y;b[9]=(-c*E+d*C-f*A)*y;b[10]=(p*u-q*t+s*z)*y;b[11]=(-j*u+k*t-n*z)*y;b[12]=(-g*D+h*B-i*A)*y;b[13]=(c*D-d*B+e*A)*y;b[14]=(-p*v+q*w-r*z)*y;b[15]=(j*v-k*w+m*z)*y;return!0};goog.vec.Mat4.equals=function(a,b){return a.length==b.length&&a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]&&a[5]==b[5]&&a[6]==b[6]&&a[7]==b[7]&&a[8]==b[8]&&a[9]==b[9]&&a[10]==b[10]&&a[11]==b[11]&&a[12]==b[12]&&a[13]==b[13]&&a[14]==b[14]&&a[15]==b[15]}; +goog.vec.Mat4.invert=function(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],i=a[6],l=a[7],j=a[8],k=a[9],m=a[10],n=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=c*h-d*g,x=c*i-e*g,u=c*l-f*g,v=d*i-e*h,w=d*l-f*h,y=e*l-f*i,A=j*q-k*p,B=j*r-m*p,C=j*s-n*p,D=k*r-m*q,E=k*s-n*q,F=m*s-n*r,z=t*F-x*E+u*D+v*C-w*B+y*A;if(0==z)return!1;z=1/z;b[0]=(h*F-i*E+l*D)*z;b[1]=(-d*F+e*E-f*D)*z;b[2]=(q*y-r*w+s*v)*z;b[3]=(-k*y+m*w-n*v)*z;b[4]=(-g*F+i*C-l*B)*z;b[5]=(c*F-e*C+f*B)*z;b[6]=(-p*y+r*u-s*x)*z;b[7]=(j*y-m*u+n*x)*z;b[8]= +(g*E-h*C+l*A)*z;b[9]=(-c*E+d*C-f*A)*z;b[10]=(p*w-q*u+s*t)*z;b[11]=(-j*w+k*u-n*t)*z;b[12]=(-g*D+h*B-i*A)*z;b[13]=(c*D-d*B+e*A)*z;b[14]=(-p*v+q*x-r*t)*z;b[15]=(j*v-k*x+m*t)*z;return!0};goog.vec.Mat4.equals=function(a,b){return a.length==b.length&&a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]&&a[5]==b[5]&&a[6]==b[6]&&a[7]==b[7]&&a[8]==b[8]&&a[9]==b[9]&&a[10]==b[10]&&a[11]==b[11]&&a[12]==b[12]&&a[13]==b[13]&&a[14]==b[14]&&a[15]==b[15]}; goog.vec.Mat4.multVec3=function(a,b,c){var d=b[0],e=b[1],b=b[2];c[0]=d*a[0]+e*a[4]+b*a[8]+a[12];c[1]=d*a[1]+e*a[5]+b*a[9]+a[13];c[2]=d*a[2]+e*a[6]+b*a[10]+a[14];return c};goog.vec.Mat4.multVec3NoTranslate=function(a,b,c){var d=b[0],e=b[1],b=b[2];c[0]=d*a[0]+e*a[4]+b*a[8];c[1]=d*a[1]+e*a[5]+b*a[9];c[2]=d*a[2]+e*a[6]+b*a[10];return c}; goog.vec.Mat4.multVec3Projective=function(a,b,c){var d=b[0],e=b[1],b=b[2],f=1/(d*a[3]+e*a[7]+b*a[11]+a[15]);c[0]=(d*a[0]+e*a[4]+b*a[8]+a[12])*f;c[1]=(d*a[1]+e*a[5]+b*a[9]+a[13])*f;c[2]=(d*a[2]+e*a[6]+b*a[10]+a[14])*f;return c};goog.vec.Mat4.multVec4=function(a,b,c){var d=b[0],e=b[1],f=b[2],b=b[3];c[0]=d*a[0]+e*a[4]+f*a[8]+b*a[12];c[1]=d*a[1]+e*a[5]+f*a[9]+b*a[13];c[2]=d*a[2]+e*a[6]+f*a[10]+b*a[14];c[3]=d*a[3]+e*a[7]+f*a[11]+b*a[15];return c}; goog.vec.Mat4.makeTranslate=function(a,b,c,d){goog.vec.Mat4.makeIdentity(a);return goog.vec.Mat4.setColumnValues(a,3,b,c,d,1)};goog.vec.Mat4.makeScale=function(a,b,c,d){goog.vec.Mat4.makeIdentity(a);return goog.vec.Mat4.setDiagonalValues(a,b,c,d,1)};goog.vec.Mat4.makeRotate=function(a,b,c,d,e){var f=Math.cos(b),g=1-f,b=Math.sin(b);return goog.vec.Mat4.setFromValues(a,c*c*g+f,c*d*g+e*b,c*e*g-d*b,0,c*d*g-e*b,d*d*g+f,d*e*g+c*b,0,c*e*g+d*b,d*e*g-c*b,e*e*g+f,0,0,0,0,1)}; @@ -462,17 +462,17 @@ goog.vec.Mat4.makeLookAt=function(a,b,c,d){var e=goog.vec.Mat4.tmpVec4_[0];goog. goog.vec.Mat4.makeEulerZXZ=function(a,b,c,d){var e=Math.cos(b),b=Math.sin(b),f=Math.cos(c),c=Math.sin(c),g=Math.cos(d),d=Math.sin(d);a[0]=e*g-f*b*d;a[1]=f*e*d+g*b;a[2]=d*c;a[3]=0;a[4]=-e*d-g*f*b;a[5]=e*f*g-b*d;a[6]=g*c;a[7]=0;a[8]=c*b;a[9]=-e*c;a[10]=f;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1;return a}; goog.vec.Mat4.toEulerZXZ=function(a,b,c){var d=Math.sqrt(a[2]*a[2]+a[6]*a[6]),c=c?-1:1;d>goog.vec.EPSILON?(b[2]=Math.atan2(a[2]*c,a[6]*c),b[1]=Math.atan2(d*c,a[10]),b[0]=Math.atan2(a[8]*c,-a[9]*c)):(b[0]=0,b[1]=Math.atan2(d*c,a[10]),b[2]=Math.atan2(a[1],a[0]));b[0]=(b[0]+2*Math.PI)%(2*Math.PI);b[2]=(b[2]+2*Math.PI)%(2*Math.PI);b[1]=(b[1]*c+2*Math.PI)%(2*Math.PI)*c;return b}; goog.vec.Mat4.translate=function(a,b,c,d){return goog.vec.Mat4.setColumnValues(a,3,a[0]*b+a[4]*c+a[8]*d+a[12],a[1]*b+a[5]*c+a[9]*d+a[13],a[2]*b+a[6]*c+a[10]*d+a[14],a[3]*b+a[7]*c+a[11]*d+a[15])};goog.vec.Mat4.scale=function(a,b,c,d){return goog.vec.Mat4.setFromValues(a,a[0]*b,a[1]*b,a[2]*b,a[3]*b,a[4]*c,a[5]*c,a[6]*c,a[7]*c,a[8]*d,a[9]*d,a[10]*d,a[11]*d,a[12],a[13],a[14],a[15])}; -goog.vec.Mat4.rotate=function(a,b,c,d,e){var f=a[0],g=a[1],h=a[2],i=a[3],l=a[4],j=a[5],k=a[6],m=a[7],n=a[8],p=a[9],q=a[10],r=a[11],s=a[12],z=a[13],w=a[14],t=a[15],v=Math.cos(b),u=Math.sin(b),x=1-v,b=c*c*x+v,A=c*d*x+e*u,B=c*e*x-d*u,C=c*d*x-e*u,D=d*d*x+v,E=d*e*x+c*u,F=c*e*x+d*u,c=d*e*x-c*u,e=e*e*x+v;return goog.vec.Mat4.setFromValues(a,f*b+l*A+n*B,g*b+j*A+p*B,h*b+k*A+q*B,i*b+m*A+r*B,f*C+l*D+n*E,g*C+j*D+p*E,h*C+k*D+q*E,i*C+m*D+r*E,f*F+l*c+n*e,g*F+j*c+p*e,h*F+k*c+q*e,i*F+m*c+r*e,s,z,w,t)}; +goog.vec.Mat4.rotate=function(a,b,c,d,e){var f=a[0],g=a[1],h=a[2],i=a[3],l=a[4],j=a[5],k=a[6],m=a[7],n=a[8],p=a[9],q=a[10],r=a[11],s=a[12],t=a[13],x=a[14],u=a[15],v=Math.cos(b),w=Math.sin(b),y=1-v,b=c*c*y+v,A=c*d*y+e*w,B=c*e*y-d*w,C=c*d*y-e*w,D=d*d*y+v,E=d*e*y+c*w,F=c*e*y+d*w,c=d*e*y-c*w,e=e*e*y+v;return goog.vec.Mat4.setFromValues(a,f*b+l*A+n*B,g*b+j*A+p*B,h*b+k*A+q*B,i*b+m*A+r*B,f*C+l*D+n*E,g*C+j*D+p*E,h*C+k*D+q*E,i*C+m*D+r*E,f*F+l*c+n*e,g*F+j*c+p*e,h*F+k*c+q*e,i*F+m*c+r*e,s,t,x,u)}; goog.vec.Mat4.rotateX=function(a,b){var c=a[4],d=a[5],e=a[6],f=a[7],g=a[8],h=a[9],i=a[10],l=a[11],j=Math.cos(b),k=Math.sin(b);a[4]=c*j+g*k;a[5]=d*j+h*k;a[6]=e*j+i*k;a[7]=f*j+l*k;a[8]=c*-k+g*j;a[9]=d*-k+h*j;a[10]=e*-k+i*j;a[11]=f*-k+l*j;return a};goog.vec.Mat4.rotateY=function(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[8],h=a[9],i=a[10],l=a[11],j=Math.cos(b),k=Math.sin(b);a[0]=c*j+g*-k;a[1]=d*j+h*-k;a[2]=e*j+i*-k;a[3]=f*j+l*-k;a[8]=c*k+g*j;a[9]=d*k+h*j;a[10]=e*k+i*j;a[11]=f*k+l*j;return a}; goog.vec.Mat4.rotateZ=function(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],i=a[6],l=a[7],j=Math.cos(b),k=Math.sin(b);a[0]=c*j+g*k;a[1]=d*j+h*k;a[2]=e*j+i*k;a[3]=f*j+l*k;a[4]=c*-k+g*j;a[5]=d*-k+h*j;a[6]=e*-k+i*j;a[7]=f*-k+l*j;return a};goog.vec.Mat4.getTranslation=function(a,b){b[0]=a[12];b[1]=a[13];b[2]=a[14];return b};goog.vec.Mat4.tmpVec3_=[goog.vec.Vec3.createFloat64(),goog.vec.Vec3.createFloat64()];goog.vec.Mat4.tmpVec4_=[goog.vec.Vec4.createFloat64(),goog.vec.Vec4.createFloat64(),goog.vec.Vec4.createFloat64()]; goog.vec.Mat4.tmpMat4_=[goog.vec.Mat4.createFloat64()];ol.QuadKeyCharCode={ZERO:48,ONE:49,TWO:50,THREE:51};ol.TileCoord=function(a,b,c){ol.Coordinate.call(this,b,c);this.z=a};goog.inherits(ol.TileCoord,ol.Coordinate);ol.TileCoord.createFromQuadKey=function(a){var b=a.length,c=0,d=0,e=1<>=1}return new ol.TileCoord(b,c,d)}; ol.TileCoord.createFromString=function(a){a=a.split("/");a=goog.array.map(a,function(a){return parseInt(a,10)});return new ol.TileCoord(a[0],a[1],a[2])};ol.TileCoord.prototype.hash=function(){return(this.x<>=1;return a.join("")}; ol.TileCoord.prototype.toString=function(){return[this.z,this.x,this.y].join("/")};ol.TileRange=function(a,b,c,d){this.minX=a;this.minY=b;this.maxX=c;this.maxY=d};goog.inherits(ol.TileRange,ol.Rectangle);ol.TileRange.boundingTileRange=function(a){var b=arguments[0],c=new ol.TileRange(b.x,b.y,b.x,b.y),d,e;for(d=1;d>1};ol.TileQueue.prototype.heapify_=function(){for(var a=(this.heap_.length>>1)-1;0<=a;a--)this.siftUp_(a)};ol.TileQueue.prototype.loadMoreTiles=function(){for(var a;0>1};ol.TileQueue.prototype.heapify_=function(){for(var a=(this.heap_.length>>1)-1;0<=a;a--)this.siftUp_(a)};ol.TileQueue.prototype.loadMoreTiles=function(){for(var a;0>1;){var f=this.getLeftChildIndex_(a),g=this.getRightChildIndex_(a),f=ga;){var e=this.getParentIndex_(b);if(c[e][0]>d[0])c[b]=c[e],b=e;else break}c[b]=d}; -ol.TileQueue.prototype.reprioritize=function(){var a=this.heap_,b,c=0,d,e,f,g;for(b=0;ba?goog.fx.easing.inAndOut(2*a):1-goog.fx.easing.inAndOut(2*(a-0.5))};ol.easing.elastic=function(a){return Math.pow(2,-10*a)*Math.sin((a-0.075)*2*Math.PI/0.3)+1};ol.easing.bounce=function(a){a<1/2.75?a*=7.5625*a:a<2/2.75?(a-=1.5/2.75,a=7.5625*a*a+0.75):a<2.5/2.75?(a-=2.25/2.75,a=7.5625*a*a+0.9375):(a-=2.625/2.75,a=7.5625*a*a+0.984375);return a};ol.animation={};ol.animation.bounce=function(a){var b=a.resolution,c=goog.isDef(a.start)?a.start:goog.now(),d=goog.isDef(a.duration)?a.duration:1E3,e=goog.isDef(a.easing)?a.easing:ol.easing.upAndDown;return function(a,g){if(g.timea?ol.easing.inAndOut(2*a):1-ol.easing.inAndOut(2*(a-0.5))};ol.animation={};ol.animation.bounce=function(a){var b=a.resolution,c=goog.isDef(a.start)?a.start:goog.now(),d=goog.isDef(a.duration)?a.duration:1E3,e=goog.isDef(a.easing)?a.easing:ol.easing.upAndDown;return function(a,g){if(g.timeb?(d="\u2032",a*=60):d="\u00b0":this.units_==ol.control.ScaleLineUnits.IMPERIAL?0.9144>b?(d="in",a/=0.0254):1609.344>b?(d="ft",a/=0.3048):(d="mi",a/=1609.344):this.units_==ol.control.ScaleLineUnits.NAUTICAL? -(a/=1852,d="nm"):this.units_==ol.control.ScaleLineUnits.METRIC?1>b?(d="mm",a*=1E3):1E3>b?d="m":(d="km",a/=1E3):this.units_==ol.control.ScaleLineUnits.US?0.9144>b?(d="in",a*=39.37):1609.344>b?(d="ft",a/=0.30480061):(d="mi",a/=1609.3472):goog.asserts.assert(!1);for(var b=3*Math.floor(Math.log(this.minWidth_*a)/Math.log(10)),e,f;;){e=ol.control.ScaleLine.LEADING_DIGITS[b%3]*Math.pow(10,Math.floor(b/3));f=Math.round(e/a);if(f>=this.minWidth_)break;++b}e+=d;this.renderedHTML_!=e&&(this.renderedHTML_=this.innerElement_.innerHTML= -e);this.renderedWidth_!=f&&(this.innerElement_.style.width=f+"px",this.renderedWidth_=f);this.renderedVisible_||(goog.style.showElement(this.element_,!0),this.renderedVisible_=!0)}};ol.control.ZOOM_DURATION=250; +!0),delete b[g];for(g in b)goog.dom.removeNode(this.attributionElements_[g]),delete this.attributionElements_[g],delete this.attributionElementRenderedVisible_[g];d=!goog.array.isEmpty(a);this.renderedVisible_!=d&&(goog.style.showElement(this.element,d),this.renderedVisible_=d)}};ol.control.ZOOM_DURATION=250; ol.control.Zoom=function(a){var a=goog.isDef(a)?a:{},b=goog.dom.createDom(goog.dom.TagName.A,{href:"#zoomIn","class":"ol-zoom-in"});goog.events.listen(b,[goog.events.EventType.TOUCHEND,goog.events.EventType.CLICK],this.handleIn_,!1,this);var c=goog.dom.createDom(goog.dom.TagName.A,{href:"#zoomOut","class":"ol-zoom-out"});goog.events.listen(c,[goog.events.EventType.TOUCHEND,goog.events.EventType.CLICK],this.handleOut_,!1,this);b=goog.dom.createDom(goog.dom.TagName.DIV,"ol-zoom ol-unselectable",b,c); -ol.control.Control.call(this,{element:b,map:a.map,target:a.target});this.delta_=goog.isDef(a.delta)?a.delta:1};goog.inherits(ol.control.Zoom,ol.control.Control);ol.control.Zoom.prototype.handleIn_=function(a){a.preventDefault();a=this.getMap();a.requestRenderFrame();a.getView().zoomByDelta(a,this.delta_,void 0,ol.control.ZOOM_DURATION)};ol.control.Zoom.prototype.handleOut_=function(a){a.preventDefault();a=this.getMap();a.requestRenderFrame();a.getView().zoomByDelta(a,-this.delta_,void 0,ol.control.ZOOM_DURATION)};ol.control.defaults=function(a,b){var c=goog.isDef(a)?a:{},d=[];if(goog.isDef(c.attribution)?c.attribution:1){var e=goog.isDef(c.attributionOptions)?c.attributionOptions:void 0;d.push(new ol.control.Attribution(e))}goog.isDef(c.scaleLine)&&c.scaleLine&&(e=goog.isDef(c.scaleLineOptions)?c.scaleLineOptions:void 0,d.push(new ol.control.ScaleLine(e)));if(goog.isDef(c.zoom)?c.zoom:1)c=goog.isDef(c.zoomControlOptions)?c.zoomControlOptions:void 0,d.push(new ol.control.Zoom(c));goog.isDef(b)&&goog.array.extend(d, -b);return d};ol.Kinetic=function(a,b,c){this.decay_=a;this.minVelocity_=b;this.delay_=c;this.points_=[];this.initialVelocity_=this.angle_=0};ol.Kinetic.prototype.begin=function(){this.initialVelocity_=this.angle_=this.points_.length=0};ol.Kinetic.prototype.update=function(a,b){this.points_.push({x:a,y:b,t:goog.now()})}; +ol.control.Control.call(this,{element:b,map:a.map,target:a.target});this.delta_=goog.isDef(a.delta)?a.delta:1};goog.inherits(ol.control.Zoom,ol.control.Control);ol.control.Zoom.prototype.handleIn_=function(a){a.preventDefault();a=this.getMap();a.requestRenderFrame();a.getView().zoomByDelta(a,this.delta_,void 0,ol.control.ZOOM_DURATION)};ol.control.Zoom.prototype.handleOut_=function(a){a.preventDefault();a=this.getMap();a.requestRenderFrame();a.getView().zoomByDelta(a,-this.delta_,void 0,ol.control.ZOOM_DURATION)};ol.control.defaults=function(a,b){var c=goog.isDef(a)?a:{},d=[];if(goog.isDef(c.attribution)?c.attribution:1){var e=goog.isDef(c.attributionOptions)?c.attributionOptions:void 0;d.push(new ol.control.Attribution(e))}if(goog.isDef(c.zoom)?c.zoom:1)c=goog.isDef(c.zoomControlOptions)?c.zoomControlOptions:void 0,d.push(new ol.control.Zoom(c));goog.isDef(b)&&goog.array.extend(d,b);return d};ol.Kinetic=function(a,b,c){this.decay_=a;this.minVelocity_=b;this.delay_=c;this.points_=[];this.initialVelocity_=this.angle_=0};ol.Kinetic.prototype.begin=function(){this.initialVelocity_=this.angle_=this.points_.length=0};ol.Kinetic.prototype.update=function(a,b){this.points_.push({x:a,y:b,t:goog.now()})}; ol.Kinetic.prototype.end=function(){for(var a=goog.now(),b=this.points_.length-1,c=b-1;0<=c&&this.points_[c].t>a-this.delay_;)c--;if(0<=c){var a=this.points_[c],b=this.points_[b],c=b.x-a.x,d=b.y-a.y;this.angle_=Math.atan2(d,c);this.initialVelocity_=Math.sqrt(c*c+d*d)/(b.t-a.t);return this.initialVelocity_>this.minVelocity_}return!1}; ol.Kinetic.prototype.pan=function(a){var b=this.decay_,c=this.initialVelocity_,d=this.minVelocity_,e=this.getDuration_();return ol.animation.pan({source:a,duration:e,easing:function(a){return c*(Math.exp(b*a*e)-1)/(d-c)}})};ol.Kinetic.prototype.getDuration_=function(){return Math.log(this.minVelocity_/this.initialVelocity_)/this.decay_};ol.Kinetic.prototype.getDistance=function(){return(this.minVelocity_-this.initialVelocity_)/this.decay_};ol.Kinetic.prototype.getAngle=function(){return this.angle_};ol.interaction={};ol.interaction.Interaction=function(){};ol.interaction.DBLCLICKZOOM_ANIMATION_DURATION=250;ol.interaction.DblClickZoom=function(a){this.delta_=a;ol.interaction.Interaction.call(this)};goog.inherits(ol.interaction.DblClickZoom,ol.interaction.Interaction); ol.interaction.DblClickZoom.prototype.handleMapBrowserEvent=function(a){var b=a.browserEvent;if(a.type==ol.MapBrowserEvent.EventType.DBLCLICK&&a.isMouseActionButton()){var c=a.map,d=a.getCoordinate(),e=a.browserEvent.shiftKey?-this.delta_:this.delta_,f=c.getView();goog.asserts.assert(f instanceof ol.View2D);f.zoomByDelta(c,e,d,ol.interaction.DBLCLICKZOOM_ANIMATION_DURATION);a.preventDefault();b.preventDefault()}};ol.interaction.condition={};ol.interaction.condition.altKeyOnly=function(a){return a.altKey&&!a.platformModifierKey&&!a.shiftKey};ol.interaction.condition.altShiftKeysOnly=function(a){return a.altKey&&!a.platformModifierKey&&a.shiftKey};ol.interaction.condition.noModifierKeys=function(a){return!a.altKey&&!a.platformModifierKey&&!a.shiftKey};ol.interaction.condition.platformModifierKeyOnly=function(a){return!a.altKey&&a.platformModifierKey&&!a.shiftKey}; @@ -568,10 +563,10 @@ ol.interaction.DragRotate.prototype.handleDragStart=function(a){var b=a.browserE ol.control.DragBox.prototype.setMap=function(a){goog.isNull(this.dragListenKey_)||(goog.events.unlistenByKey(this.dragListenKey_),this.dragListenKey_=null);goog.isNull(a)||(this.startPixel_=a.getPixelFromCoordinate(this.startCoordinate_),goog.asserts.assert(goog.isDef(this.startPixel_)),goog.style.setPosition(this.element,this.startPixel_),goog.style.setBorderBoxSize(this.element,new ol.Size(0,0)),this.dragListenKey_=goog.events.listen(a,ol.MapBrowserEvent.EventType.DRAG,this.updateBox_,!1,this)); ol.control.DragBox.superClass_.setMap.call(this,a)};ol.control.DragBox.prototype.updateBox_=function(a){var b=this.getMap(),a=a.getCoordinate();goog.asserts.assert(goog.isDef(a));b=b.getPixelFromCoordinate(a);goog.style.setPosition(this.element,new ol.Pixel(Math.min(b.x,this.startPixel_.x),Math.min(b.y,this.startPixel_.y)));goog.style.setBorderBoxSize(this.element,new ol.Size(Math.abs(b.x-this.startPixel_.x),Math.abs(b.y-this.startPixel_.y)))};ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS=8;ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED=ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS*ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS;ol.interaction.DragZoom=function(a){ol.interaction.Drag.call(this);this.condition_=a;this.dragBox_=null};goog.inherits(ol.interaction.DragZoom,ol.interaction.Drag); ol.interaction.DragZoom.prototype.handleDragEnd=function(a){this.dragBox_.setMap(null);this.dragBox_=null;if(this.deltaX*this.deltaX+this.deltaY*this.deltaY>=ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED){var b=a.map,c=ol.Extent.boundingExtent(this.startCoordinate,a.getCoordinate());b.withFrozenRendering(function(){var a=b.getView();goog.asserts.assert(a instanceof ol.View2D);var e=b.getSize();a.fitExtent(c,e);a.setRotation(0)})}}; -ol.interaction.DragZoom.prototype.handleDragStart=function(a){var b=a.browserEvent;return b.isMouseActionButton()&&this.condition_(b)?(this.dragBox_=new ol.control.DragBox({map:a.map,startCoordinate:this.startCoordinate}),!0):!1};ol.interaction.KeyboardPan=function(a){ol.interaction.Interaction.call(this);this.pixelDelta_=a};goog.inherits(ol.interaction.KeyboardPan,ol.interaction.Interaction); -ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent=function(a){if(a.type==goog.events.KeyHandler.EventType.KEY){var b=a.browserEvent,c=b.keyCode;if(c==goog.events.KeyCodes.DOWN||c==goog.events.KeyCodes.LEFT||c==goog.events.KeyCodes.RIGHT||c==goog.events.KeyCodes.UP){var d=a.map.getView();goog.asserts.assert(d instanceof ol.View2D);var e=d.getResolution()*this.pixelDelta_;c==goog.events.KeyCodes.DOWN?c=new ol.Coordinate(0,-e):c==goog.events.KeyCodes.LEFT?c=new ol.Coordinate(-e,0):c==goog.events.KeyCodes.RIGHT? -c=new ol.Coordinate(e,0):(goog.asserts.assert(c==goog.events.KeyCodes.UP),c=new ol.Coordinate(0,e));e=d.getCenter();c=new ol.Coordinate(e.x+c.x,e.y+c.y);d.setCenter(c);b.preventDefault();a.preventDefault()}}};ol.interaction.KEYBOARD_ZOOM_DURATION=100;ol.interaction.KeyboardZoom=function(){ol.interaction.Interaction.call(this)};goog.inherits(ol.interaction.KeyboardZoom,ol.interaction.Interaction); -ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent=function(a){if(a.type==goog.events.KeyHandler.EventType.KEY){var b=a.browserEvent,c=b.charCode;if(43==c||45==c){var d=a.map,c=43==c?4:-4;d.requestRenderFrame();var e=d.getView();goog.asserts.assert(e instanceof ol.View2D);e.zoomByDelta(d,c,void 0,ol.interaction.KEYBOARD_ZOOM_DURATION);b.preventDefault();a.preventDefault()}}};ol.interaction.MOUSEWHEELZOOM_ANIMATION_DURATION=250;ol.interaction.MOUSEWHEELZOOM_MAXDELTA=1;ol.interaction.MOUSEWHEELZOOM_TIMEOUT_DURATION=80;ol.interaction.MouseWheelZoom=function(){ol.interaction.Interaction.call(this);this.delta_=0;this.lastAnchor_=null;this.timeoutId_=this.startTime_=void 0};goog.inherits(ol.interaction.MouseWheelZoom,ol.interaction.Interaction); +ol.interaction.DragZoom.prototype.handleDragStart=function(a){var b=a.browserEvent;return b.isMouseActionButton()&&this.condition_(b)?(this.dragBox_=new ol.control.DragBox({map:a.map,startCoordinate:this.startCoordinate}),!0):!1};ol.interaction.KEYBOARD_PAN_DURATION=100;ol.interaction.KeyboardPan=function(a){ol.interaction.Interaction.call(this);a=goog.isDef(a)?a:{};this.delta_=goog.isDef(a.delta)?a.delta:128};goog.inherits(ol.interaction.KeyboardPan,ol.interaction.Interaction); +ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent=function(a){if(a.type==goog.events.KeyHandler.EventType.KEY){var b=a.browserEvent,c=b.keyCode;if(c==goog.events.KeyCodes.DOWN||c==goog.events.KeyCodes.LEFT||c==goog.events.KeyCodes.RIGHT||c==goog.events.KeyCodes.UP){var d=a.map,e=d.getView();goog.asserts.assert(e instanceof ol.View2D);var f=e.getResolution(),g=e.getRotation(),f=f*this.delta_,h=0,i=0;c==goog.events.KeyCodes.DOWN?i=-f:c==goog.events.KeyCodes.LEFT?h=-f:c==goog.events.KeyCodes.RIGHT? +h=f:i=f;c=new ol.Coordinate(h,i);c.rotate(g);e.pan(d,c,ol.interaction.KEYBOARD_PAN_DURATION);b.preventDefault();a.preventDefault()}}};ol.interaction.KEYBOARD_ZOOM_DURATION=100;ol.interaction.KeyboardZoom=function(a){ol.interaction.Interaction.call(this);a=goog.isDef(a)?a:{};this.delta_=goog.isDef(a.delta)?a.delta:1};goog.inherits(ol.interaction.KeyboardZoom,ol.interaction.Interaction); +ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent=function(a){if(a.type==goog.events.KeyHandler.EventType.KEY){var b=a.browserEvent,c=b.charCode;if(43==c||45==c){var d=a.map,c=43==c?this.delta_:-this.delta_;d.requestRenderFrame();var e=d.getView();goog.asserts.assert(e instanceof ol.View2D);e.zoomByDelta(d,c,void 0,ol.interaction.KEYBOARD_ZOOM_DURATION);b.preventDefault();a.preventDefault()}}};ol.interaction.MOUSEWHEELZOOM_ANIMATION_DURATION=250;ol.interaction.MOUSEWHEELZOOM_MAXDELTA=1;ol.interaction.MOUSEWHEELZOOM_TIMEOUT_DURATION=80;ol.interaction.MouseWheelZoom=function(){ol.interaction.Interaction.call(this);this.delta_=0;this.lastAnchor_=null;this.timeoutId_=this.startTime_=void 0};goog.inherits(ol.interaction.MouseWheelZoom,ol.interaction.Interaction); ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent=function(a){if(a.type==goog.events.MouseWheelHandler.EventType.MOUSEWHEEL){var b=a.map,c=a.browserEvent;goog.asserts.assert(c instanceof goog.events.MouseWheelEvent);this.lastAnchor_=a.getCoordinate();this.delta_+=c.deltaY/3;goog.isDef(this.startTime_)||(this.startTime_=goog.now());var d=Math.max(ol.interaction.MOUSEWHEELZOOM_TIMEOUT_DURATION-(goog.now()-this.startTime_),0);goog.global.clearTimeout(this.timeoutId_);this.timeoutId_=goog.global.setTimeout(goog.bind(this.doZoom_, this,b),d);a.preventDefault();c.preventDefault()}};ol.interaction.MouseWheelZoom.prototype.doZoom_=function(a){var b=ol.interaction.MOUSEWHEELZOOM_MAXDELTA,b=goog.math.clamp(this.delta_,-b,b),c=a.getView();goog.asserts.assert(c instanceof ol.View2D);a.requestRenderFrame();c.zoomByDelta(a,-b,this.lastAnchor_,ol.interaction.MOUSEWHEELZOOM_ANIMATION_DURATION);this.delta_=0;this.lastAnchor_=null;this.timeoutId_=this.startTime_=void 0};ol.interaction.Touch=function(){ol.interaction.Interaction.call(this);this.handled_=!1;this.trackedTouches_={};this.targetTouches=[]};goog.inherits(ol.interaction.Touch,ol.interaction.Interaction);ol.interaction.Touch.centroid=function(a){for(var b=a.length,c=0,d=0,e=0;ethis.targetTouches.length){var a=a.map,b=a.getView();b.zoom(a,b.getResolution(),void 0,ol.interaction.TOUCHZOOM_ANIMATION_DURATION);b.setHint(ol.ViewHint.INTERACTING,-1);return!1}return!0};ol.interaction.TouchZoom.prototype.handleTouchStart=function(a){return 2<=this.targetTouches.length?(a=a.map.getView(),this.lastDistance_=void 0,a.setHint(ol.ViewHint.INTERACTING,1),!0):!1};ol.interaction.defaults=function(a,b){var c=goog.isDef(a)?a:{},d=new ol.Collection;(goog.isDef(c.rotate)?c.rotate:1)&&d.push(new ol.interaction.DragRotate(ol.interaction.condition.altShiftKeysOnly));if(goog.isDef(c.doubleClickZoom)?c.doubleClickZoom:1){var e=goog.isDef(c.zoomDelta)?c.zoomDelta:1;d.push(new ol.interaction.DblClickZoom(e))}(goog.isDef(c.touchPan)?c.touchPan:1)&&d.push(new ol.interaction.TouchPan(new ol.Kinetic(-0.005,0.05,100)));(goog.isDef(c.touchRotate)?c.touchRotate:1)&&d.push(new ol.interaction.TouchRotate); -(goog.isDef(c.touchZoom)?c.touchZoom:1)&&d.push(new ol.interaction.TouchZoom);(goog.isDef(c.dragPan)?c.dragPan:1)&&d.push(new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys,new ol.Kinetic(-0.005,0.05,100)));var e=goog.isDef(c.keyboard)?c.keyboard:!0,f=goog.isDef(c.keyboardPanOffset)?c.keyboardPanOffset:80;e&&(d.push(new ol.interaction.KeyboardPan(f)),d.push(new ol.interaction.KeyboardZoom));(goog.isDef(c.mouseWheelZoom)?c.mouseWheelZoom:1)&&d.push(new ol.interaction.MouseWheelZoom); -(goog.isDef(c.shiftDragZoom)?c.shiftDragZoom:1)&&d.push(new ol.interaction.DragZoom(ol.interaction.condition.shiftKeyOnly));goog.isDef(b)&&d.extend(b);return d};ol.math={};ol.math.cosh=function(a){return(Math.exp(a)+Math.exp(-a))/2};ol.math.coth=function(a){a=Math.exp(-2*a);return(1+a)/(1-a)};ol.math.csch=function(a){return 2/(Math.exp(a)-Math.exp(-a))};ol.math.sech=function(a){return 2/(Math.exp(a)+Math.exp(-a))};ol.math.sinh=function(a){return(Math.exp(a)-Math.exp(-a))/2};ol.math.tanh=function(a){a=Math.exp(-2*a);return(1-a)/(1+a)};ol.projection.EPSG3857=function(a){ol.Projection.call(this,a,ol.ProjectionUnits.METERS,ol.projection.EPSG3857.EXTENT)};goog.inherits(ol.projection.EPSG3857,ol.Projection);ol.projection.EPSG3857.RADIUS=6378137;ol.projection.EPSG3857.HALF_SIZE=Math.PI*ol.projection.EPSG3857.RADIUS;ol.projection.EPSG3857.EXTENT=new ol.Extent(-ol.projection.EPSG3857.HALF_SIZE,-ol.projection.EPSG3857.HALF_SIZE,ol.projection.EPSG3857.HALF_SIZE,ol.projection.EPSG3857.HALF_SIZE); +(goog.isDef(c.touchZoom)?c.touchZoom:1)&&d.push(new ol.interaction.TouchZoom);(goog.isDef(c.dragPan)?c.dragPan:1)&&d.push(new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys,new ol.Kinetic(-0.005,0.05,100)));if(goog.isDef(c.keyboard)?c.keyboard:1)d.push(new ol.interaction.KeyboardPan),d.push(new ol.interaction.KeyboardZoom);(goog.isDef(c.mouseWheelZoom)?c.mouseWheelZoom:1)&&d.push(new ol.interaction.MouseWheelZoom);(goog.isDef(c.shiftDragZoom)?c.shiftDragZoom:1)&&d.push(new ol.interaction.DragZoom(ol.interaction.condition.shiftKeyOnly)); +goog.isDef(b)&&d.extend(b);return d};ol.math={};ol.math.cosh=function(a){return(Math.exp(a)+Math.exp(-a))/2};ol.math.coth=function(a){a=Math.exp(-2*a);return(1+a)/(1-a)};ol.math.csch=function(a){return 2/(Math.exp(a)-Math.exp(-a))};ol.math.sech=function(a){return 2/(Math.exp(a)+Math.exp(-a))};ol.math.sinh=function(a){return(Math.exp(a)-Math.exp(-a))/2};ol.math.tanh=function(a){a=Math.exp(-2*a);return(1-a)/(1+a)};ol.projection.EPSG3857=function(a){ol.Projection.call(this,{code:a,units:ol.ProjectionUnits.METERS,extent:ol.projection.EPSG3857.EXTENT,global:!0})};goog.inherits(ol.projection.EPSG3857,ol.Projection);ol.projection.EPSG3857.RADIUS=6378137;ol.projection.EPSG3857.HALF_SIZE=Math.PI*ol.projection.EPSG3857.RADIUS;ol.projection.EPSG3857.EXTENT=new ol.Extent(-ol.projection.EPSG3857.HALF_SIZE,-ol.projection.EPSG3857.HALF_SIZE,ol.projection.EPSG3857.HALF_SIZE,ol.projection.EPSG3857.HALF_SIZE); ol.projection.EPSG3857.CODES=["EPSG:3857","EPSG:102100","EPSG:102113","EPSG:900913"];ol.projection.EPSG3857.PROJECTIONS=goog.array.map(ol.projection.EPSG3857.CODES,function(a){return new ol.projection.EPSG3857(a)}); ol.projection.EPSG3857.fromEPSG4326=function(a,b,c){var d=a.length,c=1j&&goog.dom.insertChildAt(this.target,f.target,0)}else!a.viewHints[ol.ViewHint.ANIMATING]&&!a.viewHints[ol.ViewHint.INTERACTING]&&f.removeTilesOutsideExtent(a.extent); else goog.dom.removeNode(f.target),delete this.tileLayerZs_[j];b.opacity!=this.renderedOpacity_&&(goog.style.setOpacity(this.target,b.opacity),this.renderedOpacity_=b.opacity);b.visible&&!this.renderedVisible_&&(goog.style.showElement(this.target,!0),this.renderedVisible_=!0);this.updateUsedTiles(a.usedTiles,e,h,i);e.useLowResolutionTiles(h,a.extent,g);this.scheduleExpireCache(a,e)}else this.renderedVisible_&&(goog.style.showElement(this.target,!1),this.renderedVisible_=!1)}; ol.renderer.dom.TileLayerZ_=function(a,b){this.target=goog.dom.createElement(goog.dom.TagName.DIV);this.target.style.position="absolute";this.tileGrid_=a;this.tileCoordOrigin_=b;this.origin_=a.getTileCoordExtent(b).getTopLeft();this.resolution_=a.getResolution(b.z);this.tiles_={};this.documentFragment_=null;this.transform_=goog.vec.Mat4.createNumberIdentity()}; @@ -699,11 +694,11 @@ ol.renderer.webgl.TileLayer.prototype.getProjectionMatrix=function(){return this ol.renderer.webgl.TileLayer.prototype.renderFrame=function(a){var b=this.getMapRenderer(),c=b.getGL(),d=a.view2DState,e=d.projection,f=d.center,g=this.getTileLayer().getTileSource(),h=goog.getUid(g).toString(),i=g.getTileGrid();goog.isNull(i)&&(i=ol.tilegrid.getForProjection(e));var l=i.getZForResolution(d.resolution),j=i.getResolution(l),k=i.getTileRangeForExtentAndResolution(a.extent,j),m;if(!goog.isNull(this.renderedTileRange_)&&this.renderedTileRange_.equals(k))m=this.renderedFramebufferExtent_; else{var n=k.getSize(),p=i.getTileSize(l),n=Math.max(n.width*p.width,n.height*p.height),n=Math.pow(2,Math.ceil(Math.log(n)/Math.log(2))),q=new ol.Size(j*n,j*n),r=i.getOrigin(l),s=r.x+k.minX*p.width*j,j=r.y+k.minY*p.height*j;m=new ol.Extent(s,j,s+q.width,j+q.height);this.bindFramebuffer_(a,n);c.viewport(0,0,n,n);c.clearColor(0,0,0,0);c.clear(goog.webgl.COLOR_BUFFER_BIT);c.disable(goog.webgl.BLEND);j=b.getProgram(this.fragmentShader_,this.vertexShader_);c.useProgram(j);goog.isNull(this.locations_)&& (this.locations_={aPosition:c.getAttribLocation(j,"aPosition"),aTexCoord:c.getAttribLocation(j,"aTexCoord"),uTileOffset:c.getUniformLocation(j,"uTileOffset"),uTexture:c.getUniformLocation(j,"uTexture")});goog.isNull(this.arrayBuffer_)?(j=c.createBuffer(),c.bindBuffer(goog.webgl.ARRAY_BUFFER,j),c.bufferData(goog.webgl.ARRAY_BUFFER,new Float32Array([0,0,0,1,1,0,1,1,0,1,0,0,1,1,1,0]),goog.webgl.STATIC_DRAW),this.arrayBuffer_=j):c.bindBuffer(goog.webgl.ARRAY_BUFFER,this.arrayBuffer_);c.enableVertexAttribArray(this.locations_.aPosition); -c.vertexAttribPointer(this.locations_.aPosition,2,goog.webgl.FLOAT,!1,16,0);c.enableVertexAttribArray(this.locations_.aTexCoord);c.vertexAttribPointer(this.locations_.aTexCoord,2,goog.webgl.FLOAT,!1,16,8);c.uniform1i(this.locations_.uTexture,0);var z={};z[l]={};for(var j=this.createGetTileIfLoadedFunction(function(a){return!goog.isNull(a)&&a.getState()==ol.TileState.LOADED&&b.isTileTextureLoaded(a)},g,i,e),p=goog.bind(g.findLoadedTiles,g,z,j),j=new goog.structs.PriorityQueue,w=!0,t,v,r=k.minX;r<= -k.maxX;++r)for(v=k.minY;v<=k.maxY;++v)if(s=new ol.TileCoord(l,r,v),n=g.getTile(s,i,e),!goog.isNull(n)){t=n.getState();if(t==ol.TileState.IDLE)this.listenToTileChange(n),this.updateWantedTiles(a.wantedTiles,g,s),t=i.getTileCoordCenter(s),a.tileQueue.enqueue(n,h,t);else if(t==ol.TileState.LOADED)if(b.isTileTextureLoaded(n)){z[l][s.toString()]=n;continue}else t=i.getTileCoordCenter(s),w=t.x-f.x,t=t.y-f.y,w=Math.sqrt(w*w+t*t),j.enqueue(w,n);else if(t==ol.TileState.ERROR)continue;w=!1;i.forEachTileCoordParentTileRange(s, -p)}e=goog.array.map(goog.object.getKeys(z),Number);goog.array.sort(e);var u=goog.vec.Vec4.createFloat32();goog.array.forEach(e,function(a){goog.object.forEach(z[a],function(a){var d=i.getTileCoordExtent(a.tileCoord),e=2*d.getWidth()/q.width,f=2*d.getHeight()/q.height;goog.vec.Vec4.setFromValues(u,e,f,2*(d.minX-m.minX)/q.width-1,2*(d.minY-m.minY)/q.height-1);c.uniform4fv(this.locations_.uTileOffset,u);b.bindTileTexture(a,goog.webgl.LINEAR,goog.webgl.LINEAR);c.drawArrays(goog.webgl.TRIANGLE_STRIP,0, -4)},this)},this);j.isEmpty()||a.postRenderFunctions.push(goog.partial(function(a,b){var c,d;for(c=0;!b.isEmpty()&&4>c;++c)d=b.remove(),a.bindTileTexture(d,goog.webgl.LINEAR,goog.webgl.LINEAR)},b,j));w?(this.renderedTileRange_=k,this.renderedFramebufferExtent_=m):(this.renderedFramebufferExtent_=this.renderedTileRange_=null,a.animate=!0)}this.updateUsedTiles(a.usedTiles,g,l,k);g.useLowResolutionTiles(l,a.extent,i);this.scheduleExpireCache(a,g);goog.vec.Mat4.makeIdentity(this.texCoordMatrix_);goog.vec.Mat4.translate(this.texCoordMatrix_, -(d.center.x-m.minX)/(m.maxX-m.minX),(d.center.y-m.minY)/(m.maxY-m.minY),0);goog.vec.Mat4.rotateZ(this.texCoordMatrix_,d.rotation);goog.vec.Mat4.scale(this.texCoordMatrix_,a.size.width*d.resolution/(m.maxX-m.minX),a.size.height*d.resolution/(m.maxY-m.minY),1);goog.vec.Mat4.translate(this.texCoordMatrix_,-0.5,-0.5,0)};ol.structs={};ol.structs.LRUCache=function(){this.count_=0;this.entries_={};this.newest_=this.oldest_=null}; +c.vertexAttribPointer(this.locations_.aPosition,2,goog.webgl.FLOAT,!1,16,0);c.enableVertexAttribArray(this.locations_.aTexCoord);c.vertexAttribPointer(this.locations_.aTexCoord,2,goog.webgl.FLOAT,!1,16,8);c.uniform1i(this.locations_.uTexture,0);var t={};t[l]={};for(var j=this.createGetTileIfLoadedFunction(function(a){return!goog.isNull(a)&&a.getState()==ol.TileState.LOADED&&b.isTileTextureLoaded(a)},g,i,e),p=goog.bind(g.findLoadedTiles,g,t,j),j=new goog.structs.PriorityQueue,x=!0,u,v,r=k.minX;r<= +k.maxX;++r)for(v=k.minY;v<=k.maxY;++v){s=new ol.TileCoord(l,r,v);n=g.getTile(s,i,e);u=n.getState();if(u==ol.TileState.IDLE)this.updateWantedTiles(a.wantedTiles,g,s),u=i.getTileCoordCenter(s),a.tileQueue.enqueue(n,h,u);else if(u==ol.TileState.LOADING)this.listenToTileChange(n);else if(u==ol.TileState.LOADED)if(b.isTileTextureLoaded(n)){t[l][s.toString()]=n;continue}else u=i.getTileCoordCenter(s),x=u.x-f.x,u=u.y-f.y,x=Math.sqrt(x*x+u*u),j.enqueue(x,n);else if(u==ol.TileState.ERROR||u==ol.TileState.EMPTY)continue; +x=!1;i.forEachTileCoordParentTileRange(s,p)}e=goog.array.map(goog.object.getKeys(t),Number);goog.array.sort(e);var w=goog.vec.Vec4.createFloat32();goog.array.forEach(e,function(a){goog.object.forEach(t[a],function(a){var d=i.getTileCoordExtent(a.tileCoord),e=2*d.getWidth()/q.width,f=2*d.getHeight()/q.height;goog.vec.Vec4.setFromValues(w,e,f,2*(d.minX-m.minX)/q.width-1,2*(d.minY-m.minY)/q.height-1);c.uniform4fv(this.locations_.uTileOffset,w);b.bindTileTexture(a,goog.webgl.LINEAR,goog.webgl.LINEAR); +c.drawArrays(goog.webgl.TRIANGLE_STRIP,0,4)},this)},this);j.isEmpty()||a.postRenderFunctions.push(goog.partial(function(a,b){var c,d;for(c=0;!b.isEmpty()&&4>c;++c)d=b.remove(),a.bindTileTexture(d,goog.webgl.LINEAR,goog.webgl.LINEAR)},b,j));x?(this.renderedTileRange_=k,this.renderedFramebufferExtent_=m):(this.renderedFramebufferExtent_=this.renderedTileRange_=null,a.animate=!0)}this.updateUsedTiles(a.usedTiles,g,l,k);g.useLowResolutionTiles(l,a.extent,i);this.scheduleExpireCache(a,g);goog.vec.Mat4.makeIdentity(this.texCoordMatrix_); +goog.vec.Mat4.translate(this.texCoordMatrix_,(d.center.x-m.minX)/(m.maxX-m.minX),(d.center.y-m.minY)/(m.maxY-m.minY),0);goog.vec.Mat4.rotateZ(this.texCoordMatrix_,d.rotation);goog.vec.Mat4.scale(this.texCoordMatrix_,a.size.width*d.resolution/(m.maxX-m.minX),a.size.height*d.resolution/(m.maxY-m.minY),1);goog.vec.Mat4.translate(this.texCoordMatrix_,-0.5,-0.5,0)};ol.structs={};ol.structs.LRUCache=function(){this.count_=0;this.entries_={};this.newest_=this.oldest_=null}; ol.structs.LRUCache.prototype.assertValid=function(){if(0===this.count_)goog.asserts.assert(goog.object.isEmpty(this.entries_)),goog.asserts.assert(goog.isNull(this.oldest_)),goog.asserts.assert(goog.isNull(this.newest_));else{goog.asserts.assert(goog.object.getCount(this.entries_)==this.count_);goog.asserts.assert(!goog.isNull(this.oldest_));goog.asserts.assert(goog.isNull(this.oldest_.older));goog.asserts.assert(!goog.isNull(this.newest_));goog.asserts.assert(goog.isNull(this.newest_.newer));var a, b,c=null;a=0;for(b=this.oldest_;!goog.isNull(b);b=b.newer)goog.asserts.assert(b.older===c),c=b,++a;goog.asserts.assert(a==this.count_);c=null;a=0;for(b=this.newest_;!goog.isNull(b);b=b.older)goog.asserts.assert(b.newer===c),c=b,++a;goog.asserts.assert(a==this.count_)}};ol.structs.LRUCache.prototype.clear=function(){this.count_=0;this.entries_={};this.newest_=this.oldest_=null};ol.structs.LRUCache.prototype.containsKey=function(a){return this.entries_.hasOwnProperty(a)}; ol.structs.LRUCache.prototype.forEach=function(a,b){for(var c=this.oldest_;!goog.isNull(c);)a.call(b,c.value_,c.key_,this),c=c.newer};ol.structs.LRUCache.prototype.get=function(a){a=this.entries_[a];goog.asserts.assert(goog.isDef(a));if(a===this.newest_)return a.value_;a===this.oldest_?(this.oldest_=this.oldest_.newer,this.oldest_.older=null):(a.newer.older=a.older,a.older.newer=a.newer);a.newer=null;a.older=this.newest_;this.newest_=this.newest_.newer=a;return a.value_}; @@ -715,7 +710,7 @@ ol.webgl.SUPPORTED=function(){if(!("WebGLRenderingContext"in goog.global))return goog.inherits(ol.renderer.webgl.map.shader.Fragment,ol.renderer.webgl.FragmentShader);goog.addSingletonGetter(ol.renderer.webgl.map.shader.Fragment);ol.renderer.webgl.map.shader.Vertex=function(){ol.renderer.webgl.VertexShader.call(this,"attribute vec2 a_position;\nattribute vec2 a_texCoord;\n\nuniform mat4 u_texCoordMatrix;\nuniform mat4 u_projectionMatrix;\n\nvarying vec2 v_texCoord;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.);\n v_texCoord = (u_texCoordMatrix * vec4(a_texCoord, 0., 1.)).st;\n}")}; goog.inherits(ol.renderer.webgl.map.shader.Vertex,ol.renderer.webgl.VertexShader);goog.addSingletonGetter(ol.renderer.webgl.map.shader.Vertex); ol.renderer.webgl.Map=function(a,b){ol.renderer.Map.call(this,a,b);goog.DEBUG&&(this.logger=goog.debug.Logger.getLogger("ol.renderer.webgl.maprenderer."+goog.getUid(this)));this.canvas_=goog.dom.createElement(goog.dom.TagName.CANVAS);this.canvas_.height=a.clientHeight;this.canvas_.width=a.clientWidth;this.canvas_.className="ol-unselectable";goog.dom.insertChildAt(a,this.canvas_,0);this.renderedVisible_=!0;this.canvasSize_=new ol.Size(a.clientHeight,a.clientWidth);this.gl_=ol.webgl.getContext(this.canvas_, -{alpha:!1,antialias:!0,depth:!1,preserveDrawingBuffer:!1,stencil:!1});goog.asserts.assert(!goog.isNull(this.gl_));goog.events.listen(this.canvas_,ol.webgl.WebGLContextEventType.LOST,this.handleWebGLContextLost,!1,this);goog.events.listen(this.canvas_,ol.webgl.WebGLContextEventType.RESTORED,this.handleWebGLContextResourced,!1,this);this.arrayBuffer_=this.locations_=null;this.shaderCache_={};this.programCache_={};this.textureCache_=new ol.structs.LRUCache;this.textureCacheFrameMarkerCount_=0;this.fragmentShader_= +{alpha:!1,antialias:!0,depth:!1,preserveDrawingBuffer:!1,stencil:!1});goog.asserts.assert(!goog.isNull(this.gl_));goog.events.listen(this.canvas_,ol.webgl.WebGLContextEventType.LOST,this.handleWebGLContextLost,!1,this);goog.events.listen(this.canvas_,ol.webgl.WebGLContextEventType.RESTORED,this.handleWebGLContextRestored,!1,this);this.arrayBuffer_=this.locations_=null;this.shaderCache_={};this.programCache_={};this.textureCache_=new ol.structs.LRUCache;this.textureCacheFrameMarkerCount_=0;this.fragmentShader_= ol.renderer.webgl.map.shader.Fragment.getInstance();this.vertexShader_=ol.renderer.webgl.map.shader.Vertex.getInstance();this.initializeGL_()};goog.inherits(ol.renderer.webgl.Map,ol.renderer.Map);ol.renderer.webgl.Map.prototype.addLayer=function(a){ol.renderer.webgl.Map.superClass_.addLayer.call(this,a);a.getVisible()&&this.getMap().render()}; ol.renderer.webgl.Map.prototype.bindTileTexture=function(a,b,c){var d=this.getGL(),e=a.getKey();if(this.textureCache_.containsKey(e))a=this.textureCache_.get(e),d.bindTexture(goog.webgl.TEXTURE_2D,a.texture),a.magFilter!=b&&(d.texParameteri(goog.webgl.TEXTURE_2D,goog.webgl.TEXTURE_MAG_FILTER,b),a.magFilter=b),a.minFilter!=c&&(d.texParameteri(goog.webgl.TEXTURE_2D,goog.webgl.TEXTURE_MAG_FILTER,c),a.minFilter=c);else{var f=d.createTexture();d.bindTexture(goog.webgl.TEXTURE_2D,f);d.texImage2D(goog.webgl.TEXTURE_2D, 0,goog.webgl.RGBA,goog.webgl.RGBA,goog.webgl.UNSIGNED_BYTE,a.getImage());d.texParameteri(goog.webgl.TEXTURE_2D,goog.webgl.TEXTURE_MAG_FILTER,b);d.texParameteri(goog.webgl.TEXTURE_2D,goog.webgl.TEXTURE_MIN_FILTER,c);d.texParameteri(goog.webgl.TEXTURE_2D,goog.webgl.TEXTURE_WRAP_S,goog.webgl.CLAMP_TO_EDGE);d.texParameteri(goog.webgl.TEXTURE_2D,goog.webgl.TEXTURE_WRAP_T,goog.webgl.CLAMP_TO_EDGE);this.textureCache_.set(e,{texture:f,magFilter:b,minFilter:c})}}; @@ -726,7 +721,7 @@ ol.renderer.webgl.Map.prototype.getGL=function(){return this.gl_}; ol.renderer.webgl.Map.prototype.getProgram=function(a,b){var c=goog.getUid(a)+"/"+goog.getUid(b);if(c in this.programCache_)return this.programCache_[c];var d=this.getGL(),e=d.createProgram();d.attachShader(e,this.getShader(a));d.attachShader(e,this.getShader(b));d.linkProgram(e);goog.DEBUG&&(!d.getProgramParameter(e,goog.webgl.LINK_STATUS)&&!d.isContextLost())&&(this.logger.severe(d.getProgramInfoLog(e)),goog.asserts.assert(d.getProgramParameter(e,goog.webgl.LINK_STATUS)));return this.programCache_[c]= e};ol.renderer.webgl.Map.prototype.getShader=function(a){var b=goog.getUid(a);if(b in this.shaderCache_)return this.shaderCache_[b];var c=this.getGL(),d=c.createShader(a.getType());c.shaderSource(d,a.getSource());c.compileShader(d);goog.DEBUG&&(!c.getShaderParameter(d,goog.webgl.COMPILE_STATUS)&&!c.isContextLost())&&(this.logger.severe(c.getShaderInfoLog(d)),goog.asserts.assert(c.getShaderParameter(d,goog.webgl.COMPILE_STATUS)));return this.shaderCache_[b]=d}; ol.renderer.webgl.Map.prototype.handleWebGLContextLost=function(a){goog.DEBUG&&this.logger.info("WebGLContextLost");a.preventDefault();this.arrayBuffer_=this.locations_=null;this.shaderCache_={};this.programCache_={};this.textureCache_.clear();this.textureCacheFrameMarkerCount_=0;goog.object.forEach(this.layerRenderers,function(a){a.handleWebGLContextLost()})}; -ol.renderer.webgl.Map.prototype.handleWebGLContextResourced=function(){goog.DEBUG&&this.logger.info("WebGLContextResourced");this.initializeGL_();this.getMap().render()};ol.renderer.webgl.Map.prototype.initializeGL_=function(){var a=this.gl_;a.activeTexture(goog.webgl.TEXTURE0);a.blendFunc(goog.webgl.SRC_ALPHA,goog.webgl.ONE_MINUS_SRC_ALPHA);a.disable(goog.webgl.CULL_FACE);a.disable(goog.webgl.DEPTH_TEST);a.disable(goog.webgl.SCISSOR_TEST)};ol.renderer.webgl.Map.prototype.isTileTextureLoaded=function(a){return this.textureCache_.containsKey(a.getKey())}; +ol.renderer.webgl.Map.prototype.handleWebGLContextRestored=function(){goog.DEBUG&&this.logger.info("WebGLContextRestored");this.initializeGL_();this.getMap().render()};ol.renderer.webgl.Map.prototype.initializeGL_=function(){var a=this.gl_;a.activeTexture(goog.webgl.TEXTURE0);a.blendFunc(goog.webgl.SRC_ALPHA,goog.webgl.ONE_MINUS_SRC_ALPHA);a.disable(goog.webgl.CULL_FACE);a.disable(goog.webgl.DEPTH_TEST);a.disable(goog.webgl.SCISSOR_TEST)};ol.renderer.webgl.Map.prototype.isTileTextureLoaded=function(a){return this.textureCache_.containsKey(a.getKey())}; ol.renderer.webgl.Map.prototype.removeLayer=function(a){ol.renderer.webgl.Map.superClass_.removeLayer.call(this,a);a.getVisible()&&this.getMap().render()}; ol.renderer.webgl.Map.prototype.renderFrame=function(a){var b=this.getGL();if(goog.isNull(a))return this.renderedVisible_&&(goog.style.showElement(this.canvas_,!1),this.renderedVisible_=!1),!1;this.textureCache_.set(a.time.toString(),null);++this.textureCacheFrameMarkerCount_;goog.array.forEach(a.layersArray,function(b){var c=a.layerStates[goog.getUid(b)];c.visible&&c.ready&&this.getLayerRenderer(b).renderFrame(a,c)},this);var c=a.size;this.canvasSize_.equals(c)||(this.canvas_.width=c.width,this.canvas_.height= c.height,this.canvasSize_=c);b.bindFramebuffer(goog.webgl.FRAMEBUFFER,null);var d=a.backgroundColor;b.clearColor(d.r/255,d.g/255,d.b/255,d.a);b.clear(goog.webgl.COLOR_BUFFER_BIT);b.enable(goog.webgl.BLEND);b.viewport(0,0,c.width,c.height);c=this.getProgram(this.fragmentShader_,this.vertexShader_);b.useProgram(c);goog.isNull(this.locations_)&&(this.locations_={a_position:b.getAttribLocation(c,"a_position"),a_texCoord:b.getAttribLocation(c,"a_texCoord"),u_colorMatrix:b.getUniformLocation(c,"u_colorMatrix"), @@ -737,25 +732,26 @@ a.postRenderFunctions.push(goog.bind(this.expireCache_,this))};ol.renderer.webgl ol.Map=function(a){ol.Object.call(this);goog.DEBUG&&(this.logger=goog.debug.Logger.getLogger("ol.map."+goog.getUid(this)));a=ol.Map.createOptionsInternal(a);this.animationDelay_=new goog.async.AnimationDelay(this.renderFrame_,void 0,this);this.registerDisposable(this.animationDelay_);this.coordinateToPixelMatrix_=goog.vec.Mat4.createNumber();this.pixelToCoordinateMatrix_=goog.vec.Mat4.createNumber();this.frameState_=null;this.freezeRenderingCount_=0;this.dirty_=!1;this.target_=a.target;this.viewPropertyListenerKey_= null;this.viewport_=goog.dom.createDom(goog.dom.TagName.DIV,"ol-viewport");this.viewport_.style.position="relative";this.viewport_.style.overflow="hidden";this.viewport_.style.width="100%";this.viewport_.style.height="100%";this.viewport_.style.msTouchAction="none";goog.dom.appendChild(this.target_,this.viewport_);this.overlayContainer_=goog.dom.createDom(goog.dom.TagName.DIV,"ol-overlaycontainer");goog.events.listen(this.overlayContainer_,[goog.events.EventType.CLICK,ol.BrowserFeature.HAS_TOUCH? goog.events.EventType.TOUCHSTART:goog.events.EventType.MOUSEDOWN],goog.events.Event.stopPropagation);goog.dom.appendChild(this.viewport_,this.overlayContainer_);var b=new ol.MapBrowserEventHandler(this);goog.events.listen(b,goog.object.getValues(ol.MapBrowserEvent.EventType),this.handleMapBrowserEvent,!1,this);this.registerDisposable(b);b=new goog.events.KeyHandler(document);goog.events.listen(b,goog.events.KeyHandler.EventType.KEY,this.handleBrowserEvent,!1,this);this.registerDisposable(b);b=new goog.events.MouseWheelHandler(this.viewport_); -goog.events.listen(b,goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,this.handleBrowserEvent,!1,this);this.registerDisposable(b);this.interactions_=a.interactions;this.renderer_=new a.rendererConstructor(this.viewport_,this);this.registerDisposable(this.renderer_);this.viewportSizeMonitor_=new goog.dom.ViewportSizeMonitor;goog.events.listen(this.viewportSizeMonitor_,goog.events.EventType.RESIZE,this.handleBrowserWindowResize,!1,this);this.preRenderFunctions_=[];this.postRenderFunctions_=[];this.handlePostRender_= -goog.bind(this.handlePostRender,this);this.tileQueue_=new ol.TileQueue(goog.bind(this.getTilePriority,this));goog.events.listen(this,ol.Object.getChangedEventType(ol.MapProperty.VIEW),this.handleViewChanged_,!1,this);goog.events.listen(this,ol.Object.getChangedEventType(ol.MapProperty.SIZE),this.handleSizeChanged_,!1,this);goog.events.listen(this,ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR),this.handleBackgroundColorChanged_,!1,this);this.setValues(a.values);this.handleBrowserWindowResize(); -goog.isDef(a.controls)&&goog.array.forEach(a.controls,function(a){a.setMap(this)},this)};goog.inherits(ol.Map,ol.Object);ol.Map.prototype.addPreRenderFunction=function(a){this.requestRenderFrame();this.preRenderFunctions_.push(a)};ol.Map.prototype.addPreRenderFunctions=function(a){this.requestRenderFrame();Array.prototype.push.apply(this.preRenderFunctions_,a)};ol.Map.prototype.removePreRenderFunction=function(a){return goog.array.remove(this.preRenderFunctions_,a)}; -ol.Map.prototype.disposeInternal=function(){goog.dom.removeNode(this.viewport_);ol.Map.superClass_.disposeInternal.call(this)};ol.Map.prototype.freezeRendering=function(){++this.freezeRenderingCount_};ol.Map.prototype.getBackgroundColor=function(){return this.get(ol.MapProperty.BACKGROUND_COLOR)};goog.exportProperty(ol.Map.prototype,"getBackgroundColor",ol.Map.prototype.getBackgroundColor);ol.Map.prototype.getRenderer=function(){return this.renderer_};ol.Map.prototype.getTarget=function(){return this.target_}; -ol.Map.prototype.getCoordinateFromPixel=function(a){var b=this.frameState_;if(goog.isNull(b))return null;a=[a.x,a.y,0];goog.vec.Mat4.multVec3(b.pixelToCoordinateMatrix,a,a);return new ol.Coordinate(a[0],a[1])};ol.Map.prototype.getInteractions=function(){return this.interactions_};ol.Map.prototype.getLayers=function(){return this.get(ol.MapProperty.LAYERS)};goog.exportProperty(ol.Map.prototype,"getLayers",ol.Map.prototype.getLayers); -ol.Map.prototype.getPixelFromCoordinate=function(a){var b=this.frameState_;if(goog.isNull(b))return null;a=[a.x,a.y,0];goog.vec.Mat4.multVec3(b.coordinateToPixelMatrix,a,a);return new ol.Pixel(a[0],a[1])};ol.Map.prototype.getSize=function(){return this.get(ol.MapProperty.SIZE)};goog.exportProperty(ol.Map.prototype,"getSize",ol.Map.prototype.getSize);ol.Map.prototype.getView=function(){return this.get(ol.MapProperty.VIEW)};goog.exportProperty(ol.Map.prototype,"getView",ol.Map.prototype.getView); -ol.Map.prototype.getViewport=function(){return this.viewport_};ol.Map.prototype.getOverlayContainer=function(){return this.overlayContainer_};ol.Map.prototype.getTilePriority=function(a,b,c){var d=this.frameState_;if(goog.isNull(d)||!(b in d.wantedTiles)||!d.wantedTiles[b][a.tileCoord.toString()])return ol.TileQueue.DROP;b=d.view2DState.center;a=c.x-b.x;c=c.y-b.y;return a*a+c*c};ol.Map.prototype.handleBrowserEvent=function(a,b){var c=new ol.MapBrowserEvent(b||a.type,this,a);this.handleMapBrowserEvent(c)}; -ol.Map.prototype.handleMapBrowserEvent=function(a){a.frameState=this.frameState_;var b=this.getInteractions().getArray();if(!1!==this.dispatchEvent(a))for(var c=b.length-1;0<=c&&!(b[c].handleMapBrowserEvent(a),a.defaultPrevented);c--);};ol.Map.prototype.handlePostRender=function(){this.tileQueue_.reprioritize();this.tileQueue_.loadMoreTiles();var a=this.postRenderFunctions_,b;for(b=0;bb;++b)d=c[b],d.rotate(i),d.add(a);f.extent=ol.Extent.boundingExtent.apply(null,c)}this.frameState_=f;this.renderer_.renderFrame(f);this.dirty_=!1;goog.isNull(f)||(f.animate&&this.requestRenderFrame(),Array.prototype.push.apply(this.postRenderFunctions_,f.postRenderFunctions));this.dispatchEvent(new ol.MapEvent(ol.MapEventType.POSTRENDER,this,f));goog.global.setTimeout(this.handlePostRender_, 0)}};ol.Map.prototype.setBackgroundColor=function(a){this.set(ol.MapProperty.BACKGROUND_COLOR,a)};goog.exportProperty(ol.Map.prototype,"setBackgroundColor",ol.Map.prototype.setBackgroundColor);ol.Map.prototype.setLayers=function(a){this.set(ol.MapProperty.LAYERS,a)};goog.exportProperty(ol.Map.prototype,"setLayers",ol.Map.prototype.setLayers);ol.Map.prototype.setSize=function(a){this.set(ol.MapProperty.SIZE,a)};goog.exportProperty(ol.Map.prototype,"setSize",ol.Map.prototype.setSize); ol.Map.prototype.setView=function(a){this.set(ol.MapProperty.VIEW,a)};goog.exportProperty(ol.Map.prototype,"setView",ol.Map.prototype.setView);ol.Map.prototype.unfreezeRendering=function(){goog.asserts.assert(0this.highWaterMark_};ol.TileCache.prototype.expireCache=function(a){for(var b,c;this.canExpireCache()&&!(b=this.peekLast(),c=b.tileCoord.z.toString(),c in a&&a[c].contains(b.tileCoord));)this.pop()};ol.TileUrlFunction={};ol.TileUrlFunction.createFromTemplate=function(a){var b=/\{(\d)-(\d)\}/.exec(a)||/\{([a-z])-([a-z])\}/.exec(a);if(b){for(var c=[],d=b[1].charCodeAt(0),e=b[2].charCodeAt(0);d<=e;++d)c.push(a.replace(b[0],String.fromCharCode(d)));return ol.TileUrlFunction.createFromTemplates(c)}return function(b){return goog.isNull(b)?void 0:a.replace("{z}",b.z).replace("{x}",b.x).replace("{y}",b.y)}}; ol.TileUrlFunction.createFromTemplates=function(a){return ol.TileUrlFunction.createFromTileUrlFunctions(goog.array.map(a,ol.TileUrlFunction.createFromTemplate))};ol.TileUrlFunction.createFromTileUrlFunctions=function(a){return function(b,c,d){if(!goog.isNull(b)){var e=goog.math.modulo(b.hash(),a.length);return a[e](b,c,d)}}}; -ol.TileUrlFunction.createWMSParams=function(a,b){return function(c,d,e){if(!goog.isNull(c)){var f=d.getTileSize(c.z),c=d.getTileCoordExtent(c);return ol.source.wms.getUrl(a,b,c,f,e)}}};ol.TileUrlFunction.nullTileUrlFunction=function(){};ol.TileUrlFunction.withTileCoordTransform=function(a,b){return function(c,d,e){return goog.isNull(c)?void 0:b(a(c,d,e),d,e)}};ol.control.MousePosition=function(a){var a=goog.isDef(a)?a:{},b=goog.dom.createDom(goog.dom.TagName.DIV,{"class":"ol-mouse-position"});ol.control.Control.call(this,{element:b,map:a.map,target:a.target});this.projection_=a.projection;this.coordinateFormat_=a.coordinateFormat;this.undefinedHTML_=goog.isDef(a.undefinedHTML)?a.undefinedHTML:"";this.renderedHTML_=b.innerHTML;this.mapProjection_=null;this.transform_=ol.projection.identityTransform;this.listenerKeys_=this.lastMouseMovePixel_=this.renderedProjection_= -null};goog.inherits(ol.control.MousePosition,ol.control.Control);ol.control.MousePosition.prototype.handleMapPostrender=function(a){a=a.frameState;this.mapProjection_=goog.isNull(a)?null:a.view2DState.projection;this.updateHTML_(this.lastMouseMovePixel_)};ol.control.MousePosition.prototype.handleMouseMove=function(a){var b=this.getMap(),a=goog.style.getRelativePosition(a,b.getViewport()),a=new ol.Pixel(a.x,a.y);this.updateHTML_(a);this.lastMouseMovePixel_=a}; +ol.TileUrlFunction.createWMSParams=function(a,b){return function(c,d,e){if(!goog.isNull(c)){var f=d.getTileSize(c.z),c=d.getTileCoordExtent(c);return ol.source.wms.getUrl(a,b,c,f,e)}}};ol.TileUrlFunction.nullTileUrlFunction=function(){};ol.TileUrlFunction.withTileCoordTransform=function(a,b){return function(c,d,e){return goog.isNull(c)?void 0:b(a(c,d,e),d,e)}};ol.control.MousePosition=function(a){var a=goog.isDef(a)?a:{},b=goog.dom.createDom(goog.dom.TagName.DIV,{"class":"ol-mouse-position"});ol.control.Control.call(this,{element:b,map:a.map,target:a.target});this.projection_=ol.projection.get(a.projection);this.coordinateFormat_=a.coordinateFormat;this.undefinedHTML_=goog.isDef(a.undefinedHTML)?a.undefinedHTML:"";this.renderedHTML_=b.innerHTML;this.mapProjection_=null;this.transform_=ol.projection.identityTransform;this.listenerKeys_=this.lastMouseMovePixel_= +this.renderedProjection_=null};goog.inherits(ol.control.MousePosition,ol.control.Control);ol.control.MousePosition.prototype.handleMapPostrender=function(a){a=a.frameState;this.mapProjection_=goog.isNull(a)?null:a.view2DState.projection;this.updateHTML_(this.lastMouseMovePixel_)};ol.control.MousePosition.prototype.handleMouseMove=function(a){var b=this.getMap(),a=goog.style.getRelativePosition(a,b.getViewport()),a=new ol.Pixel(a.x,a.y);this.updateHTML_(a);this.lastMouseMovePixel_=a}; ol.control.MousePosition.prototype.handleMouseOut=function(){this.updateHTML_(null);this.lastMouseMovePixel_=null}; ol.control.MousePosition.prototype.setMap=function(a){goog.isNull(this.listenerKeys_)||(goog.array.forEach(this.listenerKeys_,goog.events.unlistenByKey),this.listenerKeys_=null);ol.control.MousePosition.superClass_.setMap.call(this,a);if(!goog.isNull(a)){var b=a.getViewport();this.listenerKeys_=[goog.events.listen(b,goog.events.EventType.MOUSEMOVE,this.handleMouseMove,!1,this),goog.events.listen(b,goog.events.EventType.MOUSEOUT,this.handleMouseOut,!1,this),goog.events.listen(a,ol.MapEventType.POSTRENDER, this.handleMapPostrender,!1,this)]}}; -ol.control.MousePosition.prototype.updateHTML_=function(a){var b=this.undefinedHTML_;goog.isNull(a)||(this.renderedProjection_!=this.mapProjection_&&(this.transform_=goog.isDef(this.projection_)?ol.projection.getTransform(this.mapProjection_,this.projection_):ol.projection.identityTransform,this.renderedProjection_=this.mapProjection_),a=this.getMap().getCoordinateFromPixel(a),goog.isNull(a)||(b=[a.x,a.y],b=this.transform_(b,b),a=new ol.Coordinate(b[0],b[1]),b=goog.isDef(this.coordinateFormat_)?this.coordinateFormat_(a): -a.toString()));if(!goog.isDef(this.renderedHTML_)||b!=this.renderedHTML_)this.renderedHTML_=this.element.innerHTML=b};ol.ellipsoid={};ol.ellipsoid.WGS84=new ol.Ellipsoid(6378137,1/298.257223563);ol.interaction.DragRotateAndZoom=function(a){ol.interaction.Drag.call(this);this.condition_=a};goog.inherits(ol.interaction.DragRotateAndZoom,ol.interaction.Drag); +ol.control.MousePosition.prototype.updateHTML_=function(a){var b=this.undefinedHTML_;goog.isNull(a)||(this.renderedProjection_!=this.mapProjection_&&(this.transform_=goog.isNull(this.projection_)?ol.projection.identityTransform:ol.projection.getTransformFromProjections(this.mapProjection_,this.projection_),this.renderedProjection_=this.mapProjection_),a=this.getMap().getCoordinateFromPixel(a),goog.isNull(a)||(b=[a.x,a.y],b=this.transform_(b,b),a=new ol.Coordinate(b[0],b[1]),b=goog.isDef(this.coordinateFormat_)? +this.coordinateFormat_(a):a.toString()));if(!goog.isDef(this.renderedHTML_)||b!=this.renderedHTML_)this.renderedHTML_=this.element.innerHTML=b};ol.control.ScaleLineUnits={DEGREES:"degrees",IMPERIAL:"imperial",NAUTICAL:"nautical",METRIC:"metric",US:"us"}; +ol.control.ScaleLine=function(a){a=a||{};this.innerElement_=goog.dom.createDom(goog.dom.TagName.DIV,{"class":"ol-scale-line-inner"});this.element_=goog.dom.createDom(goog.dom.TagName.DIV,{"class":"ol-scale-line ol-unselectable"},this.innerElement_);this.minWidth_=goog.isDef(a.minWidth)?a.minWidth:64;this.units_=goog.isDef(a.units)?a.units:ol.control.ScaleLineUnits.METRIC;this.listenerKeys_=null;this.renderedVisible_=!1;this.renderedHTML_="";this.toEPSG4326_=null;ol.control.Control.call(this,{element:this.element_, +map:a.map,target:a.target})};goog.inherits(ol.control.ScaleLine,ol.control.Control);ol.control.ScaleLine.LEADING_DIGITS=[1,2,5];ol.control.ScaleLine.prototype.handleMapPostrender=function(a){this.updateElement_(a.frameState)}; +ol.control.ScaleLine.prototype.setMap=function(a){goog.isNull(this.listenerKeys_)||(goog.array.forEach(this.listenerKeys_,goog.events.unlistenByKey),this.listenerKeys_=null);ol.control.ScaleLine.superClass_.setMap.call(this,a);goog.isNull(a)||(this.listenerKeys_=[goog.events.listen(a,ol.MapEventType.POSTRENDER,this.handleMapPostrender,!1,this)])}; +ol.control.ScaleLine.prototype.updateElement_=function(a){if(goog.isNull(a))this.renderedVisible_&&(goog.style.showElement(this.element_,!1),this.renderedVisible_=!1);else{var a=a.view2DState,b=a.center,c=a.projection,a=c.getPointResolution(a.resolution,b),d=c.getUnits();d==ol.ProjectionUnits.DEGREES&&(this.units_==ol.control.ScaleLineUnits.METRIC||this.units_==ol.control.ScaleLineUnits.IMPERIAL)?(this.toEPSG4326_=null,b=Math.cos(goog.math.toRadians(b.y)),a*=Math.PI*b*ol.sphere.NORMAL.radius/180, +d=ol.ProjectionUnits.METERS):(d==ol.ProjectionUnits.FEET||d==ol.ProjectionUnits.METERS)&&this.units_==ol.control.ScaleLineUnits.DEGREES?(goog.isNull(this.toEPSG4326_)&&(this.toEPSG4326_=ol.projection.getTransformFromProjections(c,ol.projection.get("EPSG:4326"))),b=[b.x,b.y],b=this.toEPSG4326_(b,b,2),b=Math.cos(goog.math.toRadians(b[1])),c=ol.sphere.NORMAL.radius,d==ol.ProjectionUnits.FEET&&(c/=0.3048),a*=180/(Math.PI*b*c),d=ol.ProjectionUnits.DEGREES):this.toEPSG4326_=null;goog.asserts.assert((this.units_== +ol.control.ScaleLineUnits.METRIC||this.units_==ol.control.ScaleLineUnits.IMPERIAL)&&d==ol.ProjectionUnits.METERS||this.units_==ol.control.ScaleLineUnits.DEGREES&&d==ol.ProjectionUnits.DEGREES);b=this.minWidth_*a;d="";this.units_==ol.control.ScaleLineUnits.DEGREES?b<1/60?(d="\u2033",a*=3600):1>b?(d="\u2032",a*=60):d="\u00b0":this.units_==ol.control.ScaleLineUnits.IMPERIAL?0.9144>b?(d="in",a/=0.0254):1609.344>b?(d="ft",a/=0.3048):(d="mi",a/=1609.344):this.units_==ol.control.ScaleLineUnits.NAUTICAL? +(a/=1852,d="nm"):this.units_==ol.control.ScaleLineUnits.METRIC?1>b?(d="mm",a*=1E3):1E3>b?d="m":(d="km",a/=1E3):this.units_==ol.control.ScaleLineUnits.US?0.9144>b?(d="in",a*=39.37):1609.344>b?(d="ft",a/=0.30480061):(d="mi",a/=1609.3472):goog.asserts.assert(!1);for(var b=3*Math.floor(Math.log(this.minWidth_*a)/Math.log(10)),e,f;;){e=ol.control.ScaleLine.LEADING_DIGITS[b%3]*Math.pow(10,Math.floor(b/3));f=Math.round(e/a);if(f>=this.minWidth_)break;++b}e+=d;this.renderedHTML_!=e&&(this.renderedHTML_=this.innerElement_.innerHTML= +e);this.renderedWidth_!=f&&(this.innerElement_.style.width=f+"px",this.renderedWidth_=f);this.renderedVisible_||(goog.style.showElement(this.element_,!0),this.renderedVisible_=!0)}};ol.ellipsoid={};ol.ellipsoid.WGS84=new ol.Ellipsoid(6378137,1/298.257223563);ol.interaction.DragRotateAndZoom=function(a){ol.interaction.Drag.call(this);this.condition_=a};goog.inherits(ol.interaction.DragRotateAndZoom,ol.interaction.Drag); ol.interaction.DragRotateAndZoom.prototype.handleDrag=function(a){var b=a.browserEvent,a=a.map,c=a.getSize(),c=new goog.math.Vec2(b.offsetX-c.width/2,c.height/2-b.offsetY),b=Math.atan2(c.y,c.x),c=c.magnitude(),d=a.getView();goog.asserts.assert(d instanceof ol.View2D);a.requestRenderFrame();if(goog.isDef(this.lastAngle_)){var e=b-this.lastAngle_;d.rotate(a,d.getRotation()-e)}this.lastAngle_=b;goog.isDef(this.lastMagnitude_)&&(b=this.lastMagnitude_*(d.getResolution()/c),d.zoom(a,b));this.lastMagnitude_= c};ol.interaction.DragRotateAndZoom.prototype.handleDragStart=function(a){return this.condition_(a.browserEvent)?(this.lastMagnitude_=this.lastAngle_=void 0,!0):!1};ol.interaction.Keyboard=function(){ol.interaction.Interaction.call(this);this.charCodeCallbacks_={}};goog.inherits(ol.interaction.Keyboard,ol.interaction.Interaction);ol.interaction.Keyboard.prototype.addCallback=function(a,b){var c;for(c=0;ca)break;d>>=1;e>>=1;f=new ol.TileRange(d,e,d,e);if(b.call(c,a,f))break}};ol.source.BingMaps=function(a){ol.source.ImageTileSource.call(this,{opaque:!0,projection:ol.projection.getFromCode("EPSG:3857")});this.culture_=goog.isDef(a.culture)?a.culture:"en-us";this.ready_=!1;var b=new goog.Uri("//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+a.style);(new goog.net.Jsonp(b,"jsonp")).send({include:"ImageryProviders",key:a.key},goog.bind(this.handleImageryMetadataResponse,this))};goog.inherits(ol.source.BingMaps,ol.source.ImageTileSource); +ol.source.ImageTileSource.prototype.getTile=function(a,b,c){var d=a.toString();if(this.tileCache_.containsKey(d))return this.tileCache_.get(d);goog.asserts.assert(b);goog.asserts.assert(c);b=this.tileUrlFunction(a,b,c);a=new ol.ImageTile(a,goog.isDef(b)?ol.TileState.IDLE:ol.TileState.EMPTY,goog.isDef(b)?b:"",this.crossOrigin_);this.tileCache_.set(d,a);return a};ol.source.ImageTileSource.prototype.useTile=function(a){a=a.toString();this.tileCache_.containsKey(a)&&this.tileCache_.get(a)};ol.tilegrid.XYZ=function(a){var b=Array(a.maxZoom+1),c,d=2*ol.projection.EPSG3857.HALF_SIZE/ol.DEFAULT_TILE_SIZE;for(c=0;c<=a.maxZoom;++c)b[c]=d/Math.pow(2,c);ol.tilegrid.TileGrid.call(this,{origin:new ol.Coordinate(-ol.projection.EPSG3857.HALF_SIZE,ol.projection.EPSG3857.HALF_SIZE),resolutions:b,tileSize:new ol.Size(ol.DEFAULT_TILE_SIZE,ol.DEFAULT_TILE_SIZE)})};goog.inherits(ol.tilegrid.XYZ,ol.tilegrid.TileGrid); +ol.tilegrid.XYZ.prototype.forEachTileCoordParentTileRange=function(a,b,c){for(var d=a.x,e=a.y,a=a.z,f;;){a-=1;if(0>a)break;d>>=1;e>>=1;f=new ol.TileRange(d,e,d,e);if(b.call(c,a,f))break}};ol.source.BingMaps=function(a){ol.source.ImageTileSource.call(this,{opaque:!0,projection:ol.projection.get("EPSG:3857")});this.culture_=goog.isDef(a.culture)?a.culture:"en-us";this.ready_=!1;var b=new goog.Uri("//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+a.style);(new goog.net.Jsonp(b,"jsonp")).send({include:"ImageryProviders",key:a.key},goog.bind(this.handleImageryMetadataResponse,this))};goog.inherits(ol.source.BingMaps,ol.source.ImageTileSource); ol.source.BingMaps.prototype.handleImageryMetadataResponse=function(a){goog.asserts.assert("ValidCredentials"==a.authenticationResultCode);goog.asserts.assert(200==a.statusCode);goog.asserts.assert("OK"==a.statusDescription);goog.asserts.assert(1==a.resourceSets.length);a=a.resourceSets[0];goog.asserts.assert(1==a.resources.length);var b=a.resources[0],c=b.zoomMin,d=b.zoomMax,a=new ol.Size(b.imageWidth,b.imageHeight),e=new ol.tilegrid.XYZ({maxZoom:d,tileSize:a});this.tileGrid=e;this.tileUrlFunction= -ol.TileUrlFunction.withTileCoordTransform(function(a){if(a.ze||b<=e)return null;b=goog.math.modulo(a.x,b);return new ol.TileCoord(a.z,b,e)},ol.TileUrlFunction.createFromTileUrlFunctions(goog.array.map(b.imageUrlSubdomains,function(a){var c=b.imageUrl.replace("{subdomain}",a).replace("{culture}",this.culture_);return function(a){return goog.isNull(a)?void 0:c.replace("{quadkey}",a.quadKey())}})));var f=ol.projection.getTransform(ol.projection.getFromCode("EPSG:4326"), -this.getProjection()),a=goog.array.map(b.imageryProviders,function(a){var b=a.attribution,c={};goog.array.forEach(a.coverageAreas,function(a){var b=a.zoomMin,d=a.zoomMax,a=a.bbox,a=(new ol.Extent(a[1],a[0],a[3],a[2])).transform(f),g,h;for(g=b;g<=d;++g)h=g.toString(),b=e.getTileRangeForExtentAndZ(a,g),h in c?c[h].push(b):c[h]=[b]});return new ol.Attribution(b,c)});this.setAttributions(a);this.ready_=!0;this.dispatchLoadEvent()};ol.source.BingMaps.prototype.isReady=function(){return this.ready_};ol.DebugTile_=function(a,b){ol.Tile.call(this,a);this.state=ol.TileState.LOADED;this.tileCoord_=a;this.tileSize_=b.getTileSize(a.z);this.canvasByContext_={}};goog.inherits(ol.DebugTile_,ol.Tile); +ol.TileUrlFunction.withTileCoordTransform(function(a){if(a.ze||b<=e)return null;b=goog.math.modulo(a.x,b);return new ol.TileCoord(a.z,b,e)},ol.TileUrlFunction.createFromTileUrlFunctions(goog.array.map(b.imageUrlSubdomains,function(a){var c=b.imageUrl.replace("{subdomain}",a).replace("{culture}",this.culture_);return function(a){return goog.isNull(a)?void 0:c.replace("{quadkey}",a.quadKey())}})));var f=ol.projection.getTransformFromProjections(ol.projection.get("EPSG:4326"), +this.getProjection()),a=goog.array.map(b.imageryProviders,function(a){var b=a.attribution,c={};goog.array.forEach(a.coverageAreas,function(a){var b=a.zoomMin,d=a.zoomMax,a=a.bbox,a=(new ol.Extent(a[1],a[0],a[3],a[2])).transform(f),g,h;for(g=b;g<=d;++g)h=g.toString(),b=e.getTileRangeForExtentAndZ(a,g),h in c?c[h].push(b):c[h]=[b]});return new ol.Attribution(b,c)});this.setAttributions(a);this.ready_=!0;this.dispatchLoadEvent()};ol.source.BingMaps.prototype.isReady=function(){return this.ready_};ol.DebugTile_=function(a,b){ol.Tile.call(this,a,ol.TileState.LOADED);this.tileCoord_=a;this.tileSize_=b.getTileSize(a.z);this.canvasByContext_={}};goog.inherits(ol.DebugTile_,ol.Tile); ol.DebugTile_.prototype.getImage=function(a){a=goog.isDef(a)?goog.getUid(a):-1;if(a in this.canvasByContext_)return this.canvasByContext_[a];var b=this.tileSize_,c=goog.dom.createElement(goog.dom.TagName.CANVAS);c.width=b.width;c.height=b.height;var d=c.getContext("2d");d.strokeStyle="black";d.strokeRect(0.5,0.5,b.width+0.5,b.height+0.5);d.fillStyle="black";d.textAlign="center";d.textBaseline="middle";d.font="24px sans-serif";d.fillText(this.tileCoord_.toString(),b.width/2,b.height/2);return this.canvasByContext_[a]= c};ol.source.DebugTileSource=function(a){ol.source.TileSource.call(this,{extent:a.extent,opaque:!1,projection:a.projection,tileGrid:a.tileGrid});this.tileCache_=new ol.TileCache};goog.inherits(ol.source.DebugTileSource,ol.source.TileSource);ol.source.DebugTileSource.prototype.canExpireCache=function(){return this.tileCache_.canExpireCache()};ol.source.DebugTileSource.prototype.expireCache=function(a){this.tileCache_.expireCache(a)}; -ol.source.DebugTileSource.prototype.getTile=function(a){var b=a.toString();if(this.tileCache_.containsKey(b))return this.tileCache_.get(b);a=new ol.DebugTile_(a,this.tileGrid);this.tileCache_.set(b,a);return a};ol.source.XYZ=function(a){var b=a.projection||ol.projection.getFromCode("EPSG:3857"),c=ol.TileUrlFunction.nullTileUrlFunction;goog.isDef(a.tileUrlFunction)?c=a.tileUrlFunction:goog.isDef(a.urls)?c=ol.TileUrlFunction.createFromTemplates(a.urls):goog.isDef(a.url)&&(c=ol.TileUrlFunction.createFromTemplate(a.url));var d=new ol.tilegrid.XYZ({maxZoom:a.maxZoom}),e=a.extent,c=goog.isDefAndNotNull(e)?ol.TileUrlFunction.withTileCoordTransform(function(b){if(a.maxZoomh||c<=h)return null;c=goog.math.modulo(b.x,c);return!d.getTileCoordExtent(new ol.TileCoord(b.z,c,b.y)).intersects(e)?null:new ol.TileCoord(b.z,c,h)},c):ol.TileUrlFunction.withTileCoordTransform(function(b){if(a.maxZoomd||c<=d)return null;c=goog.math.modulo(b.x,c);return new ol.TileCoord(b.z,c,d)},c);ol.source.ImageTileSource.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:b,tileGrid:d,tileUrlFunction:c})}; +ol.source.DebugTileSource.prototype.getTile=function(a){var b=a.toString();if(this.tileCache_.containsKey(b))return this.tileCache_.get(b);a=new ol.DebugTile_(a,this.tileGrid);this.tileCache_.set(b,a);return a};ol.source.XYZ=function(a){var b=a.projection||ol.projection.get("EPSG:3857"),c=ol.TileUrlFunction.nullTileUrlFunction;goog.isDef(a.tileUrlFunction)?c=a.tileUrlFunction:goog.isDef(a.urls)?c=ol.TileUrlFunction.createFromTemplates(a.urls):goog.isDef(a.url)&&(c=ol.TileUrlFunction.createFromTemplate(a.url));var d=new ol.tilegrid.XYZ({maxZoom:a.maxZoom}),e=a.extent,c=goog.isDefAndNotNull(e)?ol.TileUrlFunction.withTileCoordTransform(function(b){if(a.maxZoomh|| +c<=h)return null;c=goog.math.modulo(b.x,c);return!d.getTileCoordExtent(new ol.TileCoord(b.z,c,b.y)).intersects(e)?null:new ol.TileCoord(b.z,c,h)},c):ol.TileUrlFunction.withTileCoordTransform(function(b){if(a.maxZoomd||c<=d)return null;c=goog.math.modulo(b.x,c);return new ol.TileCoord(b.z,c,d)},c);ol.source.ImageTileSource.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:b,tileGrid:d,tileUrlFunction:c})}; goog.inherits(ol.source.XYZ,ol.source.ImageTileSource);ol.source.MapQuestOSM=function(){var a=[new ol.Attribution('Tiles Courtesy of MapQuest '),new ol.Attribution('Data © OpenStreetMap contributors, CC BY-SA')];ol.source.XYZ.call(this,{attributions:a,opaque:!0,maxZoom:28,url:"http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg"})}; goog.inherits(ol.source.MapQuestOSM,ol.source.XYZ);ol.source.MapQuestOpenAerial=function(){var a=[new ol.Attribution('Tiles Courtesy of MapQuest '),new ol.Attribution("Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency")];ol.source.XYZ.call(this,{attributions:a,maxZoom:18,opaque:!0,url:"http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg"})}; goog.inherits(ol.source.MapQuestOpenAerial,ol.source.XYZ);ol.source.OpenStreetMap=function(){var a=new ol.Attribution('© OpenStreetMap contributors, CC BY-SA');ol.source.XYZ.call(this,{attributions:[a],opaque:!0,maxZoom:18,url:"http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png"})};goog.inherits(ol.source.OpenStreetMap,ol.source.XYZ);ol.source.SingleImageWMS=function(a){var b=goog.isDef(a.url)?ol.ImageUrlFunction.createWMSParams(a.url,a.params):ol.ImageUrlFunction.nullImageUrlFunction;ol.source.ImageSource.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,resolutions:a.resolutions,imageUrlFunction:b});this.image_=null;this.ratio_=1.5};goog.inherits(ol.source.SingleImageWMS,ol.source.ImageSource); ol.source.SingleImageWMS.prototype.getImage=function(a,b,c){var b=this.findNearestResolution(b),d=this.image_;if(!goog.isNull(d)&&d.getResolution()==b&&d.getExtent().containsExtent(a))return d;a=new ol.Extent(a.minX,a.minY,a.maxX,a.maxY);a.scaleFromCenter(this.ratio_);var d=a.getWidth()/b,e=a.getHeight()/b,d=new ol.Size(d,e);return this.image_=this.createImage(a,b,d,c)};ol.source.StamenLayerConfig={terrain:{extension:"jpg",opaque:!0},"terrain-background":{extension:"jpg",opaque:!0},"terrain-labels":{extension:"png",opaque:!1},"terrain-lines":{extension:"png",opaque:!1},"toner-background":{extension:"png",opaque:!0},toner:{extension:"png",opaque:!0},"toner-hybrid":{extension:"png",opaque:!1},"toner-labels":{extension:"png",opaque:!1},"toner-lines":{extension:"png",opaque:!1},"toner-lite":{extension:"png",opaque:!0},watercolor:{extension:"jpg",opaque:!0}}; -ol.source.StamenProviderConfig={terrain:{minZoom:4,maxZoom:18},toner:{minZoom:0,maxZoom:20},watercolor:{minZoom:3,maxZoom:16}}; -ol.source.Stamen=function(a){var b=new ol.Attribution('Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'),c=a.layer.indexOf("-"),c=-1==c?a.layer:a.layer.slice(0,c);goog.asserts.assert(c in ol.source.StamenProviderConfig);c=ol.source.StamenProviderConfig[c];goog.asserts.assert(a.layer in -ol.source.StamenLayerConfig);var d=ol.source.StamenLayerConfig[a.layer],a=goog.isDef(a.url)?a.url:"http://{a-d}.tile.stamen.com/"+a.layer+"/{z}/{x}/{y}."+d.extension;ol.source.XYZ.call(this,{attributions:[b],maxZoom:c.maxZoom,opaque:d.opaque,url:a})};goog.inherits(ol.source.Stamen,ol.source.XYZ);ol.source.StaticImage=function(a){var b=ol.source.StaticImage.createImageFunction(a.url),c=a.imageExtent,d=a.imageSize,e=c.getHeight()/d.height,f=goog.isDef(a.projection)?a.projection:null;ol.source.ImageSource.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,imageUrlFunction:b,resolutions:[e]});this.image_=this.createImage(c,e,d,f)};goog.inherits(ol.source.StaticImage,ol.source.ImageSource); -ol.source.StaticImage.prototype.getImage=function(a){return a.intersects(this.image_.getExtent())?this.image_:null};ol.source.StaticImage.createImageFunction=function(a){return function(){return a}};ol.tilejson={};ol.tilejson.grids_=[];var grid=function(a){ol.tilejson.grids_.push(a)};goog.exportSymbol("grid",grid);ol.source.TileJSON=function(a){ol.source.ImageTileSource.call(this,{projection:ol.projection.getFromCode("EPSG:3857")});this.ready_=!1;this.deferred_=goog.net.jsloader.load(a.uri,{cleanupWhenDone:!0});this.deferred_.addCallback(this.handleTileJSONResponse,this)};goog.inherits(ol.source.TileJSON,ol.source.ImageTileSource); -ol.source.TileJSON.prototype.handleTileJSONResponse=function(){var a=ol.tilejson.grids_.pop(),b=ol.projection.getFromCode("EPSG:4326"),c,d;goog.isDef(a.bounds)?(c=a.bounds,c=new ol.Extent(c[0],c[1],c[2],c[3]),d=c.transform(ol.projection.getTransform(b,this.getProjection())),this.setExtent(d)):d=c=null;goog.isDef(a.scheme);goog.isDef(a.scheme)&&goog.asserts.assert("xyz"==a.scheme);var e=a.minzoom||0;goog.asserts.assert(0===e);var f=a.maxzoom||22,g=new ol.tilegrid.XYZ({maxZoom:f});this.tileGrid=g;this.tileUrlFunction= -ol.TileUrlFunction.withTileCoordTransform(function(a){if(a.zc||b<=c)return null;b=goog.math.modulo(a.x,b);return!goog.isNull(d)&&!g.getTileCoordExtent(new ol.TileCoord(a.z,b,a.y)).intersects(d)?null:new ol.TileCoord(a.z,b,c)},ol.TileUrlFunction.createFromTemplates(a.tiles));if(goog.isDef(a.attribution)){b=goog.isNull(d)?b.getExtent():d;c={};var h,i;for(h=e;h<=f;++h)i=h.toString(),c[i]=[g.getTileRangeForExtentAndZ(b,h)];this.setAttributions([new ol.Attribution(a.attribution, +ol.source.StamenProviderConfig={terrain:{minZoom:4,maxZoom:18},toner:{minZoom:0,maxZoom:20},watercolor:{minZoom:3,maxZoom:16}};ol.source.STAMEN_ATTRIBUTIONS=[new ol.Attribution('Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.')]; +ol.source.Stamen=function(a){var b=a.layer.indexOf("-"),b=-1==b?a.layer:a.layer.slice(0,b);goog.asserts.assert(b in ol.source.StamenProviderConfig);b=ol.source.StamenProviderConfig[b];goog.asserts.assert(a.layer in ol.source.StamenLayerConfig);var c=ol.source.StamenLayerConfig[a.layer],a=goog.isDef(a.url)?a.url:"http://{a-d}.tile.stamen.com/"+a.layer+"/{z}/{x}/{y}."+c.extension;ol.source.XYZ.call(this,{attributions:ol.source.STAMEN_ATTRIBUTIONS,maxZoom:b.maxZoom,opaque:c.opaque,url:a})}; +goog.inherits(ol.source.Stamen,ol.source.XYZ);ol.source.StaticImage=function(a){var b=ol.source.StaticImage.createImageFunction(a.url),c=a.imageExtent,d=a.imageSize,e=c.getHeight()/d.height,f=ol.projection.get(a.projection);ol.source.ImageSource.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,imageUrlFunction:b,resolutions:[e]});this.image_=this.createImage(c,e,d,f)};goog.inherits(ol.source.StaticImage,ol.source.ImageSource); +ol.source.StaticImage.prototype.getImage=function(a){return a.intersects(this.image_.getExtent())?this.image_:null};ol.source.StaticImage.createImageFunction=function(a){return function(){return a}};ol.tilejson={};ol.tilejson.grids_=[];var grid=function(a){ol.tilejson.grids_.push(a)};goog.exportSymbol("grid",grid);ol.source.TileJSON=function(a){ol.source.ImageTileSource.call(this,{projection:ol.projection.get("EPSG:3857")});this.ready_=!1;this.deferred_=goog.net.jsloader.load(a.uri,{cleanupWhenDone:!0});this.deferred_.addCallback(this.handleTileJSONResponse,this)};goog.inherits(ol.source.TileJSON,ol.source.ImageTileSource); +ol.source.TileJSON.prototype.handleTileJSONResponse=function(){var a=ol.tilejson.grids_.pop(),b=ol.projection.get("EPSG:4326"),c,d;goog.isDef(a.bounds)?(c=a.bounds,c=new ol.Extent(c[0],c[1],c[2],c[3]),d=c.transform(ol.projection.getTransformFromProjections(b,this.getProjection())),this.setExtent(d)):d=c=null;goog.isDef(a.scheme);goog.isDef(a.scheme)&&goog.asserts.assert("xyz"==a.scheme);var e=a.minzoom||0;goog.asserts.assert(0===e);var f=a.maxzoom||22,g=new ol.tilegrid.XYZ({maxZoom:f});this.tileGrid= +g;this.tileUrlFunction=ol.TileUrlFunction.withTileCoordTransform(function(a){if(a.zc||b<=c)return null;b=goog.math.modulo(a.x,b);return!goog.isNull(d)&&!g.getTileCoordExtent(new ol.TileCoord(a.z,b,a.y)).intersects(d)?null:new ol.TileCoord(a.z,b,c)},ol.TileUrlFunction.createFromTemplates(a.tiles));if(goog.isDef(a.attribution)){b=goog.isNull(d)?b.getExtent():d;c={};var h,i;for(h=e;h<=f;++h)i=h.toString(),c[i]=[g.getTileRangeForExtentAndZ(b,h)];this.setAttributions([new ol.Attribution(a.attribution, c)])}this.ready_=!0;this.dispatchLoadEvent()};ol.source.TileJSON.prototype.isReady=function(){return this.ready_};ol.source.TiledWMS=function(a){goog.isDef(a.tileGrid);var b;a.urls?(b=goog.array.map(a.urls,function(b){return ol.TileUrlFunction.createWMSParams(b,a.params)}),b=ol.TileUrlFunction.createFromTileUrlFunctions(b)):b=a.url?ol.TileUrlFunction.createWMSParams(a.url,a.params):ol.TileUrlFunction.nullTileUrlFunction;var c=goog.isDef(a.params.TRANSPARENT)?a.params.TRANSPARENT:!0,d=a.extent;ol.source.ImageTileSource.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:d,tileGrid:a.tileGrid, -opaque:!c,projection:a.projection,tileUrlFunction:ol.TileUrlFunction.withTileCoordTransform(function(a,b,c){if(b.getResolutions().length<=a.z)return null;var h=a.x,i=b.getTileCoordExtent(a),c=c.getExtent();d=goog.isDef(d)?d:c;d.minX===c.minX&&d.maxX===c.maxX&&(i=Math.ceil((d.maxX-d.minX)/(i.maxX-i.minX)),h=goog.math.modulo(h,i),i=b.getTileCoordExtent(new ol.TileCoord(a.z,h,a.y)));return!i.intersects(d)?null:new ol.TileCoord(a.z,h,a.y)},b)})};goog.inherits(ol.source.TiledWMS,ol.source.ImageTileSource);ol.sphere.WGS84=new ol.Sphere(6378137);ol.AnchoredElementOptionsType={};ol.MapOptionsType={};ol.View2DOptionsType={};ol.animation.BounceOptionsType={};ol.animation.PanOptionsType={};ol.animation.RotateOptionsType={};ol.animation.ZoomOptionsType={};ol.control.AttributionOptionsType={};ol.control.DefaultsOptionsType={};ol.control.MousePositionOptionsType={};ol.control.ScaleLineOptionsType={};ol.control.ZoomOptionsType={};ol.interaction.DefaultOptionsType={};ol.layer.LayerOptionsType={};ol.source.BingMapsOptionsType={}; -ol.source.DebugTileSourceOptionsType={};ol.source.SingleImageWMSOptionsType={};ol.source.StamenOptionsType={};ol.source.StaticImageOptionsType={};ol.source.TiledWMSOptionsType={};ol.tilegrid.TileGridOptionsType={};ol.tilegrid.XYZOptionsType={}; +opaque:!c,projection:a.projection,tileUrlFunction:ol.TileUrlFunction.withTileCoordTransform(function(a,b,c){if(b.getResolutions().length<=a.z)return null;var h=a.x,i=b.getTileCoordExtent(a),l=c.getExtent();d=goog.isDef(d)?d:l;!goog.isNull(d)&&(c.isGlobal()&&d.minX===l.minX&&d.maxX===l.maxX)&&(c=Math.ceil((d.maxX-d.minX)/(i.maxX-i.minX)),h=goog.math.modulo(h,c),i=b.getTileCoordExtent(new ol.TileCoord(a.z,h,a.y)));return!i.intersects(d)?null:new ol.TileCoord(a.z,h,a.y)},b)})}; +goog.inherits(ol.source.TiledWMS,ol.source.ImageTileSource);ol.sphere.WGS84=new ol.Sphere(6378137);ol.AnchoredElementOptionsType={};ol.MapOptionsType={};ol.Proj4jsProjectionOptionsType={};ol.ProjectionOptionsType={};ol.View2DOptionsType={};ol.animation.BounceOptionsType={};ol.animation.PanOptionsType={};ol.animation.RotateOptionsType={};ol.animation.ZoomOptionsType={};ol.control.AttributionOptionsType={};ol.control.DefaultsOptionsType={};ol.control.MousePositionOptionsType={};ol.control.ScaleLineOptionsType={};ol.control.ZoomOptionsType={};ol.interaction.DefaultOptionsType={}; +ol.interaction.KeyboardPanOptionsType={};ol.interaction.KeyboardZoomOptionsType={};ol.layer.LayerOptionsType={};ol.source.BingMapsOptionsType={};ol.source.DebugTileSourceOptionsType={};ol.source.SingleImageWMSOptionsType={};ol.source.StamenOptionsType={};ol.source.StaticImageOptionsType={};ol.source.TileJSONOptionsType={};ol.source.TiledWMSOptionsType={};ol.tilegrid.TileGridOptionsType={};ol.tilegrid.XYZOptionsType={}; diff --git a/master/build/ol-whitespace.js b/master/build/ol-whitespace.js index a40ef846bd..5a21236497 100644 --- a/master/build/ol-whitespace.js +++ b/master/build/ol-whitespace.js @@ -1470,18 +1470,18 @@ goog.addDependency("/third_party/closure/goog/silverlight/clipboardbutton.js", [ goog.addDependency("/third_party/closure/goog/silverlight/silverlight.js", ["goog.silverlight"], []); goog.addDependency("/third_party/closure/goog/silverlight/supporteduseragent.js", ["goog.silverlight.supportedUserAgent"], []); goog.addDependency("build/src/internal/src/requireall.js", [], ["ol", "ol.AnchoredElement", "ol.AnchoredElementPositioning", "ol.AnchoredElementProperty", "ol.Attribution", "ol.BrowserFeature", "ol.Collection", "ol.CollectionEvent", "ol.CollectionEventType", "ol.Color", "ol.Constraints", "ol.Coordinate", "ol.CoordinateFormatType", "ol.Ellipsoid", "ol.Extent", "ol.FrameState", "ol.Geolocation", "ol.GeolocationProperty", "ol.IView", "ol.IView2D", "ol.IView3D", "ol.Image", "ol.ImageState", "ol.ImageTile", -"ol.ImageUrlFunction", "ol.ImageUrlFunctionType", "ol.Kinetic", "ol.Map", "ol.MapBrowserEvent", "ol.MapBrowserEvent.EventType", "ol.MapBrowserEventHandler", "ol.MapEvent", "ol.MapEventType", "ol.MapProperty", "ol.Object", "ol.ObjectEventType", "ol.Pixel", "ol.PixelBounds", "ol.PostRenderFunction", "ol.PreRenderFunction", "ol.Projection", "ol.ProjectionUnits", "ol.Rectangle", "ol.RendererHint", "ol.RendererHints", "ol.ResolutionConstraint", "ol.ResolutionConstraintType", "ol.RotationConstraint", "ol.RotationConstraintType", -"ol.Size", "ol.Sphere", "ol.Tile", "ol.TileCache", "ol.TileCoord", "ol.TilePriorityFunction", "ol.TileQueue", "ol.TileRange", "ol.TileState", "ol.TileUrlFunction", "ol.TileUrlFunctionType", "ol.TransformFunction", "ol.View", "ol.View2D", "ol.View2DProperty", "ol.View2DState", "ol.ViewHint", "ol.animation", "ol.array", "ol.canvas", "ol.control.Attribution", "ol.control.Control", "ol.control.ControlOptions", "ol.control.DragBox", "ol.control.MousePosition", "ol.control.ScaleLine", "ol.control.ScaleLineUnits", -"ol.control.Zoom", "ol.control.defaults", "ol.dom", "ol.dom.BrowserFeature", "ol.easing", "ol.ellipsoid.WGS84", "ol.interaction.ConditionType", "ol.interaction.DblClickZoom", "ol.interaction.Drag", "ol.interaction.DragPan", "ol.interaction.DragRotate", "ol.interaction.DragRotateAndZoom", "ol.interaction.DragZoom", "ol.interaction.Interaction", "ol.interaction.Keyboard", "ol.interaction.KeyboardPan", "ol.interaction.KeyboardZoom", "ol.interaction.MouseWheelZoom", "ol.interaction.Touch", "ol.interaction.TouchPan", -"ol.interaction.TouchRotate", "ol.interaction.TouchZoom", "ol.interaction.condition", "ol.interaction.defaults", "ol.layer.ImageLayer", "ol.layer.Layer", "ol.layer.LayerProperty", "ol.layer.LayerState", "ol.layer.TileLayer", "ol.math", "ol.parser.XML", "ol.parser.ogc.ExceptionReport", "ol.parser.ogc.OWSCommon_v1", "ol.parser.ogc.OWSCommon_v1_1_0", "ol.parser.ogc.Versioned", "ol.parser.ogc.WMSCapabilities", "ol.parser.ogc.WMSCapabilities_v1", "ol.parser.ogc.WMSCapabilities_v1_1", "ol.parser.ogc.WMSCapabilities_v1_1_0", -"ol.parser.ogc.WMSCapabilities_v1_1_1", "ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC", "ol.parser.ogc.WMSCapabilities_v1_3_0", "ol.parser.ogc.WMTSCapabilities", "ol.parser.ogc.WMTSCapabilities_v1_0_0", "ol.projection", "ol.projection.EPSG3857", "ol.projection.EPSG4326", "ol.projection.addCommonProjections", "ol.renderer.Layer", "ol.renderer.Map", "ol.renderer.canvas.ImageLayer", "ol.renderer.canvas.Layer", "ol.renderer.canvas.Map", "ol.renderer.canvas.SUPPORTED", "ol.renderer.canvas.TileLayer", "ol.renderer.dom.ImageLayer", -"ol.renderer.dom.Layer", "ol.renderer.dom.Map", "ol.renderer.dom.SUPPORTED", "ol.renderer.dom.TileLayer", "ol.renderer.webgl.FragmentShader", "ol.renderer.webgl.ImageLayer", "ol.renderer.webgl.Layer", "ol.renderer.webgl.Map", "ol.renderer.webgl.SUPPORTED", "ol.renderer.webgl.TileLayer", "ol.renderer.webgl.VertexShader", "ol.renderer.webgl.map.shader", "ol.renderer.webgl.tilelayerrenderer", "ol.renderer.webgl.tilelayerrenderer.shader.Fragment", "ol.renderer.webgl.tilelayerrenderer.shader.Vertex", -"ol.source.BingMaps", "ol.source.DebugTileSource", "ol.source.ImageSource", "ol.source.ImageTileSource", "ol.source.ImageTileSourceOptions", "ol.source.MapQuestOSM", "ol.source.MapQuestOpenAerial", "ol.source.OpenStreetMap", "ol.source.SingleImageWMS", "ol.source.Source", "ol.source.Stamen", "ol.source.StaticImage", "ol.source.TileJSON", "ol.source.TileSource", "ol.source.TileSourceOptions", "ol.source.TiledWMS", "ol.source.XYZ", "ol.source.XYZOptions", "ol.source.wms", "ol.sphere.NORMAL", "ol.sphere.WGS84", -"ol.structs.LRUCache", "ol.tilegrid.TileGrid", "ol.tilegrid.XYZ", "ol.tilejson", "ol.vec.Mat4", "ol.webgl", "ol.webgl.WebGLContextEventType"]); -goog.addDependency("build/src/internal/src/types.js", ["ol.AnchoredElementOptionsType", "ol.MapOptionsType", "ol.View2DOptionsType", "ol.animation.BounceOptionsType", "ol.animation.PanOptionsType", "ol.animation.RotateOptionsType", "ol.animation.ZoomOptionsType", "ol.control.AttributionOptionsType", "ol.control.DefaultsOptionsType", "ol.control.MousePositionOptionsType", "ol.control.ScaleLineOptionsType", "ol.control.ZoomOptionsType", "ol.interaction.DefaultOptionsType", "ol.layer.LayerOptionsType", -"ol.source.BingMapsOptionsType", "ol.source.DebugTileSourceOptionsType", "ol.source.SingleImageWMSOptionsType", "ol.source.StamenOptionsType", "ol.source.StaticImageOptionsType", "ol.source.TiledWMSOptionsType", "ol.tilegrid.TileGridOptionsType", "ol.tilegrid.XYZOptionsType"], []); +"ol.ImageUrlFunction", "ol.ImageUrlFunctionType", "ol.Kinetic", "ol.Map", "ol.MapBrowserEvent", "ol.MapBrowserEvent.EventType", "ol.MapBrowserEventHandler", "ol.MapEvent", "ol.MapEventType", "ol.MapProperty", "ol.Object", "ol.ObjectEventType", "ol.Pixel", "ol.PixelBounds", "ol.PostRenderFunction", "ol.PreRenderFunction", "ol.Projection", "ol.ProjectionLike", "ol.ProjectionUnits", "ol.Rectangle", "ol.RendererHint", "ol.RendererHints", "ol.ResolutionConstraint", "ol.ResolutionConstraintType", "ol.RotationConstraint", +"ol.RotationConstraintType", "ol.Size", "ol.Sphere", "ol.Tile", "ol.TileCache", "ol.TileCoord", "ol.TilePriorityFunction", "ol.TileQueue", "ol.TileRange", "ol.TileState", "ol.TileUrlFunction", "ol.TileUrlFunctionType", "ol.TransformFunction", "ol.View", "ol.View2D", "ol.View2DProperty", "ol.View2DState", "ol.ViewHint", "ol.animation", "ol.array", "ol.canvas", "ol.control.Attribution", "ol.control.Control", "ol.control.ControlOptions", "ol.control.DragBox", "ol.control.MousePosition", "ol.control.ScaleLine", +"ol.control.ScaleLineUnits", "ol.control.Zoom", "ol.control.defaults", "ol.dom", "ol.dom.BrowserFeature", "ol.easing", "ol.ellipsoid.WGS84", "ol.interaction.ConditionType", "ol.interaction.DblClickZoom", "ol.interaction.Drag", "ol.interaction.DragPan", "ol.interaction.DragRotate", "ol.interaction.DragRotateAndZoom", "ol.interaction.DragZoom", "ol.interaction.Interaction", "ol.interaction.Keyboard", "ol.interaction.KeyboardPan", "ol.interaction.KeyboardZoom", "ol.interaction.MouseWheelZoom", "ol.interaction.Touch", +"ol.interaction.TouchPan", "ol.interaction.TouchRotate", "ol.interaction.TouchZoom", "ol.interaction.condition", "ol.interaction.defaults", "ol.layer.ImageLayer", "ol.layer.Layer", "ol.layer.LayerProperty", "ol.layer.LayerState", "ol.layer.TileLayer", "ol.math", "ol.parser.XML", "ol.parser.ogc.ExceptionReport", "ol.parser.ogc.OWSCommon_v1", "ol.parser.ogc.OWSCommon_v1_1_0", "ol.parser.ogc.Versioned", "ol.parser.ogc.WMSCapabilities", "ol.parser.ogc.WMSCapabilities_v1", "ol.parser.ogc.WMSCapabilities_v1_0_0", +"ol.parser.ogc.WMSCapabilities_v1_1", "ol.parser.ogc.WMSCapabilities_v1_1_0", "ol.parser.ogc.WMSCapabilities_v1_1_1", "ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC", "ol.parser.ogc.WMSCapabilities_v1_3_0", "ol.parser.ogc.WMTSCapabilities", "ol.parser.ogc.WMTSCapabilities_v1_0_0", "ol.projection", "ol.projection.EPSG3857", "ol.projection.EPSG4326", "ol.projection.addCommonProjections", "ol.renderer.Layer", "ol.renderer.Map", "ol.renderer.canvas.ImageLayer", "ol.renderer.canvas.Layer", "ol.renderer.canvas.Map", +"ol.renderer.canvas.SUPPORTED", "ol.renderer.canvas.TileLayer", "ol.renderer.dom.ImageLayer", "ol.renderer.dom.Layer", "ol.renderer.dom.Map", "ol.renderer.dom.SUPPORTED", "ol.renderer.dom.TileLayer", "ol.renderer.webgl.FragmentShader", "ol.renderer.webgl.ImageLayer", "ol.renderer.webgl.Layer", "ol.renderer.webgl.Map", "ol.renderer.webgl.SUPPORTED", "ol.renderer.webgl.TileLayer", "ol.renderer.webgl.VertexShader", "ol.renderer.webgl.map.shader", "ol.renderer.webgl.tilelayerrenderer", "ol.renderer.webgl.tilelayerrenderer.shader.Fragment", +"ol.renderer.webgl.tilelayerrenderer.shader.Vertex", "ol.source.BingMaps", "ol.source.DebugTileSource", "ol.source.ImageSource", "ol.source.ImageTileSource", "ol.source.ImageTileSourceOptions", "ol.source.MapQuestOSM", "ol.source.MapQuestOpenAerial", "ol.source.OpenStreetMap", "ol.source.SingleImageWMS", "ol.source.Source", "ol.source.Stamen", "ol.source.StaticImage", "ol.source.TileJSON", "ol.source.TileSource", "ol.source.TileSourceOptions", "ol.source.TiledWMS", "ol.source.XYZ", "ol.source.XYZOptions", +"ol.source.wms", "ol.sphere.NORMAL", "ol.sphere.WGS84", "ol.structs.LRUCache", "ol.tilegrid.TileGrid", "ol.tilegrid.XYZ", "ol.tilejson", "ol.vec.Mat4", "ol.webgl", "ol.webgl.WebGLContextEventType"]); +goog.addDependency("build/src/internal/src/types.js", ["ol.AnchoredElementOptionsType", "ol.MapOptionsType", "ol.Proj4jsProjectionOptionsType", "ol.ProjectionOptionsType", "ol.View2DOptionsType", "ol.animation.BounceOptionsType", "ol.animation.PanOptionsType", "ol.animation.RotateOptionsType", "ol.animation.ZoomOptionsType", "ol.control.AttributionOptionsType", "ol.control.DefaultsOptionsType", "ol.control.MousePositionOptionsType", "ol.control.ScaleLineOptionsType", "ol.control.ZoomOptionsType", +"ol.interaction.DefaultOptionsType", "ol.interaction.KeyboardPanOptionsType", "ol.interaction.KeyboardZoomOptionsType", "ol.layer.LayerOptionsType", "ol.source.BingMapsOptionsType", "ol.source.DebugTileSourceOptionsType", "ol.source.SingleImageWMSOptionsType", "ol.source.StamenOptionsType", "ol.source.StaticImageOptionsType", "ol.source.TileJSONOptionsType", "ol.source.TiledWMSOptionsType", "ol.tilegrid.TileGridOptionsType", "ol.tilegrid.XYZOptionsType"], []); goog.addDependency("src/ol/anchoredelement.js", ["ol.AnchoredElement", "ol.AnchoredElementPositioning", "ol.AnchoredElementProperty"], ["goog.dom", "goog.events", "goog.style", "ol.Coordinate", "ol.Map", "ol.MapEventType", "ol.Object"]); -goog.addDependency("src/ol/animation.js", ["ol.animation"], ["goog.fx.easing", "ol.PreRenderFunction", "ol.ViewHint", "ol.easing"]); +goog.addDependency("src/ol/animation.js", ["ol.animation"], ["ol.PreRenderFunction", "ol.ViewHint", "ol.easing"]); goog.addDependency("src/ol/array.js", ["ol.array"], ["goog.array"]); goog.addDependency("src/ol/attribution.js", ["ol.Attribution"], ["ol.TileRange"]); goog.addDependency("src/ol/browserfeature.js", ["ol.BrowserFeature"], []); @@ -1491,14 +1491,14 @@ goog.addDependency("src/ol/color.js", ["ol.Color"], ["goog.color", "goog.math"]) goog.addDependency("src/ol/constraints.js", ["ol.Constraints"], ["ol.ResolutionConstraintType", "ol.RotationConstraintType"]); goog.addDependency("src/ol/control/attributioncontrol.js", ["ol.control.Attribution"], ["goog.array", "goog.dom", "goog.dom.TagName", "goog.events", "goog.object", "goog.style", "ol.Attribution", "ol.FrameState", "ol.MapEvent", "ol.MapEventType", "ol.TileRange", "ol.control.Control", "ol.source.Source"]); goog.addDependency("src/ol/control/control.js", ["ol.control.Control", "ol.control.ControlOptions"], ["goog.Disposable"]); -goog.addDependency("src/ol/control/defaults.js", ["ol.control.defaults"], ["goog.array", "ol.control.Attribution", "ol.control.ScaleLine", "ol.control.Zoom"]); +goog.addDependency("src/ol/control/defaults.js", ["ol.control.defaults"], ["goog.array", "ol.control.Attribution", "ol.control.Zoom"]); goog.addDependency("src/ol/control/dragboxcontrol.js", ["ol.control.DragBox"], ["goog.asserts", "goog.dom", "goog.dom.TagName", "goog.events", "goog.style", "ol.Coordinate", "ol.MapBrowserEvent", "ol.MapBrowserEvent.EventType", "ol.Pixel", "ol.Size", "ol.control.Control"]); goog.addDependency("src/ol/control/mousepositioncontrol.js", ["ol.control.MousePosition"], ["goog.array", "goog.dom", "goog.events", "goog.events.EventType", "goog.style", "ol.Coordinate", "ol.CoordinateFormatType", "ol.MapEvent", "ol.MapEventType", "ol.Pixel", "ol.Projection", "ol.TransformFunction", "ol.control.Control", "ol.projection"]); goog.addDependency("src/ol/control/scalelinecontrol.js", ["ol.control.ScaleLine", "ol.control.ScaleLineUnits"], ["goog.dom", "goog.style", "ol.FrameState", "ol.MapEvent", "ol.MapEventType", "ol.ProjectionUnits", "ol.TransformFunction", "ol.control.Control", "ol.projection", "ol.sphere.NORMAL"]); goog.addDependency("src/ol/control/zoomcontrol.js", ["ol.control.Zoom"], ["goog.dom", "goog.dom.TagName", "goog.events", "goog.events.EventType", "ol.control.Control"]); goog.addDependency("src/ol/coordinate.js", ["ol.Coordinate", "ol.CoordinateFormatType"], ["goog.math", "goog.math.Vec2"]); goog.addDependency("src/ol/dom/dom.js", ["ol.dom", "ol.dom.BrowserFeature"], ["goog.vec.Mat4"]); -goog.addDependency("src/ol/easing.js", ["ol.easing"], []); +goog.addDependency("src/ol/easing.js", ["ol.easing"], ["goog.fx.easing"]); goog.addDependency("src/ol/ellipsoid.js", ["ol.Ellipsoid"], ["goog.math", "ol.Coordinate"]); goog.addDependency("src/ol/ellipsoid/wgs84.js", ["ol.ellipsoid.WGS84"], ["ol.Ellipsoid"]); goog.addDependency("src/ol/extent.js", ["ol.Extent"], ["ol.Coordinate", "ol.Rectangle", "ol.TransformFunction"]); @@ -1543,8 +1543,9 @@ goog.addDependency("src/ol/parser/ogc/exceptionreport.js", ["ol.parser.ogc.Excep goog.addDependency("src/ol/parser/ogc/owscommon_v1.js", ["ol.parser.ogc.OWSCommon_v1"], ["ol.Extent", "ol.parser.XML"]); goog.addDependency("src/ol/parser/ogc/owscommon_v1_1_0.js", ["ol.parser.ogc.OWSCommon_v1_1_0"], ["goog.object", "ol.parser.ogc.OWSCommon_v1"]); goog.addDependency("src/ol/parser/ogc/versioned.js", ["ol.parser.ogc.Versioned"], ["goog.dom.xml", "ol.parser.ogc.ExceptionReport"]); -goog.addDependency("src/ol/parser/ogc/wmscapabilities.js", ["ol.parser.ogc.WMSCapabilities"], ["ol.parser.ogc.Versioned", "ol.parser.ogc.WMSCapabilities_v1_1_0", "ol.parser.ogc.WMSCapabilities_v1_1_1", "ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC", "ol.parser.ogc.WMSCapabilities_v1_3_0"]); +goog.addDependency("src/ol/parser/ogc/wmscapabilities.js", ["ol.parser.ogc.WMSCapabilities"], ["ol.parser.ogc.Versioned", "ol.parser.ogc.WMSCapabilities_v1_0_0", "ol.parser.ogc.WMSCapabilities_v1_1_0", "ol.parser.ogc.WMSCapabilities_v1_1_1", "ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC", "ol.parser.ogc.WMSCapabilities_v1_3_0"]); goog.addDependency("src/ol/parser/ogc/wmscapabilities_v1.js", ["ol.parser.ogc.WMSCapabilities_v1"], ["goog.dom.xml", "goog.object", "ol.parser.XML"]); +goog.addDependency("src/ol/parser/ogc/wmscapabilities_v1_0_0.js", ["ol.parser.ogc.WMSCapabilities_v1_0_0"], ["goog.string", "ol.parser.ogc.WMSCapabilities_v1_1_0"]); goog.addDependency("src/ol/parser/ogc/wmscapabilities_v1_1.js", ["ol.parser.ogc.WMSCapabilities_v1_1"], ["ol.parser.ogc.WMSCapabilities_v1"]); goog.addDependency("src/ol/parser/ogc/wmscapabilities_v1_1_0.js", ["ol.parser.ogc.WMSCapabilities_v1_1_0"], ["ol.parser.ogc.WMSCapabilities_v1_1"]); goog.addDependency("src/ol/parser/ogc/wmscapabilities_v1_1_1.js", ["ol.parser.ogc.WMSCapabilities_v1_1_1"], ["ol.parser.ogc.WMSCapabilities_v1_1"]); @@ -1555,7 +1556,7 @@ goog.addDependency("src/ol/parser/ogc/wmtscapabilities_v1_0_0.js", ["ol.parser.o goog.addDependency("src/ol/parser/xml.js", ["ol.parser.XML"], []); goog.addDependency("src/ol/pixel.js", ["ol.Pixel"], ["goog.math.Coordinate"]); goog.addDependency("src/ol/pixelbounds.js", ["ol.PixelBounds"], ["ol.Rectangle"]); -goog.addDependency("src/ol/projection.js", ["ol.Projection", "ol.ProjectionUnits", "ol.projection"], ["goog.array", "goog.asserts", "goog.object", "ol.Coordinate", "ol.Extent", "ol.TransformFunction", "ol.sphere.NORMAL"]); +goog.addDependency("src/ol/projection.js", ["ol.Projection", "ol.ProjectionLike", "ol.ProjectionUnits", "ol.projection"], ["goog.array", "goog.asserts", "goog.object", "ol.Coordinate", "ol.Extent", "ol.TransformFunction", "ol.sphere.NORMAL"]); goog.addDependency("src/ol/projection/common.js", ["ol.projection.addCommonProjections"], ["ol.projection", "ol.projection.EPSG3857", "ol.projection.EPSG4326"]); goog.addDependency("src/ol/projection/epsg3857.js", ["ol.projection.EPSG3857"], ["goog.array", "ol.Extent", "ol.Projection", "ol.ProjectionUnits", "ol.math", "ol.projection"]); goog.addDependency("src/ol/projection/epsg4326.js", ["ol.projection.EPSG4326"], ["ol.Extent", "ol.Projection", "ol.ProjectionUnits", "ol.projection"]); @@ -1586,16 +1587,16 @@ goog.addDependency("src/ol/size.js", ["ol.Size"], ["goog.math.Size"]); goog.addDependency("src/ol/source/bingmapssource.js", ["ol.source.BingMaps"], ["goog.Uri", "goog.array", "goog.net.Jsonp", "ol.Attribution", "ol.Extent", "ol.Size", "ol.TileCoord", "ol.TileRange", "ol.TileUrlFunction", "ol.projection", "ol.source.ImageTileSource", "ol.tilegrid.XYZ"]); goog.addDependency("src/ol/source/debugtilesource.js", ["ol.source.DebugTileSource"], ["ol.Size", "ol.Tile", "ol.TileCache", "ol.TileCoord", "ol.TileState", "ol.source.TileSource", "ol.tilegrid.TileGrid"]); goog.addDependency("src/ol/source/imagesource.js", ["ol.source.ImageSource"], ["goog.array", "ol.Attribution", "ol.Extent", "ol.Image", "ol.ImageUrlFunction", "ol.ImageUrlFunctionType", "ol.Projection", "ol.Size", "ol.array", "ol.source.Source"]); -goog.addDependency("src/ol/source/imagetilesource.js", ["ol.source.ImageTileSource", "ol.source.ImageTileSourceOptions"], ["ol.Attribution", "ol.Extent", "ol.ImageTile", "ol.Projection", "ol.Tile", "ol.TileCache", "ol.TileUrlFunction", "ol.TileUrlFunctionType", "ol.source.TileSource", "ol.tilegrid.TileGrid"]); +goog.addDependency("src/ol/source/imagetilesource.js", ["ol.source.ImageTileSource", "ol.source.ImageTileSourceOptions"], ["ol.Attribution", "ol.Extent", "ol.ImageTile", "ol.Projection", "ol.Tile", "ol.TileCache", "ol.TileState", "ol.TileUrlFunction", "ol.TileUrlFunctionType", "ol.source.TileSource", "ol.tilegrid.TileGrid"]); goog.addDependency("src/ol/source/mapquestsource.js", ["ol.source.MapQuestOSM", "ol.source.MapQuestOpenAerial"], ["ol.Attribution", "ol.source.XYZ"]); goog.addDependency("src/ol/source/openstreetmapsource.js", ["ol.source.OpenStreetMap"], ["ol.Attribution", "ol.source.XYZ"]); goog.addDependency("src/ol/source/singleimagewmssource.js", ["ol.source.SingleImageWMS"], ["ol.Extent", "ol.Image", "ol.ImageUrlFunction", "ol.Size", "ol.source.ImageSource"]); -goog.addDependency("src/ol/source/source.js", ["ol.source.Source"], ["goog.events.EventTarget", "goog.events.EventType", "goog.functions", "ol.Attribution", "ol.Extent", "ol.Projection"]); +goog.addDependency("src/ol/source/source.js", ["ol.source.Source"], ["goog.events.EventTarget", "goog.events.EventType", "goog.functions", "ol.Attribution", "ol.Extent", "ol.projection"]); goog.addDependency("src/ol/source/stamensource.js", ["ol.source.Stamen"], ["ol.Attribution", "ol.source.XYZ"]); -goog.addDependency("src/ol/source/staticimagesource.js", ["ol.source.StaticImage"], ["ol.Image", "ol.ImageUrlFunctionType", "ol.source.ImageSource"]); +goog.addDependency("src/ol/source/staticimagesource.js", ["ol.source.StaticImage"], ["ol.Image", "ol.ImageUrlFunctionType", "ol.projection", "ol.source.ImageSource"]); goog.addDependency("src/ol/source/tiledwmssource.js", ["ol.source.TiledWMS"], ["goog.array", "ol.Extent", "ol.TileCoord", "ol.TileUrlFunction", "ol.source.ImageTileSource"]); goog.addDependency("src/ol/source/tilejsonsource.js", ["ol.source.TileJSON", "ol.tilejson"], ["goog.asserts", "goog.net.jsloader", "ol.Attribution", "ol.Extent", "ol.TileCoord", "ol.TileRange", "ol.TileUrlFunction", "ol.projection", "ol.source.ImageTileSource", "ol.tilegrid.XYZ"]); -goog.addDependency("src/ol/source/tilesource.js", ["ol.source.TileSource", "ol.source.TileSourceOptions"], ["goog.functions", "ol.Attribution", "ol.Extent", "ol.Projection", "ol.Tile", "ol.TileCoord", "ol.TileRange", "ol.source.Source", "ol.tilegrid.TileGrid"]); +goog.addDependency("src/ol/source/tilesource.js", ["ol.source.TileSource", "ol.source.TileSourceOptions"], ["goog.functions", "ol.Attribution", "ol.Extent", "ol.Tile", "ol.TileCoord", "ol.TileRange", "ol.source.Source", "ol.tilegrid.TileGrid"]); goog.addDependency("src/ol/source/wms.js", ["ol.source.wms"], []); goog.addDependency("src/ol/source/xyzsource.js", ["ol.source.XYZ", "ol.source.XYZOptions"], ["goog.math", "ol.Attribution", "ol.Extent", "ol.Projection", "ol.TileCoord", "ol.TileUrlFunction", "ol.TileUrlFunctionType", "ol.projection", "ol.source.ImageTileSource", "ol.tilegrid.XYZ"]); goog.addDependency("src/ol/sphere.js", ["ol.Sphere"], ["goog.math", "ol.Coordinate"]); @@ -1613,7 +1614,7 @@ goog.addDependency("src/ol/tileurlfunction.js", ["ol.TileUrlFunction", "ol.TileU goog.addDependency("src/ol/transformfunction.js", ["ol.TransformFunction"], []); goog.addDependency("src/ol/vec/mat4.js", ["ol.vec.Mat4"], ["goog.vec.Mat4"]); goog.addDependency("src/ol/view.js", ["ol.View", "ol.ViewHint"], ["goog.array", "ol.IView", "ol.Object"]); -goog.addDependency("src/ol/view2d.js", ["ol.View2D", "ol.View2DProperty"], ["goog.fx.easing", "ol.Constraints", "ol.Coordinate", "ol.Extent", "ol.IView2D", "ol.IView3D", "ol.Projection", "ol.ResolutionConstraint", "ol.RotationConstraint", "ol.Size", "ol.View", "ol.animation", "ol.projection"]); +goog.addDependency("src/ol/view2d.js", ["ol.View2D", "ol.View2DProperty"], ["ol.Constraints", "ol.Coordinate", "ol.Extent", "ol.IView2D", "ol.IView3D", "ol.Projection", "ol.ResolutionConstraint", "ol.RotationConstraint", "ol.Size", "ol.View", "ol.animation", "ol.easing", "ol.projection"]); goog.addDependency("src/ol/webgl/webgl.js", ["ol.webgl", "ol.webgl.WebGLContextEventType"], []); goog.provide("goog.debug.Error"); goog.debug.Error = function(opt_msg) { @@ -11147,12 +11148,11 @@ goog.require("goog.events"); goog.require("goog.events.EventTarget"); goog.require("goog.events.EventType"); goog.require("ol.TileCoord"); -ol.TileState = {IDLE:0, LOADING:1, LOADED:2, ERROR:3}; -ol.Tile = function(tileCoord) { +ol.TileState = {IDLE:0, LOADING:1, LOADED:2, ERROR:3, EMPTY:4}; +ol.Tile = function(tileCoord, state) { goog.base(this); - this.inQueue = 0; this.tileCoord = tileCoord; - this.state = ol.TileState.IDLE + this.state = state }; goog.inherits(ol.Tile, goog.events.EventTarget); ol.Tile.prototype.dispatchChangeEvent = function() { @@ -11194,8 +11194,6 @@ ol.TileQueue.prototype.dequeue_ = function() { } var tileKey = tile.getKey(); delete this.queuedTileKeys_[tileKey]; - tile.inQueue--; - goog.asserts.assert(tile.inQueue >= 0); return tile }; ol.TileQueue.prototype.enqueue = function(tile, tileSourceKey, tileCenter) { @@ -11208,9 +11206,7 @@ ol.TileQueue.prototype.enqueue = function(tile, tileSourceKey, tileCenter) { if(priority != ol.TileQueue.DROP) { this.heap_.push([priority, tile, tileSourceKey, tileCenter]); this.queuedTileKeys_[tileKey] = true; - this.siftDown_(0, this.heap_.length - 1); - tile.inQueue++; - goog.asserts.assert(tile.inQueue > 0) + this.siftDown_(0, this.heap_.length - 1) } } }; @@ -11239,6 +11235,7 @@ ol.TileQueue.prototype.loadMoreTiles = function() { tile.load(); ++this.tilesLoading_ } + return goog.isDef(tile) }; ol.TileQueue.prototype.siftUp_ = function(index) { var heap = this.heap_; @@ -11280,12 +11277,7 @@ ol.TileQueue.prototype.reprioritize = function() { priority = this.tilePriorityFunction_(tile, tileSourceKey, tileCenter); if(priority == ol.TileQueue.DROP) { tileKey = tile.getKey(); - delete this.queuedTileKeys_[tileKey]; - tile.inQueue--; - goog.asserts.assert(tile.inQueue >= 0); - if(tile.inQueue === 0) { - goog.events.removeAll(tile) - } + delete this.queuedTileKeys_[tileKey] }else { node[0] = priority; heap[n++] = node @@ -11373,6 +11365,7 @@ goog.provide("ol.sphere.NORMAL"); goog.require("ol.Sphere"); ol.sphere.NORMAL = new ol.Sphere(6370997); goog.provide("ol.Projection"); +goog.provide("ol.ProjectionLike"); goog.provide("ol.ProjectionUnits"); goog.provide("ol.projection"); goog.require("goog.array"); @@ -11384,16 +11377,18 @@ goog.require("ol.TransformFunction"); goog.require("ol.sphere.NORMAL"); ol.ENABLE_PROJ4JS = true; ol.HAVE_PROJ4JS = ol.ENABLE_PROJ4JS && typeof Proj4js == "object"; +ol.ProjectionLike; ol.ProjectionUnits = {DEGREES:"degrees", FEET:"ft", METERS:"m"}; ol.METERS_PER_UNIT = {}; ol.METERS_PER_UNIT[ol.ProjectionUnits.DEGREES] = 2 * Math.PI * ol.sphere.NORMAL.radius / 360; ol.METERS_PER_UNIT[ol.ProjectionUnits.FEET] = 0.3048; ol.METERS_PER_UNIT[ol.ProjectionUnits.METERS] = 1; -ol.Projection = function(code, units, extent, opt_axisOrientation) { - this.code_ = code; - this.units_ = units; - this.extent_ = extent; - this.axisOrientation_ = goog.isDef(opt_axisOrientation) ? opt_axisOrientation : "enu"; +ol.Projection = function(options) { + this.code_ = options.code; + this.units_ = options.units; + this.extent_ = options.extent; + this.axisOrientation_ = goog.isDef(options.axisOrientation) ? options.axisOrientation : "enu"; + this.global_ = goog.isDef(options.global) ? options.global : false; this.defaultTileGrid_ = null }; ol.Projection.prototype.getCode = function() { @@ -11412,15 +11407,20 @@ ol.Projection.prototype.getMetersPerUnit = function() { ol.Projection.prototype.getAxisOrientation = function() { return this.axisOrientation_ }; +ol.Projection.prototype.isGlobal = function() { + return this.global_ +}; ol.Projection.prototype.getDefaultTileGrid = function() { return this.defaultTileGrid_ }; ol.Projection.prototype.setDefaultTileGrid = function(tileGrid) { this.defaultTileGrid_ = tileGrid }; -ol.Proj4jsProjection_ = function(code, proj4jsProj) { +ol.Proj4jsProjection_ = function(proj4jsProj, options) { var units = proj4jsProj.units; - goog.base(this, code, units, null, proj4jsProj.axis); + var config = {units:units, axisOrientation:proj4jsProj.axis}; + goog.object.extend(config, options); + goog.base(this, config); this.proj4jsProj_ = proj4jsProj; this.toEPSG4326_ = null }; @@ -11430,7 +11430,7 @@ ol.Proj4jsProjection_.prototype.getPointResolution = function(resolution, point) return resolution }else { if(goog.isNull(this.toEPSG4326_)) { - this.toEPSG4326_ = ol.projection.getTransform(this, ol.projection.getProj4jsProjectionFromCode_("EPSG:4326")) + this.toEPSG4326_ = ol.projection.getTransformFromProjections(this, ol.projection.getProj4jsProjectionFromCode_({code:"EPSG:4326", extent:null})) } var vertices = [point.x - resolution / 2, point.y, point.x + resolution / 2, point.y, point.x, point.y - resolution / 2, point.x, point.y + resolution / 2]; vertices = this.toEPSG4326_(vertices, vertices, 2); @@ -11494,10 +11494,10 @@ ol.projection.clearAllProjections = function() { }; ol.projection.createProjection = function(projection, defaultCode) { if(!goog.isDefAndNotNull(projection)) { - return ol.projection.getFromCode(defaultCode) + return ol.projection.get(defaultCode) }else { if(goog.isString(projection)) { - return ol.projection.getFromCode(projection) + return ol.projection.get(projection) }else { goog.asserts.assert(projection instanceof ol.Projection); return projection @@ -11528,18 +11528,29 @@ ol.projection.removeTransform = function(source, destination) { } return transform }; -ol.projection.getFromCode = function(code) { - var projection = ol.projection.projections_[code]; - if(ol.HAVE_PROJ4JS && !goog.isDef(projection)) { - projection = ol.projection.getProj4jsProjectionFromCode_(code) - } - if(!goog.isDef(projection)) { - goog.asserts.assert(goog.isDef(projection)); - projection = null +ol.projection.get = function(projectionLike) { + var projection; + if(projectionLike instanceof ol.Projection) { + projection = projectionLike + }else { + if(goog.isString(projectionLike)) { + var code = projectionLike; + projection = ol.projection.projections_[code]; + if(ol.HAVE_PROJ4JS && !goog.isDef(projection)) { + projection = ol.projection.getProj4jsProjectionFromCode_({code:code, extent:null}) + } + if(!goog.isDef(projection)) { + goog.asserts.assert(goog.isDef(projection)); + projection = null + } + }else { + projection = null + } } return projection }; -ol.projection.getProj4jsProjectionFromCode_ = function(code) { +ol.projection.getProj4jsProjectionFromCode_ = function(options) { + var code = options.code; var proj4jsProjections = ol.projection.proj4jsProjections_; var proj4jsProjection = proj4jsProjections[code]; if(!goog.isDef(proj4jsProjection)) { @@ -11547,7 +11558,9 @@ ol.projection.getProj4jsProjectionFromCode_ = function(code) { var srsCode = proj4jsProj.srsCode; proj4jsProjection = proj4jsProjections[srsCode]; if(!goog.isDef(proj4jsProjection)) { - proj4jsProjection = new ol.Proj4jsProjection_(srsCode, proj4jsProj); + var config = goog.object.clone(options); + config.code = srsCode; + proj4jsProjection = new ol.Proj4jsProjection_(proj4jsProj, config); proj4jsProjections[srsCode] = proj4jsProjection } proj4jsProjections[code] = proj4jsProjection @@ -11561,32 +11574,37 @@ ol.projection.equivalent = function(projection1, projection2) { if(projection1.getUnits() != projection2.getUnits()) { return false }else { - var transformFn = ol.projection.getTransform(projection1, projection2); + var transformFn = ol.projection.getTransformFromProjections(projection1, projection2); return transformFn === ol.projection.cloneTransform } } }; ol.projection.getTransform = function(source, destination) { + var sourceProjection = ol.projection.get(source); + var destinationProjection = ol.projection.get(destination); + return ol.projection.getTransformFromProjections(sourceProjection, destinationProjection) +}; +ol.projection.getTransformFromProjections = function(sourceProjection, destinationProjection) { var transforms = ol.projection.transforms_; - var sourceCode = source.getCode(); - var destinationCode = destination.getCode(); + var sourceCode = sourceProjection.getCode(); + var destinationCode = destinationProjection.getCode(); var transform; if(goog.object.containsKey(transforms, sourceCode) && goog.object.containsKey(transforms[sourceCode], destinationCode)) { transform = transforms[sourceCode][destinationCode] } if(ol.HAVE_PROJ4JS && !goog.isDef(transform)) { var proj4jsSource; - if(source instanceof ol.Proj4jsProjection_) { - proj4jsSource = source + if(sourceProjection instanceof ol.Proj4jsProjection_) { + proj4jsSource = sourceProjection }else { - proj4jsSource = ol.projection.getProj4jsProjectionFromCode_(source.getCode()) + proj4jsSource = ol.projection.getProj4jsProjectionFromCode_({code:sourceCode, extent:null}) } var sourceProj4jsProj = proj4jsSource.getProj4jsProj(); var proj4jsDestination; - if(destination instanceof ol.Proj4jsProjection_) { - proj4jsDestination = destination + if(destinationProjection instanceof ol.Proj4jsProjection_) { + proj4jsDestination = destinationProjection }else { - proj4jsDestination = ol.projection.getProj4jsProjectionFromCode_(destination.getCode()) + proj4jsDestination = ol.projection.getProj4jsProjectionFromCode_({code:destinationCode, extent:null}) } var destinationProj4jsProj = proj4jsDestination.getProj4jsProj(); transform = function(input, opt_output, opt_dimension) { @@ -11608,7 +11626,7 @@ ol.projection.getTransform = function(source, destination) { } return output }; - ol.projection.addTransform(source, destination, transform) + ol.projection.addTransform(sourceProjection, destinationProjection, transform) } if(!goog.isDef(transform)) { goog.asserts.assert(goog.isDef(transform)); @@ -11616,11 +11634,6 @@ ol.projection.getTransform = function(source, destination) { } return transform }; -ol.projection.getTransformFromCodes = function(sourceCode, destinationCode) { - var source = ol.projection.getFromCode(sourceCode); - var destination = ol.projection.getFromCode(destinationCode); - return ol.projection.getTransform(source, destination) -}; ol.projection.identityTransform = function(input, opt_output, opt_dimension) { if(goog.isDef(opt_output) && input !== opt_output) { goog.asserts.assert(false, "This should not be used internally."); @@ -11649,12 +11662,16 @@ ol.projection.transform = function(point, source, destination) { vertex = transformFn(vertex, vertex, 2); return new ol.Coordinate(vertex[0], vertex[1]) }; -ol.projection.transformWithCodes = function(point, sourceCode, destinationCode) { - var transformFn = ol.projection.getTransformFromCodes(sourceCode, destinationCode); +ol.projection.transformWithProjections = function(point, sourceProjection, destinationProjection) { + var transformFn = ol.projection.getTransformFromProjections(sourceProjection, destinationProjection); var vertex = [point.x, point.y]; vertex = transformFn(vertex, vertex, 2); return new ol.Coordinate(vertex[0], vertex[1]) }; +ol.projection.configureProj4jsProjection = function(options) { + goog.asserts.assert(!goog.object.containsKey(ol.projection.proj4jsProjections_, options.code)); + return ol.projection.getProj4jsProjectionFromCode_(options) +}; goog.provide("ol.IView2D"); goog.provide("ol.View2DState"); goog.require("ol.Coordinate"); @@ -11678,12 +11695,12 @@ goog.require("goog.events.EventType"); goog.require("goog.functions"); goog.require("ol.Attribution"); goog.require("ol.Extent"); -goog.require("ol.Projection"); +goog.require("ol.projection"); ol.source.SourceOptions; ol.source.Source = function(sourceOptions) { goog.base(this); - this.projection_ = goog.isDef(sourceOptions.projection) ? sourceOptions.projection : null; - this.extent_ = goog.isDef(sourceOptions.extent) ? sourceOptions.extent : goog.isDef(sourceOptions.projection) ? sourceOptions.projection.getExtent() : null; + this.projection_ = ol.projection.get(sourceOptions.projection); + this.extent_ = goog.isDef(sourceOptions.extent) ? sourceOptions.extent : goog.isDef(sourceOptions.projection) ? this.projection_.getExtent() : null; this.attributions_ = goog.isDef(sourceOptions.attributions) ? sourceOptions.attributions : null }; goog.inherits(ol.source.Source, goog.events.EventTarget); @@ -12032,16 +12049,6 @@ ol.View.prototype.setHint = function(hint, delta) { this.hints_[hint] += delta; goog.asserts.assert(this.hints_[hint] >= 0) }; -goog.provide("goog.fx.easing"); -goog.fx.easing.easeIn = function(t) { - return t * t * t -}; -goog.fx.easing.easeOut = function(t) { - return 1 - Math.pow(1 - t, 3) -}; -goog.fx.easing.inAndOut = function(t) { - return 3 * t * t - 2 * t * t * t -}; goog.provide("ol.array"); goog.require("goog.array"); ol.array.binaryFindNearest = function(arr, target) { @@ -12177,20 +12184,18 @@ ol.Constraints = function(resolutionConstraint, rotationConstraint) { this.resolution = resolutionConstraint; this.rotation = rotationConstraint }; +goog.provide("goog.fx.easing"); +goog.fx.easing.easeIn = function(t) { + return t * t * t +}; +goog.fx.easing.easeOut = function(t) { + return 1 - Math.pow(1 - t, 3) +}; +goog.fx.easing.inAndOut = function(t) { + return 3 * t * t - 2 * t * t * t +}; goog.provide("ol.easing"); -ol.easing.linear = function(t) { - return t -}; -ol.easing.upAndDown = function(t) { - if(t < 0.5) { - return goog.fx.easing.inAndOut(2 * t) - }else { - return 1 - goog.fx.easing.inAndOut(2 * (t - 0.5)) - } -}; -ol.easing.elastic = function(t) { - return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * 2 * Math.PI / 0.3) + 1 -}; +goog.require("goog.fx.easing"); ol.easing.bounce = function(t) { var s = 7.5625, p = 2.75, l; if(t < 1 / p) { @@ -12211,8 +12216,23 @@ ol.easing.bounce = function(t) { } return l }; +ol.easing.easeIn = goog.fx.easing.easeIn; +ol.easing.easeOut = goog.fx.easing.easeOut; +ol.easing.elastic = function(t) { + return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * 2 * Math.PI / 0.3) + 1 +}; +ol.easing.inAndOut = goog.fx.easing.inAndOut; +ol.easing.linear = function(t) { + return t +}; +ol.easing.upAndDown = function(t) { + if(t < 0.5) { + return ol.easing.inAndOut(2 * t) + }else { + return 1 - ol.easing.inAndOut(2 * (t - 0.5)) + } +}; goog.provide("ol.animation"); -goog.require("goog.fx.easing"); goog.require("ol.PreRenderFunction"); goog.require("ol.ViewHint"); goog.require("ol.easing"); @@ -12246,7 +12266,7 @@ ol.animation.pan = function(options) { var sourceX = source.x; var sourceY = source.y; var duration = goog.isDef(options.duration) ? options.duration : 1E3; - var easing = goog.isDef(options.easing) ? options.easing : goog.fx.easing.inAndOut; + var easing = goog.isDef(options.easing) ? options.easing : ol.easing.inAndOut; return function(map, frameState) { if(frameState.time < start) { frameState.animate = true; @@ -12272,7 +12292,7 @@ ol.animation.rotate = function(options) { var sourceRotation = options.rotation; var start = goog.isDef(options.start) ? options.start : goog.now(); var duration = goog.isDef(options.duration) ? options.duration : 1E3; - var easing = goog.isDef(options.easing) ? options.easing : goog.fx.easing.inAndOut; + var easing = goog.isDef(options.easing) ? options.easing : ol.easing.inAndOut; return function(map, frameState) { if(frameState.time < start) { frameState.animate = true; @@ -12296,7 +12316,7 @@ ol.animation.zoom = function(options) { var sourceResolution = options.resolution; var start = goog.isDef(options.start) ? options.start : goog.now(); var duration = goog.isDef(options.duration) ? options.duration : 1E3; - var easing = goog.isDef(options.easing) ? options.easing : ol.easing.linear; + var easing = goog.isDef(options.easing) ? options.easing : ol.easing.inAndOut; return function(map, frameState) { if(frameState.time < start) { frameState.animate = true; @@ -12318,7 +12338,6 @@ ol.animation.zoom = function(options) { }; goog.provide("ol.View2D"); goog.provide("ol.View2DProperty"); -goog.require("goog.fx.easing"); goog.require("ol.Constraints"); goog.require("ol.Coordinate"); goog.require("ol.Extent"); @@ -12330,6 +12349,7 @@ goog.require("ol.RotationConstraint"); goog.require("ol.Size"); goog.require("ol.View"); goog.require("ol.animation"); +goog.require("ol.easing"); goog.require("ol.projection"); ol.View2DProperty = {CENTER:"center", PROJECTION:"projection", RESOLUTION:"resolution", ROTATION:"rotation"}; ol.View2D = function(opt_view2DOptions) { @@ -12421,6 +12441,16 @@ ol.View2D.prototype.setRotation = function(rotation) { this.set(ol.View2DProperty.ROTATION, rotation) }; goog.exportProperty(ol.View2D.prototype, "setRotation", ol.View2D.prototype.setRotation); +ol.View2D.prototype.pan = function(map, delta, opt_duration) { + var currentCenter = this.getCenter(); + if(goog.isDef(currentCenter)) { + if(goog.isDef(opt_duration)) { + map.requestRenderFrame(); + map.addPreRenderFunction(ol.animation.pan({source:currentCenter, duration:opt_duration, easing:ol.easing.linear})) + } + this.setCenter(new ol.Coordinate(currentCenter.x + delta.x, currentCenter.y + delta.y)) + } +}; ol.View2D.prototype.rotate = function(map, rotation, opt_anchor, opt_duration) { rotation = this.constraints_.rotation(rotation, 0); this.rotateWithoutConstraints(map, rotation, opt_anchor, opt_duration) @@ -12431,9 +12461,9 @@ ol.View2D.prototype.rotateWithoutConstraints = function(map, rotation, opt_ancho var currentCenter = this.getCenter(); if(goog.isDef(currentRotation) && goog.isDef(currentCenter) && goog.isDef(opt_duration)) { map.requestRenderFrame(); - map.addPreRenderFunction(ol.animation.rotate({rotation:currentRotation, duration:opt_duration, easing:goog.fx.easing.easeOut})); + map.addPreRenderFunction(ol.animation.rotate({rotation:currentRotation, duration:opt_duration, easing:ol.easing.easeOut})); if(goog.isDef(opt_anchor)) { - map.addPreRenderFunction(ol.animation.pan({source:currentCenter, duration:opt_duration, easing:goog.fx.easing.easeOut})) + map.addPreRenderFunction(ol.animation.pan({source:currentCenter, duration:opt_duration, easing:ol.easing.easeOut})) } } if(goog.isDefAndNotNull(opt_anchor)) { @@ -12467,9 +12497,9 @@ ol.View2D.prototype.zoomWithoutConstraints = function(map, resolution, opt_ancho var currentCenter = this.getCenter(); if(goog.isDef(currentResolution) && goog.isDef(currentCenter) && goog.isDef(opt_duration)) { map.requestRenderFrame(); - map.addPreRenderFunction(ol.animation.zoom({resolution:currentResolution, duration:opt_duration, easing:goog.fx.easing.easeOut})); + map.addPreRenderFunction(ol.animation.zoom({resolution:currentResolution, duration:opt_duration, easing:ol.easing.easeOut})); if(goog.isDef(opt_anchor)) { - map.addPreRenderFunction(ol.animation.pan({source:currentCenter, duration:opt_duration, easing:goog.fx.easing.easeOut})) + map.addPreRenderFunction(ol.animation.pan({source:currentCenter, duration:opt_duration, easing:ol.easing.easeOut})) } } if(goog.isDefAndNotNull(opt_anchor)) { @@ -12662,176 +12692,6 @@ ol.control.Attribution.prototype.updateElement_ = function(frameState) { this.renderedVisible_ = renderVisible } }; -goog.provide("ol.control.ScaleLine"); -goog.provide("ol.control.ScaleLineUnits"); -goog.require("goog.dom"); -goog.require("goog.style"); -goog.require("ol.FrameState"); -goog.require("ol.MapEvent"); -goog.require("ol.MapEventType"); -goog.require("ol.ProjectionUnits"); -goog.require("ol.TransformFunction"); -goog.require("ol.control.Control"); -goog.require("ol.projection"); -goog.require("ol.sphere.NORMAL"); -ol.control.ScaleLineUnits = {DEGREES:"degrees", IMPERIAL:"imperial", NAUTICAL:"nautical", METRIC:"metric", US:"us"}; -ol.control.ScaleLine = function(opt_options) { - var options = opt_options || {}; - this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV, {"class":"ol-scale-line-inner"}); - this.element_ = goog.dom.createDom(goog.dom.TagName.DIV, {"class":"ol-scale-line ol-unselectable"}, this.innerElement_); - this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64; - this.units_ = goog.isDef(options.units) ? options.units : ol.control.ScaleLineUnits.METRIC; - this.listenerKeys_ = null; - this.renderedVisible_ = false; - this.renderedWidth_; - this.renderedHTML_ = ""; - this.toEPSG4326_ = null; - goog.base(this, {element:this.element_, map:options.map, target:options.target}) -}; -goog.inherits(ol.control.ScaleLine, ol.control.Control); -ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5]; -ol.control.ScaleLine.prototype.handleMapPostrender = function(mapEvent) { - var frameState = mapEvent.frameState; - this.updateElement_(mapEvent.frameState) -}; -ol.control.ScaleLine.prototype.setMap = function(map) { - if(!goog.isNull(this.listenerKeys_)) { - goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); - this.listenerKeys_ = null - } - goog.base(this, "setMap", map); - if(!goog.isNull(map)) { - this.listenerKeys_ = [goog.events.listen(map, ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this)] - } -}; -ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { - if(goog.isNull(frameState)) { - if(this.renderedVisible_) { - goog.style.showElement(this.element_, false); - this.renderedVisible_ = false - } - return - } - var view2DState = frameState.view2DState; - var center = view2DState.center; - var projection = view2DState.projection; - var pointResolution = projection.getPointResolution(view2DState.resolution, center); - var projectionUnits = projection.getUnits(); - var cosLatitude; - if(projectionUnits == ol.ProjectionUnits.DEGREES && (this.units_ == ol.control.ScaleLineUnits.METRIC || this.units_ == ol.control.ScaleLineUnits.IMPERIAL)) { - this.toEPSG4326_ = null; - cosLatitude = Math.cos(goog.math.toRadians(center.y)); - pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180; - projectionUnits = ol.ProjectionUnits.METERS - }else { - if((projectionUnits == ol.ProjectionUnits.FEET || projectionUnits == ol.ProjectionUnits.METERS) && this.units_ == ol.control.ScaleLineUnits.DEGREES) { - if(goog.isNull(this.toEPSG4326_)) { - this.toEPSG4326_ = ol.projection.getTransform(projection, ol.projection.getFromCode("EPSG:4326")) - } - var vertex = [center.x, center.y]; - vertex = this.toEPSG4326_(vertex, vertex, 2); - cosLatitude = Math.cos(goog.math.toRadians(vertex[1])); - var radius = ol.sphere.NORMAL.radius; - if(projectionUnits == ol.ProjectionUnits.FEET) { - radius /= 0.3048 - } - pointResolution *= 180 / (Math.PI * cosLatitude * radius); - projectionUnits = ol.ProjectionUnits.DEGREES - }else { - this.toEPSG4326_ = null - } - } - goog.asserts.assert((this.units_ == ol.control.ScaleLineUnits.METRIC || this.units_ == ol.control.ScaleLineUnits.IMPERIAL) && projectionUnits == ol.ProjectionUnits.METERS || this.units_ == ol.control.ScaleLineUnits.DEGREES && projectionUnits == ol.ProjectionUnits.DEGREES); - var nominalCount = this.minWidth_ * pointResolution; - var suffix = ""; - if(this.units_ == ol.control.ScaleLineUnits.DEGREES) { - if(nominalCount < 1 / 60) { - suffix = "\u2033"; - pointResolution *= 3600 - }else { - if(nominalCount < 1) { - suffix = "\u2032"; - pointResolution *= 60 - }else { - suffix = "\u00b0" - } - } - }else { - if(this.units_ == ol.control.ScaleLineUnits.IMPERIAL) { - if(nominalCount < 0.9144) { - suffix = "in"; - pointResolution /= 0.0254 - }else { - if(nominalCount < 1609.344) { - suffix = "ft"; - pointResolution /= 0.3048 - }else { - suffix = "mi"; - pointResolution /= 1609.344 - } - } - }else { - if(this.units_ == ol.control.ScaleLineUnits.NAUTICAL) { - pointResolution /= 1852; - suffix = "nm" - }else { - if(this.units_ == ol.control.ScaleLineUnits.METRIC) { - if(nominalCount < 1) { - suffix = "mm"; - pointResolution *= 1E3 - }else { - if(nominalCount < 1E3) { - suffix = "m" - }else { - suffix = "km"; - pointResolution /= 1E3 - } - } - }else { - if(this.units_ == ol.control.ScaleLineUnits.US) { - if(nominalCount < 0.9144) { - suffix = "in"; - pointResolution *= 39.37 - }else { - if(nominalCount < 1609.344) { - suffix = "ft"; - pointResolution /= 0.30480061 - }else { - suffix = "mi"; - pointResolution /= 1609.3472 - } - } - }else { - goog.asserts.assert(false) - } - } - } - } - } - var i = 3 * Math.floor(Math.log(this.minWidth_ * pointResolution) / Math.log(10)); - var count, width; - while(true) { - count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] * Math.pow(10, Math.floor(i / 3)); - width = Math.round(count / pointResolution); - if(width >= this.minWidth_) { - break - } - ++i - } - var html = count + suffix; - if(this.renderedHTML_ != html) { - this.innerElement_.innerHTML = html; - this.renderedHTML_ = html - } - if(this.renderedWidth_ != width) { - this.innerElement_.style.width = width + "px"; - this.renderedWidth_ = width - } - if(!this.renderedVisible_) { - goog.style.showElement(this.element_, true); - this.renderedVisible_ = true - } -}; goog.provide("ol.control.Zoom"); goog.require("goog.dom"); goog.require("goog.dom.TagName"); @@ -12865,7 +12725,6 @@ ol.control.Zoom.prototype.handleOut_ = function(browserEvent) { goog.provide("ol.control.defaults"); goog.require("goog.array"); goog.require("ol.control.Attribution"); -goog.require("ol.control.ScaleLine"); goog.require("ol.control.Zoom"); ol.control.defaults = function(opt_options, opt_controls) { var options = goog.isDef(opt_options) ? opt_options : {}; @@ -12875,11 +12734,6 @@ ol.control.defaults = function(opt_options, opt_controls) { var attributionControlOptions = goog.isDef(options.attributionOptions) ? options.attributionOptions : undefined; controls.push(new ol.control.Attribution(attributionControlOptions)) } - var scaleLineControl = goog.isDef(options.scaleLine) ? options.scaleLine : false; - if(scaleLineControl) { - var scaleLineOptions = goog.isDef(options.scaleLineOptions) ? options.scaleLineOptions : undefined; - controls.push(new ol.control.ScaleLine(scaleLineOptions)) - } var zoomControl = goog.isDef(options.zoom) ? options.zoom : true; if(zoomControl) { var zoomControlOptions = goog.isDef(options.zoomControlOptions) ? options.zoomControlOptions : undefined; @@ -13271,9 +13125,11 @@ goog.require("goog.events.KeyHandler.EventType"); goog.require("ol.Coordinate"); goog.require("ol.View2D"); goog.require("ol.interaction.Interaction"); -ol.interaction.KeyboardPan = function(pixelDelta) { +ol.interaction.KEYBOARD_PAN_DURATION = 100; +ol.interaction.KeyboardPan = function(opt_options) { goog.base(this); - this.pixelDelta_ = pixelDelta + var options = goog.isDef(opt_options) ? opt_options : {}; + this.delta_ = goog.isDef(options.delta) ? options.delta : 128 }; goog.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction); ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { @@ -13285,25 +13141,25 @@ ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = function(mapBrowser var view = map.getView(); goog.asserts.assert(view instanceof ol.View2D); var resolution = view.getResolution(); - var delta; - var mapUnitsDelta = resolution * this.pixelDelta_; + var rotation = view.getRotation(); + var mapUnitsDelta = resolution * this.delta_; + var deltaX = 0, deltaY = 0; if(keyCode == goog.events.KeyCodes.DOWN) { - delta = new ol.Coordinate(0, -mapUnitsDelta) + deltaY = -mapUnitsDelta }else { if(keyCode == goog.events.KeyCodes.LEFT) { - delta = new ol.Coordinate(-mapUnitsDelta, 0) + deltaX = -mapUnitsDelta }else { if(keyCode == goog.events.KeyCodes.RIGHT) { - delta = new ol.Coordinate(mapUnitsDelta, 0) + deltaX = mapUnitsDelta }else { - goog.asserts.assert(keyCode == goog.events.KeyCodes.UP); - delta = new ol.Coordinate(0, mapUnitsDelta) + deltaY = mapUnitsDelta } } } - var oldCenter = view.getCenter(); - var newCenter = new ol.Coordinate(oldCenter.x + delta.x, oldCenter.y + delta.y); - view.setCenter(newCenter); + var delta = new ol.Coordinate(deltaX, deltaY); + delta.rotate(rotation); + view.pan(map, delta, ol.interaction.KEYBOARD_PAN_DURATION); keyEvent.preventDefault(); mapBrowserEvent.preventDefault() } @@ -13314,8 +13170,10 @@ goog.require("goog.events.KeyHandler.EventType"); goog.require("ol.View2D"); goog.require("ol.interaction.Interaction"); ol.interaction.KEYBOARD_ZOOM_DURATION = 100; -ol.interaction.KeyboardZoom = function() { - goog.base(this) +ol.interaction.KeyboardZoom = function(opt_options) { + goog.base(this); + var options = goog.isDef(opt_options) ? opt_options : {}; + this.delta_ = goog.isDef(options.delta) ? options.delta : 1 }; goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction); ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { @@ -13324,7 +13182,7 @@ ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent = function(mapBrowse var charCode = keyEvent.charCode; if(charCode == "+".charCodeAt(0) || charCode == "-".charCodeAt(0)) { var map = mapBrowserEvent.map; - var delta = charCode == "+".charCodeAt(0) ? 4 : -4; + var delta = charCode == "+".charCodeAt(0) ? this.delta_ : -this.delta_; map.requestRenderFrame(); var view = map.getView(); goog.asserts.assert(view instanceof ol.View2D); @@ -13673,9 +13531,8 @@ ol.interaction.defaults = function(opt_options, opt_interactions) { interactions.push(new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys, new ol.Kinetic(-0.005, 0.05, 100))) } var keyboard = goog.isDef(options.keyboard) ? options.keyboard : true; - var keyboardPanOffset = goog.isDef(options.keyboardPanOffset) ? options.keyboardPanOffset : 80; if(keyboard) { - interactions.push(new ol.interaction.KeyboardPan(keyboardPanOffset)); + interactions.push(new ol.interaction.KeyboardPan); interactions.push(new ol.interaction.KeyboardZoom) } var mouseWheelZoom = goog.isDef(options.mouseWheelZoom) ? options.mouseWheelZoom : true; @@ -13720,7 +13577,7 @@ goog.require("ol.ProjectionUnits"); goog.require("ol.math"); goog.require("ol.projection"); ol.projection.EPSG3857 = function(code) { - goog.base(this, code, ol.ProjectionUnits.METERS, ol.projection.EPSG3857.EXTENT) + goog.base(this, {code:code, units:ol.ProjectionUnits.METERS, extent:ol.projection.EPSG3857.EXTENT, global:true}) }; goog.inherits(ol.projection.EPSG3857, ol.Projection); ol.projection.EPSG3857.RADIUS = 6378137; @@ -13771,7 +13628,7 @@ goog.require("ol.Projection"); goog.require("ol.ProjectionUnits"); goog.require("ol.projection"); ol.projection.EPSG4326 = function(code, opt_axisOrientation) { - goog.base(this, code, ol.ProjectionUnits.DEGREES, ol.projection.EPSG4326.EXTENT, opt_axisOrientation) + goog.base(this, {code:code, units:ol.ProjectionUnits.DEGREES, extent:ol.projection.EPSG4326.EXTENT, axisOrientation:opt_axisOrientation, global:true}) }; goog.inherits(ol.projection.EPSG4326, ol.Projection); ol.projection.EPSG4326.EXTENT = new ol.Extent(-180, -90, 180, 90); @@ -14047,7 +13904,6 @@ goog.provide("ol.source.TileSourceOptions"); goog.require("goog.functions"); goog.require("ol.Attribution"); goog.require("ol.Extent"); -goog.require("ol.Projection"); goog.require("ol.Tile"); goog.require("ol.TileCoord"); goog.require("ol.TileRange"); @@ -14192,11 +14048,13 @@ ol.renderer.Layer.prototype.scheduleExpireCache = function(frameState, tileSourc } }; ol.renderer.Layer.prototype.updateAttributions = function(attributionsSet, attributions) { - var i; - var attribution; - for(i = 0;i < attributions.length;++i) { - attribution = attributions[i]; - attributionsSet[goog.getUid(attribution).toString()] = attribution + if(goog.isDefAndNotNull(attributions)) { + var i; + var attribution; + for(i = 0;i < attributions.length;++i) { + attribution = attributions[i]; + attributionsSet[goog.getUid(attribution).toString()] = attribution + } } }; ol.renderer.Layer.prototype.updateUsedTiles = function(usedTiles, tileSource, z, tileRange) { @@ -14337,7 +14195,7 @@ ol.renderer.Map.prototype.setLayerRenderer = function(layer, layerRenderer) { }; goog.provide("ol.source.wms"); ol.source.wms.getUrl = function(baseUrl, params, extent, size, projection) { - var baseParams = {"SERVICE":"WMS", "VERSION":"1.3.0", "REQUEST":"GetMap", "FORMAT":"image/png", "TRANSPARENT":true, "WIDTH":size.width, "HEIGHT":size.height}; + var baseParams = {"SERVICE":"WMS", "VERSION":"1.3.0", "REQUEST":"GetMap", "FORMAT":"image/png", "TRANSPARENT":true, "WIDTH":Math.round(size.width), "HEIGHT":Math.round(size.height)}; goog.object.extend(baseParams, params); var stylesParam = "STYLES"; baseParams[stylesParam] = params[stylesParam] || new String(""); @@ -14566,22 +14424,22 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = function(frameState, layerS for(y = tileRange.minY;y <= tileRange.maxY;++y) { tileCoord = new ol.TileCoord(z, x, y); tile = tileSource.getTile(tileCoord, tileGrid, projection); - if(goog.isNull(tile)) { - continue - } tileState = tile.getState(); if(tileState == ol.TileState.IDLE) { - this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter) }else { - if(tileState == ol.TileState.LOADED) { - tilesToDrawByZ[z][tileCoord.toString()] = tile; - continue + if(tileState == ol.TileState.LOADING) { + this.listenToTileChange(tile) }else { - if(tileState == ol.TileState.ERROR) { + if(tileState == ol.TileState.LOADED || tileState == ol.TileState.EMPTY) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; continue + }else { + if(tileState == ol.TileState.ERROR) { + continue + } } } } @@ -14608,10 +14466,13 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = function(frameState, layerS if(this.renderedTiles_[index] != tile) { x = tileSize.width * (tile.tileCoord.x - tileRange.minX); y = tileSize.height * (tileRange.maxY - tile.tileCoord.y); - if(!opaque) { + tileState = tile.getState(); + if(tileState == ol.TileState.EMPTY || !opaque) { context.clearRect(x, y, tileSize.width, tileSize.height) } - context.drawImage(tile.getImage(), x, y); + if(tileState == ol.TileState.LOADED) { + context.drawImage(tile.getImage(), x, y) + } this.renderedTiles_[index] = tile } } @@ -14624,10 +14485,13 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = function(frameState, layerS y = (origin.y - tileExtent.maxY) / tileResolution; width = scale * tileSize.width; height = scale * tileSize.height; - if(!opaque) { + tileState = tile.getState(); + if(tileState == ol.TileState.EMPTY || !opaque) { context.clearRect(x, y, width, height) } - context.drawImage(tile.getImage(), x, y, width, height); + if(tileState == ol.TileState.LOADED) { + context.drawImage(tile.getImage(), x, y, width, height) + } interimTileRange = tileGrid.getTileRangeForExtentAndZ(tileExtent, z); minX = Math.max(interimTileRange.minX, tileRange.minX); maxX = Math.min(interimTileRange.maxX, tileRange.maxX); @@ -14947,22 +14811,22 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = function(frameState, layerStat for(y = tileRange.minY;y <= tileRange.maxY;++y) { tileCoord = new ol.TileCoord(z, x, y); tile = tileSource.getTile(tileCoord, tileGrid, projection); - if(goog.isNull(tile)) { - continue - } tileState = tile.getState(); if(tileState == ol.TileState.IDLE) { - this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter) }else { - if(tileState == ol.TileState.LOADED) { - tilesToDrawByZ[z][tileCoord.toString()] = tile; - continue + if(tileState == ol.TileState.LOADING) { + this.listenToTileChange(tile) }else { - if(tileState == ol.TileState.ERROR) { + if(tileState == ol.TileState.LOADED) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; continue + }else { + if(tileState == ol.TileState.ERROR || tileState == ol.TileState.EMPTY) { + continue + } } } } @@ -16063,30 +15927,30 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(frameState, layerSt for(y = tileRange.minY;y <= tileRange.maxY;++y) { tileCoord = new ol.TileCoord(z, x, y); tile = tileSource.getTile(tileCoord, tileGrid, projection); - if(goog.isNull(tile)) { - continue - } tileState = tile.getState(); if(tileState == ol.TileState.IDLE) { - this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter) }else { - if(tileState == ol.TileState.LOADED) { - if(mapRenderer.isTileTextureLoaded(tile)) { - tilesToDrawByZ[z][tileCoord.toString()] = tile; - continue - }else { - tileCenter = tileGrid.getTileCoordCenter(tileCoord); - deltaX = tileCenter.x - center.x; - deltaY = tileCenter.y - center.y; - priority = Math.sqrt(deltaX * deltaX + deltaY * deltaY); - tilesToLoad.enqueue(priority, tile) - } + if(tileState == ol.TileState.LOADING) { + this.listenToTileChange(tile) }else { - if(tileState == ol.TileState.ERROR) { - continue + if(tileState == ol.TileState.LOADED) { + if(mapRenderer.isTileTextureLoaded(tile)) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; + continue + }else { + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + deltaX = tileCenter.x - center.x; + deltaY = tileCenter.y - center.y; + priority = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + tilesToLoad.enqueue(priority, tile) + } + }else { + if(tileState == ol.TileState.ERROR || tileState == ol.TileState.EMPTY) { + continue + } } } } @@ -16351,7 +16215,7 @@ ol.renderer.webgl.Map = function(container, map) { this.gl_ = ol.webgl.getContext(this.canvas_, {alpha:false, antialias:true, depth:false, preserveDrawingBuffer:false, stencil:false}); goog.asserts.assert(!goog.isNull(this.gl_)); goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST, this.handleWebGLContextLost, false, this); - goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED, this.handleWebGLContextResourced, false, this); + goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED, this.handleWebGLContextRestored, false, this); this.locations_ = null; this.arrayBuffer_ = null; this.shaderCache_ = {}; @@ -16501,9 +16365,9 @@ ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) { layerRenderer.handleWebGLContextLost() }) }; -ol.renderer.webgl.Map.prototype.handleWebGLContextResourced = function() { +ol.renderer.webgl.Map.prototype.handleWebGLContextRestored = function() { if(goog.DEBUG) { - this.logger.info("WebGLContextResourced") + this.logger.info("WebGLContextRestored") } this.initializeGL_(); this.getMap().render() @@ -16696,6 +16560,7 @@ ol.Map = function(mapOptions) { this.registerDisposable(this.renderer_); this.viewportSizeMonitor_ = new goog.dom.ViewportSizeMonitor; goog.events.listen(this.viewportSizeMonitor_, goog.events.EventType.RESIZE, this.handleBrowserWindowResize, false, this); + this.focus_ = null; this.preRenderFunctions_ = []; this.postRenderFunctions_ = []; this.handlePostRender_ = goog.bind(this.handlePostRender, this); @@ -16712,6 +16577,11 @@ ol.Map = function(mapOptions) { } }; goog.inherits(ol.Map, ol.Object); +ol.Map.prototype.addLayer = function(layer) { + var layers = this.getLayers(); + goog.asserts.assert(goog.isDef(layers)); + layers.push(layer) +}; ol.Map.prototype.addPreRenderFunction = function(preRenderFunction) { this.requestRenderFrame(); this.preRenderFunctions_.push(preRenderFunction) @@ -16790,15 +16660,20 @@ ol.Map.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter) { if(!frameState.wantedTiles[tileSourceKey][coordKey]) { return ol.TileQueue.DROP } - var center = frameState.view2DState.center; - var deltaX = tileCenter.x - center.x; - var deltaY = tileCenter.y - center.y; + var focus = goog.isNull(this.focus_) ? frameState.view2DState.center : this.focus_; + var deltaX = tileCenter.x - focus.x; + var deltaY = tileCenter.y - focus.y; return deltaX * deltaX + deltaY * deltaY }; ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) { var type = opt_type || browserEvent.type; var mapBrowserEvent = new ol.MapBrowserEvent(type, this, browserEvent); - this.handleMapBrowserEvent(mapBrowserEvent) + this.handleMapBrowserEvent(mapBrowserEvent); + if(type == goog.events.EventType.MOUSEOUT) { + this.focus_ = null + }else { + this.focus_ = mapBrowserEvent.getCoordinate() + } }; ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { mapBrowserEvent.frameState = this.frameState_; @@ -16816,7 +16691,10 @@ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { }; ol.Map.prototype.handlePostRender = function() { this.tileQueue_.reprioritize(); - this.tileQueue_.loadMoreTiles(); + var moreLoadingTiles = this.tileQueue_.loadMoreTiles(); + if(moreLoadingTiles) { + this.requestRenderFrame() + } var postRenderFunctions = this.postRenderFunctions_; var i; for(i = 0;i < postRenderFunctions.length;++i) { @@ -16871,6 +16749,11 @@ ol.Map.prototype.requestRenderFrame = function() { this.dirty_ = true } }; +ol.Map.prototype.removeLayer = function(layer) { + var layers = this.getLayers(); + goog.asserts.assert(goog.isDef(layers)); + return layers.remove(layer) +}; ol.Map.prototype.renderFrame_ = function(time) { var i; if(this.freezeRenderingCount_ != 0) { @@ -16966,7 +16849,18 @@ ol.Map.prototype.withFrozenRendering = function(f, opt_obj) { ol.MapOptionsInternal; ol.Map.createOptionsInternal = function(mapOptions) { var values = {}; - values[ol.MapProperty.LAYERS] = goog.isDef(mapOptions.layers) ? mapOptions.layers : new ol.Collection; + var layers; + if(goog.isDef(mapOptions.layers)) { + if(goog.isArray(mapOptions.layers)) { + layers = new ol.Collection(goog.array.clone(mapOptions.layers)) + }else { + goog.asserts.assert(mapOptions.layers instanceof ol.Collection); + layers = mapOptions.layers + } + }else { + layers = new ol.Collection + } + values[ol.MapProperty.LAYERS] = layers; values[ol.MapProperty.VIEW] = goog.isDef(mapOptions.view) ? mapOptions.view : new ol.View2D; var rendererConstructor = ol.renderer.Map; var rendererHints; @@ -17256,24 +17150,24 @@ goog.require("ol.Coordinate"); goog.require("ol.Object"); goog.require("ol.Projection"); goog.require("ol.projection"); -ol.GeolocationProperty = {ACCURACY:"accuracy", ALTITUDE:"altitude", ALTITUDE_ACCURACY:"altitudeAccuracy", HEADING:"heading", POSITION:"position", PROJECTION:"projection", SPEED:"speed"}; -ol.Geolocation = function(opt_positionOptions) { +ol.GeolocationProperty = {ACCURACY:"accuracy", ALTITUDE:"altitude", ALTITUDE_ACCURACY:"altitudeAccuracy", HEADING:"heading", POSITION:"position", PROJECTION:"projection", SPEED:"speed", TRACKING:"tracking", TRACKING_OPTIONS:"trackingOptions"}; +ol.Geolocation = function() { goog.base(this); this.position_ = null; - if(ol.Geolocation.SUPPORTED) { - goog.events.listen(this, ol.Object.getChangedEventType(ol.GeolocationProperty.PROJECTION), this.handleProjectionChanged_, false, this); - this.watchId_ = navigator.geolocation.watchPosition(goog.bind(this.positionChange_, this), goog.bind(this.positionError_, this), opt_positionOptions) - } + this.watchId_; + this.setTracking(false); + goog.events.listen(this, ol.Object.getChangedEventType(ol.GeolocationProperty.PROJECTION), this.handleProjectionChanged_, false, this); + goog.events.listen(this, ol.Object.getChangedEventType(ol.GeolocationProperty.TRACKING), this.handleTrackingChanged_, false, this) }; goog.inherits(ol.Geolocation, ol.Object); ol.Geolocation.prototype.disposeInternal = function() { - navigator.geolocation.clearWatch(this.watchId_); + this.setTracking(false); goog.base(this, "disposeInternal") }; ol.Geolocation.prototype.handleProjectionChanged_ = function() { var projection = this.getProjection(); if(goog.isDefAndNotNull(projection)) { - this.transformFn_ = ol.projection.getTransform(ol.projection.getFromCode("EPSG:4326"), projection); + this.transformFn_ = ol.projection.getTransformFromProjections(ol.projection.get("EPSG:4326"), projection); if(!goog.isNull(this.position_)) { var vertex = [this.position_.x, this.position_.y]; vertex = this.transformFn_(vertex, vertex, 2); @@ -17281,6 +17175,19 @@ ol.Geolocation.prototype.handleProjectionChanged_ = function() { } } }; +ol.Geolocation.prototype.handleTrackingChanged_ = function() { + if(ol.Geolocation.SUPPORTED) { + var tracking = this.getTracking(); + if(tracking && !goog.isDef(this.watchId_)) { + this.watchId_ = navigator.geolocation.watchPosition(goog.bind(this.positionChange_, this), goog.bind(this.positionError_, this), this.getTrackingOptions()) + }else { + if(!tracking && goog.isDef(this.watchId_)) { + navigator.geolocation.clearWatch(this.watchId_); + this.watchId_ = undefined + } + } + } +}; ol.Geolocation.SUPPORTED = "geolocation" in navigator; ol.Geolocation.prototype.positionChange_ = function(position) { var coords = position.coords; @@ -17324,10 +17231,26 @@ ol.Geolocation.prototype.getSpeed = function() { return this.get(ol.GeolocationProperty.SPEED) }; goog.exportProperty(ol.Geolocation.prototype, "getSpeed", ol.Geolocation.prototype.getSpeed); +ol.Geolocation.prototype.getTracking = function() { + return this.get(ol.GeolocationProperty.TRACKING) +}; +goog.exportProperty(ol.Geolocation.prototype, "getTracking", ol.Geolocation.prototype.getTracking); +ol.Geolocation.prototype.getTrackingOptions = function() { + return this.get(ol.GeolocationProperty.TRACKING_OPTIONS) +}; +goog.exportProperty(ol.Geolocation.prototype, "getTrackingOptions", ol.Geolocation.prototype.getTrackingOptions); ol.Geolocation.prototype.setProjection = function(projection) { this.set(ol.GeolocationProperty.PROJECTION, projection) }; goog.exportProperty(ol.Geolocation.prototype, "setProjection", ol.Geolocation.prototype.setProjection); +ol.Geolocation.prototype.setTracking = function(tracking) { + this.set(ol.GeolocationProperty.TRACKING, tracking) +}; +goog.exportProperty(ol.Geolocation.prototype, "setTracking", ol.Geolocation.prototype.setTracking); +ol.Geolocation.prototype.setTrackingOptions = function(options) { + this.set(ol.GeolocationProperty.TRACKING_OPTIONS, options) +}; +goog.exportProperty(ol.Geolocation.prototype, "setTrackingOptions", ol.Geolocation.prototype.setTrackingOptions); ol.Geolocation.prototype.transformFn_ = goog.functions.identity; goog.provide("ol.ImageTile"); goog.require("goog.array"); @@ -17336,8 +17259,8 @@ goog.require("goog.events.EventType"); goog.require("ol.Tile"); goog.require("ol.TileCoord"); goog.require("ol.TileState"); -ol.ImageTile = function(tileCoord, src, crossOrigin) { - goog.base(this, tileCoord); +ol.ImageTile = function(tileCoord, state, src, crossOrigin) { + goog.base(this, tileCoord, state); this.src_ = src; this.image_ = new Image; if(!goog.isNull(crossOrigin)) { @@ -17501,7 +17424,7 @@ ol.control.MousePosition = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; var element = goog.dom.createDom(goog.dom.TagName.DIV, {"class":"ol-mouse-position"}); goog.base(this, {element:element, map:options.map, target:options.target}); - this.projection_ = options.projection; + this.projection_ = ol.projection.get(options.projection); this.coordinateFormat_ = options.coordinateFormat; this.undefinedHTML_ = goog.isDef(options.undefinedHTML) ? options.undefinedHTML : ""; this.renderedHTML_ = element.innerHTML; @@ -17547,8 +17470,8 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) { var html = this.undefinedHTML_; if(!goog.isNull(pixel)) { if(this.renderedProjection_ != this.mapProjection_) { - if(goog.isDef(this.projection_)) { - this.transform_ = ol.projection.getTransform(this.mapProjection_, this.projection_) + if(!goog.isNull(this.projection_)) { + this.transform_ = ol.projection.getTransformFromProjections(this.mapProjection_, this.projection_) }else { this.transform_ = ol.projection.identityTransform } @@ -17572,6 +17495,176 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) { this.renderedHTML_ = html } }; +goog.provide("ol.control.ScaleLine"); +goog.provide("ol.control.ScaleLineUnits"); +goog.require("goog.dom"); +goog.require("goog.style"); +goog.require("ol.FrameState"); +goog.require("ol.MapEvent"); +goog.require("ol.MapEventType"); +goog.require("ol.ProjectionUnits"); +goog.require("ol.TransformFunction"); +goog.require("ol.control.Control"); +goog.require("ol.projection"); +goog.require("ol.sphere.NORMAL"); +ol.control.ScaleLineUnits = {DEGREES:"degrees", IMPERIAL:"imperial", NAUTICAL:"nautical", METRIC:"metric", US:"us"}; +ol.control.ScaleLine = function(opt_options) { + var options = opt_options || {}; + this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV, {"class":"ol-scale-line-inner"}); + this.element_ = goog.dom.createDom(goog.dom.TagName.DIV, {"class":"ol-scale-line ol-unselectable"}, this.innerElement_); + this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64; + this.units_ = goog.isDef(options.units) ? options.units : ol.control.ScaleLineUnits.METRIC; + this.listenerKeys_ = null; + this.renderedVisible_ = false; + this.renderedWidth_; + this.renderedHTML_ = ""; + this.toEPSG4326_ = null; + goog.base(this, {element:this.element_, map:options.map, target:options.target}) +}; +goog.inherits(ol.control.ScaleLine, ol.control.Control); +ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5]; +ol.control.ScaleLine.prototype.handleMapPostrender = function(mapEvent) { + var frameState = mapEvent.frameState; + this.updateElement_(mapEvent.frameState) +}; +ol.control.ScaleLine.prototype.setMap = function(map) { + if(!goog.isNull(this.listenerKeys_)) { + goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); + this.listenerKeys_ = null + } + goog.base(this, "setMap", map); + if(!goog.isNull(map)) { + this.listenerKeys_ = [goog.events.listen(map, ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this)] + } +}; +ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { + if(goog.isNull(frameState)) { + if(this.renderedVisible_) { + goog.style.showElement(this.element_, false); + this.renderedVisible_ = false + } + return + } + var view2DState = frameState.view2DState; + var center = view2DState.center; + var projection = view2DState.projection; + var pointResolution = projection.getPointResolution(view2DState.resolution, center); + var projectionUnits = projection.getUnits(); + var cosLatitude; + if(projectionUnits == ol.ProjectionUnits.DEGREES && (this.units_ == ol.control.ScaleLineUnits.METRIC || this.units_ == ol.control.ScaleLineUnits.IMPERIAL)) { + this.toEPSG4326_ = null; + cosLatitude = Math.cos(goog.math.toRadians(center.y)); + pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180; + projectionUnits = ol.ProjectionUnits.METERS + }else { + if((projectionUnits == ol.ProjectionUnits.FEET || projectionUnits == ol.ProjectionUnits.METERS) && this.units_ == ol.control.ScaleLineUnits.DEGREES) { + if(goog.isNull(this.toEPSG4326_)) { + this.toEPSG4326_ = ol.projection.getTransformFromProjections(projection, ol.projection.get("EPSG:4326")) + } + var vertex = [center.x, center.y]; + vertex = this.toEPSG4326_(vertex, vertex, 2); + cosLatitude = Math.cos(goog.math.toRadians(vertex[1])); + var radius = ol.sphere.NORMAL.radius; + if(projectionUnits == ol.ProjectionUnits.FEET) { + radius /= 0.3048 + } + pointResolution *= 180 / (Math.PI * cosLatitude * radius); + projectionUnits = ol.ProjectionUnits.DEGREES + }else { + this.toEPSG4326_ = null + } + } + goog.asserts.assert((this.units_ == ol.control.ScaleLineUnits.METRIC || this.units_ == ol.control.ScaleLineUnits.IMPERIAL) && projectionUnits == ol.ProjectionUnits.METERS || this.units_ == ol.control.ScaleLineUnits.DEGREES && projectionUnits == ol.ProjectionUnits.DEGREES); + var nominalCount = this.minWidth_ * pointResolution; + var suffix = ""; + if(this.units_ == ol.control.ScaleLineUnits.DEGREES) { + if(nominalCount < 1 / 60) { + suffix = "\u2033"; + pointResolution *= 3600 + }else { + if(nominalCount < 1) { + suffix = "\u2032"; + pointResolution *= 60 + }else { + suffix = "\u00b0" + } + } + }else { + if(this.units_ == ol.control.ScaleLineUnits.IMPERIAL) { + if(nominalCount < 0.9144) { + suffix = "in"; + pointResolution /= 0.0254 + }else { + if(nominalCount < 1609.344) { + suffix = "ft"; + pointResolution /= 0.3048 + }else { + suffix = "mi"; + pointResolution /= 1609.344 + } + } + }else { + if(this.units_ == ol.control.ScaleLineUnits.NAUTICAL) { + pointResolution /= 1852; + suffix = "nm" + }else { + if(this.units_ == ol.control.ScaleLineUnits.METRIC) { + if(nominalCount < 1) { + suffix = "mm"; + pointResolution *= 1E3 + }else { + if(nominalCount < 1E3) { + suffix = "m" + }else { + suffix = "km"; + pointResolution /= 1E3 + } + } + }else { + if(this.units_ == ol.control.ScaleLineUnits.US) { + if(nominalCount < 0.9144) { + suffix = "in"; + pointResolution *= 39.37 + }else { + if(nominalCount < 1609.344) { + suffix = "ft"; + pointResolution /= 0.30480061 + }else { + suffix = "mi"; + pointResolution /= 1609.3472 + } + } + }else { + goog.asserts.assert(false) + } + } + } + } + } + var i = 3 * Math.floor(Math.log(this.minWidth_ * pointResolution) / Math.log(10)); + var count, width; + while(true) { + count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] * Math.pow(10, Math.floor(i / 3)); + width = Math.round(count / pointResolution); + if(width >= this.minWidth_) { + break + } + ++i + } + var html = count + suffix; + if(this.renderedHTML_ != html) { + this.innerElement_.innerHTML = html; + this.renderedHTML_ = html + } + if(this.renderedWidth_ != width) { + this.innerElement_.style.width = width + "px"; + this.renderedWidth_ = width + } + if(!this.renderedVisible_) { + goog.style.showElement(this.element_, true); + this.renderedVisible_ = true + } +}; goog.provide("ol.ellipsoid.WGS84"); goog.require("ol.Ellipsoid"); ol.ellipsoid.WGS84 = new ol.Ellipsoid(6378137, 1 / 298.257223563); @@ -18412,6 +18505,50 @@ ol.parser.ogc.WMSCapabilities_v1_1_0 = function() { }}) }; goog.inherits(ol.parser.ogc.WMSCapabilities_v1_1_0, ol.parser.ogc.WMSCapabilities_v1_1); +goog.provide("ol.parser.ogc.WMSCapabilities_v1_0_0"); +goog.require("goog.string"); +goog.require("ol.parser.ogc.WMSCapabilities_v1_1_0"); +ol.parser.ogc.WMSCapabilities_v1_0_0 = function() { + goog.base(this); + this.version = "1.0.0"; + goog.object.extend(this.readers["http://www.opengis.net/wms"], {"Format":function(node, obj) { + for(var i = 0, ii = node.childNodes.length;i < ii;i++) { + var child = node.childNodes[i]; + var local = child.localName || child.nodeName.split(":").pop(); + if(goog.isArray(obj["formats"])) { + obj["formats"].push(local) + }else { + obj["format"] = local + } + } + }, "Keywords":function(node, obj) { + if(!goog.isDef(obj["keywords"])) { + obj["keywords"] = [] + } + var keywords = this.getChildValue(node).split(/ +/); + for(var i = 0, ii = keywords.length;i < ii;++i) { + if(!goog.string.isEmpty(keywords[i])) { + obj["keywords"].push({"value":keywords[i]}) + } + } + }, "OnlineResource":function(node, obj) { + obj["href"] = this.getChildValue(node) + }, "Get":function(node, obj) { + obj["get"] = {"href":node.getAttribute("onlineResource")} + }, "Post":function(node, obj) { + obj["post"] = {"href":node.getAttribute("onlineResource")} + }, "Map":function(node, obj) { + var reader = this.readers[this.defaultNamespaceURI]["GetMap"]; + reader.apply(this, arguments) + }, "Capabilities":function(node, obj) { + var reader = this.readers[this.defaultNamespaceURI]["GetCapabilities"]; + reader.apply(this, arguments) + }, "FeatureInfo":function(node, obj) { + var reader = this.readers[this.defaultNamespaceURI]["GetFeatureInfo"]; + reader.apply(this, arguments) + }}) +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_0_0, ol.parser.ogc.WMSCapabilities_v1_1_0); goog.provide("ol.parser.ogc.WMSCapabilities_v1_1_1"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1"); ol.parser.ogc.WMSCapabilities_v1_1_1 = function() { @@ -18514,10 +18651,12 @@ ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { goog.inherits(ol.parser.ogc.WMSCapabilities_v1_3_0, ol.parser.ogc.WMSCapabilities_v1); goog.provide("ol.parser.ogc.WMSCapabilities"); goog.require("ol.parser.ogc.Versioned"); +goog.require("ol.parser.ogc.WMSCapabilities_v1_0_0"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1_0"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1_1"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC"); goog.require("ol.parser.ogc.WMSCapabilities_v1_3_0"); +ol.ENABLE_WMSCAPS_1_0_0 = false; ol.ENABLE_WMSCAPS_1_1_0 = true; ol.ENABLE_WMSCAPS_1_1_1 = true; ol.ENABLE_WMSCAPS_1_3_0 = true; @@ -18526,6 +18665,9 @@ ol.parser.ogc.WMSCapabilities = function(opt_options) { opt_options = opt_options || {}; opt_options["defaultVersion"] = "1.1.1"; this.parsers = {}; + if(ol.ENABLE_WMSCAPS_1_0_0) { + this.parsers["v1_0_0"] = ol.parser.ogc.WMSCapabilities_v1_0_0 + } if(ol.ENABLE_WMSCAPS_1_1_0) { this.parsers["v1_1_0"] = ol.parser.ogc.WMSCapabilities_v1_1_0 } @@ -18590,7 +18732,7 @@ ol.parser.ogc.WMTSCapabilities_v1_0_0 = function() { }, "TopLeftCorner":function(node, obj) { var topLeftCorner = this.getChildValue(node); var coords = topLeftCorner.split(" "); - var axisOrientation = ol.projection.getFromCode(obj["supportedCRS"]).getAxisOrientation(); + var axisOrientation = ol.projection.get(obj["supportedCRS"]).getAxisOrientation(); obj["topLeftCorner"] = ol.Coordinate.fromProjectedArray([parseFloat(coords[0]), parseFloat(coords[1])], axisOrientation) }, "TileWidth":function(node, obj) { obj["tileWidth"] = parseInt(this.getChildValue(node), 10) @@ -19099,6 +19241,7 @@ goog.require("ol.ImageTile"); goog.require("ol.Projection"); goog.require("ol.Tile"); goog.require("ol.TileCache"); +goog.require("ol.TileState"); goog.require("ol.TileUrlFunction"); goog.require("ol.TileUrlFunctionType"); goog.require("ol.source.TileSource"); @@ -19125,13 +19268,8 @@ ol.source.ImageTileSource.prototype.getTile = function(tileCoord, tileGrid, proj goog.asserts.assert(tileGrid); goog.asserts.assert(projection); var tileUrl = this.tileUrlFunction(tileCoord, tileGrid, projection); - var tile; - if(goog.isDef(tileUrl)) { - tile = new ol.ImageTile(tileCoord, tileUrl, this.crossOrigin_); - this.tileCache_.set(key, tile) - }else { - tile = null - } + var tile = new ol.ImageTile(tileCoord, goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY, goog.isDef(tileUrl) ? tileUrl : "", this.crossOrigin_); + this.tileCache_.set(key, tile); return tile } }; @@ -19190,7 +19328,7 @@ goog.require("ol.projection"); goog.require("ol.source.ImageTileSource"); goog.require("ol.tilegrid.XYZ"); ol.source.BingMaps = function(bingMapsOptions) { - goog.base(this, {opaque:true, projection:ol.projection.getFromCode("EPSG:3857")}); + goog.base(this, {opaque:true, projection:ol.projection.get("EPSG:3857")}); this.culture_ = goog.isDef(bingMapsOptions.culture) ? bingMapsOptions.culture : "en-us"; this.ready_ = false; var uri = new goog.Uri("//dev.virtualearth.net/REST/v1/Imagery/Metadata/" + bingMapsOptions.style); @@ -19235,7 +19373,7 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse = function(response) } } }))); - var transform = ol.projection.getTransform(ol.projection.getFromCode("EPSG:4326"), this.getProjection()); + var transform = ol.projection.getTransformFromProjections(ol.projection.get("EPSG:4326"), this.getProjection()); var attributions = goog.array.map(resource.imageryProviders, function(imageryProvider) { var html = imageryProvider.attribution; var tileRanges = {}; @@ -19274,8 +19412,7 @@ goog.require("ol.TileState"); goog.require("ol.source.TileSource"); goog.require("ol.tilegrid.TileGrid"); ol.DebugTile_ = function(tileCoord, tileGrid) { - goog.base(this, tileCoord); - this.state = ol.TileState.LOADED; + goog.base(this, tileCoord, ol.TileState.LOADED); this.tileCoord_ = tileCoord; this.tileSize_ = tileGrid.getTileSize(tileCoord.z); this.canvasByContext_ = {} @@ -19337,7 +19474,7 @@ goog.require("ol.source.ImageTileSource"); goog.require("ol.tilegrid.XYZ"); ol.source.XYZOptions; ol.source.XYZ = function(xyzOptions) { - var projection = xyzOptions.projection || ol.projection.getFromCode("EPSG:3857"); + var projection = xyzOptions.projection || ol.projection.get("EPSG:3857"); var tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction; if(goog.isDef(xyzOptions.tileUrlFunction)) { tileUrlFunction = xyzOptions.tileUrlFunction @@ -19442,8 +19579,8 @@ goog.require("ol.source.XYZ"); ol.source.StamenLayerConfig = {"terrain":{extension:"jpg", opaque:true}, "terrain-background":{extension:"jpg", opaque:true}, "terrain-labels":{extension:"png", opaque:false}, "terrain-lines":{extension:"png", opaque:false}, "toner-background":{extension:"png", opaque:true}, "toner":{extension:"png", opaque:true}, "toner-hybrid":{extension:"png", opaque:false}, "toner-labels":{extension:"png", opaque:false}, "toner-lines":{extension:"png", opaque:false}, "toner-lite":{extension:"png", opaque:true}, "watercolor":{extension:"jpg", opaque:true}}; ol.source.StamenProviderConfig = {"terrain":{minZoom:4, maxZoom:18}, "toner":{minZoom:0, maxZoom:20}, "watercolor":{minZoom:3, maxZoom:16}}; +ol.source.STAMEN_ATTRIBUTIONS = [new ol.Attribution('Map tiles by Stamen Design, under ' + 'CC BY 3.0. ' + 'Data by OpenStreetMap, under ' + 'CC BY SA.')]; ol.source.Stamen = function(options) { - var attribution = new ol.Attribution('Map tiles by Stamen Design, ' + "under " + 'CC BY 3.0. ' + 'Data by OpenStreetMap, ' + "under " + 'CC BY SA.'); var i = options.layer.indexOf("-"); var provider = i == -1 ? options.layer : options.layer.slice(0, i); goog.asserts.assert(provider in ol.source.StamenProviderConfig); @@ -19451,19 +19588,20 @@ ol.source.Stamen = function(options) { goog.asserts.assert(options.layer in ol.source.StamenLayerConfig); var layerConfig = ol.source.StamenLayerConfig[options.layer]; var url = goog.isDef(options.url) ? options.url : "http://{a-d}.tile.stamen.com/" + options.layer + "/{z}/{x}/{y}." + layerConfig.extension; - goog.base(this, {attributions:[attribution], maxZoom:providerConfig.maxZoom, opaque:layerConfig.opaque, url:url}) + goog.base(this, {attributions:ol.source.STAMEN_ATTRIBUTIONS, maxZoom:providerConfig.maxZoom, opaque:layerConfig.opaque, url:url}) }; goog.inherits(ol.source.Stamen, ol.source.XYZ); goog.provide("ol.source.StaticImage"); goog.require("ol.Image"); goog.require("ol.ImageUrlFunctionType"); +goog.require("ol.projection"); goog.require("ol.source.ImageSource"); ol.source.StaticImage = function(options) { var imageFunction = ol.source.StaticImage.createImageFunction(options.url); var imageExtent = options.imageExtent; var imageSize = options.imageSize; var imageResolution = imageExtent.getHeight() / imageSize.height; - var projection = goog.isDef(options.projection) ? options.projection : null; + var projection = ol.projection.get(options.projection); goog.base(this, {attributions:options.attributions, crossOrigin:options.crossOrigin, extent:options.extent, projection:options.projection, imageUrlFunction:imageFunction, resolutions:[imageResolution]}); this.image_ = this.createImage(imageExtent, imageResolution, imageSize, projection) }; @@ -19491,14 +19629,13 @@ goog.require("ol.TileUrlFunction"); goog.require("ol.projection"); goog.require("ol.source.ImageTileSource"); goog.require("ol.tilegrid.XYZ"); -ol.source.TileJSONOptions; ol.tilejson.grids_ = []; var grid = function(tileJSON) { ol.tilejson.grids_.push(tileJSON) }; goog.exportSymbol("grid", grid); ol.source.TileJSON = function(tileJsonOptions) { - goog.base(this, {projection:ol.projection.getFromCode("EPSG:3857")}); + goog.base(this, {projection:ol.projection.get("EPSG:3857")}); this.ready_ = false; this.deferred_ = goog.net.jsloader.load(tileJsonOptions.uri, {cleanupWhenDone:true}); this.deferred_.addCallback(this.handleTileJSONResponse, this) @@ -19506,12 +19643,12 @@ ol.source.TileJSON = function(tileJsonOptions) { goog.inherits(ol.source.TileJSON, ol.source.ImageTileSource); ol.source.TileJSON.prototype.handleTileJSONResponse = function() { var tileJSON = ol.tilejson.grids_.pop(); - var epsg4326Projection = ol.projection.getFromCode("EPSG:4326"); + var epsg4326Projection = ol.projection.get("EPSG:4326"); var epsg4326Extent, extent; if(goog.isDef(tileJSON.bounds)) { var bounds = tileJSON.bounds; epsg4326Extent = new ol.Extent(bounds[0], bounds[1], bounds[2], bounds[3]); - extent = epsg4326Extent.transform(ol.projection.getTransform(epsg4326Projection, this.getProjection())); + extent = epsg4326Extent.transform(ol.projection.getTransformFromProjections(epsg4326Projection, this.getProjection())); this.setExtent(extent) }else { epsg4326Extent = null; @@ -19594,7 +19731,7 @@ ol.source.TiledWMS = function(tiledWMSOptions) { var tileExtent = tileGrid.getTileCoordExtent(tileCoord); var projectionExtent = projection.getExtent(); extent = goog.isDef(extent) ? extent : projectionExtent; - if(extent.minX === projectionExtent.minX && extent.maxX === projectionExtent.maxX) { + if(!goog.isNull(extent) && projection.isGlobal() && extent.minX === projectionExtent.minX && extent.maxX === projectionExtent.maxX) { var numCols = Math.ceil((extent.maxX - extent.minX) / (tileExtent.maxX - tileExtent.minX)); x = goog.math.modulo(x, numCols); tileExtent = tileGrid.getTileCoordExtent(new ol.TileCoord(tileCoord.z, x, tileCoord.y)) @@ -19651,6 +19788,7 @@ goog.require("ol.PixelBounds"); goog.require("ol.PostRenderFunction"); goog.require("ol.PreRenderFunction"); goog.require("ol.Projection"); +goog.require("ol.ProjectionLike"); goog.require("ol.ProjectionUnits"); goog.require("ol.Rectangle"); goog.require("ol.RendererHint"); @@ -19723,6 +19861,7 @@ goog.require("ol.parser.ogc.OWSCommon_v1_1_0"); goog.require("ol.parser.ogc.Versioned"); goog.require("ol.parser.ogc.WMSCapabilities"); goog.require("ol.parser.ogc.WMSCapabilities_v1"); +goog.require("ol.parser.ogc.WMSCapabilities_v1_0_0"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1_0"); goog.require("ol.parser.ogc.WMSCapabilities_v1_1_1"); @@ -19787,6 +19926,8 @@ goog.require("ol.webgl"); goog.require("ol.webgl.WebGLContextEventType"); goog.provide("ol.AnchoredElementOptionsType"); goog.provide("ol.MapOptionsType"); +goog.provide("ol.Proj4jsProjectionOptionsType"); +goog.provide("ol.ProjectionOptionsType"); goog.provide("ol.View2DOptionsType"); goog.provide("ol.animation.BounceOptionsType"); goog.provide("ol.animation.PanOptionsType"); @@ -19798,17 +19939,22 @@ goog.provide("ol.control.MousePositionOptionsType"); goog.provide("ol.control.ScaleLineOptionsType"); goog.provide("ol.control.ZoomOptionsType"); goog.provide("ol.interaction.DefaultOptionsType"); +goog.provide("ol.interaction.KeyboardPanOptionsType"); +goog.provide("ol.interaction.KeyboardZoomOptionsType"); goog.provide("ol.layer.LayerOptionsType"); goog.provide("ol.source.BingMapsOptionsType"); goog.provide("ol.source.DebugTileSourceOptionsType"); goog.provide("ol.source.SingleImageWMSOptionsType"); goog.provide("ol.source.StamenOptionsType"); goog.provide("ol.source.StaticImageOptionsType"); +goog.provide("ol.source.TileJSONOptionsType"); goog.provide("ol.source.TiledWMSOptionsType"); goog.provide("ol.tilegrid.TileGridOptionsType"); goog.provide("ol.tilegrid.XYZOptionsType"); ol.AnchoredElementOptions; ol.MapOptions; +ol.Proj4jsProjectionOptions; +ol.ProjectionOptions; ol.View2DOptions; ol.animation.BounceOptions; ol.animation.PanOptions; @@ -19820,12 +19966,15 @@ ol.control.MousePositionOptions; ol.control.ScaleLineOptions; ol.control.ZoomOptions; ol.interaction.DefaultOptions; +ol.interaction.KeyboardPanOptions; +ol.interaction.KeyboardZoomOptions; ol.layer.LayerOptions; ol.source.BingMapsOptions; ol.source.DebugTileSourceOptions; ol.source.SingleImageWMSOptions; ol.source.StamenOptions; ol.source.StaticImageOptions; +ol.source.TileJSONOptions; ol.source.TiledWMSOptions; ol.tilegrid.TileGridOptions; ol.tilegrid.XYZOptions; diff --git a/master/build/ol.js b/master/build/ol.js index 859354b600..81437bf309 100644 --- a/master/build/ol.js +++ b/master/build/ol.js @@ -1,240 +1,242 @@ -(function(){var h=void 0,j=!0,k=null,l=!1;function aa(){return function(a){return a}}function m(a){return function(){return this[a]}}var p,w=this;function ba(){}function ca(a){a.Ya=function(){return a.qc?a.qc:a.qc=new a}} +(function(){var h=void 0,i=!0,k=null,l=!1;function aa(){return function(a){return a}}function n(a){return function(){return this[a]}}var p,w=this;function ba(){}function ca(a){a.cb=function(){return a.wc?a.wc:a.wc=new a}} function da(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; -else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function x(a){return a!==h}function ea(a){return"array"==da(a)}function fa(a){var b=da(a);return"array"==b||"object"==b&&"number"==typeof a.length}function ga(a){return"string"==typeof a}function ha(a){return"function"==da(a)}function ia(a){var b=typeof a;return"object"==b&&a!=k||"function"==b}function y(a){return a[ja]||(a[ja]=++ka)}var ja="closure_uid_"+Math.floor(2147483648*Math.random()).toString(36),ka=0; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function y(a){return a!==h}function ea(a){return"array"==da(a)}function fa(a){var b=da(a);return"array"==b||"object"==b&&"number"==typeof a.length}function ga(a){return"string"==typeof a}function ha(a){return"function"==da(a)}function ia(a){var b=typeof a;return"object"==b&&a!=k||"function"==b}function z(a){return a[ja]||(a[ja]=++ka)}var ja="closure_uid_"+Math.floor(2147483648*Math.random()).toString(36),ka=0; function la(a,b,c){return a.call.apply(a.bind,arguments)}function ma(a,b,c){if(!a)throw Error();if(2")&&(a=a.replace(wa,">"));-1!=a.indexOf('"')&&(a=a.replace(xa,"""));return a}var ua=/&/g,va=//g,xa=/\"/g,ta=/[&<>\"]/;var ya=Array.prototype,za=ya.indexOf?function(a,b,c){return ya.indexOf.call(a,b,c)}:function(a,b,c){c=c==k?0:0>c?Math.max(0,a.length+c):c;if(ga(a))return!ga(b)||1!=b.length?-1:a.indexOf(b,c);for(;c=arguments.length?ya.slice.call(a,b):ya.slice.call(a,b,c)}function Ja(a){ya.sort.call(a,Ka)} -function Ka(a,b){return a>b?1:a2*this.n&&Za(this),j):l};function Za(a){if(a.n!=a.a.length){for(var b=0,c=0;bparseFloat(sb)){rb=String(wb);break a}}rb=sb}var yb={}; -function zb(a){var b;if(!(b=yb[a])){b=0;for(var c=String(rb).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),f=0;0==b&&f(0==q[1].length?0:parseInt(q[1],10))?1:0)||((0==s[2].length)<(0==q[2].length)?-1:(0==s[2].length)>(0==q[2].length)?1:0)||(s[2]q[2]?1:0)}while(0==b)}b=yb[a]=0<=b}return b}var Ab={};function Bb(a){return Ab[a]||(Ab[a]=F&&!!document.documentMode&&document.documentMode>=a)};var Cb,Db=!F||Bb(9);!nb&&!F||F&&Bb(9)||nb&&zb("1.9.1");F&&zb("9");function Eb(a,b){var c;c=a.className;c=ga(c)&&c.match(/\S+/g)||[];for(var d=Ia(arguments,1),e=c.length+d.length,f=c,g=0;gc*b?c+b:c};function Hb(a,b){this.x=x(a)?a:0;this.y=x(b)?b:0}Hb.prototype.S=function(){return new Hb(this.x,this.y)};function Ib(a,b){this.width=a;this.height=b}p=Ib.prototype;p.S=function(){return new Ib(this.width,this.height)};p.Ia=function(){return!(this.width*this.height)};p.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};p.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};p.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function Jb(a){return a?new Kb(Lb(a)):Cb||(Cb=new Kb)}function Mb(a,b){La(b,function(b,d){"style"==d?a.style.cssText=b:"class"==d?a.className=b:"for"==d?a.htmlFor=b:d in Nb?a.setAttribute(Nb[d],b):0==d.lastIndexOf("aria-",0)||0==d.lastIndexOf("data-",0)?a.setAttribute(d,b):a[d]=b})}var Nb={cellpadding:"cellPadding",cellspacing:"cellSpacing",colspan:"colSpan",frameborder:"frameBorder",height:"height",maxlength:"maxLength",role:"role",rowspan:"rowSpan",type:"type",usemap:"useMap",valign:"vAlign",width:"width"}; -function Ob(a){a=a.document.documentElement;return new Ib(a.clientWidth,a.clientHeight)}function Pb(a,b,c){var d=arguments,e=document,f=d[0],g=d[1];if(!Db&&g&&(g.name||g.type)){f=["<",f];g.name&&f.push(' name="',ra(g.name),'"');if(g.type){f.push(' type="',ra(g.type),'"');var i={};Va(i,g);delete i.type;g=i}f.push(">");f=f.join("")}f=e.createElement(f);g&&(ga(g)?f.className=g:ea(g)?Eb.apply(k,[f].concat(g)):Mb(f,g));2=a.keyCode)a.keyCode=-1}catch(b){}};p.cd=m("K");function mc(){}var nc=0;mc.prototype.key=0;mc.prototype.za=l;mc.prototype.a=l;mc.prototype.handleEvent=function(a){return this.b?this.Ja.call(this.Ob||this.src,a):this.Ja.handleEvent.call(this.Ja,a)};var oc={},pc={},qc={},rc={}; -function H(a,b,c,d,e){if(b){if(ea(b)){for(var f=0;f")&&(a=a.replace(xa,">"));-1!=a.indexOf('"')&&(a=a.replace(ya,"""));return a}var ta=/&/g,wa=//g,ya=/\"/g,sa=/[&<>\"]/;var za=Array.prototype,Aa=za.indexOf?function(a,b,c){return za.indexOf.call(a,b,c)}:function(a,b,c){c=c==k?0:0>c?Math.max(0,a.length+c):c;if(ga(a))return!ga(b)||1!=b.length?-1:a.indexOf(b,c);for(;c=arguments.length?za.slice.call(a,b):za.slice.call(a,b,c)}function Ka(a){za.sort.call(a,La)} +function La(a,b){return a>b?1:a2*this.o&&$a(this),i):l};function $a(a){if(a.o!=a.a.length){for(var b=0,c=0;bparseFloat(ub)){tb=String(yb);break a}}tb=ub}var Ab={}; +function Bb(a){var b;if(!(b=Ab[a])){b=0;for(var c=String(tb).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),f=0;0==b&&f(0==q[1].length?0:parseInt(q[1],10))?1:0)||((0==s[2].length)<(0==q[2].length)?-1:(0==s[2].length)>(0==q[2].length)?1:0)||(s[2]q[2]?1:0)}while(0==b)}b=Ab[a]=0<=b}return b}var Cb={};function Db(a){return Cb[a]||(Cb[a]=E&&!!document.documentMode&&document.documentMode>=a)};var Eb,Fb=!E||Db(9);!ob&&!E||E&&Db(9)||ob&&Bb("1.9.1");E&&Bb("9");function Gb(a,b){var c;c=a.className;c=ga(c)&&c.match(/\S+/g)||[];for(var d=Ja(arguments,1),e=c.length+d.length,f=c,g=0;gc*b?c+b:c};function Jb(a,b){this.x=y(a)?a:0;this.y=y(b)?b:0}Jb.prototype.T=function(){return new Jb(this.x,this.y)};function Kb(a,b){this.width=a;this.height=b}p=Kb.prototype;p.T=function(){return new Kb(this.width,this.height)};p.Pa=function(){return!(this.width*this.height)};p.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};p.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};p.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function Lb(a){return a?new Mb(Nb(a)):Eb||(Eb=new Mb)}function Ob(a,b){Ma(b,function(b,d){"style"==d?a.style.cssText=b:"class"==d?a.className=b:"for"==d?a.htmlFor=b:d in Pb?a.setAttribute(Pb[d],b):0==d.lastIndexOf("aria-",0)||0==d.lastIndexOf("data-",0)?a.setAttribute(d,b):a[d]=b})}var Pb={cellpadding:"cellPadding",cellspacing:"cellSpacing",colspan:"colSpan",frameborder:"frameBorder",height:"height",maxlength:"maxLength",role:"role",rowspan:"rowSpan",type:"type",usemap:"useMap",valign:"vAlign",width:"width"}; +function Qb(a){a=a.document.documentElement;return new Kb(a.clientWidth,a.clientHeight)}function Rb(a,b,c){var d=arguments,e=document,f=d[0],g=d[1];if(!Fb&&g&&(g.name||g.type)){f=["<",f];g.name&&f.push(' name="',ra(g.name),'"');if(g.type){f.push(' type="',ra(g.type),'"');var j={};Wa(j,g);delete j.type;g=j}f.push(">");f=f.join("")}f=e.createElement(f);g&&(ga(g)?f.className=g:ea(g)?Gb.apply(k,[f].concat(g)):Ob(f,g));2=a.keyCode)a.keyCode=-1}catch(b){}};p.jd=n("L");function oc(){}var pc=0;oc.prototype.key=0;oc.prototype.Ea=l;oc.prototype.a=l;oc.prototype.handleEvent=function(a){return this.b?this.Ra.call(this.Sb||this.src,a):this.Ra.handleEvent.call(this.Ra,a)};var qc={},rc={},sc={},tc={}; +function F(a,b,c,d,e){if(b){if(ea(b)){for(var f=0;ff.keyCode||f.returnValue!=h)return j;a:{var r=l;if(0==f.keyCode)try{f.keyCode=-1;break a}catch(s){r=j}if(r||f.returnValue==h)f.returnValue=j}}r=new ic;jc(r,f,this);f=j;try{if(i){for(var q=[],v=r.c;v;v=v.parentNode)q.push(v);g=e[j];g.Q=g.n;for(var u=q.length- -1;!r.qa&&0<=u&&g.Q;u--)r.c=q[u],f&=xc(g,q[u],d,j,r);if(n){g=e[l];g.Q=g.n;for(u=0;!r.qa&&u=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom:a.x>=this.left&&a.x<=this.right&&a.y>=this.top&&a.y<=this.bottom};function Ac(a,b){var c=Lb(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,k))?c[b]||c.getPropertyValue(b)||"":""}function Bc(a,b){return a.currentStyle?a.currentStyle[b]:k}function Cc(a,b){return Ac(a,b)||Bc(a,b)||a.style&&a.style[b]}function Dc(a,b){var c,d,e=nb&&(fb||qb)&&zb("1.9");b instanceof Hb?(c=b.x,d=b.y):(c=b,d=h);a.style.left=Ec(c,e);a.style.top=Ec(d,e)} -function Fc(a){var b=a.getBoundingClientRect();F&&(a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop);return b} -function Gc(a){if(F&&!Bb(8))return a.offsetParent;for(var b=Lb(a),c=Cc(a,"position"),d="fixed"==c||"absolute"==c,a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=Cc(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return k}function Hc(a,b){var c=Ic(a),d=Ic(b);return new Hb(c.x-d.x,c.y-d.y)} -function Ic(a){var b=new Hb;if(1==a.nodeType){if(a.getBoundingClientRect){var c=Fc(a);b.x=c.left;b.y=c.top}else{c=Wb(Jb(a));var d,e=Lb(a),f=Cc(a,"position"),g=nb&&e.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==f&&(d=e.getBoxObjectFor(a))&&(0>d.screenX||0>d.screenY),i=new Hb(0,0),n;d=e?Lb(e):document;if(n=F)if(n=!Bb(9))Jb(d),n=l;n=n?d.body:d.documentElement;if(a!=n)if(a.getBoundingClientRect)d=Fc(a),e=Wb(Jb(e)),i.x=d.left+e.x,i.y=d.top+e.y;else if(e.getBoxObjectFor&&!g)d=e.getBoxObjectFor(a), -e=e.getBoxObjectFor(n),i.x=d.screenX-e.screenX,i.y=d.screenY-e.screenY;else{g=a;do{i.x+=g.offsetLeft;i.y+=g.offsetTop;g!=a&&(i.x+=g.clientLeft||0,i.y+=g.clientTop||0);if(G&&"fixed"==Cc(g,"position")){i.x+=e.body.scrollLeft;i.y+=e.body.scrollTop;break}g=g.offsetParent}while(g&&g!=a);if(mb||G&&"absolute"==f)i.y-=e.body.offsetTop;for(g=a;(g=Gc(g))&&g!=e.body&&g!=n;)if(i.x-=g.scrollLeft,!mb||"TR"!=g.tagName)i.y-=g.scrollTop}b.x=i.x-c.x;b.y=i.y-c.y}if(nb&&!zb(12)){var r;F?r="-ms-transform":G?r="-webkit-transform": -mb?r="-o-transform":nb&&(r="-moz-transform");var s;r&&(s=Cc(a,r));s||(s=Cc(a,"transform"));s?(a=s.match(Jc),a=!a?new Hb(0,0):new Hb(parseFloat(a[1]),parseFloat(a[2]))):a=new Hb(0,0);b=new Hb(b.x+a.x,b.y+a.y)}}else r=ha(a.cd),s=a,a.targetTouches?s=a.targetTouches[0]:r&&a.K.targetTouches&&(s=a.K.targetTouches[0]),b.x=s.clientX,b.y=s.clientY;return b}function Ec(a,b){"number"==typeof a&&(a=(b?Math.round(a):a)+"px");return a} -function Kc(a){var b=a.offsetWidth,c=a.offsetHeight,d=G&&!b&&!c;return(!x(b)||d)&&a.getBoundingClientRect?(a=Fc(a),new Ib(a.right-a.left,a.bottom-a.top)):new Ib(b,c)}function Lc(a,b){a.style.display=b?"":"none"} -function Mc(a,b){Jb(Lb(a));if(F&&!zb("8")){var c=a.style,d;if(F){d=Nc(a,Bc(a,"paddingLeft"));var e=Nc(a,Bc(a,"paddingRight")),f=Nc(a,Bc(a,"paddingTop")),g=Nc(a,Bc(a,"paddingBottom"));d=new zc(f,e,g,d)}else d=Ac(a,"paddingLeft"),e=Ac(a,"paddingRight"),f=Ac(a,"paddingTop"),g=Ac(a,"paddingBottom"),d=new zc(parseFloat(f),parseFloat(e),parseFloat(g),parseFloat(d));if(F)var e=Oc(a,"borderLeft"),f=Oc(a,"borderRight"),g=Oc(a,"borderTop"),i=Oc(a,"borderBottom"),e=new zc(g,f,i,e);else e=Ac(a,"borderLeftWidth"), -f=Ac(a,"borderRightWidth"),g=Ac(a,"borderTopWidth"),i=Ac(a,"borderBottomWidth"),e=new zc(parseFloat(g),parseFloat(f),parseFloat(i),parseFloat(e));c.pixelWidth=b.width-e.left-d.left-d.right-e.right;c.pixelHeight=b.height-e.top-d.top-d.bottom-e.bottom}else c=a.style,nb?c.MozBoxSizing="border-box":G?c.WebkitBoxSizing="border-box":c.boxSizing="border-box",c.width=Math.max(b.width,0)+"px",c.height=Math.max(b.height,0)+"px"} -function Nc(a,b){if(/^\d+px?$/.test(b))return parseInt(b,10);var c=a.style.left,d=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;a.style.left=b;var e=a.style.pixelLeft;a.style.left=c;a.runtimeStyle.left=d;return e}var Pc={thin:2,medium:4,thick:6};function Oc(a,b){if("none"==Bc(a,b+"Style"))return 0;var c=Bc(a,b+"Width");return c in Pc?Pc[c]:Nc(a,c)}var Jc=/matrix\([0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, ([0-9\.\-]+)p?x?, ([0-9\.\-]+)p?x?\)/;function Qc(a,b){this.x=a;this.y=b}B(Qc,Hb);Qc.prototype.S=function(){return new Qc(this.x,this.y)};Qc.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};Qc.prototype.rotate=function(a){var b=Math.cos(a),a=Math.sin(a),c=this.y*b+this.x*a;this.x=this.x*b-this.y*a;this.y=c;return this};function L(a,b){Qc.call(this,a,b)}B(L,Qc);function Rc(a,b){var c=Gb(a+180,360)-180,d=Math.abs(Math.round(3600*c));return Math.floor(d/3600)+"\u00b0 "+Math.floor(d/60%60)+"\u2032 "+Math.floor(d%60)+"\u2033 "+b.charAt(0>c?1:0)};var Sc=RegExp("^(?:([^:/?#.]+):)?(?://(?:([^/?#]*)@)?([\\w\\d\\-\\u0100-\\uffff.%]*)(?::([0-9]+))?)?([^?#]+)?(?:\\?([^#]*))?(?:#(.*))?$");function Tc(a,b,c){if(ea(b))for(var d=0;db)throw Error("Bad port number "+b);a.rb=b}else a.rb=k} -function Yc(a,b,c){Wc(a);if(b instanceof Zc){a.a=b;b=a.a;if((a=a.la)&&!b.b){ed(b);b.a=k;var d=b.D,c=function(a,b){var c=b.toLowerCase();b!=c&&(this.remove(b),fd(this,c,a))};if("function"==typeof d.forEach)d.forEach(c,b);else if(fa(d)||ga(d))C(d,c,b);else{var e;if("function"==typeof d.W)e=d.W();else if("function"!=typeof d.N)if(fa(d)||ga(d)){e=[];for(var f=d.length,g=0;g>4&15).toString(16)+(a&15).toString(16)}var ad=/[#\/\?@]/g,cd=/[\#\?:]/g,bd=/[\#\?]/g,gd=/[\#\?@]/g,dd=/#/g;function Zc(a,b,c){this.a=a||k;this.b=!!c} -function ed(a){if(!a.D&&(a.D=new Xa,a.n=0,a.a))for(var b=a.a.split("&"),c=0;c=a||96<=a&&106>=a||65<=a&&90>=a||G&&0==a)return j;switch(a){case 32:case 63:case 107:case 109:case 110:case 111:case 186:case 59:case 189:case 187:case 61:case 188:case 190:case 191:case 192:case 222:case 219:case 220:case 221:return j;default:return l}} -function Cd(a){switch(a){case 61:return 187;case 59:return 186;case 224:return 91;case 0:return 224;default:return a}};function Dd(a,b){$b.call(this);a&&(this.hb&&Ed(this),this.Da=a,this.gb=H(this.Da,"keypress",this,b),this.Pb=H(this.Da,"keydown",this.a,b,this),this.hb=H(this.Da,"keyup",this.b,b,this))}B(Dd,md);p=Dd.prototype;p.Da=k;p.gb=k;p.Pb=k;p.hb=k;p.ga=-1;p.fa=-1;p.Bb=l; -var Fd={3:13,12:144,63232:38,63233:40,63234:37,63235:39,63236:112,63237:113,63238:114,63239:115,63240:116,63241:117,63242:118,63243:119,63244:120,63245:121,63246:122,63247:123,63248:44,63272:46,63273:36,63275:35,63276:33,63277:34,63289:144,63302:45},Gd={Up:38,Down:40,Left:37,Right:39,Enter:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,"U+007F":46,Home:36,End:35,PageUp:33,PageDown:34,Insert:45},Hd=F||G&&zb("525"),Id=fb&&nb; -Dd.prototype.a=function(a){if(G&&(17==this.ga&&!a.ab||18==this.ga&&!a.ca))this.fa=this.ga=-1;Hd&&!Ad(a.va,this.ga,a.ma,a.ab,a.ca)?this.handleEvent(a):(this.fa=nb?Cd(a.va):a.va,Id&&(this.Bb=a.ca))};Dd.prototype.b=function(a){this.fa=this.ga=-1;this.Bb=a.ca}; -Dd.prototype.handleEvent=function(a){var b=a.K,c,d,e=b.altKey;F&&"keypress"==a.type?(c=this.fa,d=13!=c&&27!=c?b.keyCode:0):G&&"keypress"==a.type?(c=this.fa,d=0<=b.charCode&&63232>b.charCode&&Bd(c)?b.charCode:0):mb?(c=this.fa,d=Bd(c)?b.keyCode:0):(c=b.keyCode||this.fa,d=b.charCode||0,Id&&(e=this.Bb),fb&&(63==d&&224==c)&&(c=191));var f=c,g=b.keyIdentifier;c?63232<=c&&c in Fd?f=Fd[c]:25==c&&a.ma&&(f=9):g&&g in Gd&&(f=Gd[g]);a=f==this.ga;this.ga=f;b=new Jd(f,d,a,b);b.ca=e;K(this,b)}; -function Ed(a){a.gb&&(I(a.gb),I(a.Pb),I(a.hb),a.gb=k,a.Pb=k,a.hb=k);a.Da=k;a.ga=-1;a.fa=-1}Dd.prototype.r=function(){Dd.v.r.call(this);Ed(this)};function Jd(a,b,c,d){d&&jc(this,d,h);this.type="key";this.va=a;this.$a=b;this.b=c}B(Jd,ic);function Kd(a){$b.call(this);this.a=a;a=ia(this.a)&&1==this.a.nodeType?this.a:this.a?this.a.body:k;this.e=!!a&&"rtl"==Cc(a,"direction");this.b=H(this.a,nb?"DOMMouseScroll":"mousewheel",this)}B(Kd,md); -Kd.prototype.handleEvent=function(a){var b=0,c=0,d=0,a=a.K;if("mousewheel"==a.type){c=1;if(F||G&&(gb||zb("532.0")))c=40;d=Ld(-a.wheelDelta,c);x(a.wheelDeltaX)?(b=Ld(-a.wheelDeltaX,c),c=Ld(-a.wheelDeltaY,c)):c=d}else d=a.detail,100d&&(d=-3),x(a.axis)&&a.axis===a.HORIZONTAL_AXIS?b=d:c=d;"number"==typeof this.c&&(b=Fb(b,-this.c,this.c));"number"==typeof this.d&&(c=Fb(c,-this.d,this.d));this.e&&(b=-b);b=new Md(d,a,b,c);K(this,b)};function Ld(a,b){return G&&(fb||hb)&&0!=a%b?a:a/b} -Kd.prototype.r=function(){Kd.v.r.call(this);I(this.b);delete this.b};function Md(a,b,c,d){b&&jc(this,b,h);this.type="mousewheel";this.e=a;this.d=c;this.b=d}B(Md,ic);var Nd=document&&"ontouchstart"in document.documentElement||!!window.navigator.msPointerEnabled;function M(a){$b.call(this);this.o={};x(a)&&this.nb(a)}B(M,md);var Od={},Pd={},Qd={};function Rd(a){return a.substr(0,1).toUpperCase()+a.substr(1)}function Sd(a){return a.ol_accessors_||(a.ol_accessors_={})}function Td(a){return Od.hasOwnProperty(a)?Od[a]:Od[a]=a.toLowerCase()+"_changed"}function Ud(a){return a.ol_bindings_||(a.ol_bindings_={})}p=M.prototype; -p.Uc=function(a,b,c,d){c=c||a;this.Wb(a);var e=Td(c);Ud(this)[a]=H(b,e,function(){Vd(this,a)},h,this);Sd(this)[a]={target:b,key:c};d||Vd(this,a)};p.Xc=ba;p.s=function(a){var b,c=Sd(this);c.hasOwnProperty(a)?(b=c[a],a=b.target,b=b.key,c=Pd.hasOwnProperty(b)?Pd[b]:Pd[b]="get"+Rd(b),b=a[c]?a[c]():a.s(b)):this.o.hasOwnProperty(a)&&(b=this.o[a]);return b}; -p.W=function(){for(var a=Sa(Sd(this)).concat(Sa(this.o)),b={},c=0,d=0;d=b.i&&a.j<=b.k&&a.k>=b.j}$d.prototype.toString=function(){return"("+[this.i,this.j,this.l,this.k].join(", ")+")"};function be(a,b,c,d){$d.call(this,a,b,c,d)}B(be,$d);function ce(a){var b=arguments[0],b=new be(b.x,b.y,b.x,b.y),c;for(c=1;c>=1;return b.join("")}re.prototype.toString=function(){return[this.m,this.x,this.y].join("/")};function te(a,b,c,d){this.i=a;this.j=b;this.l=c;this.k=d}B(te,$d);te.prototype.contains=function(a){return this.i<=a.x&&a.x<=this.l&&this.j<=a.y&&a.y<=this.k};te.prototype.aa=function(){return this.k-this.j+1};te.prototype.ea=function(){return this.l-this.i+1};function ue(a,b){this.b=a;this.a=b||k};function ve(a){$b.call(this);this.e=0;this.V=a;this.a=0}B(ve,md);ve.prototype.b=function(){return y(this).toString()};function we(a){this.d=a;this.f=8;this.c=0;this.a=[];this.b={}}function xe(a,b,c,d){if(0==b.a){var e=b.b();if(!(e in a.b)){var f=a.d(b,c,d);Infinity!=f&&(a.a.push([f,b,c,d]),a.b[e]=j,ye(a,0,a.a.length-1),b.e++)}}}we.prototype.e=function(){--this.c};function ze(a,b){for(var c=a.a,d=c.length,e=c[b],f=b;b>1;){var g=2*b+1,i=2*b+2,g=ib;){var e=c-1>>1;if(a[e][0]>d[0])a[c]=a[e],c=e;else break}a[c]=d};/* +function uc(a,b){if(!qc[a])return i;var c=qc[a],d=c.type,e=rc;if(!(d in e))return i;var e=e[d],f,g;if(!$b){var j;if(!(j=b))a:{j=["window","event"];for(var m=w;f=j.shift();)if(m[f]!=k)m=m[f];else{j=k;break a}j=m}f=j;j=i in e;m=l in e;if(j){if(0>f.keyCode||f.returnValue!=h)return i;a:{var r=l;if(0==f.keyCode)try{f.keyCode=-1;break a}catch(s){r=i}if(r||f.returnValue==h)f.returnValue=i}}r=new kc;lc(r,f,this);f=i;try{if(j){for(var q=[],v=r.c;v;v=v.parentNode)q.push(v);g=e[i];g.R=g.o;for(var u=q.length- +1;!r.sa&&0<=u&&g.R;u--)r.c=q[u],f&=yc(g,q[u],d,i,r);if(m){g=e[l];g.R=g.o;for(u=0;!r.sa&&u=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom:a.x>=this.left&&a.x<=this.right&&a.y>=this.top&&a.y<=this.bottom};function Bc(a,b){var c=Nb(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,k))?c[b]||c.getPropertyValue(b)||"":""}function Cc(a,b){return a.currentStyle?a.currentStyle[b]:k}function Dc(a,b){return Bc(a,b)||Cc(a,b)||a.style&&a.style[b]}function Ec(a,b){var c,d,e=ob&&(gb||sb)&&Bb("1.9");b instanceof Jb?(c=b.x,d=b.y):(c=b,d=h);a.style.left=Fc(c,e);a.style.top=Fc(d,e)} +function Gc(a){var b=a.getBoundingClientRect();E&&(a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop);return b} +function Hc(a){if(E&&!Db(8))return a.offsetParent;for(var b=Nb(a),c=Dc(a,"position"),d="fixed"==c||"absolute"==c,a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=Dc(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return k}function Ic(a,b){var c=Jc(a),d=Jc(b);return new Jb(c.x-d.x,c.y-d.y)} +function Jc(a){var b=new Jb;if(1==a.nodeType){if(a.getBoundingClientRect){var c=Gc(a);b.x=c.left;b.y=c.top}else{c=Yb(Lb(a));var d,e=Nb(a),f=Dc(a,"position"),g=ob&&e.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==f&&(d=e.getBoxObjectFor(a))&&(0>d.screenX||0>d.screenY),j=new Jb(0,0),m;d=e?Nb(e):document;if(m=E)if(m=!Db(9))Lb(d),m=l;m=m?d.body:d.documentElement;if(a!=m)if(a.getBoundingClientRect)d=Gc(a),e=Yb(Lb(e)),j.x=d.left+e.x,j.y=d.top+e.y;else if(e.getBoxObjectFor&&!g)d=e.getBoxObjectFor(a), +e=e.getBoxObjectFor(m),j.x=d.screenX-e.screenX,j.y=d.screenY-e.screenY;else{g=a;do{j.x+=g.offsetLeft;j.y+=g.offsetTop;g!=a&&(j.x+=g.clientLeft||0,j.y+=g.clientTop||0);if(pb&&"fixed"==Dc(g,"position")){j.x+=e.body.scrollLeft;j.y+=e.body.scrollTop;break}g=g.offsetParent}while(g&&g!=a);if(nb||pb&&"absolute"==f)j.y-=e.body.offsetTop;for(g=a;(g=Hc(g))&&g!=e.body&&g!=m;)if(j.x-=g.scrollLeft,!nb||"TR"!=g.tagName)j.y-=g.scrollTop}b.x=j.x-c.x;b.y=j.y-c.y}if(ob&&!Bb(12)){var r;E?r="-ms-transform":pb?r="-webkit-transform": +nb?r="-o-transform":ob&&(r="-moz-transform");var s;r&&(s=Dc(a,r));s||(s=Dc(a,"transform"));s?(a=s.match(Kc),a=!a?new Jb(0,0):new Jb(parseFloat(a[1]),parseFloat(a[2]))):a=new Jb(0,0);b=new Jb(b.x+a.x,b.y+a.y)}}else r=ha(a.jd),s=a,a.targetTouches?s=a.targetTouches[0]:r&&a.L.targetTouches&&(s=a.L.targetTouches[0]),b.x=s.clientX,b.y=s.clientY;return b}function Fc(a,b){"number"==typeof a&&(a=(b?Math.round(a):a)+"px");return a} +function Lc(a){var b=a.offsetWidth,c=a.offsetHeight,d=pb&&!b&&!c;return(!y(b)||d)&&a.getBoundingClientRect?(a=Gc(a),new Kb(a.right-a.left,a.bottom-a.top)):new Kb(b,c)}function Mc(a,b){a.style.display=b?"":"none"} +function Nc(a,b){Lb(Nb(a));if(E&&!Bb("8")){var c=a.style,d;if(E){d=Oc(a,Cc(a,"paddingLeft"));var e=Oc(a,Cc(a,"paddingRight")),f=Oc(a,Cc(a,"paddingTop")),g=Oc(a,Cc(a,"paddingBottom"));d=new Ac(f,e,g,d)}else d=Bc(a,"paddingLeft"),e=Bc(a,"paddingRight"),f=Bc(a,"paddingTop"),g=Bc(a,"paddingBottom"),d=new Ac(parseFloat(f),parseFloat(e),parseFloat(g),parseFloat(d));if(E)var e=Pc(a,"borderLeft"),f=Pc(a,"borderRight"),g=Pc(a,"borderTop"),j=Pc(a,"borderBottom"),e=new Ac(g,f,j,e);else e=Bc(a,"borderLeftWidth"), +f=Bc(a,"borderRightWidth"),g=Bc(a,"borderTopWidth"),j=Bc(a,"borderBottomWidth"),e=new Ac(parseFloat(g),parseFloat(f),parseFloat(j),parseFloat(e));c.pixelWidth=b.width-e.left-d.left-d.right-e.right;c.pixelHeight=b.height-e.top-d.top-d.bottom-e.bottom}else c=a.style,ob?c.MozBoxSizing="border-box":pb?c.WebkitBoxSizing="border-box":c.boxSizing="border-box",c.width=Math.max(b.width,0)+"px",c.height=Math.max(b.height,0)+"px"} +function Oc(a,b){if(/^\d+px?$/.test(b))return parseInt(b,10);var c=a.style.left,d=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;a.style.left=b;var e=a.style.pixelLeft;a.style.left=c;a.runtimeStyle.left=d;return e}var Qc={thin:2,medium:4,thick:6};function Pc(a,b){if("none"==Cc(a,b+"Style"))return 0;var c=Cc(a,b+"Width");return c in Qc?Qc[c]:Oc(a,c)}var Kc=/matrix\([0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, ([0-9\.\-]+)p?x?, ([0-9\.\-]+)p?x?\)/;function Rc(a,b){this.x=a;this.y=b}B(Rc,Jb);Rc.prototype.T=function(){return new Rc(this.x,this.y)};Rc.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};Rc.prototype.rotate=function(a){var b=Math.cos(a),a=Math.sin(a),c=this.y*b+this.x*a;this.x=this.x*b-this.y*a;this.y=c;return this};function K(a,b){Rc.call(this,a,b)}B(K,Rc);function Sc(a,b){var c=Ib(a+180,360)-180,d=Math.abs(Math.round(3600*c));return Math.floor(d/3600)+"\u00b0 "+Math.floor(d/60%60)+"\u2032 "+Math.floor(d%60)+"\u2033 "+b.charAt(0>c?1:0)};var Tc=RegExp("^(?:([^:/?#.]+):)?(?://(?:([^/?#]*)@)?([\\w\\d\\-\\u0100-\\uffff.%]*)(?::([0-9]+))?)?([^?#]+)?(?:\\?([^#]*))?(?:#(.*))?$");function Uc(a,b,c){if(ea(b))for(var d=0;db)throw Error("Bad port number "+b);a.wb=b}else a.wb=k} +function Zc(a,b,c){Xc(a);if(b instanceof $c){a.a=b;b=a.a;if((a=a.pa)&&!b.b){fd(b);b.a=k;var d=b.F,c=function(a,b){var c=b.toLowerCase();b!=c&&(this.remove(b),gd(this,c,a))};if("function"==typeof d.forEach)d.forEach(c,b);else if(fa(d)||ga(d))D(d,c,b);else{var e;if("function"==typeof d.Z)e=d.Z();else if("function"!=typeof d.O)if(fa(d)||ga(d)){e=[];for(var f=d.length,g=0;g>4&15).toString(16)+(a&15).toString(16)}var bd=/[#\/\?@]/g,dd=/[\#\?:]/g,cd=/[\#\?]/g,hd=/[\#\?@]/g,ed=/#/g;function $c(a,b,c){this.a=a||k;this.b=!!c} +function fd(a){if(!a.F&&(a.F=new Ya,a.o=0,a.a))for(var b=a.a.split("&"),c=0;c=a||96<=a&&106>=a||65<=a&&90>=a||pb&&0==a)return i;switch(a){case 32:case 63:case 107:case 109:case 110:case 111:case 186:case 59:case 189:case 187:case 61:case 188:case 190:case 191:case 192:case 222:case 219:case 220:case 221:return i;default:return l}} +function Dd(a){switch(a){case 61:return 187;case 59:return 186;case 224:return 91;case 0:return 224;default:return a}};function Ed(a,b){bc.call(this);a&&(this.mb&&Fd(this),this.Ka=a,this.lb=F(this.Ka,"keypress",this,b),this.Tb=F(this.Ka,"keydown",this.a,b,this),this.mb=F(this.Ka,"keyup",this.b,b,this))}B(Ed,nd);p=Ed.prototype;p.Ka=k;p.lb=k;p.Tb=k;p.mb=k;p.ja=-1;p.ia=-1;p.Fb=l; +var Gd={3:13,12:144,63232:38,63233:40,63234:37,63235:39,63236:112,63237:113,63238:114,63239:115,63240:116,63241:117,63242:118,63243:119,63244:120,63245:121,63246:122,63247:123,63248:44,63272:46,63273:36,63275:35,63276:33,63277:34,63289:144,63302:45},Hd={Up:38,Down:40,Left:37,Right:39,Enter:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,"U+007F":46,Home:36,End:35,PageUp:33,PageDown:34,Insert:45},Id=E||pb&&Bb("525"),Jd=gb&&ob; +Ed.prototype.a=function(a){if(pb&&(17==this.ja&&!a.gb||18==this.ja&&!a.ea))this.ia=this.ja=-1;Id&&!Bd(a.za,this.ja,a.qa,a.gb,a.ea)?this.handleEvent(a):(this.ia=ob?Dd(a.za):a.za,Jd&&(this.Fb=a.ea))};Ed.prototype.b=function(a){this.ia=this.ja=-1;this.Fb=a.ea}; +Ed.prototype.handleEvent=function(a){var b=a.L,c,d,e=b.altKey;E&&"keypress"==a.type?(c=this.ia,d=13!=c&&27!=c?b.keyCode:0):pb&&"keypress"==a.type?(c=this.ia,d=0<=b.charCode&&63232>b.charCode&&Cd(c)?b.charCode:0):nb?(c=this.ia,d=Cd(c)?b.keyCode:0):(c=b.keyCode||this.ia,d=b.charCode||0,Jd&&(e=this.Fb),gb&&(63==d&&224==c)&&(c=191));var f=c,g=b.keyIdentifier;c?63232<=c&&c in Gd?f=Gd[c]:25==c&&a.qa&&(f=9):g&&g in Hd&&(f=Hd[g]);a=f==this.ja;this.ja=f;b=new Kd(f,d,a,b);b.ea=e;J(this,b)}; +function Fd(a){a.lb&&(H(a.lb),H(a.Tb),H(a.mb),a.lb=k,a.Tb=k,a.mb=k);a.Ka=k;a.ja=-1;a.ia=-1}Ed.prototype.s=function(){Ed.w.s.call(this);Fd(this)};function Kd(a,b,c,d){d&&lc(this,d,h);this.type="key";this.za=a;this.fb=b;this.b=c}B(Kd,kc);function Ld(a){bc.call(this);this.a=a;a=ia(this.a)&&1==this.a.nodeType?this.a:this.a?this.a.body:k;this.e=!!a&&"rtl"==Dc(a,"direction");this.b=F(this.a,ob?"DOMMouseScroll":"mousewheel",this)}B(Ld,nd); +Ld.prototype.handleEvent=function(a){var b=0,c=0,d=0,a=a.L;if("mousewheel"==a.type){c=1;if(E||pb&&(hb||Bb("532.0")))c=40;d=Md(-a.wheelDelta,c);y(a.wheelDeltaX)?(b=Md(-a.wheelDeltaX,c),c=Md(-a.wheelDeltaY,c)):c=d}else d=a.detail,100d&&(d=-3),y(a.axis)&&a.axis===a.HORIZONTAL_AXIS?b=d:c=d;"number"==typeof this.c&&(b=Hb(b,-this.c,this.c));"number"==typeof this.d&&(c=Hb(c,-this.d,this.d));this.e&&(b=-b);b=new Nd(d,a,b,c);J(this,b)};function Md(a,b){return pb&&(gb||ib)&&0!=a%b?a:a/b} +Ld.prototype.s=function(){Ld.w.s.call(this);H(this.b);delete this.b};function Nd(a,b,c,d){b&&lc(this,b,h);this.type="mousewheel";this.e=a;this.d=c;this.b=d}B(Nd,kc);var Od=document&&"ontouchstart"in document.documentElement||!!window.navigator.msPointerEnabled;function M(a){bc.call(this);this.t={};y(a)&&this.sb(a)}B(M,nd);var Pd={},Qd={},Rd={};function Sd(a){return a.substr(0,1).toUpperCase()+a.substr(1)}function Td(a){return a.ol_accessors_||(a.ol_accessors_={})}function Ud(a){return Pd.hasOwnProperty(a)?Pd[a]:Pd[a]=a.toLowerCase()+"_changed"}function Vd(a){return a.ol_bindings_||(a.ol_bindings_={})}p=M.prototype; +p.Yc=function(a,b,c,d){c=c||a;this.$b(a);var e=Ud(c);Vd(this)[a]=F(b,e,function(){Wd(this,a)},h,this);Td(this)[a]={target:b,key:c};d||Wd(this,a)};p.ad=ba;p.q=function(a){var b,c=Td(this);c.hasOwnProperty(a)?(b=c[a],a=b.target,b=b.key,c=Qd.hasOwnProperty(b)?Qd[b]:Qd[b]="get"+Sd(b),b=a[c]?a[c]():a.q(b)):this.t.hasOwnProperty(a)&&(b=this.t[a]);return b}; +p.Z=function(){for(var a=Oa(Td(this)).concat(Oa(this.t)),b={},c=0,d=0;d=b.i&&a.j<=b.k&&a.k>=b.j}ae.prototype.toString=function(){return"("+[this.i,this.j,this.l,this.k].join(", ")+")"};function ce(a,b,c,d){ae.call(this,a,b,c,d)}B(ce,ae);function de(a){var b=arguments[0],b=new ce(b.x,b.y,b.x,b.y),c;for(c=1;c>=1;return b.join("")}se.prototype.toString=function(){return[this.n,this.x,this.y].join("/")};function ue(a,b,c,d){this.i=a;this.j=b;this.l=c;this.k=d}B(ue,ae);ue.prototype.contains=function(a){return this.i<=a.x&&a.x<=this.l&&this.j<=a.y&&a.y<=this.k};ue.prototype.ca=function(){return this.k-this.j+1};ue.prototype.ha=function(){return this.l-this.i+1};function ve(a,b){this.b=a;this.a=b||k};function we(a,b){bc.call(this);this.X=a;this.a=b}B(we,nd);we.prototype.b=function(){return z(this).toString()};function xe(a){this.d=a;this.f=8;this.c=0;this.a=[];this.b={}}function ye(a,b,c,d){if(0==b.a){var e=b.b();if(!(e in a.b)){var f=a.d(b,c,d);Infinity!=f&&(a.a.push([f,b,c,d]),a.b[e]=i,ze(a,0,a.a.length-1))}}}xe.prototype.e=function(){--this.c};function Ae(a,b){for(var c=a.a,d=c.length,e=c[b],f=b;b>1;){var g=2*b+1,j=2*b+2,g=jb;){var e=c-1>>1;if(a[e][0]>d[0])a[c]=a[e],c=e;else break}a[c]=d};/* Latitude/longitude spherical geodesy formulae taken from http://www.movable-type.co.uk/scripts/latlong.html Licenced under CC-BY-3.0. */ -function Ae(a,b){var c=a.y*Math.PI/180,d=b.y*Math.PI/180,e=(d-c)/2,f=(b.x-a.x)*Math.PI/180/2,c=Math.sin(e)*Math.sin(e)+Math.sin(f)*Math.sin(f)*Math.cos(c)*Math.cos(d);return 2*Be.a*Math.atan2(Math.sqrt(c),Math.sqrt(1-c))};var Be=new function(){this.a=6370997};var Ce="object"==typeof Proj4js,De={Nc:"degrees",ye:"ft",Ce:"m"};function O(a,b,c,d){this.a=a;this.c=b;this.na=c;this.d=x(d)?d:"enu";this.f=k}O.prototype.h=m("a");O.prototype.H=m("na");O.prototype.o=m("c");O.prototype.g=m("d");function Ee(a,b){O.call(this,a,b.units,k,b.axis);this.Ac=b;this.e=k}B(Ee,O); -Ee.prototype.b=function(a,b){if("degrees"==this.c)return a;this.e===k&&(this.e=Fe(this,Ge("EPSG:4326")));var c=[b.x-a/2,b.y,b.x+a/2,b.y,b.x,b.y-a/2,b.x,b.y+a/2],c=this.e(c,c,2),c=(Ae(new L(c[0],c[1]),new L(c[2],c[3]))+Ae(new L(c[4],c[5]),new L(c[6],c[7])))/2;"ft"==this.c&&(c/=0.3048);return c};var He={},Ie={},Je={};function Ke(a){C(a,function(a){Le(a)});C(a,function(b){C(a,function(a){b!==a&&Me(b,a,Ne)})})}function Le(a){Ie[a.a]=a;Me(a,a,Ne)} -function Oe(a){return a!=k?ga(a)?Pe(a):a:Pe("EPSG:3857")}function Me(a,b,c){a=a.a;b=b.a;a in Je||(Je[a]={});Je[a][b]=c}function Pe(a){var b=Ie[a];Ce&&!x(b)&&(b=Ge(a));x(b)||(b=k);return b}function Ge(a){var b=He[a];if(!x(b)){var c=new Proj4js.Proj(a),d=c.srsCode,b=He[d];x(b)||(b=new Ee(d,c),He[d]=b);He[a]=b}return b} -function Fe(a,b){var c=a.a,d=b.a,e;c in Je&&d in Je[c]&&(e=Je[c][d]);if(Ce&&!x(e)){var f;f=(a instanceof Ee?a:Ge(a.a)).Ac;var g;g=(b instanceof Ee?b:Ge(b.a)).Ac;e=function(a,b,c){var d=a.length,c=1=Math.abs(a+c)?0:a+c}};var pf={rc:aa(),Jc:function(a){return 0.5>a?mf(2*a):1-mf(2*(a-0.5))},$c:function(a){return Math.pow(2,-10*a)*Math.sin((a-0.075)*2*Math.PI/0.3)+1},Cb:function(a){a<1/2.75?a*=7.5625*a:a<2/2.75?(a-=1.5/2.75,a=7.5625*a*a+0.75):a<2.5/2.75?(a-=2.25/2.75,a=7.5625*a*a+0.9375):(a-=2.625/2.75,a=7.5625*a*a+0.984375);return a}};var qf={Cb:function(a){var b=a.resolution,c=x(a.start)?a.start:pa(),d=x(a.duration)?a.duration:1E3,e=x(a.easing)?a.easing:pf.Jc;return function(a,g){if(g.timeb?(d="\u2032",a*=60):d="\u00b0":"imperial"==this.c?0.9144>b?(d="in",a/=0.0254):1609.344>b?(d="ft",a/=0.3048):(d="mi",a/=1609.344):"nautical"==this.c?(a/=1852,d="nm"):"metric"==this.c?1>b?(d="mm",a*=1E3):1E3>b?d="m":(d="km",a/=1E3):"us"==this.c&&(0.9144>b?(d="in",a*=39.37):1609.344>b?(d="ft",a/=0.30480061):(d="mi",a/=1609.3472));for(var b=3*Math.floor(Math.log(this.h*a)/Math.log(10)),e,f;;){e=Af[b%3]*Math.pow(10,Math.floor(b/3));f=Math.round(e/a);if(f>=this.h)break;++b}e=e+d;this.t!=e&& -(this.t=this.g.innerHTML=e);this.F!=f&&(this.g.style.width=f+"px",this.F=f);this.f||(Lc(this.o,j),this.f=j)}};zf.prototype.a=function(a){this.e!==k&&(C(this.e,I),this.e=k);zf.v.a.call(this,a);a!==k&&(this.e=[H(a,"postrender",this.w,l,this)])};function Bf(a){var a=x(a)?a:{},b=Pb("A",{href:"#zoomIn","class":"ol-zoom-in"});H(b,["touchend","click"],this.d,l,this);var c=Pb("A",{href:"#zoomOut","class":"ol-zoom-out"});H(c,["touchend","click"],this.e,l,this);b=Pb("DIV","ol-zoom ol-unselectable",b,c);wf.call(this,{element:b,map:a.map,target:a.target});this.c=x(a.delta)?a.delta:1}B(Bf,wf);Bf.prototype.d=function(a){a.C();a=this.b;sf(a);vf(a.a(),a,this.c,h,250)};Bf.prototype.e=function(a){a.C();a=this.b;sf(a);vf(a.a(),a,-this.c,h,250)};function Cf(a,b){var c=x(a)?a:{},d=[];if(x(c.attribution)?c.attribution:1)d.push(new xf(x(c.Nd)?c.Nd:h));x(c.Od)&&c.Od&&d.push(new zf(x(c.Pd)?c.Pd:h));if(x(c.zoom)?c.zoom:1)d.push(new Bf(x(c.ke)?c.ke:h));x(b)&&Ga(d,b);return d};function Df(a,b,c){this.e=a;this.d=b;this.f=c;this.a=[];this.b=this.c=0}function Ef(a){for(var b=pa(),c=a.a.length-1,d=c-1;0<=d&&a.a[d].Na>b-a.f;)d--;if(0<=d){var b=a.a[d],c=a.a[c],d=c.x-b.x,e=c.y-b.y;a.c=Math.atan2(e,d);a.b=Math.sqrt(d*d+e*e)/(c.Na-b.Na);return a.b>a.d}return l}Df.prototype.pa=function(a){var b=this.e,c=this.b,d=this.d,e=Math.log(this.d/this.b)/this.e;return qf.pa({source:a,duration:e,easing:function(a){return c*(Math.exp(b*a*e)-1)/(d-c)}})};function Ff(){};function Gf(a){this.a=a}B(Gf,Ff);Gf.prototype.oa=function(a){var b=a.a;if(a.type==Ze&&(Nd||lc(a.a))){var c=a.map,d=a.d(),e=a.a.ma?-this.a:this.a;vf(c.a(),c,e,d,250);a.C();b.C()}};function Hf(a){return a.ca&&!a.qb&&a.ma}function If(a){return!a.ca&&!a.qb&&!a.ma}function Jf(a){return!a.ca&&!a.qb&&a.ma};function Kf(){this.e=l;this.p=this.na=this.h=this.g=0;this.Ma=this.f=k}B(Kf,Ff);p=Kf.prototype;p.Ib=ba;p.cb=ba;p.eb=od;p.pc=ba;p.oa=function(a){var b=a.map;if(b.Ha()){var b=b.a(),c=a.a;a.type==bf&&this.pc(a);this.e?a.type==df?(this.d=c.clientX-this.g,this.b=c.clientY-this.h,this.Ib(a)):a.type==af&&(this.d=c.clientX-this.g,this.b=c.clientY-this.h,this.cb(a),this.e=l):a.type==cf&&(this.g=c.clientX,this.h=c.clientY,this.b=this.d=0,this.f=b.M(),this.Ma=a.d(),this.eb(a)&&(this.e=j,a.C()))}};function Lf(a,b){Kf.call(this);this.o=a;this.a=b;this.c=k}B(Lf,Kf);Lf.prototype.Ib=function(a){this.a&&this.a.a.push({x:a.a.clientX,y:a.a.clientY,Na:pa()});var a=a.map,b=a.a(),c=b.P(),d=b.X(),c=new L(-c*this.d,c*this.b);c.rotate(d);d=new L(this.f.x+c.x,this.f.y+c.y);sf(a);b.a(d)}; -Lf.prototype.cb=function(a){var b=a.map,a=b.a();kf(a,-1);if(this.a&&Ef(this.a)){var c=(this.a.d-this.a.b)/this.a.e,d=this.a.c,e=a.M();this.c=this.a.pa(e);b.c(this.c);e=Mf(b,e);b=We(b,new Ue(e.x-c*Math.cos(d),e.y-c*Math.sin(d)));a.a(b)}};Lf.prototype.eb=function(a){var b=a.a;if(this.o(b)){if(this.a){var c=this.a;c.a.length=0;c.c=0;c.b=0;this.a.a.push({x:b.clientX,y:b.clientY,Na:pa()})}a=a.map;sf(a);kf(a.a(),1);return j}return l}; -Lf.prototype.pc=function(a){var b=a.map,c=b.a();this.c!==k&&Da(b.h,this.c)&&(sf(b),c.a(a.b.u.center),this.c=k)};function Nf(a){Kf.call(this);this.c=a}B(Nf,Kf);Nf.prototype.Ib=function(a){var b=a.map,c=b.f(),a=Xe(a),c=Math.atan2(c.height/2-a.y,a.x-c.width/2);if(x(this.a)){var a=c-this.a,d=b.a();sf(b);rf(d,b,d.X()-a)}this.a=c};Nf.prototype.cb=function(a){var a=a.map,b=a.a();b.rotate(a,b.X(),h,250);kf(b,-1)};Nf.prototype.eb=function(a){var b=a.a;return lc(b)&&this.c(b)?(a=a.map,b=a.a(),sf(a),this.a=h,kf(b,1),j):l};function Of(a){var b=Pb("DIV","ol-dragbox");this.c=k;this.e=a.Ma;this.d=k;wf.call(this,{element:b,map:a.map})}B(Of,wf);Of.prototype.a=function(a){this.d!==k&&(I(this.d),this.d=k);a!==k&&(this.c=Mf(a,this.e),Dc(this.element,this.c),Mc(this.element,new Zd(0,0)),this.d=H(a,df,this.f,l,this));Of.v.a.call(this,a)};Of.prototype.f=function(a){var b=this.b,a=a.d(),b=Mf(b,a);Dc(this.element,new Ue(Math.min(b.x,this.c.x),Math.min(b.y,this.c.y)));Mc(this.element,new Zd(Math.abs(b.x-this.c.x),Math.abs(b.y-this.c.y)))};function Pf(a){Kf.call(this);this.c=a;this.a=k}B(Pf,Kf);Pf.prototype.cb=function(a){this.a.a(k);this.a=k;if(64<=this.d*this.d+this.b*this.b){var b=a.map,c=ce(this.Ma,a.d());tf(b,function(){var a=b.a(),e=b.f();a.f(c,e);a.d(0)})}};Pf.prototype.eb=function(a){var b=a.a;return lc(b)&&this.c(b)?(this.a=new Of({map:a.map,Ma:this.Ma}),j):l};function Qf(a){this.a=a}B(Qf,Ff);Qf.prototype.oa=function(a){if("key"==a.type){var b=a.a,c=b.va;if(40==c||37==c||39==c||38==c){var d=a.map.a(),e=d.P()*this.a,c=40==c?new L(0,-e):37==c?new L(-e,0):39==c?new L(e,0):new L(0,e),e=d.M();d.a(new L(e.x+c.x,e.y+c.y));b.C();a.C()}}};function Rf(){}B(Rf,Ff);Rf.prototype.oa=function(a){if("key"==a.type){var b=a.a,c=b.$a;if(43==c||45==c){var d=a.map,c=43==c?4:-4;sf(d);vf(d.a(),d,c,h,100);b.C();a.C()}}};function Sf(){this.a=0;this.c=k;this.d=this.b=h}B(Sf,Ff);Sf.prototype.oa=function(a){if("mousewheel"==a.type){var b=a.map,c=a.a;this.c=a.d();this.a+=c.b/3;x(this.b)||(this.b=pa());var d=Math.max(80-(pa()-this.b),0);w.clearTimeout(this.d);this.d=w.setTimeout(na(this.e,this,b),d);a.C();c.C()}};Sf.prototype.e=function(a){var b=Fb(this.a,-1,1),c=a.a();sf(a);vf(c,a,-b,this.c,250);this.a=0;this.c=k;this.d=this.b=h};function Tf(){this.g=l;this.h={};this.targetTouches=[]}B(Tf,Ff);function Uf(a){for(var b=a.length,c=0,d=0,e=0;ethis.o&&(this.a=j));this.c=c;var a=a.map,c=a.a(),d=Ic(a.b),e=Uf(this.targetTouches);e.x-=d.x;e.y-=d.y;d=We(a,e);this.a&&rf(c,a,c.X()+b,d)}; -Wf.prototype.d=function(a){if(2>this.targetTouches.length){var a=a.map,b=a.a();this.a&&b.rotate(a,b.X(),h,250);kf(b,-1);return l}return j};Wf.prototype.f=function(a){return 2<=this.targetTouches.length?(a=a.map.a(),this.c=h,this.a=l,this.b=0,kf(a,1),j):l};function Xf(){Tf.call(this)}B(Xf,Tf);Xf.prototype.e=function(a){var b=1,c=this.targetTouches[0],d=this.targetTouches[1],e=c.clientX-d.clientX,c=c.clientY-d.clientY,e=Math.sqrt(e*e+c*c);x(this.a)&&(b=this.a/e);this.a=e;a=a.map;e=a.a();c=Ic(a.b);d=Uf(this.targetTouches);d.x-=c.x;d.y-=c.y;c=We(a,d);uf(e,a,e.P()*b,c)};Xf.prototype.d=function(a){if(2>this.targetTouches.length){var a=a.map,b=a.a();b.zoom(a,b.P(),h,250);kf(b,-1);return l}return j}; -Xf.prototype.f=function(a){return 2<=this.targetTouches.length?(a=a.map.a(),this.a=h,kf(a,1),j):l};function Yf(a,b){var c=x(a)?a:{},d=new N;(x(c.rotate)?c.rotate:1)&&d.push(new Nf(Hf));if(x(c.Qd)?c.Qd:1)d.push(new Gf(x(c.le)?c.le:1));(x(c.Wd)?c.Wd:1)&&d.push(new Vf(new Df(-0.005,0.05,100)));(x(c.Xd)?c.Xd:1)&&d.push(new Wf);(x(c.Yd)?c.Yd:1)&&d.push(new Xf);(x(c.Rd)?c.Rd:1)&&d.push(new Lf(If,new Df(-0.005,0.05,100)));var e=x(c.Td)?c.Td:80;if(x(c.Sd)?c.Sd:1)d.push(new Qf(e)),d.push(new Rf);(x(c.Ud)?c.Ud:1)&&d.push(new Sf);(x(c.Vd)?c.Vd:1)&&d.push(new Pf(Jf));if(x(b))for(c=0;cc?a[1]="?":c==f.length-1&&(a[1]=h));return a.join("")};function Gg(a,b){return function(c,d,e){return Fg(a,b,c,d,e)}}function Hg(){};function Ig(a){Se.call(this,{attributions:a.attributions,extent:a.extent,projection:a.projection});this.Ga=x(a.Ga)?a.Ga:Hg;this.d=x(a.crossOrigin)?a.crossOrigin:"anonymous";this.a=x(a.resolutions)?a.resolutions:k}B(Ig,Se);function Jg(a,b,c,d,e){var f=k,d=a.Ga(b,d,e);x(d)&&(f=new fg(b,c,d,a.d,a.ka()));return f};function Kg(a){P.call(this,a)}B(Kg,P);function Lg(a){P.call(this,a)}B(Lg,P);function Mg(a,b){sg.call(this,a,b)}B(Mg,sg);function Ng(a,b){sg.call(this,a,b);this.b=k;this.c=ge()}B(Ng,Mg);Ng.prototype.I=function(){return this.b===k?k:gg(this.b,this)};Ng.prototype.xa=m("c"); -Ng.prototype.ha=function(a){var b=a.u,c=b.center,d=b.resolution,e=b.rotation,f=this.a.Y(),g=a.B;!g[0]&&!g[1]&&(b=f.I(a.extent,d,b.projection),b!==k&&(f=b.a,0==f?(tc(b,"change",this.Jb,l,this),hg(b)):2==f&&(this.b=b)));if(this.b!==k){var b=this.b,f=b.H(),g=b.e,i=this.c;ke(i);oe(i,a.size.width/2,a.size.height/2);qe(i,e);pe(i,g/d,g/d);oe(i,(f.i-c.x)/g,(c.y-f.k)/g);wg(a.attributions,b.ka())}};function Og(a,b){sg.call(this,a,b);this.e=this.c=this.d=k;this.f=ge();this.b=k}B(Og,Mg);Og.prototype.I=m("d");Og.prototype.xa=m("f"); -Og.prototype.ha=function(a){var b=a.u,c=b.projection,d=this.a.Y(),e=y(d).toString(),f=d.tileGrid;f===k&&(f=pg(c));var g=nf(f.a,b.resolution),i=og(f,g),n=f.a[g],r=kg(f,a.extent,n),s=r.ea(),q=r.aa(),i=new Zd(i.width*s,i.height*q),v,u;this.d===k?(v=Rb("CANVAS"),v.width=i.width,v.height=i.height,u=v.getContext("2d"),this.d=v,this.c=i,this.e=u,this.b=Array(s*q)):(v=this.d,u=this.e,this.c.width==i.width&&this.c.height==i.height||(v.width=i.width,v.height=i.height,this.c=i,this.b=Array(s*q)));q={};q[g]= -{};var i=na(d.d,d,q,zg(function(a){return a!==k&&2==a.a},d,f,c)),t,z,E,D;for(E=r.i;E<=r.l;++E)for(D=r.j;D<=r.k;++D)if(z=new re(g,E,D),t=d.b(z,f,c),t!==k){v=t.a;if(0==v)ug(this,t),yg(a.Qa,d,z),v=ng(f,z),xe(a.Vb,t,e,v);else if(2==v){q[g][z.toString()]=t;continue}else if(3==v)continue;f.b(z,i)}e=Aa(Sa(q),Number);Ja(e);v=d.G;var c=de(jg(f,new re(g,r.i,r.k))),U,R,J,Z,V,sa;for(U=0;Uc;++c)d[c]=b[c].toFixed(6);c=d.join(",")}else c=b.join(",");c="matrix3d("+c+")";d=a.style;d.WebkitTransform=c;d.MozTransform=c;d.a=c;d.transform=c};function Sg(a,b,c){sg.call(this,a,b);this.target=c}B(Sg,sg);Sg.prototype.r=function(){Vb(this.target);Sg.v.r.call(this)};function Tg(a,b){var c=Rb("DIV");c.className="ol-layer-image";c.style.position="absolute";Sg.call(this,a,b,c);this.b=k;this.c=ie()}B(Tg,Sg); -Tg.prototype.ha=function(a){var b=a.u,c=b.center,d=b.resolution,e=b.rotation,f=this.b,g=this.a.Y(),i=a.B;!i[0]&&!i[1]&&(b=g.I(a.extent,d,b.projection),b!==k&&(g=b.a,0==g?(tc(b,"change",this.Jb,l,this),hg(b)):2==g&&(f=b)));f!==k&&(g=f.H(),i=f.e,b=ge(),ke(b),oe(b,a.size.width/2,a.size.height/2),qe(b,e),pe(b,i/d,i/d),oe(b,(g.i-c.x)/i,(c.y-g.k)/i),f!=this.b&&(c=gg(f,this),c.style.position="absolute",Tb(this.target),this.target.appendChild(c),this.b=f),me(b,this.c)||(Rg(this.target,b),je(this.c,b)),wg(a.attributions, -f.ka()))};function Ug(a,b){var c=Rb("DIV");c.className="ol-layer-tile";c.style.position="absolute";Sg.call(this,a,b,c);this.c=j;this.d=1;this.b={}}B(Ug,Sg); -Ug.prototype.ha=function(a,b){if(b.visible){var c=a.u,d=c.projection,e=this.a.Y(),f=y(e).toString(),g=e.tileGrid;g===k&&(g=pg(d));var i=nf(g.a,c.resolution),n=kg(g,a.extent,g.a[i]),r={};r[i]={};var s=na(e.d,e,r,zg(function(a){return a!==k&&2==a.a},e,g,d)),q,v,u,t,z;for(t=n.i;t<=n.l;++t)for(z=n.j;z<=n.k;++z)if(u=new re(i,t,z),q=e.b(u,g,d),q!==k){v=q.a;if(0==v)ug(this,q),yg(a.Qa,e,u),v=ng(g,u),xe(a.Vb,q,f,v);else if(2==v){r[i][u.toString()]=q;continue}else if(3==v)continue;g.b(u,s)}s=Aa(Sa(r),Number); -Ja(s);var d={},E;for(q=0;qu&&Ub(this.target,f.target)}else{if(!a.B[0]&&!a.B[1]){v=kg(f.d,a.extent,f.d.a[f.c.m]);u=[];z=t=h;for(z in f.b)t=f.b[z],v.contains(t.V)||u.push(t); -v=h;for(v=0;v=a.$()){for(var a=this.a,d=0;d>1,a[d].L>c.L)a[b]=a[d],b=d;else break;a[b]=c}p=dh.prototype; -p.remove=function(){var a=this.a,b=a.length,c=a[0];if(!(0>=b)){if(1==b)Ca(a);else{a[0]=a.pop();for(var a=0,b=this.a,d=b.length,e=b[a];a>1;){var f=2*a+1,g=2*a+2,f=ge.L)break;b[a]=b[f];a=f}b[a]=e}return c.Z}};p.N=function(){for(var a=this.a,b=[],c=a.length,d=0;dc;++c)d=b.remove(),lh(a,d)},b,u));R?(this.b=q,this.w=v):(this.w=this.b=k,a.R=j)}xg(a.Pa,g,r,q);rg(g,r,a.extent,n);vg(a,g);ke(this.d); -oe(this.d,(d.center.x-v.i)/(v.l-v.i),(d.center.y-v.j)/(v.k-v.j));qe(this.d,d.rotation);pe(this.d,a.size.width*d.resolution/(v.l-v.i),a.size.height*d.resolution/(v.k-v.j));oe(this.d,-0.5,-0.5)};function mh(){this.n=0;this.c={};this.b=this.a=k}p=mh.prototype;p.clear=function(){this.n=0;this.c={};this.b=this.a=k};function kh(a,b){return a.c.hasOwnProperty(b)}p.forEach=function(a,b){for(var c=this.a;c!==k;)a.call(b,c.Z,c.L,this),c=c.U};function nh(a,b){var c=a.c[b];if(c===a.b)return c.Z;c===a.a?(a.a=a.a.U,a.a.ia=k):(c.U.ia=c.ia,c.ia.U=c.U);c.U=k;c.ia=a.b;a.b.U=c;a.b=c;return c.Z}p.$=m("n");p.W=function(){var a=Array(this.n),b=0,c;for(c=this.b;c!==k;c=c.ia)a[b++]=c.L;return a}; -p.N=function(){var a=Array(this.n),b=0,c;for(c=this.b;c!==k;c=c.ia)a[b++]=c.Z;return a};function oh(a){var b=a.a;delete a.c[b.L];b.U!==k&&(b.U.ia=k);a.a=b.U;a.a===k&&(a.b=k);--a.n}function ph(a,b,c){c={L:b,U:k,ia:a.b,Z:c};a.b===k?a.a=c:a.b.U=c;a.b=c;a.c[b]=c;++a.n};var qh=["webgl","webgl-experimental","webkit-3d","moz-webgl"];function rh(a,b){var c,d,e=qh.length;for(d=0;d>1)-1;0<=b;b--)ze(a,b);for(a=this.J;0b;++b)e=c[b],e.rotate(d),e.add(a);f.extent=ce.apply(k,c)}this.e=f;this.G.ob(f);this.p=l;f!==k&&(f.R&&sf(this),Array.prototype.push.apply(this.yb, -f.wa));K(this,new Te("postrender",this,f));w.setTimeout(this.Pc,0)}};p.ae=function(a){this.q("backgroundColor",a)};S.prototype.setBackgroundColor=S.prototype.ae;S.prototype.Rc=function(a){this.q(Bg,a)};S.prototype.setLayers=S.prototype.Rc;S.prototype.Ra=function(a){this.q("size",a)};S.prototype.setSize=S.prototype.Ra;S.prototype.Sc=function(a){this.q("view",a)};S.prototype.setView=S.prototype.Sc;function tf(a,b,c){++a.g;try{b.call(c)}finally{0===--a.g&&a.p&&(a=a.d,sd(a),a.Gb())}} -yh.Yc=function(a){var b=w.location.search.substring(1),a=x(a)?a:new Zc(b);return kd(a,"renderers")?ld(a,"renderers").split(","):kd(a,"renderer")?[ld(a,"renderer")]:Ah};Ke(bg);Ke(eg);function Bh(a,b,c){var d=a.length,c=1=Math.abs(a+c)?0:a+c}};var Q={Gb:function(a){a<1/2.75?a*=7.5625*a:a<2/2.75?(a-=1.5/2.75,a=7.5625*a*a+0.75):a<2.5/2.75?(a-=2.25/2.75,a=7.5625*a*a+0.9375):(a-=2.625/2.75,a=7.5625*a*a+0.984375);return a},dd:function(a){return a*a*a},Ia:function(a){return 1-Math.pow(1-a,3)},ed:function(a){return Math.pow(2,-10*a)*Math.sin((a-0.075)*2*Math.PI/0.3)+1},Aa:function(a){return 3*a*a-2*a*a*a},xc:aa(),Oc:function(a){return 0.5>a?Q.Aa(2*a):1-Q.Aa(2*(a-0.5))}};var pf={Gb:function(a){var b=a.resolution,c=y(a.start)?a.start:pa(),d=y(a.duration)?a.duration:1E3,e=y(a.easing)?a.easing:Q.Oc;return function(a,g){if(g.timeb-a.f;)d--;if(0<=d){var b=a.a[d],c=a.a[c],d=c.x-b.x,e=c.y-b.y;a.c=Math.atan2(e,d);a.b=Math.sqrt(d*d+e*e)/(c.Ua-b.Ua);return a.b>a.d}return l}zf.prototype.aa=function(a){var b=this.e,c=this.b,d=this.d,e=Math.log(this.d/this.b)/this.e;return pf.aa({source:a,duration:e,easing:function(a){return c*(Math.exp(b*a*e)-1)/(d-c)}})};function Bf(){};function Cf(a){this.a=a}B(Cf,Bf);Cf.prototype.ra=function(a){var b=a.a;if(a.type==af&&(Od||nc(a.a))){var c=a.map,d=a.b(),e=a.a.qa?-this.a:this.a;uf(c.a(),c,e,d,250);a.D();b.D()}};function Df(a){return a.ea&&!a.vb&&a.qa}function Ef(a){return!a.ea&&!a.vb&&!a.qa}function Ff(a){return!a.ea&&!a.vb&&a.qa};function Gf(){this.e=l;this.r=this.Qa=this.h=this.g=0;this.Ta=this.f=k}B(Gf,Bf);p=Gf.prototype;p.Mb=ba;p.ib=ba;p.jb=pd;p.vc=ba;p.ra=function(a){var b=a.map;if(b.Oa()){var b=b.a(),c=a.a;a.type==df&&this.vc(a);this.e?a.type==ff?(this.d=c.clientX-this.g,this.b=c.clientY-this.h,this.Mb(a)):a.type==cf&&(this.d=c.clientX-this.g,this.b=c.clientY-this.h,this.ib(a),this.e=l):a.type==ef&&(this.g=c.clientX,this.h=c.clientY,this.b=this.d=0,this.f=b.N(),this.Ta=a.b(),this.jb(a)&&(this.e=i,a.D()))}};function Hf(a,b){Gf.call(this);this.t=a;this.a=b;this.c=k}B(Hf,Gf);Hf.prototype.Mb=function(a){this.a&&this.a.a.push({x:a.a.clientX,y:a.a.clientY,Ua:pa()});var a=a.map,b=a.a(),c=b.Q(),d=b.V(),c=new K(-c*this.d,c*this.b);c.rotate(d);d=new K(this.f.x+c.x,this.f.y+c.y);qf(a);b.a(d)}; +Hf.prototype.ib=function(a){var b=a.map,a=b.a();mf(a,-1);if(this.a&&Af(this.a)){var c=(this.a.d-this.a.b)/this.a.e,d=this.a.c,e=a.N();this.c=this.a.aa(e);b.ga(this.c);e=If(b,e);b=Ye(b,new We(e.x-c*Math.cos(d),e.y-c*Math.sin(d)));a.a(b)}};Hf.prototype.jb=function(a){var b=a.a;if(this.t(b)){if(this.a){var c=this.a;c.a.length=0;c.c=0;c.b=0;this.a.a.push({x:b.clientX,y:b.clientY,Ua:pa()})}a=a.map;qf(a);mf(a.a(),1);return i}return l}; +Hf.prototype.vc=function(a){var b=a.map,c=b.a();this.c!==k&&Ea(b.h,this.c)&&(qf(b),c.a(a.d.v.center),this.c=k)};function Jf(a){Gf.call(this);this.c=a}B(Jf,Gf);Jf.prototype.Mb=function(a){var b=a.map,c=b.f(),a=Ze(a),c=Math.atan2(c.height/2-a.y,a.x-c.width/2);if(y(this.a)){var a=c-this.a,d=b.a();qf(b);rf(d,b,d.V()-a)}this.a=c};Jf.prototype.ib=function(a){var a=a.map,b=a.a();b.rotate(a,b.V(),h,250);mf(b,-1)};Jf.prototype.jb=function(a){var b=a.a;return nc(b)&&this.c(b)?(a=a.map,b=a.a(),qf(a),this.a=h,mf(b,1),i):l};function Kf(a){var b=Rb("DIV","ol-dragbox");this.c=k;this.e=a.Ta;this.d=k;vf.call(this,{element:b,map:a.map})}B(Kf,vf);Kf.prototype.a=function(a){this.d!==k&&(H(this.d),this.d=k);a!==k&&(this.c=If(a,this.e),Ec(this.element,this.c),Nc(this.element,new $d(0,0)),this.d=F(a,ff,this.f,l,this));Kf.w.a.call(this,a)};Kf.prototype.f=function(a){var b=this.b,a=a.b(),b=If(b,a);Ec(this.element,new We(Math.min(b.x,this.c.x),Math.min(b.y,this.c.y)));Nc(this.element,new $d(Math.abs(b.x-this.c.x),Math.abs(b.y-this.c.y)))};function Lf(a){Gf.call(this);this.c=a;this.a=k}B(Lf,Gf);Lf.prototype.ib=function(a){this.a.a(k);this.a=k;if(64<=this.d*this.d+this.b*this.b){var b=a.map,c=de(this.Ta,a.b());sf(b,function(){var a=b.a(),e=b.f();a.f(c,e);a.d(0)})}};Lf.prototype.jb=function(a){var b=a.a;return nc(b)&&this.c(b)?(this.a=new Kf({map:a.map,Ta:this.Ta}),i):l};function Mf(a){a=y(a)?a:{};this.a=y(a.delta)?a.delta:128}B(Mf,Bf);Mf.prototype.ra=function(a){if("key"==a.type){var b=a.a,c=b.za;if(40==c||37==c||39==c||38==c){var d=a.map,e=d.a(),f=e.Q(),g=e.V(),f=f*this.a,j=0,m=0;40==c?m=-f:37==c?j=-f:39==c?j=f:m=f;c=new K(j,m);c.rotate(g);e.aa(d,c,100);b.D();a.D()}}};function Nf(a){a=y(a)?a:{};this.a=y(a.delta)?a.delta:1}B(Nf,Bf);Nf.prototype.ra=function(a){if("key"==a.type){var b=a.a,c=b.fb;if(43==c||45==c){var d=a.map,c=43==c?this.a:-this.a;qf(d);uf(d.a(),d,c,h,100);b.D();a.D()}}};function Of(){this.a=0;this.c=k;this.d=this.b=h}B(Of,Bf);Of.prototype.ra=function(a){if("mousewheel"==a.type){var b=a.map,c=a.a;this.c=a.b();this.a+=c.b/3;y(this.b)||(this.b=pa());var d=Math.max(80-(pa()-this.b),0);w.clearTimeout(this.d);this.d=w.setTimeout(na(this.e,this,b),d);a.D();c.D()}};Of.prototype.e=function(a){var b=Hb(this.a,-1,1),c=a.a();qf(a);uf(c,a,-b,this.c,250);this.a=0;this.c=k;this.d=this.b=h};function Pf(){this.g=l;this.h={};this.targetTouches=[]}B(Pf,Bf);function Qf(a){for(var b=a.length,c=0,d=0,e=0;ethis.t&&(this.a=i));this.c=c;var a=a.map,c=a.a(),d=Jc(a.b),e=Qf(this.targetTouches);e.x-=d.x;e.y-=d.y;d=Ye(a,e);this.a&&rf(c,a,c.V()+b,d)}; +Sf.prototype.d=function(a){if(2>this.targetTouches.length){var a=a.map,b=a.a();this.a&&b.rotate(a,b.V(),h,250);mf(b,-1);return l}return i};Sf.prototype.f=function(a){return 2<=this.targetTouches.length?(a=a.map.a(),this.c=h,this.a=l,this.b=0,mf(a,1),i):l};function Tf(){Pf.call(this)}B(Tf,Pf);Tf.prototype.e=function(a){var b=1,c=this.targetTouches[0],d=this.targetTouches[1],e=c.clientX-d.clientX,c=c.clientY-d.clientY,e=Math.sqrt(e*e+c*c);y(this.a)&&(b=this.a/e);this.a=e;a=a.map;e=a.a();c=Jc(a.b);d=Qf(this.targetTouches);d.x-=c.x;d.y-=c.y;c=Ye(a,d);tf(e,a,e.Q()*b,c)};Tf.prototype.d=function(a){if(2>this.targetTouches.length){var a=a.map,b=a.a();b.zoom(a,b.Q(),h,250);mf(b,-1);return l}return i}; +Tf.prototype.f=function(a){return 2<=this.targetTouches.length?(a=a.map.a(),this.a=h,mf(a,1),i):l};function Uf(a,b){var c=y(a)?a:{},d=new N;(y(c.rotate)?c.rotate:1)&&d.push(new Jf(Df));if(y(c.$d)?c.$d:1)d.push(new Cf(y(c.ue)?c.ue:1));(y(c.ee)?c.ee:1)&&d.push(new Rf(new zf(-0.005,0.05,100)));(y(c.fe)?c.fe:1)&&d.push(new Sf);(y(c.ge)?c.ge:1)&&d.push(new Tf);(y(c.ae)?c.ae:1)&&d.push(new Hf(Ef,new zf(-0.005,0.05,100)));if(y(c.be)?c.be:1)d.push(new Mf),d.push(new Nf);(y(c.ce)?c.ce:1)&&d.push(new Of);(y(c.de)?c.de:1)&&d.push(new Lf(Ff));if(y(b))for(c=0;cc?a[1]="?":c==f.length-1&&(a[1]=h));return a.join("")} +;function Cg(a,b){return function(c,d,e){return Bg(a,b,c,d,e)}}function Dg(){};function Eg(a){Ue.call(this,{attributions:a.attributions,extent:a.extent,projection:a.projection});this.Na=y(a.Na)?a.Na:Dg;this.d=y(a.crossOrigin)?a.crossOrigin:"anonymous";this.a=y(a.resolutions)?a.resolutions:k}B(Eg,Ue);function Fg(a,b,c,d,e){var f=k,d=a.Na(b,d,e);y(d)&&(f=new bg(b,c,d,a.d,a.oa()));return f};function Gg(a){P.call(this,a)}B(Gg,P);function Hg(a){P.call(this,a)}B(Hg,P);function Ig(a,b){og.call(this,a,b)}B(Ig,og);function Jg(a,b){og.call(this,a,b);this.b=k;this.c=he()}B(Jg,Ig);Jg.prototype.J=function(){return this.b===k?k:cg(this.b,this)};Jg.prototype.ma=n("c"); +Jg.prototype.ka=function(a){var b=a.v,c=b.center,d=b.resolution,e=b.rotation,f=this.a.$(),g=a.C;!g[0]&&!g[1]&&(b=f.J(a.extent,d,b.projection),b!==k&&(f=b.a,0==f?(vc(b,"change",this.Nb,l,this),dg(b)):2==f&&(this.b=b)));if(this.b!==k){var b=this.b,f=b.I(),g=b.e,j=this.c;le(j);pe(j,a.size.width/2,a.size.height/2);re(j,e);qe(j,g/d,g/d);pe(j,(f.i-c.x)/g,(c.y-f.k)/g);sg(a.attributions,b.oa())}};function Kg(a,b){og.call(this,a,b);this.e=this.c=this.d=k;this.f=he();this.b=k}B(Kg,Ig);Kg.prototype.J=n("d");Kg.prototype.ma=n("f"); +Kg.prototype.ka=function(a){var b=a.v,c=b.projection,d=this.a.$(),e=z(d).toString(),f=d.tileGrid;f===k&&(f=lg(c));var g=nf(f.a,b.resolution),j=kg(f,g),m=f.a[g],r=gg(f,a.extent,m),s=r.ha(),q=r.ca(),j=new $d(j.width*s,j.height*q),v,u;this.d===k?(v=Tb("CANVAS"),v.width=j.width,v.height=j.height,u=v.getContext("2d"),this.d=v,this.c=j,this.e=u,this.b=Array(s*q)):(v=this.d,u=this.e,this.c.width==j.width&&this.c.height==j.height||(v.width=j.width,v.height=j.height,this.c=j,this.b=Array(s*q)));q={};q[g]= +{};var j=na(d.d,d,q,vg(function(a){return a!==k&&2==a.a},d,f,c)),t,x,C,G,I;for(G=r.i;G<=r.l;++G)for(I=r.j;I<=r.k;++I){x=new se(g,G,I);t=d.b(x,f,c);C=t.a;if(0==C)ug(a.Wa,d,x),v=jg(f,x),ye(a.Zb,t,e,v);else if(1==C)qg(this,t);else if(2==C||4==C){q[g][x.toString()]=t;continue}else if(3==C)continue;f.b(x,j)}e=Ba(Oa(q),Number);Ka(e);v=d.H;var c=ee(fg(f,new se(g,r.i,r.k))),T,L,W,$,ua,va;for(T=0;Tc;++c)d[c]=b[c].toFixed(6);c=d.join(",")}else c=b.join(",");c="matrix3d("+c+")";d=a.style;d.WebkitTransform=c;d.MozTransform=c;d.a=c;d.transform=c};function Og(a,b,c){og.call(this,a,b);this.target=c}B(Og,og);Og.prototype.s=function(){Xb(this.target);Og.w.s.call(this)};function Pg(a,b){var c=Tb("DIV");c.className="ol-layer-image";c.style.position="absolute";Og.call(this,a,b,c);this.b=k;this.c=je()}B(Pg,Og); +Pg.prototype.ka=function(a){var b=a.v,c=b.center,d=b.resolution,e=b.rotation,f=this.b,g=this.a.$(),j=a.C;!j[0]&&!j[1]&&(b=g.J(a.extent,d,b.projection),b!==k&&(g=b.a,0==g?(vc(b,"change",this.Nb,l,this),dg(b)):2==g&&(f=b)));f!==k&&(g=f.I(),j=f.e,b=he(),le(b),pe(b,a.size.width/2,a.size.height/2),re(b,e),qe(b,j/d,j/d),pe(b,(g.i-c.x)/j,(c.y-g.k)/j),f!=this.b&&(c=cg(f,this),c.style.position="absolute",Vb(this.target),this.target.appendChild(c),this.b=f),ne(b,this.c)||(Ng(this.target,b),ke(this.c,b)),sg(a.attributions, +f.oa()))};function Qg(a,b){var c=Tb("DIV");c.className="ol-layer-tile";c.style.position="absolute";Og.call(this,a,b,c);this.c=i;this.d=1;this.b={}}B(Qg,Og); +Qg.prototype.ka=function(a,b){if(b.visible){var c=a.v,d=c.projection,e=this.a.$(),f=z(e).toString(),g=e.tileGrid;g===k&&(g=lg(d));var j=nf(g.a,c.resolution),m=gg(g,a.extent,g.a[j]),r={};r[j]={};var s=na(e.d,e,r,vg(function(a){return a!==k&&2==a.a},e,g,d)),q,v,u,t,x;for(t=m.i;t<=m.l;++t)for(x=m.j;x<=m.k;++x){u=new se(j,t,x);q=e.b(u,g,d);v=q.a;if(0==v)ug(a.Wa,e,u),v=jg(g,u),ye(a.Zb,q,f,v);else if(1==v)qg(this,q);else if(2==v){r[j][u.toString()]=q;continue}else if(3==v||4==v)continue;g.b(u,s)}s=Ba(Oa(r), +Number);Ka(s);var d={},C;for(q=0;qu&&Wb(this.target,f.target)}else{if(!a.C[0]&&!a.C[1]){v=gg(f.d,a.extent,f.d.a[f.c.n]);u=[];x=t=h;for(x in f.b)t=f.b[x],v.contains(t.X)|| +u.push(t);v=h;for(v=0;v=a.ba()){for(var a=this.a,d=0;d>1,a[d].M>c.M)a[b]=a[d],b=d;else break;a[b]=c}p=$g.prototype; +p.remove=function(){var a=this.a,b=a.length,c=a[0];if(!(0>=b)){if(1==b)Da(a);else{a[0]=a.pop();for(var a=0,b=this.a,d=b.length,e=b[a];a>1;){var f=2*a+1,g=2*a+2,f=ge.M)break;b[a]=b[f];a=f}b[a]=e}return c.Y}};p.O=function(){for(var a=this.a,b=[],c=a.length,d=0;dc;++c)d=b.remove(),hh(a,d)},b,u));T?(this.b=q,this.z=v):(this.z=this.b=k,a.S=i)}tg(a.Va,g,r,q);ng(g,r,a.extent,m);rg(a, +g);le(this.d);pe(this.d,(d.center.x-v.i)/(v.l-v.i),(d.center.y-v.j)/(v.k-v.j));re(this.d,d.rotation);qe(this.d,a.size.width*d.resolution/(v.l-v.i),a.size.height*d.resolution/(v.k-v.j));pe(this.d,-0.5,-0.5)};function ih(){this.o=0;this.c={};this.b=this.a=k}p=ih.prototype;p.clear=function(){this.o=0;this.c={};this.b=this.a=k};function gh(a,b){return a.c.hasOwnProperty(b)}p.forEach=function(a,b){for(var c=this.a;c!==k;)a.call(b,c.Y,c.M,this),c=c.W};function jh(a,b){var c=a.c[b];if(c===a.b)return c.Y;c===a.a?(a.a=a.a.W,a.a.la=k):(c.W.la=c.la,c.la.W=c.W);c.W=k;c.la=a.b;a.b.W=c;a.b=c;return c.Y}p.ba=n("o");p.Z=function(){var a=Array(this.o),b=0,c;for(c=this.b;c!==k;c=c.la)a[b++]=c.M;return a}; +p.O=function(){var a=Array(this.o),b=0,c;for(c=this.b;c!==k;c=c.la)a[b++]=c.Y;return a};p.pop=function(){var a=this.a;delete this.c[a.M];a.W!==k&&(a.W.la=k);this.a=a.W;this.a===k&&(this.b=k);--this.o;return a.Y};function kh(a,b,c){c={M:b,W:k,la:a.b,Y:c};a.b===k?a.a=c:a.b.W=c;a.b=c;a.c[b]=c;++a.o};var lh=["webgl","webgl-experimental","webkit-3d","moz-webgl"];function mh(a,b){var c,d,e=lh.length;for(d=0;d>1)-1;0<=b;b--)Ae(a,b);for(var a=this.K,m;0b;++b)e=c[b],e.rotate(d),e.add(a);f.extent=de.apply(k,c)}this.d=f;this.H.tb(f);this.r=l;f!==k&&(f.S&&qf(this),Array.prototype.push.apply(this.wa, +f.Ca));J(this,new Ve("postrender",this,f));w.setTimeout(this.Sc,0)}};p.je=function(a){this.p("backgroundColor",a)};S.prototype.setBackgroundColor=S.prototype.je;S.prototype.Uc=function(a){this.p(xg,a)};S.prototype.setLayers=S.prototype.Uc;S.prototype.ya=function(a){this.p("size",a)};S.prototype.setSize=S.prototype.ya;S.prototype.Vc=function(a){this.p("view",a)};S.prototype.setView=S.prototype.Vc;function sf(a,b,c){++a.g;try{b.call(c)}finally{0===--a.g&&a.r&&(a=a.c,td(a),a.Kb())}} +th.bd=function(a){var b=w.location.search.substring(1),a=y(a)?a:new $c(b);return ld(a,"renderers")?md(a,"renderers").split(","):ld(a,"renderer")?[md(a,"renderer")]:vh};Me(Yf);Me(ag);function wh(a,b,c){var d=a.length,c=1b?(d="\u2032",a*=60):d="\u00b0":"imperial"==this.c?0.9144>b?(d="in",a/=0.0254):1609.344>b?(d="ft",a/=0.3048):(d="mi",a/=1609.344):"nautical"==this.c?(a/=1852,d="nm"):"metric"==this.c?1>b?(d="mm",a*=1E3):1E3>b?d="m":(d="km",a/=1E3):"us"==this.c&&(0.9144>b?(d="in",a*=39.37):1609.344>b?(d="ft",a/=0.30480061):(d="mi",a/=1609.3472));for(var b=3*Math.floor(Math.log(this.h*a)/Math.log(10)),e,f;;){e=Fh[b%3]*Math.pow(10,Math.floor(b/3));f=Math.round(e/a);if(f>=this.h)break;++b}e=e+d;this.u!=e&& +(this.u=this.g.innerHTML=e);this.G!=f&&(this.g.style.width=f+"px",this.G=f);this.f||(Mc(this.t,i),this.f=i)}};Eh.prototype.a=function(a){this.e!==k&&(D(this.e,H),this.e=k);Eh.w.a.call(this,a);a!==k&&(this.e=[F(a,"postrender",this.z,l,this)])};function Gh(){this.a={}}B(Gh,Bf);Gh.prototype.b=function(a,b){var c;for(c=0;cthis.d&&!(b=this.a.Z,c=b.V.m.toString(),c in a&&a[c].contains(b.V));)oh(this)};function ui(a){qg.call(this,{attributions:a.attributions,extent:a.extent,opaque:a.opaque,projection:a.projection,tileGrid:a.tileGrid});this.da=x(a.da)?a.da:qi;this.F=x(a.crossOrigin)?a.crossOrigin:"anonymous";this.a=new ti}B(ui,qg);ui.prototype.f=function(){return this.a.$()>this.a.d};ui.prototype.Ca=function(a){this.a.Ca(a)};ui.prototype.b=function(a,b,c){var d=a.toString();if(kh(this.a,d))return nh(this.a,d);b=this.da(a,b,c);x(b)?(a=new si(a,b,this.F),ph(this.a,d,a)):a=k;return a}; -ui.prototype.p=function(a){a=a.toString();kh(this.a,a)&&nh(this.a,a)};function vi(a){var b=Array(a.maxZoom+1),c,d=2*ag/256;for(c=0;c<=a.maxZoom;++c)b[c]=d/Math.pow(2,c);ig.call(this,{origin:new L(-ag,ag),resolutions:b,tileSize:new Zd(256,256)})}B(vi,ig);vi.prototype.b=function(a,b,c){for(var d=a.x,e=a.y,a=a.m,f;;){a-=1;if(0>a)break;d>>=1;e>>=1;f=new te(d,e,d,e);if(b.call(c,a,f))break}};function wi(a){ui.call(this,{opaque:j,projection:Pe("EPSG:3857")});this.Zc=x(a.culture)?a.culture:"en-us";this.g=l;var b=new Uc("//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+a.style),b=new ki(b),a={include:"ImageryProviders",key:a.key},c=na(this.t,this),a=a||k,d="_"+(li++).toString(36)+pa().toString(36);w._callbacks_||(w._callbacks_={});var e=b.b.S();if(a)for(var f in a)(!a.hasOwnProperty||a.hasOwnProperty(f))&&hd(e,f,a[f]);c&&(w._callbacks_[d]=function(a){mi(d,j);c.apply(h,arguments)},hd(e, -b.a,"_callbacks_."+d));f=ei(e.toString(),{timeout:b.vb,dc:j});f.a.push([k,function(){mi(d,l)},h]);f.ja&&ai(f)}B(wi,ui); -wi.prototype.t=function(a){var b=a.resourceSets[0].resources[0],c=b.zoomMin,d=b.zoomMax,e=new vi({maxZoom:d,tileSize:new Zd(b.imageWidth,b.imageHeight)});this.tileGrid=e;this.da=ri(function(a){if(a.me||b<=e?k:new re(a.m,Gb(a.x,b),e)},oi(Aa(b.imageUrlSubdomains,function(a){var c=b.imageUrl.replace("{subdomain}",a).replace("{culture}",this.Zc);return function(a){return a===k?h:c.replace("{quadkey}",se(a))}})));var f=Fe(Pe("EPSG:4326"),this.o);this.e= -Aa(b.imageryProviders,function(a){var b=a.attribution,c={};C(a.coverageAreas,function(a){var b=a.zoomMin,d=a.zoomMax,a=a.bbox,a=(new be(a[1],a[0],a[3],a[2])).transform(f),g,i;for(g=b;g<=d;++g)i=g.toString(),b=kg(e,a,e.a[g]),i in c?c[i].push(b):c[i]=[b]});return new ue(b,c)});this.g=j;K(this,"load")};wi.prototype.c=m("g");function xi(a,b){ve.call(this,a);this.a=2;this.f=a;this.d=og(b,a.m);this.c={}}B(xi,ve);xi.prototype.I=function(a){a=x(a)?y(a):-1;if(a in this.c)return this.c[a];var b=this.d,c=Rb("CANVAS");c.width=b.width;c.height=b.height;var d=c.getContext("2d");d.strokeStyle="black";d.strokeRect(0.5,0.5,b.width+0.5,b.height+0.5);d.fillStyle="black";d.textAlign="center";d.textBaseline="middle";d.font="24px sans-serif";d.fillText(this.f.toString(),b.width/2,b.height/2);return this.c[a]=c}; -function yi(a){qg.call(this,{extent:a.extent,opaque:l,projection:a.projection,tileGrid:a.tileGrid});this.a=new ti}B(yi,qg);yi.prototype.f=function(){return this.a.$()>this.a.d};yi.prototype.Ca=function(a){this.a.Ca(a)};yi.prototype.b=function(a){var b=a.toString();if(kh(this.a,b))return nh(this.a,b);a=new xi(a,this.tileGrid);ph(this.a,b,a);return a};function zi(a){var b=a.projection||Pe("EPSG:3857"),c=qi;x(a.da)?c=a.da:x(a.urls)?c=oi(Aa(a.urls,ni)):x(a.url)&&(c=ni(a.url));var d=new vi({maxZoom:a.maxZoom}),e=a.extent,c=e!=k?ri(function(b){if(a.maxZoomi||c<=i)return k;c=Gb(b.x,c);return!ae(jg(d,new re(b.m,c,b.y)),e)?k:new re(b.m,c,i)},c):ri(function(b){if(a.maxZoomd||c<=d?k:new re(b.m,Gb(b.x,c),d)},c);ui.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin, -extent:a.extent,projection:b,tileGrid:d,da:c})}B(zi,ui);function Ai(){zi.call(this,{attributions:[new ue('Tiles Courtesy of MapQuest '),new ue('Data © OpenStreetMap contributors, CC BY-SA')],opaque:j,maxZoom:28,url:"http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg"})}B(Ai,zi); -function Bi(){zi.call(this,{attributions:[new ue('Tiles Courtesy of MapQuest '),new ue("Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency")],maxZoom:18,opaque:j,url:"http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg"})}B(Bi,zi);function Ci(){zi.call(this,{attributions:[new ue('© OpenStreetMap contributors, CC BY-SA')],opaque:j,maxZoom:18,url:"http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png"})}B(Ci,zi);function Di(a){Ig.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,resolutions:a.resolutions,Ga:x(a.url)?Gg(a.url,a.params):Hg});this.b=k;this.f=1.5}B(Di,Ig); -Di.prototype.I=function(a,b,c){this.a===k||(b=this.a[nf(this.a,b)]);var d=this.b,e;if(e=d!==k)if(e=d.e==b)e=d.H(),e=e.i<=a.i&&a.l<=e.l&&e.j<=a.j&&a.k<=e.k;if(e)return d;var d=a=new be(a.i,a.j,a.l,a.k),f=this.f;e=d.ea()/2*(f-1);f=d.aa()/2*(f-1);d.i-=e;d.j-=f;d.l+=e;d.k+=f;return this.b=Jg(this,a,b,new Zd(a.ea()/b,a.aa()/b),c)};var Ei={terrain:{T:"jpg",opaque:j},"terrain-background":{T:"jpg",opaque:j},"terrain-labels":{T:"png",opaque:l},"terrain-lines":{T:"png",opaque:l},"toner-background":{T:"png",opaque:j},toner:{T:"png",opaque:j},"toner-hybrid":{T:"png",opaque:l},"toner-labels":{T:"png",opaque:l},"toner-lines":{T:"png",opaque:l},"toner-lite":{T:"png",opaque:j},watercolor:{T:"jpg",opaque:j}},Fi={terrain:{minZoom:4,maxZoom:18},toner:{minZoom:0,maxZoom:20},watercolor:{minZoom:3,maxZoom:16}}; -function Gi(a){var b=new ue('Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'),c=a.layer.indexOf("-"),c=-1==c?a.layer:a.layer.slice(0,c),d=Ei[a.layer];zi.call(this,{attributions:[b],maxZoom:Fi[c].maxZoom,opaque:d.opaque,url:x(a.url)?a.url:"http://{a-d}.tile.stamen.com/"+a.layer+ -"/{z}/{x}/{y}."+d.T})}B(Gi,zi);function Hi(a){var b=a.imageExtent,c=a.imageSize,d=b.aa()/c.height,e=x(a.projection)?a.projection:k,f=a.url;Ig.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,Ga:function(){return f},resolutions:[d]});this.b=Jg(this,b,d,c,e)}B(Hi,Ig);Hi.prototype.I=function(a){return ae(a,this.b.H())?this.b:k};var Ii=[];A("grid",function(a){Ii.push(a)});function Ji(a){ui.call(this,{projection:Pe("EPSG:3857")});this.g=l;a=this.t=ei(a.uri,{dc:j});a.a.push([this.w,k,this]);a.ja&&ai(a)}B(Ji,ui); -Ji.prototype.w=function(){var a=Ii.pop(),b=Pe("EPSG:4326"),c,d;x(a.bounds)?(c=a.bounds,c=new be(c[0],c[1],c[2],c[3]),this.h=d=c.transform(Fe(b,this.o))):d=c=k;var e=a.minzoom||0,f=a.maxzoom||22,g=new vi({maxZoom:f});this.tileGrid=g;this.da=ri(function(a){if(a.mc||b<=c)return k;b=Gb(a.x,b);return d!==k&&!ae(jg(g,new re(a.m,b,a.y)),d)?k:new re(a.m,b,c)},oi(Aa(a.tiles,ni)));if(x(a.attribution)){b=d===k?b.H():d;c={};var i,n;for(i=e;i<=f;++i)n=i.toString(), -c[n]=[kg(g,b,g.a[i])];this.e=[new ue(a.attribution,c)]}this.g=j;K(this,"load")};Ji.prototype.c=m("g");function Ki(a){var b;a.urls?(b=Aa(a.urls,function(b){return pi(b,a.params)}),b=oi(b)):b=a.url?pi(a.url,a.params):qi;var c=a.extent;ui.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:c,tileGrid:a.tileGrid,opaque:!(x(a.params.TRANSPARENT)?a.params.TRANSPARENT:1),projection:a.projection,da:ri(function(a,b,f){if(b.Fb().length<=a.m)return k;var g=a.x,i=jg(b,a),f=f.H();c=x(c)?c:f;c.i===f.i&&c.l===f.l&&(i=Math.ceil((c.l-c.i)/(i.l-i.i)),g=Gb(g,i),i=jg(b,new re(a.m,g,a.y)));return!ae(i, -c)?k:new re(a.m,g,a.y)},b)})}B(Ki,ui);A("goog.require",ba);function Li(a){T.call(this,{element:a.element,map:a.map,position:a.position,positioning:a.positioning})}B(Li,T);A("ol.AnchoredElement",Li);A("ol.AnchoredElementPositioning",Dh);Dh.BOTTOM_LEFT="bottom-left";Dh.BOTTOM_RIGHT="bottom-right";Dh.TOP_LEFT="top-left";Dh.TOP_RIGHT="top-right";A("ol.Attribution",ue);A("ol.Collection",N);N.prototype.clear=N.prototype.clear;N.prototype.forEach=N.prototype.forEach;N.prototype.getAt=N.prototype.bd;N.prototype.getLength=N.prototype.Za; -N.prototype.insertAt=N.prototype.fb;N.prototype.pop=N.prototype.wc;N.prototype.push=N.prototype.push;N.prototype.remove=N.prototype.remove;N.prototype.removeAt=N.prototype.Rb;N.prototype.setAt=N.prototype.$d;A("ol.Coordinate",L);L.toStringHDMS=function(a){return x(a)?Rc(a.y,"NS")+" "+Rc(a.x,"EW"):""};A("ol.Extent",be);be.prototype.getHeight=be.prototype.aa;be.prototype.getWidth=be.prototype.ea;A("ol.Geolocation",X); -function Mi(a){S.call(this,{controls:a.controls,interactions:a.interactions,layers:a.layers,renderer:a.renderer,renderers:a.renderers,target:a.target,view:a.view})}B(Mi,S);A("ol.Map",Mi);S.prototype.addPreRenderFunction=S.prototype.c;S.prototype.addPreRenderFunctions=S.prototype.Ab;S.prototype.getInteractions=S.prototype.Mc;S.prototype.getRenderer=S.prototype.Oc;Ve.prototype.getCoordinate=Ve.prototype.d;A("ol.Object",M);M.prototype.bindTo=M.prototype.Uc;M.prototype.changed=M.prototype.Xc; -M.prototype.get=M.prototype.s;M.prototype.notify=M.prototype.vc;M.prototype.set=M.prototype.q;M.prototype.setOptions=M.prototype.Ec;M.prototype.setValues=M.prototype.nb;M.prototype.unbind=M.prototype.Wb;M.prototype.unbindAll=M.prototype.je;A("ol.Projection",O);O.prototype.getAxisOrientation=O.prototype.g;O.prototype.getCode=O.prototype.h;O.prototype.getExtent=O.prototype.H;O.prototype.getPointResolution=O.prototype.b;O.prototype.getUnits=O.prototype.o;A("ol.ProjectionUnits",De);De.DEGREES="degrees"; -De.METERS="m";A("ol.RendererHint",zh);zh.CANVAS="canvas";zh.DOM="dom";zh.WEBGL="webgl";A("ol.RendererHints",yh);yh.createFromQueryData=yh.Yc;function Ni(a){Q.call(this,{center:a.center,maxResolution:a.maxResolution,numZoomLevels:a.numZoomLevels,projection:a.projection,resolution:a.resolution,resolutions:a.resolutions,rotation:a.rotation,zoom:a.zoom,zoomFactor:a.zoomFactor})}B(Ni,Q);A("ol.View2D",Ni);Q.prototype.fitExtent=Q.prototype.f;Q.prototype.getView2D=Q.prototype.g;A("ol.animation",qf); -qf.bounce=qf.Cb;qf.pan=qf.pa;qf.rotate=qf.rotate;qf.zoom=qf.zoom;function Oi(a){xf.call(this,{map:a.map,target:a.target})}B(Oi,xf);A("ol.control.Attribution",Oi);xf.prototype.setMap=xf.prototype.a;function Pi(a){Gh.call(this,{coordinateFormat:a.coordinateFormat,map:a.map,projection:a.projection,target:a.target,undefinedHTML:a.undefinedHTML})}B(Pi,Gh);A("ol.control.MousePosition",Pi);Gh.prototype.setMap=Gh.prototype.a; -function Qi(a){zf.call(this,{map:a.map,minWidth:a.minWidth,target:a.target,units:a.units})}B(Qi,zf);A("ol.control.ScaleLine",Qi);zf.prototype.setMap=zf.prototype.a;A("ol.control.ScaleLineUnits",yf);yf.DEGREES="degrees";yf.IMPERIAL="imperial";yf.METRIC="metric";yf.NAUTICAL="nautical";yf.US="us";function Ri(a){Bf.call(this,{delta:a.delta,map:a.map,target:a.target})}B(Ri,Bf);A("ol.control.Zoom",Ri);Bf.prototype.setMap=Bf.prototype.a;A("ol.control.defaults",Cf);A("ol.easing",pf);pf.bounce=pf.Cb; -pf.elastic=pf.$c;pf.linear=pf.rc;pf.upAndDown=pf.Jc;A("ol.interaction.Keyboard",Ih);Ih.prototype.addCallback=Ih.prototype.b;A("ol.interaction.defaults",Yf);function Si(a){P.call(this,{brightness:a.brightness,contrast:a.contrast,hue:a.hue,opacity:a.opacity,saturation:a.saturation,source:a.source,visible:a.visible})}B(Si,Kg);A("ol.layer.ImageLayer",Si); -function Ti(a){P.call(this,{brightness:a.brightness,contrast:a.contrast,hue:a.hue,opacity:a.opacity,saturation:a.saturation,source:a.source,visible:a.visible})}B(Ti,Lg);A("ol.layer.TileLayer",Ti);A("ol.parser.ogc.WMSCapabilities",Uh);Uh.prototype.read=Uh.prototype.ra;A("ol.parser.ogc.WMTSCapabilities",Yh);Yh.prototype.read=Yh.prototype.ra;A("ol.projection.addProjection",Le);A("ol.projection.getFromCode",Pe);A("ol.projection.getTransform",Fe);A("ol.projection.getTransformFromCodes",Re); -A("ol.projection.transform",function(a,b,c){b=Fe(b,c);a=[a.x,a.y];a=b(a,a,2);return new L(a[0],a[1])});A("ol.projection.transformWithCodes",function(a,b,c){b=Re(b,c);a=[a.x,a.y];a=b(a,a,2);return new L(a[0],a[1])});Pg.prototype.getCanvas=Pg.prototype.Xa;A("ol.source.BingMaps",wi);function Ui(a){yi.call(this,{extent:a.extent,projection:a.projection,tileGrid:a.tileGrid})}B(Ui,yi);A("ol.source.DebugTileSource",Ui);A("ol.source.MapQuestOSM",Ai);A("ol.source.MapQuestOpenAerial",Bi); -A("ol.source.OpenStreetMap",Ci);A("ol.source.SingleImageWMS",Di);A("ol.source.Stamen",Gi);A("ol.source.StaticImage",Hi);A("ol.source.TileJSON",Ji);A("ol.source.TiledWMS",Ki);function Vi(a){ig.call(this,{origin:a.origin,origins:a.origins,resolutions:a.resolutions,tileSize:a.tileSize,tileSizes:a.tileSizes})}B(Vi,ig);A("ol.tilegrid.TileGrid",Vi);function Wi(a){vi.call(this,{maxZoom:a.maxZoom})}B(Wi,vi);A("ol.tilegrid.XYZ",Wi);qf.oe={};qf.Fe={};qf.Ge={};qf.Pe={};})(); +function Xh(a,b){this.a=[];this.f=a;this.e=b||k}p=Xh.prototype;p.na=l;p.La=l;p.Sa=0;p.Kc=l;p.$c=l;p.Zc=0;p.jc=function(a,b){Yh(this,a,b);this.Sa--;0==this.Sa&&this.na&&Zh(this)};function Yh(a,b,c){a.na=i;a.b=c;a.La=!b;Zh(a)}function $h(a){if(a.na){if(!a.Kc)throw new ai(a);a.Kc=l}}function bi(a){return Ca(a.a,function(a){return ha(a[1])})} +function Zh(a){a.c&&(a.na&&bi(a))&&(w.clearTimeout(a.c),delete a.c);a.d&&(a.d.Zc--,delete a.d);for(var b=a.b,c=l,d=l;a.a.length&&0==a.Sa;){var e=a.a.shift(),f=e[0],g=e[1],e=e[2];if(f=a.La?g:f)try{var j=f.call(e||a.e,b);y(j)&&(a.La=a.La&&(j==b||j instanceof Error),a.b=b=j);b instanceof Xh&&(d=i,a.Sa++)}catch(m){b=m,a.La=i,bi(a)||(c=i)}}a.b=b;d&&a.Sa&&(d=b,j=na(a.jc,a,i),f=na(a.jc,a,l),d.a.push([j,f,h]),d.na&&Zh(d),b.$c=i);c&&(a.c=w.setTimeout(function(){throw b;},0))} +function ai(a){qa.call(this);this.a=a}B(ai,qa);ai.prototype.message="Deferred has already fired";ai.prototype.name="AlreadyCalledError";function ci(a,b){var c=b||{},d=c.document||document,e=Tb("SCRIPT"),f={Hc:e,Ab:h},g=new Xh(di,f),j=k,m=c.timeout!=k?c.timeout:5E3;0this.d&&!(b=this.a.Y,c=b.X.n.toString(),c in a&&a[c].contains(b.X));)this.pop()};function si(a){mg.call(this,{attributions:a.attributions,extent:a.extent,opaque:a.opaque,projection:a.projection,tileGrid:a.tileGrid});this.fa=y(a.fa)?a.fa:oi;this.G=y(a.crossOrigin)?a.crossOrigin:"anonymous";this.a=new ri}B(si,mg);si.prototype.g=function(){return this.a.ba()>this.a.d};si.prototype.Ja=function(a){this.a.Ja(a)};si.prototype.b=function(a,b,c){var d=a.toString();if(gh(this.a,d))return jh(this.a,d);b=this.fa(a,b,c);a=new qi(a,y(b)?0:4,y(b)?b:"",this.G);kh(this.a,d,a);return a}; +si.prototype.r=function(a){a=a.toString();gh(this.a,a)&&jh(this.a,a)};function ti(a){var b=Array(a.maxZoom+1),c,d=2*Xf/256;for(c=0;c<=a.maxZoom;++c)b[c]=d/Math.pow(2,c);eg.call(this,{origin:new K(-Xf,Xf),resolutions:b,tileSize:new $d(256,256)})}B(ti,eg);ti.prototype.b=function(a,b,c){for(var d=a.x,e=a.y,a=a.n,f;;){a-=1;if(0>a)break;d>>=1;e>>=1;f=new ue(d,e,d,e);if(b.call(c,a,f))break}};function ui(a){si.call(this,{opaque:i,projection:Re("EPSG:3857")});this.cd=y(a.culture)?a.culture:"en-us";this.h=l;var b=new Vc("//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+a.style),b=new ii(b),a={include:"ImageryProviders",key:a.key},c=na(this.u,this),a=a||k,d="_"+(ji++).toString(36)+pa().toString(36);w._callbacks_||(w._callbacks_={});var e=b.b.T();if(a)for(var f in a)(!a.hasOwnProperty||a.hasOwnProperty(f))&&id(e,f,a[f]);c&&(w._callbacks_[d]=function(a){ki(d,i);c.apply(h,arguments)},id(e, +b.a,"_callbacks_."+d));f=ci(e.toString(),{timeout:b.Ab,hc:i});f.a.push([k,function(){ki(d,l)},h]);f.na&&Zh(f)}B(ui,si); +ui.prototype.u=function(a){var b=a.resourceSets[0].resources[0],c=b.zoomMin,d=b.zoomMax,e=new ti({maxZoom:d,tileSize:new $d(b.imageWidth,b.imageHeight)});this.tileGrid=e;this.fa=pi(function(a){if(a.ne||b<=e?k:new se(a.n,Ib(a.x,b),e)},mi(Ba(b.imageUrlSubdomains,function(a){var c=b.imageUrl.replace("{subdomain}",a).replace("{culture}",this.cd);return function(a){return a===k?h:c.replace("{quadkey}",te(a))}})));var f=He(Re("EPSG:4326"),this.f);this.e= +Ba(b.imageryProviders,function(a){var b=a.attribution,c={};D(a.coverageAreas,function(a){var b=a.zoomMin,d=a.zoomMax,a=a.bbox,a=(new ce(a[1],a[0],a[3],a[2])).transform(f),g,j;for(g=b;g<=d;++g)j=g.toString(),b=gg(e,a,e.a[g]),j in c?c[j].push(b):c[j]=[b]});return new ve(b,c)});this.h=i;J(this,"load")};ui.prototype.c=n("h");function vi(a,b){we.call(this,a,2);this.e=a;this.d=kg(b,a.n);this.c={}}B(vi,we);vi.prototype.J=function(a){a=y(a)?z(a):-1;if(a in this.c)return this.c[a];var b=this.d,c=Tb("CANVAS");c.width=b.width;c.height=b.height;var d=c.getContext("2d");d.strokeStyle="black";d.strokeRect(0.5,0.5,b.width+0.5,b.height+0.5);d.fillStyle="black";d.textAlign="center";d.textBaseline="middle";d.font="24px sans-serif";d.fillText(this.e.toString(),b.width/2,b.height/2);return this.c[a]=c}; +function wi(a){mg.call(this,{extent:a.extent,opaque:l,projection:a.projection,tileGrid:a.tileGrid});this.a=new ri}B(wi,mg);wi.prototype.g=function(){return this.a.ba()>this.a.d};wi.prototype.Ja=function(a){this.a.Ja(a)};wi.prototype.b=function(a){var b=a.toString();if(gh(this.a,b))return jh(this.a,b);a=new vi(a,this.tileGrid);kh(this.a,b,a);return a};function xi(a){var b=a.projection||Re("EPSG:3857"),c=oi;y(a.fa)?c=a.fa:y(a.urls)?c=mi(Ba(a.urls,li)):y(a.url)&&(c=li(a.url));var d=new ti({maxZoom:a.maxZoom}),e=a.extent,c=e!=k?pi(function(b){if(a.maxZoomj||c<=j)return k;c=Ib(b.x,c);return!be(fg(d,new se(b.n,c,b.y)),e)?k:new se(b.n,c,j)},c):pi(function(b){if(a.maxZoomd||c<=d?k:new se(b.n,Ib(b.x,c),d)},c);si.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin, +extent:a.extent,projection:b,tileGrid:d,fa:c})}B(xi,si);function yi(){xi.call(this,{attributions:[new ve('Tiles Courtesy of MapQuest '),new ve('Data © OpenStreetMap contributors, CC BY-SA')],opaque:i,maxZoom:28,url:"http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg"})}B(yi,xi); +function zi(){xi.call(this,{attributions:[new ve('Tiles Courtesy of MapQuest '),new ve("Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency")],maxZoom:18,opaque:i,url:"http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg"})}B(zi,xi);function Ai(){xi.call(this,{attributions:[new ve('© OpenStreetMap contributors, CC BY-SA')],opaque:i,maxZoom:18,url:"http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png"})}B(Ai,xi);function Bi(a){Eg.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,resolutions:a.resolutions,Na:y(a.url)?Cg(a.url,a.params):Dg});this.b=k;this.g=1.5}B(Bi,Eg); +Bi.prototype.J=function(a,b,c){this.a===k||(b=this.a[nf(this.a,b)]);var d=this.b,e;if(e=d!==k)if(e=d.e==b)e=d.I(),e=e.i<=a.i&&a.l<=e.l&&e.j<=a.j&&a.k<=e.k;if(e)return d;var d=a=new ce(a.i,a.j,a.l,a.k),f=this.g;e=d.ha()/2*(f-1);f=d.ca()/2*(f-1);d.i-=e;d.j-=f;d.l+=e;d.k+=f;return this.b=Fg(this,a,b,new $d(a.ha()/b,a.ca()/b),c)};var Ci={terrain:{U:"jpg",opaque:i},"terrain-background":{U:"jpg",opaque:i},"terrain-labels":{U:"png",opaque:l},"terrain-lines":{U:"png",opaque:l},"toner-background":{U:"png",opaque:i},toner:{U:"png",opaque:i},"toner-hybrid":{U:"png",opaque:l},"toner-labels":{U:"png",opaque:l},"toner-lines":{U:"png",opaque:l},"toner-lite":{U:"png",opaque:i},watercolor:{U:"jpg",opaque:i}},Di={terrain:{minZoom:4,maxZoom:18},toner:{minZoom:0,maxZoom:20},watercolor:{minZoom:3,maxZoom:16}},Ei=[new ve('Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.')]; +function Fi(a){var b=a.layer.indexOf("-"),b=-1==b?a.layer:a.layer.slice(0,b),c=Ci[a.layer];xi.call(this,{attributions:Ei,maxZoom:Di[b].maxZoom,opaque:c.opaque,url:y(a.url)?a.url:"http://{a-d}.tile.stamen.com/"+a.layer+"/{z}/{x}/{y}."+c.U})}B(Fi,xi);function Gi(a){var b=a.url,c=a.imageExtent,d=a.imageSize,e=c.ca()/d.height,f=Re(a.projection);Eg.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,Na:function(){return b},resolutions:[e]});this.b=Fg(this,c,e,d,f)}B(Gi,Eg);Gi.prototype.J=function(a){return be(a,this.b.I())?this.b:k};var Hi=[];A("grid",function(a){Hi.push(a)});function Ii(a){si.call(this,{projection:Re("EPSG:3857")});this.h=l;a=this.u=ci(a.uri,{hc:i});a.a.push([this.z,k,this]);a.na&&Zh(a)}B(Ii,si); +Ii.prototype.z=function(){var a=Hi.pop(),b=Re("EPSG:4326"),c,d;y(a.bounds)?(c=a.bounds,c=new ce(c[0],c[1],c[2],c[3]),this.t=d=c.transform(He(b,this.f))):d=c=k;var e=a.minzoom||0,f=a.maxzoom||22,g=new ti({maxZoom:f});this.tileGrid=g;this.fa=pi(function(a){if(a.nc||b<=c)return k;b=Ib(a.x,b);return d!==k&&!be(fg(g,new se(a.n,b,a.y)),d)?k:new se(a.n,b,c)},mi(Ba(a.tiles,li)));if(y(a.attribution)){b=d===k?b.I():d;c={};var j,m;for(j=e;j<=f;++j)m=j.toString(), +c[m]=[gg(g,b,g.a[j])];this.e=[new ve(a.attribution,c)]}this.h=i;J(this,"load")};Ii.prototype.c=n("h");function Ji(a){var b;a.urls?(b=Ba(a.urls,function(b){return ni(b,a.params)}),b=mi(b)):b=a.url?ni(a.url,a.params):oi;var c=a.extent;si.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:c,tileGrid:a.tileGrid,opaque:!(y(a.params.TRANSPARENT)?a.params.TRANSPARENT:1),projection:a.projection,fa:pi(function(a,b,f){if(b.Jb().length<=a.n)return k;var g=a.x,j=fg(b,a),m=f.I();c=y(c)?c:m;c!==k&&(f.sc&&c.i===m.i&&c.l===m.l)&&(f=Math.ceil((c.l-c.i)/(j.l-j.i)),g=Ib(g,f),j=fg(b,new se(a.n,g, +a.y)));return!be(j,c)?k:new se(a.n,g,a.y)},b)})}B(Ji,si);A("goog.require",ba);function Ki(a){U.call(this,{element:a.element,map:a.map,position:a.position,positioning:a.positioning})}B(Ki,U);A("ol.AnchoredElement",Ki);A("ol.AnchoredElementPositioning",yh);yh.BOTTOM_LEFT="bottom-left";yh.BOTTOM_RIGHT="bottom-right";yh.TOP_LEFT="top-left";yh.TOP_RIGHT="top-right";A("ol.Attribution",ve);A("ol.Collection",N);N.prototype.clear=N.prototype.clear;N.prototype.forEach=N.prototype.forEach;N.prototype.getAt=N.prototype.gd;N.prototype.getLength=N.prototype.eb; +N.prototype.insertAt=N.prototype.kb;N.prototype.pop=N.prototype.pop;N.prototype.push=N.prototype.push;N.prototype.remove=N.prototype.remove;N.prototype.removeAt=N.prototype.Wb;N.prototype.setAt=N.prototype.ie;A("ol.Coordinate",K);K.toStringHDMS=function(a){return y(a)?Sc(a.y,"NS")+" "+Sc(a.x,"EW"):""};A("ol.Extent",ce);ce.prototype.getHeight=ce.prototype.ca;ce.prototype.getWidth=ce.prototype.ha;A("ol.Geolocation",V); +function Li(a){S.call(this,{controls:a.controls,interactions:a.interactions,layers:a.layers,renderer:a.renderer,renderers:a.renderers,target:a.target,view:a.view})}B(Li,S);A("ol.Map",Li);S.prototype.addLayer=S.prototype.Xd;S.prototype.addPreRenderFunction=S.prototype.ga;S.prototype.addPreRenderFunctions=S.prototype.Xc;S.prototype.getInteractions=S.prototype.Eb;S.prototype.getRenderer=S.prototype.Qc;S.prototype.removeLayer=S.prototype.Yd;Xe.prototype.getCoordinate=Xe.prototype.b;A("ol.Object",M); +M.prototype.bindTo=M.prototype.Yc;M.prototype.changed=M.prototype.ad;M.prototype.get=M.prototype.q;M.prototype.notify=M.prototype.Bc;M.prototype.set=M.prototype.p;M.prototype.setOptions=M.prototype.Jc;M.prototype.setValues=M.prototype.sb;M.prototype.unbind=M.prototype.$b;M.prototype.unbindAll=M.prototype.se;function Mi(a){O.call(this,{axisOrientation:a.axisOrientation,code:a.code,extent:a.extent,global:a.global,units:a.units})}B(Mi,O);A("ol.Projection",Mi);O.prototype.getAxisOrientation=O.prototype.hd; +O.prototype.getCode=O.prototype.kd;O.prototype.getExtent=O.prototype.I;O.prototype.getMetersPerUnit=O.prototype.ld;O.prototype.getPointResolution=O.prototype.c;O.prototype.getUnits=O.prototype.nd;O.prototype.isGlobal=O.prototype.Ud;A("ol.ProjectionUnits",Ee);Ee.DEGREES="degrees";Ee.FEET="ft";Ee.METERS="m";A("ol.RendererHint",uh);uh.CANVAS="canvas";uh.DOM="dom";uh.WEBGL="webgl";A("ol.RendererHints",th);th.createFromQueryData=th.bd; +function Ni(a){R.call(this,{center:a.center,maxResolution:a.maxResolution,numZoomLevels:a.numZoomLevels,projection:a.projection,resolution:a.resolution,resolutions:a.resolutions,rotation:a.rotation,zoom:a.zoom,zoomFactor:a.zoomFactor})}B(Ni,R);A("ol.View2D",Ni);R.prototype.fitExtent=R.prototype.f;R.prototype.getView2D=R.prototype.g;A("ol.animation",pf);pf.bounce=pf.Gb;pf.pan=pf.aa;pf.rotate=pf.rotate;pf.zoom=pf.zoom;function Oi(a){wf.call(this,{map:a.map,target:a.target})}B(Oi,wf); +A("ol.control.Attribution",Oi);wf.prototype.setMap=wf.prototype.a;function Pi(a){Bh.call(this,{coordinateFormat:a.coordinateFormat,map:a.map,projection:a.projection,target:a.target,undefinedHTML:a.undefinedHTML})}B(Pi,Bh);A("ol.control.MousePosition",Pi);Bh.prototype.setMap=Bh.prototype.a;function Qi(a){Eh.call(this,{map:a.map,minWidth:a.minWidth,target:a.target,units:a.units})}B(Qi,Eh);A("ol.control.ScaleLine",Qi);Eh.prototype.setMap=Eh.prototype.a;A("ol.control.ScaleLineUnits",Dh);Dh.DEGREES="degrees"; +Dh.IMPERIAL="imperial";Dh.METRIC="metric";Dh.NAUTICAL="nautical";Dh.US="us";function Ri(a){xf.call(this,{delta:a.delta,map:a.map,target:a.target})}B(Ri,xf);A("ol.control.Zoom",Ri);xf.prototype.setMap=xf.prototype.a;A("ol.control.defaults",yf);A("ol.easing",Q);Q.bounce=Q.Gb;Q.easeIn=Q.dd;Q.easeOut=Q.Ia;Q.elastic=Q.ed;Q.inAndOut=Q.Aa;Q.linear=Q.xc;Q.upAndDown=Q.Oc;A("ol.interaction.Keyboard",Gh);Gh.prototype.addCallback=Gh.prototype.b;A("ol.interaction.defaults",Uf); +function Si(a){P.call(this,{brightness:a.brightness,contrast:a.contrast,hue:a.hue,opacity:a.opacity,saturation:a.saturation,source:a.source,visible:a.visible})}B(Si,Gg);A("ol.layer.ImageLayer",Si);function Ti(a){P.call(this,{brightness:a.brightness,contrast:a.contrast,hue:a.hue,opacity:a.opacity,saturation:a.saturation,source:a.source,visible:a.visible})}B(Ti,Hg);A("ol.layer.TileLayer",Ti);A("ol.parser.ogc.WMSCapabilities",Sh);Sh.prototype.read=Sh.prototype.ta;A("ol.parser.ogc.WMTSCapabilities",Wh); +Wh.prototype.read=Wh.prototype.ta;A("ol.projection.addProjection",Ne);A("ol.projection.configureProj4jsProjection",function(a){return Ie(a)});A("ol.projection.get",Re);A("ol.projection.getTransform",Se);A("ol.projection.getTransformFromProjections",He);A("ol.projection.transform",function(a,b,c){b=Se(b,c);a=[a.x,a.y];a=b(a,a,2);return new K(a[0],a[1])});A("ol.projection.transformWithProjections",function(a,b,c){b=He(b,c);a=[a.x,a.y];a=b(a,a,2);return new K(a[0],a[1])});Lg.prototype.getCanvas=Lg.prototype.bb; +function Ui(a){ui.call(this,{culture:a.culture,key:a.key,style:a.style})}B(Ui,ui);A("ol.source.BingMaps",Ui);function Vi(a){wi.call(this,{extent:a.extent,projection:a.projection,tileGrid:a.tileGrid})}B(Vi,wi);A("ol.source.DebugTileSource",Vi);A("ol.source.MapQuestOSM",yi);A("ol.source.MapQuestOpenAerial",zi);A("ol.source.OpenStreetMap",Ai); +function Wi(a){Bi.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,params:a.params,projection:a.projection,resolutions:a.resolutions,url:a.url})}B(Wi,Bi);A("ol.source.SingleImageWMS",Wi);function Xi(a){Fi.call(this,{layer:a.layer,maxZoom:a.maxZoom,minZoom:a.minZoom,opaque:a.opaque,url:a.url})}B(Xi,Fi);A("ol.source.Stamen",Xi); +function Yi(a){Gi.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,imageExtent:a.imageExtent,imageSize:a.imageSize,projection:a.projection,url:a.url})}B(Yi,Gi);A("ol.source.StaticImage",Yi);function Zi(a){Ii.call(this,{uri:a.uri})}B(Zi,Ii);A("ol.source.TileJSON",Zi);function $i(a){Ji.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,maxZoom:a.maxZoom,params:a.params,projection:a.projection,tileGrid:a.tileGrid,url:a.url,urls:a.urls})} +B($i,Ji);A("ol.source.TiledWMS",$i);function aj(a){eg.call(this,{origin:a.origin,origins:a.origins,resolutions:a.resolutions,tileSize:a.tileSize,tileSizes:a.tileSizes})}B(aj,eg);A("ol.tilegrid.TileGrid",aj);function bj(a){ti.call(this,{maxZoom:a.maxZoom})}B(bj,ti);A("ol.tilegrid.XYZ",bj);pf.xe={};pf.Oe={};pf.Pe={};pf.Ye={};})(); diff --git a/master/closure-library/closure/goog/array/array.js b/master/closure-library/closure/goog/array/array.js new file mode 100644 index 0000000000..9faac38bc9 --- /dev/null +++ b/master/closure-library/closure/goog/array/array.js @@ -0,0 +1,1416 @@ +// Copyright 2006 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 Utilities for manipulating arrays. + * + */ + + +goog.provide('goog.array'); +goog.provide('goog.array.ArrayLike'); + +goog.require('goog.asserts'); + + +/** + * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should + * rely on Array.prototype functions, if available. + * + * The Array.prototype functions can be defined by external libraries like + * Prototype and setting this flag to false forces closure to use its own + * goog.array implementation. + * + * If your javascript can be loaded by a third party site and you are wary about + * relying on the prototype functions, specify + * "--define goog.NATIVE_ARRAY_PROTOTYPES=false" to the JSCompiler. + */ +goog.NATIVE_ARRAY_PROTOTYPES = true; + + +/** + * @typedef {Array|NodeList|Arguments|{length: number}} + */ +goog.array.ArrayLike; + + +/** + * Returns the last element in an array without removing it. + * @param {goog.array.ArrayLike} array The array. + * @return {*} Last item in array. + */ +goog.array.peek = function(array) { + return array[array.length - 1]; +}; + + +/** + * Reference to the original {@code Array.prototype}. + * @private + */ +goog.array.ARRAY_PROTOTYPE_ = Array.prototype; + + +// NOTE(arv): Since most of the array functions are generic it allows you to +// pass an array-like object. Strings have a length and are considered array- +// like. However, the 'in' operator does not work on strings so we cannot just +// use the array path even if the browser supports indexing into strings. We +// therefore end up splitting the string. + + +/** + * Returns the index of the first element of an array with a specified + * value, or -1 if the element is not present in the array. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof} + * + * @param {goog.array.ArrayLike} arr The array to be searched. + * @param {*} obj The object for which we are searching. + * @param {number=} opt_fromIndex The index at which to start the search. If + * omitted the search starts at index 0. + * @return {number} The index of the first matching array element. + */ +goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.indexOf ? + function(arr, obj, opt_fromIndex) { + goog.asserts.assert(arr.length != null); + + return goog.array.ARRAY_PROTOTYPE_.indexOf.call(arr, obj, opt_fromIndex); + } : + function(arr, obj, opt_fromIndex) { + var fromIndex = opt_fromIndex == null ? + 0 : (opt_fromIndex < 0 ? + Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex); + + if (goog.isString(arr)) { + // Array.prototype.indexOf uses === so only strings should be found. + if (!goog.isString(obj) || obj.length != 1) { + return -1; + } + return arr.indexOf(obj, fromIndex); + } + + for (var i = fromIndex; i < arr.length; i++) { + if (i in arr && arr[i] === obj) + return i; + } + return -1; + }; + + +/** + * Returns the index of the last element of an array with a specified value, or + * -1 if the element is not present in the array. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof} + * + * @param {goog.array.ArrayLike} arr The array to be searched. + * @param {*} obj The object for which we are searching. + * @param {?number=} opt_fromIndex The index at which to start the search. If + * omitted the search starts at the end of the array. + * @return {number} The index of the last matching array element. + */ +goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.lastIndexOf ? + function(arr, obj, opt_fromIndex) { + goog.asserts.assert(arr.length != null); + + // Firefox treats undefined and null as 0 in the fromIndex argument which + // leads it to always return -1 + var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex; + return goog.array.ARRAY_PROTOTYPE_.lastIndexOf.call(arr, obj, fromIndex); + } : + function(arr, obj, opt_fromIndex) { + var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex; + + if (fromIndex < 0) { + fromIndex = Math.max(0, arr.length + fromIndex); + } + + if (goog.isString(arr)) { + // Array.prototype.lastIndexOf uses === so only strings should be found. + if (!goog.isString(obj) || obj.length != 1) { + return -1; + } + return arr.lastIndexOf(obj, fromIndex); + } + + for (var i = fromIndex; i >= 0; i--) { + if (i in arr && arr[i] === obj) + return i; + } + return -1; + }; + + +/** + * Calls a function for each element in an array. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach} + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this: S, T, number, ?): ?} f The function to call for every + * element. + * This function takes 3 arguments (the element, the index and the array). + * The return value is ignored. The function is called only for indexes of + * the array which have assigned values; it is not called for indexes which + * have been deleted or which have never been assigned values. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @template T,S + */ +goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.forEach ? + function(arr, f, opt_obj) { + goog.asserts.assert(arr.length != null); + + goog.array.ARRAY_PROTOTYPE_.forEach.call(arr, f, opt_obj); + } : + function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = 0; i < l; i++) { + if (i in arr2) { + f.call(opt_obj, arr2[i], i, arr); + } + } + }; + + +/** + * Calls a function for each element in an array, starting from the last + * element rather than the first. + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this: S, T, number, ?): ?} f The function to call for every + * element. This function + * takes 3 arguments (the element, the index and the array). The return + * value is ignored. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @template T,S + */ +goog.array.forEachRight = function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = l - 1; i >= 0; --i) { + if (i in arr2) { + f.call(opt_obj, arr2[i], i, arr); + } + } +}; + + +/** + * Calls a function for each element in an array, and if the function returns + * true adds the element to a new array. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-filter} + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?):boolean} f The function to call for + * every element. This function + * takes 3 arguments (the element, the index and the array) and must + * return a Boolean. If the return value is true the element is added to the + * result array. If it is false the element is not included. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @return {!Array} a new array in which only elements that passed the test are + * present. + * @template T,S + */ +goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.filter ? + function(arr, f, opt_obj) { + goog.asserts.assert(arr.length != null); + + return goog.array.ARRAY_PROTOTYPE_.filter.call(arr, f, opt_obj); + } : + function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var res = []; + var resLength = 0; + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = 0; i < l; i++) { + if (i in arr2) { + var val = arr2[i]; // in case f mutates arr2 + if (f.call(opt_obj, val, i, arr)) { + res[resLength++] = val; + } + } + } + return res; + }; + + +/** + * Calls a function for each element in an array and inserts the result into a + * new array. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-map} + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?):?} f The function to call for every + * element. This function + * takes 3 arguments (the element, the index and the array) and should + * return something. The result will be inserted into a new array. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @return {!Array} a new array with the results from f. + * @template T,S + */ +goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.map ? + function(arr, f, opt_obj) { + goog.asserts.assert(arr.length != null); + + return goog.array.ARRAY_PROTOTYPE_.map.call(arr, f, opt_obj); + } : + function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var res = new Array(l); + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = 0; i < l; i++) { + if (i in arr2) { + res[i] = f.call(opt_obj, arr2[i], i, arr); + } + } + return res; + }; + + +/** + * Passes every element of an array into a function and accumulates the result. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce} + * + * For example: + * var a = [1, 2, 3, 4]; + * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0); + * returns 10 + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, R, T, number, ?) : R} f The function to call for + * every element. This function + * takes 4 arguments (the function's previous result or the initial value, + * the value of the current array element, the current array index, and the + * array itself) + * function(previousValue, currentValue, index, array). + * @param {?} val The initial value to pass into the function on the first call. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @return {R} Result of evaluating f repeatedly across the values of the array. + * @template T,S,R + */ +goog.array.reduce = function(arr, f, val, opt_obj) { + if (arr.reduce) { + if (opt_obj) { + return arr.reduce(goog.bind(f, opt_obj), val); + } else { + return arr.reduce(f, val); + } + } + var rval = val; + goog.array.forEach(arr, function(val, index) { + rval = f.call(opt_obj, rval, val, index, arr); + }); + return rval; +}; + + +/** + * Passes every element of an array into a function and accumulates the result, + * starting from the last element and working towards the first. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright} + * + * For example: + * var a = ['a', 'b', 'c']; + * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, ''); + * returns 'cba' + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, R, T, number, ?) : R} f The function to call for + * every element. This function + * takes 4 arguments (the function's previous result or the initial value, + * the value of the current array element, the current array index, and the + * array itself) + * function(previousValue, currentValue, index, array). + * @param {?} val The initial value to pass into the function on the first call. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @return {R} Object returned as a result of evaluating f repeatedly across the + * values of the array. + * @template T,S,R + */ +goog.array.reduceRight = function(arr, f, val, opt_obj) { + if (arr.reduceRight) { + if (opt_obj) { + return arr.reduceRight(goog.bind(f, opt_obj), val); + } else { + return arr.reduceRight(f, val); + } + } + var rval = val; + goog.array.forEachRight(arr, function(val, index) { + rval = f.call(opt_obj, rval, val, index, arr); + }); + return rval; +}; + + +/** + * Calls f for each element of an array. If any call returns true, some() + * returns true (without checking the remaining elements). If all calls + * return false, some() returns false. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-some} + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call for + * for every element. This function takes 3 arguments (the element, the + * index and the array) and should return a boolean. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @return {boolean} true if any element passes the test. + * @template T,S + */ +goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.some ? + function(arr, f, opt_obj) { + goog.asserts.assert(arr.length != null); + + return goog.array.ARRAY_PROTOTYPE_.some.call(arr, f, opt_obj); + } : + function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = 0; i < l; i++) { + if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) { + return true; + } + } + return false; + }; + + +/** + * Call f for each element of an array. If all calls return true, every() + * returns true. If any call returns false, every() returns false and + * does not continue to check the remaining elements. + * + * See {@link http://tinyurl.com/developer-mozilla-org-array-every} + * + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call for + * for every element. This function takes 3 arguments (the element, the + * index and the array) and should return a boolean. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within f. + * @return {boolean} false if any element fails the test. + * @template T,S + */ +goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES && + goog.array.ARRAY_PROTOTYPE_.every ? + function(arr, f, opt_obj) { + goog.asserts.assert(arr.length != null); + + return goog.array.ARRAY_PROTOTYPE_.every.call(arr, f, opt_obj); + } : + function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = 0; i < l; i++) { + if (i in arr2 && !f.call(opt_obj, arr2[i], i, arr)) { + return false; + } + } + return true; + }; + + +/** + * Search an array for the first element that satisfies a given condition and + * return that element. + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call + * for every element. This function takes 3 arguments (the element, the + * index and the array) and should return a boolean. + * @param {S=} opt_obj An optional "this" context for the function. + * @return {T} The first array element that passes the test, or null if no + * element is found. + * @template T,S + */ +goog.array.find = function(arr, f, opt_obj) { + var i = goog.array.findIndex(arr, f, opt_obj); + return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]; +}; + + +/** + * Search an array for the first element that satisfies a given condition and + * return its index. + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call for + * every element. This function + * takes 3 arguments (the element, the index and the array) and should + * return a boolean. + * @param {S=} opt_obj An optional "this" context for the function. + * @return {number} The index of the first array element that passes the test, + * or -1 if no element is found. + * @template T,S + */ +goog.array.findIndex = function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = 0; i < l; i++) { + if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) { + return i; + } + } + return -1; +}; + + +/** + * Search an array (in reverse order) for the last element that satisfies a + * given condition and return that element. + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call + * for every element. This function + * takes 3 arguments (the element, the index and the array) and should + * return a boolean. + * @param {S=} opt_obj An optional "this" context for the function. + * @return {T} The last array element that passes the test, or null if no + * element is found. + * @template T,S + */ +goog.array.findRight = function(arr, f, opt_obj) { + var i = goog.array.findIndexRight(arr, f, opt_obj); + return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]; +}; + + +/** + * Search an array (in reverse order) for the last element that satisfies a + * given condition and return its index. + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call + * for every element. This function + * takes 3 arguments (the element, the index and the array) and should + * return a boolean. + * @param {Object=} opt_obj An optional "this" context for the function. + * @return {number} The index of the last array element that passes the test, + * or -1 if no element is found. + * @template T,S + */ +goog.array.findIndexRight = function(arr, f, opt_obj) { + var l = arr.length; // must be fixed during loop... see docs + var arr2 = goog.isString(arr) ? arr.split('') : arr; + for (var i = l - 1; i >= 0; i--) { + if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) { + return i; + } + } + return -1; +}; + + +/** + * Whether the array contains the given object. + * @param {goog.array.ArrayLike} arr The array to test for the presence of the + * element. + * @param {*} obj The object for which to test. + * @return {boolean} true if obj is present. + */ +goog.array.contains = function(arr, obj) { + return goog.array.indexOf(arr, obj) >= 0; +}; + + +/** + * Whether the array is empty. + * @param {goog.array.ArrayLike} arr The array to test. + * @return {boolean} true if empty. + */ +goog.array.isEmpty = function(arr) { + return arr.length == 0; +}; + + +/** + * Clears the array. + * @param {goog.array.ArrayLike} arr Array or array like object to clear. + */ +goog.array.clear = function(arr) { + // For non real arrays we don't have the magic length so we delete the + // indices. + if (!goog.isArray(arr)) { + for (var i = arr.length - 1; i >= 0; i--) { + delete arr[i]; + } + } + arr.length = 0; +}; + + +/** + * Pushes an item into an array, if it's not already in the array. + * @param {Array.} arr Array into which to insert the item. + * @param {T} obj Value to add. + * @template T + */ +goog.array.insert = function(arr, obj) { + if (!goog.array.contains(arr, obj)) { + arr.push(obj); + } +}; + + +/** + * Inserts an object at the given index of the array. + * @param {goog.array.ArrayLike} arr The array to modify. + * @param {*} obj The object to insert. + * @param {number=} opt_i The index at which to insert the object. If omitted, + * treated as 0. A negative index is counted from the end of the array. + */ +goog.array.insertAt = function(arr, obj, opt_i) { + goog.array.splice(arr, opt_i, 0, obj); +}; + + +/** + * Inserts at the given index of the array, all elements of another array. + * @param {goog.array.ArrayLike} arr The array to modify. + * @param {goog.array.ArrayLike} elementsToAdd The array of elements to add. + * @param {number=} opt_i The index at which to insert the object. If omitted, + * treated as 0. A negative index is counted from the end of the array. + */ +goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) { + goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd); +}; + + +/** + * Inserts an object into an array before a specified object. + * @param {Array.} arr The array to modify. + * @param {T} obj The object to insert. + * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2 + * is omitted or not found, obj is inserted at the end of the array. + * @template T + */ +goog.array.insertBefore = function(arr, obj, opt_obj2) { + var i; + if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) { + arr.push(obj); + } else { + goog.array.insertAt(arr, obj, i); + } +}; + + +/** + * Removes the first occurrence of a particular value from an array. + * @param {goog.array.ArrayLike} arr Array from which to remove value. + * @param {*} obj Object to remove. + * @return {boolean} True if an element was removed. + */ +goog.array.remove = function(arr, obj) { + var i = goog.array.indexOf(arr, obj); + var rv; + if ((rv = i >= 0)) { + goog.array.removeAt(arr, i); + } + return rv; +}; + + +/** + * Removes from an array the element at index i + * @param {goog.array.ArrayLike} arr Array or array like object from which to + * remove value. + * @param {number} i The index to remove. + * @return {boolean} True if an element was removed. + */ +goog.array.removeAt = function(arr, i) { + goog.asserts.assert(arr.length != null); + + // use generic form of splice + // splice returns the removed items and if successful the length of that + // will be 1 + return goog.array.ARRAY_PROTOTYPE_.splice.call(arr, i, 1).length == 1; +}; + + +/** + * Removes the first value that satisfies the given condition. + * @param {Array.|goog.array.ArrayLike} arr Array or array + * like object over which to iterate. + * @param {?function(this:S, T, number, ?) : boolean} f The function to call + * for every element. This function + * takes 3 arguments (the element, the index and the array) and should + * return a boolean. + * @param {S=} opt_obj An optional "this" context for the function. + * @return {boolean} True if an element was removed. + * @template T,S + */ +goog.array.removeIf = function(arr, f, opt_obj) { + var i = goog.array.findIndex(arr, f, opt_obj); + if (i >= 0) { + goog.array.removeAt(arr, i); + return true; + } + return false; +}; + + +/** + * Returns a new array that is the result of joining the arguments. If arrays + * are passed then their items are added, however, if non-arrays are passed they + * will be added to the return array as is. + * + * Note that ArrayLike objects will be added as is, rather than having their + * items added. + * + * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4] + * goog.array.concat(0, [1, 2]) -> [0, 1, 2] + * goog.array.concat([1, 2], null) -> [1, 2, null] + * + * There is bug in all current versions of IE (6, 7 and 8) where arrays created + * in an iframe become corrupted soon (not immediately) after the iframe is + * destroyed. This is common if loading data via goog.net.IframeIo, for example. + * This corruption only affects the concat method which will start throwing + * Catastrophic Errors (#-2147418113). + * + * See http://endoflow.com/scratch/corrupted-arrays.html for a test case. + * + * Internally goog.array should use this, so that all methods will continue to + * work on these broken array objects. + * + * @param {...*} var_args Items to concatenate. Arrays will have each item + * added, while primitives and objects will be added as is. + * @return {!Array} The new resultant array. + */ +goog.array.concat = function(var_args) { + return goog.array.ARRAY_PROTOTYPE_.concat.apply( + goog.array.ARRAY_PROTOTYPE_, arguments); +}; + + +/** + * Converts an object to an array. + * @param {goog.array.ArrayLike} object The object to convert to an array. + * @return {!Array} The object converted into an array. If object has a + * length property, every property indexed with a non-negative number + * less than length will be included in the result. If object does not + * have a length property, an empty array will be returned. + */ +goog.array.toArray = function(object) { + var length = object.length; + + // If length is not a number the following it false. This case is kept for + // backwards compatibility since there are callers that pass objects that are + // not array like. + if (length > 0) { + var rv = new Array(length); + for (var i = 0; i < length; i++) { + rv[i] = object[i]; + } + return rv; + } + return []; +}; + + +/** + * Does a shallow copy of an array. + * @param {goog.array.ArrayLike} arr Array or array-like object to clone. + * @return {!Array} Clone of the input array. + */ +goog.array.clone = goog.array.toArray; + + +/** + * Extends an array with another array, element, or "array like" object. + * This function operates 'in-place', it does not create a new Array. + * + * Example: + * var a = []; + * goog.array.extend(a, [0, 1]); + * a; // [0, 1] + * goog.array.extend(a, 2); + * a; // [0, 1, 2] + * + * @param {Array} arr1 The array to modify. + * @param {...*} var_args The elements or arrays of elements to add to arr1. + */ +goog.array.extend = function(arr1, var_args) { + for (var i = 1; i < arguments.length; i++) { + var arr2 = arguments[i]; + // If we have an Array or an Arguments object we can just call push + // directly. + var isArrayLike; + if (goog.isArray(arr2) || + // Detect Arguments. ES5 says that the [[Class]] of an Arguments object + // is "Arguments" but only V8 and JSC/Safari gets this right. We instead + // detect Arguments by checking for array like and presence of "callee". + (isArrayLike = goog.isArrayLike(arr2)) && + // The getter for callee throws an exception in strict mode + // according to section 10.6 in ES5 so check for presence instead. + arr2.hasOwnProperty('callee')) { + arr1.push.apply(arr1, arr2); + + } else if (isArrayLike) { + // Otherwise loop over arr2 to prevent copying the object. + var len1 = arr1.length; + var len2 = arr2.length; + for (var j = 0; j < len2; j++) { + arr1[len1 + j] = arr2[j]; + } + } else { + arr1.push(arr2); + } + } +}; + + +/** + * Adds or removes elements from an array. This is a generic version of Array + * splice. This means that it might work on other objects similar to arrays, + * such as the arguments object. + * + * @param {goog.array.ArrayLike} arr The array to modify. + * @param {number|undefined} index The index at which to start changing the + * array. If not defined, treated as 0. + * @param {number} howMany How many elements to remove (0 means no removal. A + * value below 0 is treated as zero and so is any other non number. Numbers + * are floored). + * @param {...*} var_args Optional, additional elements to insert into the + * array. + * @return {!Array} the removed elements. + */ +goog.array.splice = function(arr, index, howMany, var_args) { + goog.asserts.assert(arr.length != null); + + return goog.array.ARRAY_PROTOTYPE_.splice.apply( + arr, goog.array.slice(arguments, 1)); +}; + + +/** + * Returns a new array from a segment of an array. This is a generic version of + * Array slice. This means that it might work on other objects similar to + * arrays, such as the arguments object. + * + * @param {Array.|goog.array.ArrayLike} arr The array from + * which to copy a segment. + * @param {number} start The index of the first element to copy. + * @param {number=} opt_end The index after the last element to copy. + * @return {!Array.} A new array containing the specified segment of the + * original array. + * @template T + */ +goog.array.slice = function(arr, start, opt_end) { + goog.asserts.assert(arr.length != null); + + // passing 1 arg to slice is not the same as passing 2 where the second is + // null or undefined (in that case the second argument is treated as 0). + // we could use slice on the arguments object and then use apply instead of + // testing the length + if (arguments.length <= 2) { + return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start); + } else { + return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start, opt_end); + } +}; + + +/** + * Removes all duplicates from an array (retaining only the first + * occurrence of each array element). This function modifies the + * array in place and doesn't change the order of the non-duplicate items. + * + * For objects, duplicates are identified as having the same unique ID as + * defined by {@link goog.getUid}. + * + * Runtime: N, + * Worstcase space: 2N (no dupes) + * + * @param {goog.array.ArrayLike} arr The array from which to remove duplicates. + * @param {Array=} opt_rv An optional array in which to return the results, + * instead of performing the removal inplace. If specified, the original + * array will remain unchanged. + */ +goog.array.removeDuplicates = function(arr, opt_rv) { + var returnArray = opt_rv || arr; + + var seen = {}, cursorInsert = 0, cursorRead = 0; + while (cursorRead < arr.length) { + var current = arr[cursorRead++]; + + // Prefix each type with a single character representing the type to + // prevent conflicting keys (e.g. true and 'true'). + var key = goog.isObject(current) ? + 'o' + goog.getUid(current) : + (typeof current).charAt(0) + current; + + if (!Object.prototype.hasOwnProperty.call(seen, key)) { + seen[key] = true; + returnArray[cursorInsert++] = current; + } + } + returnArray.length = cursorInsert; +}; + + +/** + * Searches the specified array for the specified target using the binary + * search algorithm. If no opt_compareFn is specified, elements are compared + * using goog.array.defaultCompare, which compares the elements + * using the built in < and > operators. This will produce the expected + * behavior for homogeneous arrays of String(s) and Number(s). The array + * specified must be sorted in ascending order (as defined by the + * comparison function). If the array is not sorted, results are undefined. + * If the array contains multiple instances of the specified target value, any + * of these instances may be found. + * + * Runtime: O(log n) + * + * @param {goog.array.ArrayLike} arr The array to be searched. + * @param {*} target The sought value. + * @param {Function=} opt_compareFn Optional comparison function by which the + * array is ordered. Should take 2 arguments to compare, and return a + * negative number, zero, or a positive number depending on whether the + * first argument is less than, equal to, or greater than the second. + * @return {number} Lowest index of the target value if found, otherwise + * (-(insertion point) - 1). The insertion point is where the value should + * be inserted into arr to preserve the sorted property. Return value >= 0 + * iff target is found. + */ +goog.array.binarySearch = function(arr, target, opt_compareFn) { + return goog.array.binarySearch_(arr, + opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */, + target); +}; + + +/** + * Selects an index in the specified array using the binary search algorithm. + * The evaluator receives an element and determines whether the desired index + * is before, at, or after it. The evaluator must be consistent (formally, + * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign) + * must be monotonically non-increasing). + * + * Runtime: O(log n) + * + * @param {goog.array.ArrayLike} arr The array to be searched. + * @param {Function} evaluator Evaluator function that receives 3 arguments + * (the element, the index and the array). Should return a negative number, + * zero, or a positive number depending on whether the desired index is + * before, at, or after the element passed to it. + * @param {Object=} opt_obj The object to be used as the value of 'this' + * within evaluator. + * @return {number} Index of the leftmost element matched by the evaluator, if + * such exists; otherwise (-(insertion point) - 1). The insertion point is + * the index of the first element for which the evaluator returns negative, + * or arr.length if no such element exists. The return value is non-negative + * iff a match is found. + */ +goog.array.binarySelect = function(arr, evaluator, opt_obj) { + return goog.array.binarySearch_(arr, evaluator, true /* isEvaluator */, + undefined /* opt_target */, opt_obj); +}; + + +/** + * Implementation of a binary search algorithm which knows how to use both + * comparison functions and evaluators. If an evaluator is provided, will call + * the evaluator with the given optional data object, conforming to the + * interface defined in binarySelect. Otherwise, if a comparison function is + * provided, will call the comparison function against the given data object. + * + * This implementation purposefully does not use goog.bind or goog.partial for + * performance reasons. + * + * Runtime: O(log n) + * + * @param {goog.array.ArrayLike} arr The array to be searched. + * @param {Function} compareFn Either an evaluator or a comparison function, + * as defined by binarySearch and binarySelect above. + * @param {boolean} isEvaluator Whether the function is an evaluator or a + * comparison function. + * @param {*=} opt_target If the function is a comparison function, then this is + * the target to binary search for. + * @param {Object=} opt_selfObj If the function is an evaluator, this is an + * optional this object for the evaluator. + * @return {number} Lowest index of the target value if found, otherwise + * (-(insertion point) - 1). The insertion point is where the value should + * be inserted into arr to preserve the sorted property. Return value >= 0 + * iff target is found. + * @private + */ +goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target, + opt_selfObj) { + var left = 0; // inclusive + var right = arr.length; // exclusive + var found; + while (left < right) { + var middle = (left + right) >> 1; + var compareResult; + if (isEvaluator) { + compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr); + } else { + compareResult = compareFn(opt_target, arr[middle]); + } + if (compareResult > 0) { + left = middle + 1; + } else { + right = middle; + // We are looking for the lowest index so we can't return immediately. + found = !compareResult; + } + } + // left is the index if found, or the insertion point otherwise. + // ~left is a shorthand for -left - 1. + return found ? left : ~left; +}; + + +/** + * Sorts the specified array into ascending order. If no opt_compareFn is + * specified, elements are compared using + * goog.array.defaultCompare, which compares the elements using + * the built in < and > operators. This will produce the expected behavior + * for homogeneous arrays of String(s) and Number(s), unlike the native sort, + * but will give unpredictable results for heterogenous lists of strings and + * numbers with different numbers of digits. + * + * This sort is not guaranteed to be stable. + * + * Runtime: Same as Array.prototype.sort + * + * @param {Array.} arr The array to be sorted. + * @param {?function(T,T):number=} opt_compareFn Optional comparison + * function by which the + * array is to be ordered. Should take 2 arguments to compare, and return a + * negative number, zero, or a positive number depending on whether the + * first argument is less than, equal to, or greater than the second. + * @template T + */ +goog.array.sort = function(arr, opt_compareFn) { + // TODO(arv): Update type annotation since null is not accepted. + goog.asserts.assert(arr.length != null); + + goog.array.ARRAY_PROTOTYPE_.sort.call( + arr, opt_compareFn || goog.array.defaultCompare); +}; + + +/** + * Sorts the specified array into ascending order in a stable way. If no + * opt_compareFn is specified, elements are compared using + * goog.array.defaultCompare, which compares the elements using + * the built in < and > operators. This will produce the expected behavior + * for homogeneous arrays of String(s) and Number(s). + * + * Runtime: Same as Array.prototype.sort, plus an additional + * O(n) overhead of copying the array twice. + * + * @param {Array.} arr The array to be sorted. + * @param {?function(T, T): number=} opt_compareFn Optional comparison function + * by which the array is to be ordered. Should take 2 arguments to compare, + * and return a negative number, zero, or a positive number depending on + * whether the first argument is less than, equal to, or greater than the + * second. + * @template T + */ +goog.array.stableSort = function(arr, opt_compareFn) { + for (var i = 0; i < arr.length; i++) { + arr[i] = {index: i, value: arr[i]}; + } + var valueCompareFn = opt_compareFn || goog.array.defaultCompare; + function stableCompareFn(obj1, obj2) { + return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index; + }; + goog.array.sort(arr, stableCompareFn); + for (var i = 0; i < arr.length; i++) { + arr[i] = arr[i].value; + } +}; + + +/** + * Sorts an array of objects by the specified object key and compare + * function. If no compare function is provided, the key values are + * compared in ascending order using goog.array.defaultCompare. + * This won't work for keys that get renamed by the compiler. So use + * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}. + * @param {Array.} arr An array of objects to sort. + * @param {string} key The object key to sort by. + * @param {Function=} opt_compareFn The function to use to compare key + * values. + */ +goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) { + var compare = opt_compareFn || goog.array.defaultCompare; + goog.array.sort(arr, function(a, b) { + return compare(a[key], b[key]); + }); +}; + + +/** + * Tells if the array is sorted. + * @param {!Array.} arr The array. + * @param {?function(T,T):number=} opt_compareFn Function to compare the + * array elements. + * Should take 2 arguments to compare, and return a negative number, zero, + * or a positive number depending on whether the first argument is less + * than, equal to, or greater than the second. + * @param {boolean=} opt_strict If true no equal elements are allowed. + * @return {boolean} Whether the array is sorted. + * @template T + */ +goog.array.isSorted = function(arr, opt_compareFn, opt_strict) { + var compare = opt_compareFn || goog.array.defaultCompare; + for (var i = 1; i < arr.length; i++) { + var compareResult = compare(arr[i - 1], arr[i]); + if (compareResult > 0 || compareResult == 0 && opt_strict) { + return false; + } + } + return true; +}; + + +/** + * Compares two arrays for equality. Two arrays are considered equal if they + * have the same length and their corresponding elements are equal according to + * the comparison function. + * + * @param {goog.array.ArrayLike} arr1 The first array to compare. + * @param {goog.array.ArrayLike} arr2 The second array to compare. + * @param {Function=} opt_equalsFn Optional comparison function. + * Should take 2 arguments to compare, and return true if the arguments + * are equal. Defaults to {@link goog.array.defaultCompareEquality} which + * compares the elements using the built-in '===' operator. + * @return {boolean} Whether the two arrays are equal. + */ +goog.array.equals = function(arr1, arr2, opt_equalsFn) { + if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) || + arr1.length != arr2.length) { + return false; + } + var l = arr1.length; + var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality; + for (var i = 0; i < l; i++) { + if (!equalsFn(arr1[i], arr2[i])) { + return false; + } + } + return true; +}; + + +/** + * @deprecated Use {@link goog.array.equals}. + * @param {goog.array.ArrayLike} arr1 See {@link goog.array.equals}. + * @param {goog.array.ArrayLike} arr2 See {@link goog.array.equals}. + * @param {Function=} opt_equalsFn See {@link goog.array.equals}. + * @return {boolean} See {@link goog.array.equals}. + */ +goog.array.compare = function(arr1, arr2, opt_equalsFn) { + return goog.array.equals(arr1, arr2, opt_equalsFn); +}; + + +/** + * 3-way array compare function. + * @param {!goog.array.ArrayLike} arr1 The first array to compare. + * @param {!goog.array.ArrayLike} arr2 The second array to compare. + * @param {?function(?, ?): number=} opt_compareFn Optional comparison function + * by which the array is to be ordered. Should take 2 arguments to compare, + * and return a negative number, zero, or a positive number depending on + * whether the first argument is less than, equal to, or greater than the + * second. + * @return {number} Negative number, zero, or a positive number depending on + * whether the first argument is less than, equal to, or greater than the + * second. + */ +goog.array.compare3 = function(arr1, arr2, opt_compareFn) { + var compare = opt_compareFn || goog.array.defaultCompare; + var l = Math.min(arr1.length, arr2.length); + for (var i = 0; i < l; i++) { + var result = compare(arr1[i], arr2[i]); + if (result != 0) { + return result; + } + } + return goog.array.defaultCompare(arr1.length, arr2.length); +}; + + +/** + * Compares its two arguments for order, using the built in < and > + * operators. + * @param {*} a The first object to be compared. + * @param {*} b The second object to be compared. + * @return {number} A negative number, zero, or a positive number as the first + * argument is less than, equal to, or greater than the second. + */ +goog.array.defaultCompare = function(a, b) { + return a > b ? 1 : a < b ? -1 : 0; +}; + + +/** + * Compares its two arguments for equality, using the built in === operator. + * @param {*} a The first object to compare. + * @param {*} b The second object to compare. + * @return {boolean} True if the two arguments are equal, false otherwise. + */ +goog.array.defaultCompareEquality = function(a, b) { + return a === b; +}; + + +/** + * Inserts a value into a sorted array. The array is not modified if the + * value is already present. + * @param {Array.} array The array to modify. + * @param {T} value The object to insert. + * @param {?function(T,T):number=} opt_compareFn Optional comparison function by + * which the + * array is ordered. Should take 2 arguments to compare, and return a + * negative number, zero, or a positive number depending on whether the + * first argument is less than, equal to, or greater than the second. + * @return {boolean} True if an element was inserted. + * @template T + */ +goog.array.binaryInsert = function(array, value, opt_compareFn) { + var index = goog.array.binarySearch(array, value, opt_compareFn); + if (index < 0) { + goog.array.insertAt(array, value, -(index + 1)); + return true; + } + return false; +}; + + +/** + * Removes a value from a sorted array. + * @param {Array} array The array to modify. + * @param {*} value The object to remove. + * @param {Function=} opt_compareFn Optional comparison function by which the + * array is ordered. Should take 2 arguments to compare, and return a + * negative number, zero, or a positive number depending on whether the + * first argument is less than, equal to, or greater than the second. + * @return {boolean} True if an element was removed. + */ +goog.array.binaryRemove = function(array, value, opt_compareFn) { + var index = goog.array.binarySearch(array, value, opt_compareFn); + return (index >= 0) ? goog.array.removeAt(array, index) : false; +}; + + +/** + * Splits an array into disjoint buckets according to a splitting function. + * @param {Array.} array The array. + * @param {function(T,number,Array.):?} sorter Function to call for every + * element. This + * takes 3 arguments (the element, the index and the array) and must + * return a valid object key (a string, number, etc), or undefined, if + * that object should not be placed in a bucket. + * @return {!Object} An object, with keys being all of the unique return values + * of sorter, and values being arrays containing the items for + * which the splitter returned that key. + * @template T + */ +goog.array.bucket = function(array, sorter) { + var buckets = {}; + + for (var i = 0; i < array.length; i++) { + var value = array[i]; + var key = sorter(value, i, array); + if (goog.isDef(key)) { + // Push the value to the right bucket, creating it if necessary. + var bucket = buckets[key] || (buckets[key] = []); + bucket.push(value); + } + } + + return buckets; +}; + + +/** + * Creates a new object built from the provided array and the key-generation + * function. + * @param {Array.|goog.array.ArrayLike} arr Array or array like object over + * which to iterate whose elements will be the values in the new object. + * @param {?function(this:S, T, number, ?) : string} keyFunc The function to + * call for every element. This function takes 3 arguments (the element, the + * index and the array) and should return a string that will be used as the + * key for the element in the new object. If the function returns the same + * key for more than one element, the value for that key is + * implementation-defined. + * @param {S=} opt_obj The object to be used as the value of 'this' + * within keyFunc. + * @return {!Object.} The new object. + * @template T,S + */ +goog.array.toObject = function(arr, keyFunc, opt_obj) { + var ret = {}; + goog.array.forEach(arr, function(element, index) { + ret[keyFunc.call(opt_obj, element, index, arr)] = element; + }); + return ret; +}; + + +/** + * Returns an array consisting of the given value repeated N times. + * + * @param {*} value The value to repeat. + * @param {number} n The repeat count. + * @return {!Array} An array with the repeated value. + */ +goog.array.repeat = function(value, n) { + var array = []; + for (var i = 0; i < n; i++) { + array[i] = value; + } + return array; +}; + + +/** + * Returns an array consisting of every argument with all arrays + * expanded in-place recursively. + * + * @param {...*} var_args The values to flatten. + * @return {!Array} An array containing the flattened values. + */ +goog.array.flatten = function(var_args) { + var result = []; + for (var i = 0; i < arguments.length; i++) { + var element = arguments[i]; + if (goog.isArray(element)) { + result.push.apply(result, goog.array.flatten.apply(null, element)); + } else { + result.push(element); + } + } + return result; +}; + + +/** + * Rotates an array in-place. After calling this method, the element at + * index i will be the element previously at index (i - n) % + * array.length, for all values of i between 0 and array.length - 1, + * inclusive. + * + * For example, suppose list comprises [t, a, n, k, s]. After invoking + * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k]. + * + * @param {!Array.} array The array to rotate. + * @param {number} n The amount to rotate. + * @return {!Array.} The array. + * @template T + */ +goog.array.rotate = function(array, n) { + goog.asserts.assert(array.length != null); + + if (array.length) { + n %= array.length; + if (n > 0) { + goog.array.ARRAY_PROTOTYPE_.unshift.apply(array, array.splice(-n, n)); + } else if (n < 0) { + goog.array.ARRAY_PROTOTYPE_.push.apply(array, array.splice(0, -n)); + } + } + return array; +}; + + +/** + * Creates a new array for which the element at position i is an array of the + * ith element of the provided arrays. The returned array will only be as long + * as the shortest array provided; additional values are ignored. For example, + * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]]. + * + * This is similar to the zip() function in Python. See {@link + * http://docs.python.org/library/functions.html#zip} + * + * @param {...!goog.array.ArrayLike} var_args Arrays to be combined. + * @return {!Array.} A new array of arrays created from provided arrays. + */ +goog.array.zip = function(var_args) { + if (!arguments.length) { + return []; + } + var result = []; + for (var i = 0; true; i++) { + var value = []; + for (var j = 0; j < arguments.length; j++) { + var arr = arguments[j]; + // If i is larger than the array length, this is the shortest array. + if (i >= arr.length) { + return result; + } + value.push(arr[i]); + } + result.push(value); + } +}; + + +/** + * Shuffles the values in the specified array using the Fisher-Yates in-place + * shuffle (also known as the Knuth Shuffle). By default, calls Math.random() + * and so resets the state of that random number generator. Similarly, may reset + * the state of the any other specified random number generator. + * + * Runtime: O(n) + * + * @param {!Array} arr The array to be shuffled. + * @param {function():number=} opt_randFn Optional random function to use for + * shuffling. + * Takes no arguments, and returns a random number on the interval [0, 1). + * Defaults to Math.random() using JavaScript's built-in Math library. + */ +goog.array.shuffle = function(arr, opt_randFn) { + var randFn = opt_randFn || Math.random; + + for (var i = arr.length - 1; i > 0; i--) { + // Choose a random array index in [0, i] (inclusive with i). + var j = Math.floor(randFn() * (i + 1)); + + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } +}; diff --git a/master/closure-library/closure/goog/asserts/asserts.js b/master/closure-library/closure/goog/asserts/asserts.js new file mode 100644 index 0000000000..2ec57626ea --- /dev/null +++ b/master/closure-library/closure/goog/asserts/asserts.js @@ -0,0 +1,282 @@ +// Copyright 2008 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 Utilities to check the preconditions, postconditions and + * invariants runtime. + * + * Methods in this package should be given special treatment by the compiler + * for type-inference. For example, goog.asserts.assert(foo) + * will restrict foo to a truthy value. + * + * The compiler has an option to disable asserts. So code like: + * + * var x = goog.asserts.assert(foo()); goog.asserts.assert(bar()); + * + * will be transformed into: + * + * var x = foo(); + * + * The compiler will leave in foo() (because its return value is used), + * but it will remove bar() because it assumes it does not have side-effects. + * + */ + +goog.provide('goog.asserts'); +goog.provide('goog.asserts.AssertionError'); + +goog.require('goog.debug.Error'); +goog.require('goog.string'); + + +/** + * @define {boolean} Whether to strip out asserts or to leave them in. + */ +goog.asserts.ENABLE_ASSERTS = goog.DEBUG; + + + +/** + * Error object for failed assertions. + * @param {string} messagePattern The pattern that was used to form message. + * @param {!Array.<*>} messageArgs The items to substitute into the pattern. + * @constructor + * @extends {goog.debug.Error} + */ +goog.asserts.AssertionError = function(messagePattern, messageArgs) { + messageArgs.unshift(messagePattern); + goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs)); + // Remove the messagePattern afterwards to avoid permenantly modifying the + // passed in array. + messageArgs.shift(); + + /** + * The message pattern used to format the error message. Error handlers can + * use this to uniquely identify the assertion. + * @type {string} + */ + this.messagePattern = messagePattern; +}; +goog.inherits(goog.asserts.AssertionError, goog.debug.Error); + + +/** @override */ +goog.asserts.AssertionError.prototype.name = 'AssertionError'; + + +/** + * Throws an exception with the given message and "Assertion failed" prefixed + * onto it. + * @param {string} defaultMessage The message to use if givenMessage is empty. + * @param {Array.<*>} defaultArgs The substitution arguments for defaultMessage. + * @param {string|undefined} givenMessage Message supplied by the caller. + * @param {Array.<*>} givenArgs The substitution arguments for givenMessage. + * @throws {goog.asserts.AssertionError} When the value is not a number. + * @private + */ +goog.asserts.doAssertFailure_ = + function(defaultMessage, defaultArgs, givenMessage, givenArgs) { + var message = 'Assertion failed'; + if (givenMessage) { + message += ': ' + givenMessage; + var args = givenArgs; + } else if (defaultMessage) { + message += ': ' + defaultMessage; + args = defaultArgs; + } + // The '' + works around an Opera 10 bug in the unit tests. Without it, + // a stack trace is added to var message above. With this, a stack trace is + // not added until this line (it causes the extra garbage to be added after + // the assertion message instead of in the middle of it). + throw new goog.asserts.AssertionError('' + message, args || []); +}; + + +/** + * Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is + * true. + * @param {*} condition The condition to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {*} The value of the condition. + * @throws {goog.asserts.AssertionError} When the condition evaluates to false. + */ +goog.asserts.assert = function(condition, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !condition) { + goog.asserts.doAssertFailure_('', null, opt_message, + Array.prototype.slice.call(arguments, 2)); + } + return condition; +}; + + +/** + * Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case + * when we want to add a check in the unreachable area like switch-case + * statement: + * + *
+ *  switch(type) {
+ *    case FOO: doSomething(); break;
+ *    case BAR: doSomethingElse(); break;
+ *    default: goog.assert.fail('Unrecognized type: ' + type);
+ *      // We have only 2 types - "default:" section is unreachable code.
+ *  }
+ * 
+ * + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @throws {goog.asserts.AssertionError} Failure. + */ +goog.asserts.fail = function(opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS) { + throw new goog.asserts.AssertionError( + 'Failure' + (opt_message ? ': ' + opt_message : ''), + Array.prototype.slice.call(arguments, 1)); + } +}; + + +/** + * Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true. + * @param {*} value The value to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {number} The value, guaranteed to be a number when asserts enabled. + * @throws {goog.asserts.AssertionError} When the value is not a number. + */ +goog.asserts.assertNumber = function(value, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) { + goog.asserts.doAssertFailure_('Expected number but got %s: %s.', + [goog.typeOf(value), value], opt_message, + Array.prototype.slice.call(arguments, 2)); + } + return /** @type {number} */ (value); +}; + + +/** + * Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true. + * @param {*} value The value to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {string} The value, guaranteed to be a string when asserts enabled. + * @throws {goog.asserts.AssertionError} When the value is not a string. + */ +goog.asserts.assertString = function(value, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) { + goog.asserts.doAssertFailure_('Expected string but got %s: %s.', + [goog.typeOf(value), value], opt_message, + Array.prototype.slice.call(arguments, 2)); + } + return /** @type {string} */ (value); +}; + + +/** + * Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true. + * @param {*} value The value to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {!Function} The value, guaranteed to be a function when asserts + * enabled. + * @throws {goog.asserts.AssertionError} When the value is not a function. + */ +goog.asserts.assertFunction = function(value, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) { + goog.asserts.doAssertFailure_('Expected function but got %s: %s.', + [goog.typeOf(value), value], opt_message, + Array.prototype.slice.call(arguments, 2)); + } + return /** @type {!Function} */ (value); +}; + + +/** + * Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true. + * @param {*} value The value to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {!Object} The value, guaranteed to be a non-null object. + * @throws {goog.asserts.AssertionError} When the value is not an object. + */ +goog.asserts.assertObject = function(value, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) { + goog.asserts.doAssertFailure_('Expected object but got %s: %s.', + [goog.typeOf(value), value], + opt_message, Array.prototype.slice.call(arguments, 2)); + } + return /** @type {!Object} */ (value); +}; + + +/** + * Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true. + * @param {*} value The value to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {!Array} The value, guaranteed to be a non-null array. + * @throws {goog.asserts.AssertionError} When the value is not an array. + */ +goog.asserts.assertArray = function(value, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) { + goog.asserts.doAssertFailure_('Expected array but got %s: %s.', + [goog.typeOf(value), value], opt_message, + Array.prototype.slice.call(arguments, 2)); + } + return /** @type {!Array} */ (value); +}; + + +/** + * Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true. + * @param {*} value The value to check. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @return {boolean} The value, guaranteed to be a boolean when asserts are + * enabled. + * @throws {goog.asserts.AssertionError} When the value is not a boolean. + */ +goog.asserts.assertBoolean = function(value, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) { + goog.asserts.doAssertFailure_('Expected boolean but got %s: %s.', + [goog.typeOf(value), value], opt_message, + Array.prototype.slice.call(arguments, 2)); + } + return /** @type {boolean} */ (value); +}; + + +/** + * Checks if the value is an instance of the user-defined type if + * goog.asserts.ENABLE_ASSERTS is true. + * + * The compiler may tighten the type returned by this function. + * + * @param {*} value The value to check. + * @param {!Function} type A user-defined constructor. + * @param {string=} opt_message Error message in case of failure. + * @param {...*} var_args The items to substitute into the failure message. + * @throws {goog.asserts.AssertionError} When the value is not an instance of + * type. + * @return {!Object} + */ +goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) { + if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) { + goog.asserts.doAssertFailure_('instanceof check failed.', null, + opt_message, Array.prototype.slice.call(arguments, 3)); + } + return /** @type {!Object} */(value); +}; + diff --git a/master/closure-library/closure/goog/async/animationdelay.js b/master/closure-library/closure/goog/async/animationdelay.js new file mode 100644 index 0000000000..5ee7773b94 --- /dev/null +++ b/master/closure-library/closure/goog/async/animationdelay.js @@ -0,0 +1,268 @@ +// 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 A delayed callback that pegs to the next animation frame + * instead of a user-configurable timeout. + * + */ + +goog.provide('goog.async.AnimationDelay'); + +goog.require('goog.async.Delay'); +goog.require('goog.functions'); + + + +// TODO(nicksantos): Should we factor out the common code between this and +// goog.async.Delay? I'm not sure if there's enough code for this to really +// make sense. Subclassing seems like the wrong approach for a variety of +// reasons. Maybe there should be a common interface? + +/** + * A delayed callback that pegs to the next animation frame + * instead of a user configurable timeout. By design, this should have + * the same interface as goog.async.Delay. + * + * Uses requestAnimationFrame and friends when available, but falls + * back to a timeout of goog.async.AnimationDelay.TIMEOUT. + * + * For more on requestAnimationFrame and how you can use it to create smoother + * animations, see: + * @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * + * @param {function(number)} listener Function to call when the delay completes. + * Will be passed the timestamp when it's called, in unix ms. + * @param {Window=} opt_window The window object to execute the delay in. + * Defaults to the global object. + * @param {Object=} opt_handler The object scope to invoke the function in. + * @constructor + * @extends {goog.Disposable} + */ +goog.async.AnimationDelay = function(listener, opt_window, opt_handler) { + goog.base(this); + + /** + * The function that will be invoked after a delay. + * @type {function(number)} + * @private + */ + this.listener_ = listener; + + /** + * The object context to invoke the callback in. + * @type {Object|undefined} + * @private + */ + this.handler_ = opt_handler; + + /** + * @type {Window} + * @private + */ + this.win_ = opt_window || window; + + /** + * Cached callback function invoked when the delay finishes. + * @type {function()} + * @private + */ + this.callback_ = goog.bind(this.doAction_, this); +}; +goog.inherits(goog.async.AnimationDelay, goog.Disposable); + + +/** + * Identifier of the active delay timeout, or event listener, + * or null when inactive. + * @type {?number} + * @private + */ +goog.async.AnimationDelay.prototype.id_ = null; + + +/** + * If we're using dom listeners. + * @type {?boolean} + * @private + */ +goog.async.AnimationDelay.prototype.usingListeners_ = false; + + +/** + * Default wait timeout for animations (in milliseconds). Only used for timed + * animation, which uses a timer (setTimeout) to schedule animation. + * + * @type {number} + * @const + */ +goog.async.AnimationDelay.TIMEOUT = 20; + + +/** + * Name of event received from the requestAnimationFrame in Firefox. + * + * @type {string} + * @const + * @private + */ +goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_ = 'MozBeforePaint'; + + +/** + * Starts the delay timer. The provided listener function will be called + * before the next animation frame. + */ +goog.async.AnimationDelay.prototype.start = function() { + this.stop(); + this.usingListeners_ = false; + + var raf = this.getRaf_(); + var cancelRaf = this.getCancelRaf_(); + if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) { + // Because Firefox (Gecko) runs animation in separate threads, it also saves + // time by running the requestAnimationFrame callbacks in that same thread. + // Sadly this breaks the assumption of implicit thread-safety in JS, and can + // thus create thread-based inconsistencies on counters etc. + // + // Calling cycleAnimations_ using the MozBeforePaint event instead of as + // callback fixes this. + // + // Trigger this condition only if the mozRequestAnimationFrame is available, + // but not the W3C requestAnimationFrame function (as in draft) or the + // equivalent cancel functions. + this.id_ = goog.events.listen( + this.win_, + goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_, + this.callback_); + this.win_.mozRequestAnimationFrame(null); + this.usingListeners_ = true; + } else if (raf && cancelRaf) { + this.id_ = raf.call(this.win_, this.callback_); + } else { + this.id_ = this.win_.setTimeout( + // Prior to Firefox 13, Gecko passed a non-standard parameter + // to the callback that we want to ignore. + goog.functions.lock(this.callback_), + goog.async.AnimationDelay.TIMEOUT); + } +}; + + +/** + * Stops the delay timer if it is active. No action is taken if the timer is not + * in use. + */ +goog.async.AnimationDelay.prototype.stop = function() { + if (this.isActive()) { + var raf = this.getRaf_(); + var cancelRaf = this.getCancelRaf_(); + if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) { + goog.events.unlistenByKey(this.id_); + } else if (raf && cancelRaf) { + cancelRaf.call(this.win_, /** @type {number} */ (this.id_)); + } else { + this.win_.clearTimeout(this.id_); + } + } + this.id_ = null; +}; + + +/** + * Fires delay's action even if timer has already gone off or has not been + * started yet; guarantees action firing. Stops the delay timer. + */ +goog.async.AnimationDelay.prototype.fire = function() { + this.stop(); + this.doAction_(); +}; + + +/** + * Fires delay's action only if timer is currently active. Stops the delay + * timer. + */ +goog.async.AnimationDelay.prototype.fireIfActive = function() { + if (this.isActive()) { + this.fire(); + } +}; + + +/** + * @return {boolean} True if the delay is currently active, false otherwise. + */ +goog.async.AnimationDelay.prototype.isActive = function() { + return this.id_ != null; +}; + + +/** + * Invokes the callback function after the delay successfully completes. + * @private + */ +goog.async.AnimationDelay.prototype.doAction_ = function() { + if (this.usingListeners_ && this.id_) { + goog.events.unlistenByKey(this.id_); + } + this.id_ = null; + + // We are not using the timestamp returned by requestAnimationFrame + // because it may be either a Date.now-style time or a + // high-resolution time (depending on browser implementation). Using + // goog.now() will ensure that the timestamp used is consistent and + // compatible with goog.fx.Animation. + this.listener_.call(this.handler_, goog.now()); +}; + + +/** @override */ +goog.async.AnimationDelay.prototype.disposeInternal = function() { + this.stop(); + goog.base(this, 'disposeInternal'); +}; + + +/** + * @return {?function(function(number)): number} The requestAnimationFrame + * function, or null if not available on this browser. + * @private + */ +goog.async.AnimationDelay.prototype.getRaf_ = function() { + var win = this.win_; + return win.requestAnimationFrame || + win.webkitRequestAnimationFrame || + win.mozRequestAnimationFrame || + win.oRequestAnimationFrame || + win.msRequestAnimationFrame || + null; +}; + + +/** + * @return {?function(number): number} The cancelAnimationFrame function, + * or null if not available on this browser. + * @private + */ +goog.async.AnimationDelay.prototype.getCancelRaf_ = function() { + var win = this.win_; + return win.cancelRequestAnimationFrame || + win.webkitCancelRequestAnimationFrame || + win.mozCancelRequestAnimationFrame || + win.oCancelRequestAnimationFrame || + win.msCancelRequestAnimationFrame || + null; +}; + diff --git a/master/closure-library/closure/goog/async/conditionaldelay.js b/master/closure-library/closure/goog/async/conditionaldelay.js new file mode 100644 index 0000000000..1e3897579f --- /dev/null +++ b/master/closure-library/closure/goog/async/conditionaldelay.js @@ -0,0 +1,235 @@ +// Copyright 2008 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 Defines a class useful for handling functions that must be + * invoked later when some condition holds. Examples include deferred function + * calls that return a boolean flag whether it succedeed or not. + * + * Example: + * + * function deferred() { + * var succeeded = false; + * // ... custom code + * return succeeded; + * } + * + * var deferredCall = new goog.async.ConditionalDelay(deferred); + * deferredCall.onSuccess = function() { + * alert('Success: The deferred function has been successfully executed.'); + * } + * deferredCall.onFailure = function() { + * alert('Failure: Time limit exceeded.'); + * } + * + * // Call the deferred() every 100 msec until it returns true, + * // or 5 seconds pass. + * deferredCall.start(100, 5000); + * + * // Stop the deferred function call (does nothing if it's not active). + * deferredCall.stop(); + * + */ + + +goog.provide('goog.async.ConditionalDelay'); + +goog.require('goog.Disposable'); +goog.require('goog.async.Delay'); + + + +/** + * A ConditionalDelay object invokes the associated function after a specified + * interval delay and checks its return value. If the function returns + * {@code true} the conditional delay is cancelled and {@see #onSuccess} + * is called. Otherwise this object keeps to invoke the deferred function until + * either it returns {@code true} or the timeout is exceeded. In the latter case + * the {@see #onFailure} method will be called. + * + * The interval duration and timeout can be specified each time the delay is + * started. Calling start on an active delay will reset the timer. + * + * @param {function():boolean} listener Function to call when the delay + * completes. Should return a value that type-converts to {@code true} if + * the call succeeded and this delay should be stopped. + * @param {Object=} opt_handler The object scope to invoke the function in. + * @constructor + * @extends {goog.Disposable} + */ +goog.async.ConditionalDelay = function(listener, opt_handler) { + goog.Disposable.call(this); + + /** + * The function that will be invoked after a delay. + * @type {function():boolean} + * @private + */ + this.listener_ = listener; + + /** + * The object context to invoke the callback in. + * @type {Object|undefined} + * @private + */ + this.handler_ = opt_handler; + + /** + * The underlying goog.async.Delay delegate object. + * @type {goog.async.Delay} + * @private + */ + this.delay_ = new goog.async.Delay( + goog.bind(this.onTick_, this), 0 /*interval*/, this /*scope*/); +}; +goog.inherits(goog.async.ConditionalDelay, goog.Disposable); + + +/** + * The delay interval in milliseconds to between the calls to the callback. + * Note, that the callback may be invoked earlier than this interval if the + * timeout is exceeded. + * @type {number} + * @private + */ +goog.async.ConditionalDelay.prototype.interval_ = 0; + + +/** + * The timeout timestamp until which the delay is to be executed. + * A negative value means no timeout. + * @type {number} + * @private + */ +goog.async.ConditionalDelay.prototype.runUntil_ = 0; + + +/** + * True if the listener has been executed, and it returned {@code true}. + * @type {boolean} + * @private + */ +goog.async.ConditionalDelay.prototype.isDone_ = false; + + +/** @override */ +goog.async.ConditionalDelay.prototype.disposeInternal = function() { + this.delay_.dispose(); + delete this.listener_; + delete this.handler_; + goog.async.ConditionalDelay.superClass_.disposeInternal.call(this); +}; + + +/** + * Starts the delay timer. The provided listener function will be called + * repeatedly after the specified interval until the function returns + * {@code true} or the timeout is exceeded. Calling start on an active timer + * will stop the timer first. + * @param {number=} opt_interval The time interval between the function + * invocations (in milliseconds). Default is 0. + * @param {number=} opt_timeout The timeout interval (in milliseconds). Takes + * precedence over the {@code opt_interval}, i.e. if the timeout is less + * than the invocation interval, the function will be called when the + * timeout is exceeded. A negative value means no timeout. Default is 0. + */ +goog.async.ConditionalDelay.prototype.start = function(opt_interval, + opt_timeout) { + this.stop(); + this.isDone_ = false; + + var timeout = opt_timeout || 0; + this.interval_ = Math.max(opt_interval || 0, 0); + this.runUntil_ = timeout < 0 ? -1 : (goog.now() + timeout); + this.delay_.start( + timeout < 0 ? this.interval_ : Math.min(this.interval_, timeout)); +}; + + +/** + * Stops the delay timer if it is active. No action is taken if the timer is not + * in use. + */ +goog.async.ConditionalDelay.prototype.stop = function() { + this.delay_.stop(); +}; + + +/** + * @return {boolean} True if the delay is currently active, false otherwise. + */ +goog.async.ConditionalDelay.prototype.isActive = function() { + return this.delay_.isActive(); +}; + + +/** + * @return {boolean} True if the listener has been executed and returned + * {@code true} since the last call to {@see #start}. + */ +goog.async.ConditionalDelay.prototype.isDone = function() { + return this.isDone_; +}; + + +/** + * Called when the listener has been successfully executed and returned + * {@code true}. The {@see #isDone} method should return {@code true} by now. + * Designed for inheritance, should be overridden by subclasses or on the + * instances if they care. + */ +goog.async.ConditionalDelay.prototype.onSuccess = function() { + // Do nothing by default. +}; + + +/** + * Called when this delayed call is cancelled because the timeout has been + * exceeded, and the listener has never returned {@code true}. + * Designed for inheritance, should be overridden by subclasses or on the + * instances if they care. + */ +goog.async.ConditionalDelay.prototype.onFailure = function() { + // Do nothing by default. +}; + + +/** + * A callback function for the underlying {@code goog.async.Delay} object. When + * executed the listener function is called, and if it returns {@code true} + * the delay is stopped and the {@see #onSuccess} method is invoked. + * If the timeout is exceeded the delay is stopped and the + * {@see #onFailure} method is called. + * @private + */ +goog.async.ConditionalDelay.prototype.onTick_ = function() { + var successful = this.listener_.call(this.handler_); + if (successful) { + this.isDone_ = true; + this.onSuccess(); + } else { + // Try to reschedule the task. + if (this.runUntil_ < 0) { + // No timeout. + this.delay_.start(this.interval_); + } else { + var timeLeft = this.runUntil_ - goog.now(); + if (timeLeft <= 0) { + this.onFailure(); + } else { + this.delay_.start(Math.min(this.interval_, timeLeft)); + } + } + } +}; diff --git a/master/closure-library/closure/goog/async/delay.js b/master/closure-library/closure/goog/async/delay.js new file mode 100644 index 0000000000..3f3b262aef --- /dev/null +++ b/master/closure-library/closure/goog/async/delay.js @@ -0,0 +1,177 @@ +// Copyright 2007 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 Defines a class useful for handling functions that must be + * invoked after a delay, especially when that delay is frequently restarted. + * Examples include delaying before displaying a tooltip, menu hysteresis, + * idle timers, etc. + * @author brenneman@google.com (Shawn Brenneman) + * @see ../demos/timers.html + */ + + +goog.provide('goog.Delay'); +goog.provide('goog.async.Delay'); + +goog.require('goog.Disposable'); +goog.require('goog.Timer'); + + + +/** + * A Delay object invokes the associated function after a specified delay. The + * interval duration can be specified once in the constructor, or can be defined + * each time the delay is started. Calling start on an active delay will reset + * the timer. + * + * @param {Function} listener Function to call when the delay completes. + * @param {number=} opt_interval The default length of the invocation delay (in + * milliseconds). + * @param {Object=} opt_handler The object scope to invoke the function in. + * @constructor + * @extends {goog.Disposable} + */ +goog.async.Delay = function(listener, opt_interval, opt_handler) { + goog.Disposable.call(this); + + /** + * The function that will be invoked after a delay. + * @type {Function} + * @private + */ + this.listener_ = listener; + + /** + * The default amount of time to delay before invoking the callback. + * @type {number} + * @private + */ + this.interval_ = opt_interval || 0; + + /** + * The object context to invoke the callback in. + * @type {Object|undefined} + * @private + */ + this.handler_ = opt_handler; + + + /** + * Cached callback function invoked when the delay finishes. + * @type {Function} + * @private + */ + this.callback_ = goog.bind(this.doAction_, this); +}; +goog.inherits(goog.async.Delay, goog.Disposable); + + + +/** + * A deprecated alias. + * @deprecated Use goog.async.Delay instead. + * @constructor + */ +goog.Delay = goog.async.Delay; + + +/** + * Identifier of the active delay timeout, or 0 when inactive. + * @type {number} + * @private + */ +goog.async.Delay.prototype.id_ = 0; + + +/** + * Disposes of the object, cancelling the timeout if it is still outstanding and + * removing all object references. + * @override + * @protected + */ +goog.async.Delay.prototype.disposeInternal = function() { + goog.async.Delay.superClass_.disposeInternal.call(this); + this.stop(); + delete this.listener_; + delete this.handler_; +}; + + +/** + * Starts the delay timer. The provided listener function will be called after + * the specified interval. Calling start on an active timer will reset the + * delay interval. + * @param {number=} opt_interval If specified, overrides the object's default + * interval with this one (in milliseconds). + */ +goog.async.Delay.prototype.start = function(opt_interval) { + this.stop(); + this.id_ = goog.Timer.callOnce( + this.callback_, + goog.isDef(opt_interval) ? opt_interval : this.interval_); +}; + + +/** + * Stops the delay timer if it is active. No action is taken if the timer is not + * in use. + */ +goog.async.Delay.prototype.stop = function() { + if (this.isActive()) { + goog.Timer.clear(this.id_); + } + this.id_ = 0; +}; + + +/** + * Fires delay's action even if timer has already gone off or has not been + * started yet; guarantees action firing. Stops the delay timer. + */ +goog.async.Delay.prototype.fire = function() { + this.stop(); + this.doAction_(); +}; + + +/** + * Fires delay's action only if timer is currently active. Stops the delay + * timer. + */ +goog.async.Delay.prototype.fireIfActive = function() { + if (this.isActive()) { + this.fire(); + } +}; + + +/** + * @return {boolean} True if the delay is currently active, false otherwise. + */ +goog.async.Delay.prototype.isActive = function() { + return this.id_ != 0; +}; + + +/** + * Invokes the callback function after the delay successfully completes. + * @private + */ +goog.async.Delay.prototype.doAction_ = function() { + this.id_ = 0; + if (this.listener_) { + this.listener_.call(this.handler_); + } +}; diff --git a/master/closure-library/closure/goog/async/throttle.js b/master/closure-library/closure/goog/async/throttle.js new file mode 100644 index 0000000000..c8ece971bd --- /dev/null +++ b/master/closure-library/closure/goog/async/throttle.js @@ -0,0 +1,189 @@ +// Copyright 2007 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 Definition of the goog.async.Throttle class. + * + * @see ../demos/timers.html + */ + +goog.provide('goog.Throttle'); +goog.provide('goog.async.Throttle'); + +goog.require('goog.Disposable'); +goog.require('goog.Timer'); + + + +/** + * Throttle will perform an action that is passed in no more than once + * per interval (specified in milliseconds). If it gets multiple signals + * to perform the action while it is waiting, it will only perform the action + * once at the end of the interval. + * @param {Function} listener Function to callback when the action is triggered. + * @param {number} interval Interval over which to throttle. The handler can + * only be called once per interval. + * @param {Object=} opt_handler Object in whose scope to call the listener. + * @constructor + * @extends {goog.Disposable} + */ +goog.async.Throttle = function(listener, interval, opt_handler) { + goog.Disposable.call(this); + + /** + * Function to callback + * @type {Function} + * @private + */ + this.listener_ = listener; + + /** + * Interval for the throttle time + * @type {number} + * @private + */ + this.interval_ = interval; + + /** + * "this" context for the listener + * @type {Object|undefined} + * @private + */ + this.handler_ = opt_handler; + + /** + * Cached callback function invoked after the throttle timeout completes + * @type {Function} + * @private + */ + this.callback_ = goog.bind(this.onTimer_, this); +}; +goog.inherits(goog.async.Throttle, goog.Disposable); + + + +/** + * A deprecated alias. + * @deprecated Use goog.async.Throttle instead. + * @constructor + */ +goog.Throttle = goog.async.Throttle; + + +/** + * Indicates that the action is pending and needs to be fired. + * @type {boolean} + * @private + */ +goog.async.Throttle.prototype.shouldFire_ = false; + + +/** + * Indicates the count of nested pauses currently in effect on the throttle. + * When this count is not zero, fired actions will be postponed until the + * throttle is resumed enough times to drop the pause count to zero. + * @type {number} + * @private + */ +goog.async.Throttle.prototype.pauseCount_ = 0; + + +/** + * Timer for scheduling the next callback + * @type {?number} + * @private + */ +goog.async.Throttle.prototype.timer_ = null; + + +/** + * Notifies the throttle that the action has happened. It will throttle the call + * so that the callback is not called too often according to the interval + * parameter passed to the constructor. + */ +goog.async.Throttle.prototype.fire = function() { + if (!this.timer_ && !this.pauseCount_) { + this.doAction_(); + } else { + this.shouldFire_ = true; + } +}; + + +/** + * Cancels any pending action callback. The throttle can be restarted by + * calling {@link #fire}. + */ +goog.async.Throttle.prototype.stop = function() { + if (this.timer_) { + goog.Timer.clear(this.timer_); + this.timer_ = null; + this.shouldFire_ = false; + } +}; + + +/** + * Pauses the throttle. All pending and future action callbacks will be + * delayed until the throttle is resumed. Pauses can be nested. + */ +goog.async.Throttle.prototype.pause = function() { + this.pauseCount_++; +}; + + +/** + * Resumes the throttle. If doing so drops the pausing count to zero, pending + * action callbacks will be executed as soon as possible, but still no sooner + * than an interval's delay after the previous call. Future action callbacks + * will be executed as normal. + */ +goog.async.Throttle.prototype.resume = function() { + this.pauseCount_--; + if (!this.pauseCount_ && this.shouldFire_ && !this.timer_) { + this.shouldFire_ = false; + this.doAction_(); + } +}; + + +/** @override */ +goog.async.Throttle.prototype.disposeInternal = function() { + goog.async.Throttle.superClass_.disposeInternal.call(this); + this.stop(); +}; + + +/** + * Handler for the timer to fire the throttle + * @private + */ +goog.async.Throttle.prototype.onTimer_ = function() { + this.timer_ = null; + + if (this.shouldFire_ && !this.pauseCount_) { + this.shouldFire_ = false; + this.doAction_(); + } +}; + + +/** + * Calls the callback + * @private + */ +goog.async.Throttle.prototype.doAction_ = function() { + this.timer_ = goog.Timer.callOnce(this.callback_, this.interval_); + this.listener_.call(this.handler_); +}; diff --git a/master/closure-library/closure/goog/base.js b/master/closure-library/closure/goog/base.js new file mode 100644 index 0000000000..a73c7c1732 --- /dev/null +++ b/master/closure-library/closure/goog/base.js @@ -0,0 +1,1545 @@ +// Copyright 2006 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 Bootstrap for the Google JS Library (Closure). + * + * In uncompiled mode base.js will write out Closure's deps file, unless the + * global CLOSURE_NO_DEPS is set to true. This allows projects to + * include their own deps file(s) from different locations. + * + */ + + +/** + * @define {boolean} Overridden to true by the compiler when --closure_pass + * or --mark_as_compiled is specified. + */ +var COMPILED = false; + + +/** + * Base namespace for the Closure library. Checks to see goog is + * already defined in the current scope before assigning to prevent + * clobbering if base.js is loaded more than once. + * + * @const + */ +var goog = goog || {}; // Identifies this file as the Closure base. + + +/** + * @define {boolean} + */ +goog.NODE_JS = false; + + +// eval() is used so that "global" does not need to be an extern. +goog.global = goog.NODE_JS ? eval('global') : this; + + +/** + * @define {boolean} DEBUG is provided as a convenience so that debugging code + * that should not be included in a production js_binary can be easily stripped + * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most + * toString() methods should be declared inside an "if (goog.DEBUG)" conditional + * because they are generally used for debugging purposes and it is difficult + * for the JSCompiler to statically determine whether they are used. + */ +goog.DEBUG = true; + + +/** + * @define {string} LOCALE defines the locale being used for compilation. It is + * used to select locale specific data to be compiled in js binary. BUILD rule + * can specify this value by "--define goog.LOCALE=" as JSCompiler + * option. + * + * Take into account that the locale code format is important. You should use + * the canonical Unicode format with hyphen as a delimiter. Language must be + * lowercase, Language Script - Capitalized, Region - UPPERCASE. + * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN. + * + * See more info about locale codes here: + * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers + * + * For language codes you should use values defined by ISO 693-1. See it here + * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from + * this rule: the Hebrew language. For legacy reasons the old code (iw) should + * be used instead of the new code (he), see http://wiki/Main/IIISynonyms. + */ +goog.LOCALE = 'en'; // default to en + + +/** + * Creates object stubs for a namespace. The presence of one or more + * goog.provide() calls indicate that the file defines the given + * objects/namespaces. Build tools also scan for provide/require statements + * to discern dependencies, build dependency files (see deps.js), etc. + * @see goog.require + * @param {string} name Namespace provided by this file in the form + * "goog.package.part". + */ +goog.provide = function(name) { + if (!COMPILED) { + // Ensure that the same namespace isn't provided twice. This is intended + // to teach new developers that 'goog.provide' is effectively a variable + // declaration. And when JSCompiler transforms goog.provide into a real + // variable declaration, the compiled JS should work the same as the raw + // JS--even when the raw JS uses goog.provide incorrectly. + if (goog.isProvided_(name)) { + throw Error('Namespace "' + name + '" already declared.'); + } + delete goog.implicitNamespaces_[name]; + + var namespace = name; + while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { + if (goog.getObjectByName(namespace)) { + break; + } + goog.implicitNamespaces_[namespace] = true; + } + } + + goog.exportPath_(name); +}; + + +/** + * Marks that the current file should only be used for testing, and never for + * live code in production. + * @param {string=} opt_message Optional message to add to the error that's + * raised when used in production code. + */ +goog.setTestOnly = function(opt_message) { + if (COMPILED && !goog.DEBUG) { + opt_message = opt_message || ''; + throw Error('Importing test-only code into non-debug environment' + + opt_message ? ': ' + opt_message : '.'); + } +}; + + +if (!COMPILED) { + + /** + * Check if the given name has been goog.provided. This will return false for + * names that are available only as implicit namespaces. + * @param {string} name name of the object to look for. + * @return {boolean} Whether the name has been provided. + * @private + */ + goog.isProvided_ = function(name) { + return !goog.implicitNamespaces_[name] && !!goog.getObjectByName(name); + }; + + /** + * Namespaces implicitly defined by goog.provide. For example, + * goog.provide('goog.events.Event') implicitly declares + * that 'goog' and 'goog.events' must be namespaces. + * + * @type {Object} + * @private + */ + goog.implicitNamespaces_ = {}; +} + + +/** + * Used in the context of Node JS to determine whether the argument is an + * existing variable in the global namespace, or if it should be added as a + * property of goog.global in order to create it. + * + * @param {string} goog The namespace to test. This is deliberately named "goog" + * rather than "nameSpace" or something more appropriate because the goal is + * to avoid introducing any new variables into the scope of the function + * that would alter the behavior of eval(). + * + * Because it is known that "goog" is an existing global variable, shadowing + * it with a local variable here does not introduce a new variable in the + * scope of this function. Further, it is known that when the local variable + * goog is the value 'goog', this function should always return true, which + * it does. + * + * Ideally, this function would not declare any arguments and would simply + * reference arguments[0], but that yields a WRONG_ARGUMENT_COUNT warning + * at the call sites of goog.isExistingGlobalVariable_() from the Closure + * Compiler when type-checking is enabled. + * @return {boolean} + * @private + */ +goog.isExistingGlobalVariable_ = function(goog) { + // Note that if the variable is declared globally with "var" but is undefined, + // then this function will return a false negative. + // Similarly, if goog is 'arguments', 'parseInt', or any other member that is + // in scope, it will return a false positive. + return String(eval('typeof ' + goog)) !== 'undefined'; +}; + + +/** + * Builds an object structure for the provided namespace path, + * ensuring that names that already exist are not overwritten. For + * example: + * "a.b.c" -> a = {};a.b={};a.b.c={}; + * Used by goog.provide and goog.exportSymbol. + * @param {string} name name of the object that this file defines. + * @param {*=} opt_object the object to expose at the end of the path. + * @param {Object=} opt_objectToExportTo The object to add the path to; default + * is |goog.global|. + * @private + */ +goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) { + var parts = name.split('.'); + var cur = opt_objectToExportTo || goog.global; + + // Internet Explorer exhibits strange behavior when throwing errors from + // methods externed in this manner. See the testExportSymbolExceptions in + // base_test.html for an example. + if (!(parts[0] in cur) && cur.execScript) { + cur.execScript('var ' + parts[0]); + } + + if (goog.NODE_JS && cur === goog.global) { + // If parts[0] is already a variable global scope such as "goog", then do + // not access it from goog.global because then there will be a global + // variable "goog" as well as a "global.goog", and they will be different + // objects, causing all sorts of problems. + if (goog.isExistingGlobalVariable_(parts[0])) { + cur = eval(parts[0]); + parts.shift(); + } + } + + // Certain browsers cannot parse code in the form for((a in b); c;); + // This pattern is produced by the JSCompiler when it collapses the + // statement above into the conditional loop below. To prevent this from + // happening, use a for-loop and reserve the init logic as below. + + // Parentheses added to eliminate strict JS warning in Firefox. + for (var part; parts.length && (part = parts.shift());) { + if (!parts.length && goog.isDef(opt_object)) { + // last part and we have an object; use it + cur[part] = opt_object; + } else if (cur[part]) { + cur = cur[part]; + } else { + cur = cur[part] = {}; + } + } +}; + + +/** + * Returns an object based on its fully qualified external name. If you are + * using a compilation pass that renames property names beware that using this + * function will not find renamed properties. + * + * @param {string} name The fully qualified name. + * @param {Object=} opt_obj The object within which to look; default is + * |goog.global|. + * @return {?} The value (object or primitive) or, if not found, null. + */ +goog.getObjectByName = function(name, opt_obj) { + var parts = name.split('.'); + var cur = opt_obj || goog.global; + + if (goog.NODE_JS && cur === goog.global) { + // If parts[0] is already a variable global scope such as "goog", then do + // not access it from goog.global because then there will be a global + // variable "goog" as well as a "global.goog", and they will be different + // objects, causing all sorts of problems. + if (goog.isExistingGlobalVariable_(parts[0])) { + cur = eval(parts[0]); + parts.shift(); + } + } + + for (var part; part = parts.shift(); ) { + if (goog.isDefAndNotNull(cur[part])) { + cur = cur[part]; + } else { + return null; + } + } + return cur; +}; + + +/** + * Globalizes a whole namespace, such as goog or goog.lang. + * + * @param {Object} obj The namespace to globalize. + * @param {Object=} opt_global The object to add the properties to. + * @deprecated Properties may be explicitly exported to the global scope, but + * this should no longer be done in bulk. + */ +goog.globalize = function(obj, opt_global) { + var global = opt_global || goog.global; + for (var x in obj) { + global[x] = obj[x]; + } +}; + + +/** + * Adds a dependency from a file to the files it requires. + * @param {string} relPath The path to the js file. + * @param {Array} provides An array of strings with the names of the objects + * this file provides. + * @param {Array} requires An array of strings with the names of the objects + * this file requires. + */ +goog.addDependency = function(relPath, provides, requires) { + if (!COMPILED) { + var provide, require; + var path = relPath.replace(/\\/g, '/'); + var deps = goog.dependencies_; + for (var i = 0; provide = provides[i]; i++) { + deps.nameToPath[provide] = path; + if (!(path in deps.pathToNames)) { + deps.pathToNames[path] = {}; + } + deps.pathToNames[path][provide] = true; + } + for (var j = 0; require = requires[j]; j++) { + if (!(path in deps.requires)) { + deps.requires[path] = {}; + } + deps.requires[path][require] = true; + } + } +}; + + + + +// NOTE(nnaze): The debug DOM loader was included in base.js as an orignal +// way to do "debug-mode" development. The dependency system can sometimes +// be confusing, as can the debug DOM loader's asyncronous nature. +// +// With the DOM loader, a call to goog.require() is not blocking -- the +// script will not load until some point after the current script. If a +// namespace is needed at runtime, it needs to be defined in a previous +// script, or loaded via require() with its registered dependencies. +// User-defined namespaces may need their own deps file. See http://go/js_deps, +// http://go/genjsdeps, or, externally, DepsWriter. +// http://code.google.com/closure/library/docs/depswriter.html +// +// Because of legacy clients, the DOM loader can't be easily removed from +// base.js. Work is being done to make it disableable or replaceable for +// different environments (DOM-less JavaScript interpreters like Rhino or V8, +// for example). See bootstrap/ for more information. + + +/** + * @define {boolean} Whether to enable the debug loader. + * + * If enabled, a call to goog.require() will attempt to load the namespace by + * appending a script tag to the DOM (if the namespace has been registered). + * + * If disabled, goog.require() will simply assert that the namespace has been + * provided (and depend on the fact that some outside tool correctly ordered + * the script). + */ +goog.ENABLE_DEBUG_LOADER = true; + + +/** + * Implements a system for the dynamic resolution of dependencies + * that works in parallel with the BUILD system. Note that all calls + * to goog.require will be stripped by the JSCompiler when the + * --closure_pass option is used. + * @see goog.provide + * @param {string} name Namespace to include (as was given in goog.provide()) + * in the form "goog.package.part". + */ +goog.require = function(name) { + + // if the object already exists we do not need do do anything + // TODO(arv): If we start to support require based on file name this has + // to change + // TODO(arv): If we allow goog.foo.* this has to change + // TODO(arv): If we implement dynamic load after page load we should probably + // not remove this code for the compiled output + if (!COMPILED) { + if (goog.isProvided_(name)) { + return; + } + + if (goog.ENABLE_DEBUG_LOADER) { + var path = goog.getPathFromDeps_(name); + if (path) { + goog.included_[path] = true; + goog.writeScripts_(); + return; + } + } + + var errorMessage = 'goog.require could not find: ' + name; + if (goog.global.console) { + goog.global.console['error'](errorMessage); + } + + + throw Error(errorMessage); + + } +}; + + +/** + * Path for included scripts + * @type {string} + */ +goog.basePath = ''; + + +/** + * A hook for overriding the base path. + * @type {string|undefined} + */ +goog.global.CLOSURE_BASE_PATH; + + +/** + * Whether to write out Closure's deps file. By default, + * the deps are written. + * @type {boolean|undefined} + */ +goog.global.CLOSURE_NO_DEPS; + + +/** + * A function to import a single script. This is meant to be overridden when + * Closure is being run in non-HTML contexts, such as web workers. It's defined + * in the global scope so that it can be set before base.js is loaded, which + * allows deps.js to be imported properly. + * + * The function is passed the script source, which is a relative URI. It should + * return true if the script was imported, false otherwise. + */ +goog.global.CLOSURE_IMPORT_SCRIPT; + + +/** + * Null function used for default values of callbacks, etc. + * @return {void} Nothing. + */ +goog.nullFunction = function() {}; + + +/** + * The identity function. Returns its first argument. + * + * @param {*=} opt_returnValue The single value that will be returned. + * @param {...*} var_args Optional trailing arguments. These are ignored. + * @return {?} The first argument. We can't know the type -- just pass it along + * without type. + * @deprecated Use goog.functions.identity instead. + */ +goog.identityFunction = function(opt_returnValue, var_args) { + return opt_returnValue; +}; + + +/** + * When defining a class Foo with an abstract method bar(), you can do: + * + * Foo.prototype.bar = goog.abstractMethod + * + * Now if a subclass of Foo fails to override bar(), an error + * will be thrown when bar() is invoked. + * + * Note: This does not take the name of the function to override as + * an argument because that would make it more difficult to obfuscate + * our JavaScript code. + * + * @type {!Function} + * @throws {Error} when invoked to indicate the method should be + * overridden. + */ +goog.abstractMethod = function() { + throw Error('unimplemented abstract method'); +}; + + +/** + * Adds a {@code getInstance} static method that always return the same instance + * object. + * @param {!Function} ctor The constructor for the class to add the static + * method to. + */ +goog.addSingletonGetter = function(ctor) { + ctor.getInstance = function() { + if (ctor.instance_) { + return ctor.instance_; + } + if (goog.DEBUG) { + // NOTE: JSCompiler can't optimize away Array#push. + goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor; + } + return ctor.instance_ = new ctor; + }; +}; + + +/** + * All singleton classes that have been instantiated, for testing. Don't read + * it directly, use the {@code goog.testing.singleton} module. The compiler + * removes this variable if unused. + * @type {!Array.} + * @private + */ +goog.instantiatedSingletons_ = []; + + +if (!COMPILED && goog.ENABLE_DEBUG_LOADER) { + /** + * Object used to keep track of urls that have already been added. This + * record allows the prevention of circular dependencies. + * @type {Object} + * @private + */ + goog.included_ = {}; + + + /** + * This object is used to keep track of dependencies and other data that is + * used for loading scripts + * @private + * @type {Object} + */ + goog.dependencies_ = { + pathToNames: {}, // 1 to many + nameToPath: {}, // 1 to 1 + requires: {}, // 1 to many + // used when resolving dependencies to prevent us from + // visiting the file twice + visited: {}, + written: {} // used to keep track of script files we have written + }; + + + /** + * Tries to detect whether is in the context of an HTML document. + * @return {boolean} True if it looks like HTML document. + * @private + */ + goog.inHtmlDocument_ = function() { + var doc = goog.global.document; + return typeof doc != 'undefined' && + 'write' in doc; // XULDocument misses write. + }; + + + /** + * Tries to detect the base path of the base.js script that bootstraps Closure + * @private + */ + goog.findBasePath_ = function() { + if (goog.global.CLOSURE_BASE_PATH) { + goog.basePath = goog.global.CLOSURE_BASE_PATH; + return; + } else if (!goog.inHtmlDocument_()) { + return; + } + var doc = goog.global.document; + var scripts = doc.getElementsByTagName('script'); + // Search backwards since the current script is in almost all cases the one + // that has base.js. + for (var i = scripts.length - 1; i >= 0; --i) { + var src = scripts[i].src; + var qmark = src.lastIndexOf('?'); + var l = qmark == -1 ? src.length : qmark; + if (src.substr(l - 7, 7) == 'base.js') { + goog.basePath = src.substr(0, l - 7); + return; + } + } + }; + + + /** + * Imports a script if, and only if, that script hasn't already been imported. + * (Must be called at execution time) + * @param {string} src Script source. + * @private + */ + goog.importScript_ = function(src) { + var importScript = goog.global.CLOSURE_IMPORT_SCRIPT || + goog.writeScriptTag_; + if (!goog.dependencies_.written[src] && importScript(src)) { + goog.dependencies_.written[src] = true; + } + }; + + + /** + * The default implementation of the import function. Writes a script tag to + * import the script. + * + * @param {string} src The script source. + * @return {boolean} True if the script was imported, false otherwise. + * @private + */ + goog.writeScriptTag_ = function(src) { + if (goog.inHtmlDocument_()) { + var doc = goog.global.document; + doc.write( + ''); + assertEquals('SCRIPT', script.tagName); + + if (goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) { + // Removing an Element from a DOM tree in IE sets its parentNode to a new + // DocumentFragment. Bizarre! + assertEquals(goog.dom.NodeType.DOCUMENT_FRAGMENT, + goog.dom.removeNode(div).parentNode.nodeType); + } else { + assertNull(div.parentNode); + } +} + +function testAppend() { + var div = document.createElement('div'); + var b = document.createElement('b'); + var c = document.createTextNode('c'); + goog.dom.append(div, 'a', b, c); + assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); +} + +function testAppend2() { + var div = myIframeDoc.createElement('div'); + var b = myIframeDoc.createElement('b'); + var c = myIframeDoc.createTextNode('c'); + goog.dom.append(div, 'a', b, c); + assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); +} + +function testAppend3() { + var div = document.createElement('div'); + var b = document.createElement('b'); + var c = document.createTextNode('c'); + goog.dom.append(div, ['a', b, c]); + assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); +} + +function testAppend4() { + var div = document.createElement('div'); + var div2 = document.createElement('div'); + div2.innerHTML = 'ac'; + goog.dom.append(div, div2.childNodes); + assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); + assertFalse(div2.hasChildNodes()); +} + +function testGetDocumentScroll() { + // setUpPage added divForTestingScrolling to the DOM. It's not init'd here so + // it can be shared amonst other tests. + window.scrollTo(100, 100); + + assertEquals(100, goog.dom.getDocumentScroll().x); + assertEquals(100, goog.dom.getDocumentScroll().y); +} + +function testGetDocumentScrollOfFixedViewport() { + // iOS and perhaps other environments don't actually support scrolling. + // Instead, you view the document's fixed layout through a screen viewport. + // We need getDocumentScroll to handle this case though. + var fakeDocumentScrollElement = {scrollLeft: 0, scrollTop: 0}; + var fakeDocument = { + defaultView: {pageXOffset: 100, pageYOffset: 100}, + documentElement: fakeDocumentScrollElement, + body: fakeDocumentScrollElement + }; + var dh = goog.dom.getDomHelper(document); + dh.setDocument(fakeDocument); + assertEquals(100, dh.getDocumentScroll().x); + assertEquals(100, dh.getDocumentScroll().y); +} + +function testActiveElementIE() { + if (!goog.userAgent.IE) { + return; + } + + var link = goog.dom.getElement('link'); + link.focus(); + + assertEquals(link.tagName, goog.dom.getActiveElement(document).tagName); + assertEquals(link, goog.dom.getActiveElement(document)); +} + +function testParentElement() { + var testEl = $('testEl'); + var bodyEl = goog.dom.getParentElement(testEl); + assertNotNull(bodyEl); + var htmlEl = goog.dom.getParentElement(bodyEl); + assertNotNull(htmlEl); + var documentNotAnElement = goog.dom.getParentElement(htmlEl); + assertNull(documentNotAnElement); + + var tree = goog.dom.htmlToDocumentFragment( + '
' + + '

Some text

' + + '
Some special text
' + + '
Foo
' + + '
'); + assertNull(goog.dom.getParentElement(tree)); + pEl = goog.dom.getNextNode(tree); + var fragmentRootEl = goog.dom.getParentElement(pEl); + assertEquals(tree, fragmentRootEl); + + var detachedEl = goog.dom.createDom('div'); + var detachedHasNoParent = goog.dom.getParentElement(detachedEl); + assertNull(detachedHasNoParent); +} + +/** + * @return {boolean} Returns true if the userAgent is IE8 or higher. + */ +function isIE8OrHigher() { + return goog.userAgent.IE && goog.userAgent.product.isVersion('8'); +} diff --git a/master/closure-library/closure/goog/dom/fontsizemonitor.js b/master/closure-library/closure/goog/dom/fontsizemonitor.js new file mode 100644 index 0000000000..e505257f1c --- /dev/null +++ b/master/closure-library/closure/goog/dom/fontsizemonitor.js @@ -0,0 +1,158 @@ +// 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 A class that can be used to listen to font size changes. + */ + +goog.provide('goog.dom.FontSizeMonitor'); +goog.provide('goog.dom.FontSizeMonitor.EventType'); + +goog.require('goog.dom'); +goog.require('goog.events'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('goog.userAgent'); + + +// TODO(arv): Move this to goog.events instead. + + + +/** + * This class can be used to monitor changes in font size. Instances will + * dispatch a {@code goog.dom.FontSizeMonitor.EventType.CHANGE} event. + * Example usage: + *
+ * var fms = new goog.dom.FontSizeMonitor();
+ * goog.events.listen(fms, goog.dom.FontSizeMonitor.EventType.CHANGE,
+ *     function(e) {
+ *       alert('Font size was changed');
+ *     });
+ * 
+ * @param {goog.dom.DomHelper=} opt_domHelper DOM helper object that is used to + * determine where to insert the DOM nodes used to determine when the font + * size changes. + * @constructor + * @extends {goog.events.EventTarget} + */ +goog.dom.FontSizeMonitor = function(opt_domHelper) { + goog.events.EventTarget.call(this); + + var dom = opt_domHelper || goog.dom.getDomHelper(); + + /** + * Offscreen iframe which we use to detect resize events. + * @type {Element} + * @private + */ + this.sizeElement_ = dom.createDom( + // The size of the iframe is expressed in em, which are font size relative + // which will cause the iframe to be resized when the font size changes. + // The actual values are not relevant as long as we can ensure that the + // iframe has a non zero size and is completely off screen. + goog.userAgent.IE ? 'div' : 'iframe', { + 'style': 'position:absolute;width:9em;height:9em;top:-99em', + 'tabIndex': -1, + 'aria-hidden': 'true' + }); + var p = dom.getDocument().body; + p.insertBefore(this.sizeElement_, p.firstChild); + + /** + * The object that we listen to resize events on. + * @type {Element|Window} + * @private + */ + var resizeTarget = this.resizeTarget_ = + goog.userAgent.IE ? this.sizeElement_ : + goog.dom.getFrameContentWindow( + /** @type {HTMLIFrameElement} */ (this.sizeElement_)); + + // We need to open and close the document to get Firefox 2 to work. We must + // not do this for IE in case we are using HTTPS since accessing the document + // on an about:blank iframe in IE using HTTPS raises a Permission Denied + // error. + if (goog.userAgent.GECKO) { + var doc = resizeTarget.document; + doc.open(); + doc.close(); + } + + // Listen to resize event on the window inside the iframe. + goog.events.listen(resizeTarget, goog.events.EventType.RESIZE, + this.handleResize_, false, this); + + /** + * Last measured width of the iframe element. + * @type {number} + * @private + */ + this.lastWidth_ = this.sizeElement_.offsetWidth; +}; +goog.inherits(goog.dom.FontSizeMonitor, goog.events.EventTarget); + + +/** + * The event types that the FontSizeMonitor fires. + * @enum {string} + */ +goog.dom.FontSizeMonitor.EventType = { + // TODO(arv): Change value to 'change' after updating the callers. + CHANGE: 'fontsizechange' +}; + + +/** + * Constant for the change event. + * @type {string} + * @deprecated Use {@code goog.dom.FontSizeMonitor.EventType.CHANGE} instead. + */ +goog.dom.FontSizeMonitor.CHANGE_EVENT = + goog.dom.FontSizeMonitor.EventType.CHANGE; + + +/** @override */ +goog.dom.FontSizeMonitor.prototype.disposeInternal = function() { + goog.dom.FontSizeMonitor.superClass_.disposeInternal.call(this); + + goog.events.unlisten(this.resizeTarget_, goog.events.EventType.RESIZE, + this.handleResize_, false, this); + this.resizeTarget_ = null; + + // Firefox 2 crashes if the iframe is removed during the unload phase. + if (!goog.userAgent.GECKO || goog.userAgent.isVersion('1.9')) { + goog.dom.removeNode(this.sizeElement_); + } + delete this.sizeElement_; +}; + + +/** + * Handles the onresize event of the iframe and dispatches a change event in + * case its size really changed. + * @param {goog.events.BrowserEvent} e The event object. + * @private + */ +goog.dom.FontSizeMonitor.prototype.handleResize_ = function(e) { + // Only dispatch the event if the size really changed. Some newer browsers do + // not really change the font-size, instead they zoom the whole page. This + // does trigger window resize events on the iframe but the logical pixel size + // remains the same (the device pixel size changes but that is irrelevant). + var currentWidth = this.sizeElement_.offsetWidth; + if (this.lastWidth_ != currentWidth) { + this.lastWidth_ = currentWidth; + this.dispatchEvent(goog.dom.FontSizeMonitor.EventType.CHANGE); + } +}; diff --git a/master/closure-library/closure/goog/dom/forms.js b/master/closure-library/closure/goog/dom/forms.js new file mode 100644 index 0000000000..57ba4cbe2c --- /dev/null +++ b/master/closure-library/closure/goog/dom/forms.js @@ -0,0 +1,413 @@ +// Copyright 2006 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 Utilities for manipulating a form and elements. + * + * @author arv@google.com (Erik Arvidsson) + * @author jonp@google.com (Jon Perlow) + * @author elsigh@google.com (Lindsey Simon) + */ + +goog.provide('goog.dom.forms'); + +goog.require('goog.structs.Map'); + + +/** + * Returns form data as a map of name to value arrays. This doesn't + * support file inputs. + * @param {HTMLFormElement} form The form. + * @return {!goog.structs.Map} A map of the form data as form name to arrays of + * values. + */ +goog.dom.forms.getFormDataMap = function(form) { + var map = new goog.structs.Map(); + goog.dom.forms.getFormDataHelper_(form, map, + goog.dom.forms.addFormDataToMap_); + return map; +}; + + +/** + * Returns the form data as an application/x-www-url-encoded string. This + * doesn't support file inputs. + * @param {HTMLFormElement} form The form. + * @return {string} An application/x-www-url-encoded string. + */ +goog.dom.forms.getFormDataString = function(form) { + var sb = []; + goog.dom.forms.getFormDataHelper_(form, sb, + goog.dom.forms.addFormDataToStringBuffer_); + return sb.join('&'); +}; + + +/** + * Returns the form data as a map or an application/x-www-url-encoded + * string. This doesn't support file inputs. + * @param {HTMLFormElement} form The form. + * @param {Object} result The object form data is being put in. + * @param {Function} fnAppend Function that takes {@code result}, an element + * name, and an element value, and adds the name/value pair to the result + * object. + * @private + */ +goog.dom.forms.getFormDataHelper_ = function(form, result, fnAppend) { + var els = form.elements; + for (var el, i = 0; el = els[i]; i++) { + if (// Make sure we don't include elements that are not part of the form. + // Some browsers include non-form elements. Check for 'form' property. + // See http://code.google.com/p/closure-library/issues/detail?id=227 + // and + // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#the-input-element + (el.form != form) || + el.disabled || + // HTMLFieldSetElement has a form property but no value. + el.tagName.toLowerCase() == 'fieldset') { + continue; + } + + var name = el.name; + switch (el.type.toLowerCase()) { + case 'file': + // file inputs are not supported + case 'submit': + case 'reset': + case 'button': + // don't submit these + break; + case 'select-multiple': + var values = goog.dom.forms.getValue(el); + if (values != null) { + for (var value, j = 0; value = values[j]; j++) { + fnAppend(result, name, value); + } + } + break; + default: + var value = goog.dom.forms.getValue(el); + if (value != null) { + fnAppend(result, name, value); + } + } + } + + // input[type=image] are not included in the elements collection + var inputs = form.getElementsByTagName('input'); + for (var input, i = 0; input = inputs[i]; i++) { + if (input.form == form && input.type.toLowerCase() == 'image') { + name = input.name; + fnAppend(result, name, input.value); + fnAppend(result, name + '.x', '0'); + fnAppend(result, name + '.y', '0'); + } + } +}; + + +/** + * Adds the name/value pair to the map. + * @param {goog.structs.Map} map The map to add to. + * @param {string} name The name. + * @param {string} value The value. + * @private + */ +goog.dom.forms.addFormDataToMap_ = function(map, name, value) { + var array = map.get(name); + if (!array) { + array = []; + map.set(name, array); + } + array.push(value); +}; + + +/** + * Adds a name/value pair to an string buffer array in the form 'name=value'. + * @param {Array} sb The string buffer array for storing data. + * @param {string} name The name. + * @param {string} value The value. + * @private + */ +goog.dom.forms.addFormDataToStringBuffer_ = function(sb, name, value) { + sb.push(encodeURIComponent(name) + '=' + encodeURIComponent(value)); +}; + + +/** + * Whether the form has a file input. + * @param {HTMLFormElement} form The form. + * @return {boolean} Whether the form has a file input. + */ +goog.dom.forms.hasFileInput = function(form) { + var els = form.elements; + for (var el, i = 0; el = els[i]; i++) { + if (!el.disabled && el.type && el.type.toLowerCase() == 'file') { + return true; + } + } + return false; +}; + + +/** + * Enables or disables either all elements in a form or a single form element. + * @param {Element} el The element, either a form or an element within a form. + * @param {boolean} disabled Whether the element should be disabled. + */ +goog.dom.forms.setDisabled = function(el, disabled) { + // disable all elements in a form + if (el.tagName == 'FORM') { + var els = el.elements; + for (var i = 0; el = els[i]; i++) { + goog.dom.forms.setDisabled(el, disabled); + } + } else { + // makes sure to blur buttons, multi-selects, and any elements which + // maintain keyboard/accessibility focus when disabled + if (disabled == true) { + el.blur(); + } + el.disabled = disabled; + } +}; + + +/** + * Focuses, and optionally selects the content of, a form element. + * @param {Element} el The form element. + */ +goog.dom.forms.focusAndSelect = function(el) { + el.focus(); + if (el.select) { + el.select(); + } +}; + + +/** + * Whether a form element has a value. + * @param {Element} el The element. + * @return {boolean} Whether the form has a value. + */ +goog.dom.forms.hasValue = function(el) { + var value = goog.dom.forms.getValue(el); + return !!value; +}; + + +/** + * Whether a named form field has a value. + * @param {HTMLFormElement} form The form element. + * @param {string} name Name of an input to the form. + * @return {boolean} Whether the form has a value. + */ +goog.dom.forms.hasValueByName = function(form, name) { + var value = goog.dom.forms.getValueByName(form, name); + return !!value; +}; + + +/** + * Gets the current value of any element with a type. + * @param {Element} el The element. + * @return {string|Array.|null} The current value of the element + * (or null). + */ +goog.dom.forms.getValue = function(el) { + var type = el.type; + if (!goog.isDef(type)) { + return null; + } + switch (type.toLowerCase()) { + case 'checkbox': + case 'radio': + return goog.dom.forms.getInputChecked_(el); + case 'select-one': + return goog.dom.forms.getSelectSingle_(el); + case 'select-multiple': + return goog.dom.forms.getSelectMultiple_(el); + default: + return goog.isDef(el.value) ? el.value : null; + } +}; + + +/** + * Alias for goog.dom.form.element.getValue + * @type {Function} + * @deprecated Use {@link goog.dom.forms.getValue} instead. + */ +goog.dom.$F = goog.dom.forms.getValue; + + +/** + * Returns the value of the named form field. In the case of radio buttons, + * returns the value of the checked button with the given name. + * + * @param {HTMLFormElement} form The form element. + * @param {string} name Name of an input to the form. + * + * @return {Array.|string|null} The value of the form element, or + * null if the form element does not exist or has no value. + */ +goog.dom.forms.getValueByName = function(form, name) { + var els = form.elements[name]; + + if (els.type) { + return goog.dom.forms.getValue(els); + } else { + for (var i = 0; i < els.length; i++) { + var val = goog.dom.forms.getValue(els[i]); + if (val) { + return val; + } + } + + return null; + } +}; + + +/** + * Gets the current value of a checkable input element. + * @param {Element} el The element. + * @return {?string} The value of the form element (or null). + * @private + */ +goog.dom.forms.getInputChecked_ = function(el) { + return el.checked ? el.value : null; +}; + + +/** + * Gets the current value of a select-one element. + * @param {Element} el The element. + * @return {?string} The value of the form element (or null). + * @private + */ +goog.dom.forms.getSelectSingle_ = function(el) { + var selectedIndex = el.selectedIndex; + return selectedIndex >= 0 ? el.options[selectedIndex].value : null; +}; + + +/** + * Gets the current value of a select-multiple element. + * @param {Element} el The element. + * @return {Array.?} The value of the form element (or null). + * @private + */ +goog.dom.forms.getSelectMultiple_ = function(el) { + var values = []; + for (var option, i = 0; option = el.options[i]; i++) { + if (option.selected) { + values.push(option.value); + } + } + return values.length ? values : null; +}; + + +/** + * Sets the current value of any element with a type. + * @param {Element} el The element. + * @param {*=} opt_value The value to give to the element, which will be coerced + * by the browser in the default case using toString. This value should be + * an array for setting the value of select multiple elements. + */ +goog.dom.forms.setValue = function(el, opt_value) { + var type = el.type; + if (goog.isDef(type)) { + switch (type.toLowerCase()) { + case 'checkbox': + case 'radio': + goog.dom.forms.setInputChecked_(el, + /** @type {string} */ (opt_value)); + break; + case 'select-one': + goog.dom.forms.setSelectSingle_(el, + /** @type {string} */ (opt_value)); + break; + case 'select-multiple': + goog.dom.forms.setSelectMultiple_(el, + /** @type {Array} */ (opt_value)); + break; + default: + el.value = goog.isDefAndNotNull(opt_value) ? opt_value : ''; + } + } +}; + + +/** + * Sets a checkable input element's checked property. + * #TODO(user): This seems potentially unintuitive since it doesn't set + * the value property but my hunch is that the primary use case is to check a + * checkbox, not to reset its value property. + * @param {Element} el The element. + * @param {string|boolean=} opt_value The value, sets the element checked if + * val is set. + * @private + */ +goog.dom.forms.setInputChecked_ = function(el, opt_value) { + el.checked = opt_value ? 'checked' : null; +}; + + +/** + * Sets the value of a select-one element. + * @param {Element} el The element. + * @param {string=} opt_value The value of the selected option element. + * @private + */ +goog.dom.forms.setSelectSingle_ = function(el, opt_value) { + // unset any prior selections + el.selectedIndex = -1; + if (goog.isString(opt_value)) { + for (var option, i = 0; option = el.options[i]; i++) { + if (option.value == opt_value) { + option.selected = true; + break; + } + } + } +}; + + +/** + * Sets the value of a select-multiple element. + * @param {Element} el The element. + * @param {Array.|string=} opt_value The value of the selected option + * element(s). + * @private + */ +goog.dom.forms.setSelectMultiple_ = function(el, opt_value) { + // reset string opt_values as an array + if (goog.isString(opt_value)) { + opt_value = [opt_value]; + } + for (var option, i = 0; option = el.options[i]; i++) { + // we have to reset the other options to false for select-multiple + option.selected = false; + if (opt_value) { + for (var value, j = 0; value = opt_value[j]; j++) { + if (option.value == value) { + option.selected = true; + } + } + } + } +}; diff --git a/master/closure-library/closure/goog/dom/fullscreen.js b/master/closure-library/closure/goog/dom/fullscreen.js new file mode 100644 index 0000000000..d1f1297314 --- /dev/null +++ b/master/closure-library/closure/goog/dom/fullscreen.js @@ -0,0 +1,124 @@ +// 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 Functions for managing full screen status of the DOM. + * + */ + +goog.provide('goog.dom.fullscreen'); +goog.provide('goog.dom.fullscreen.EventType'); + +goog.require('goog.dom'); +goog.require('goog.userAgent'); +goog.require('goog.userAgent.product'); + + +/** + * Event types for full screen. + * @enum {string} + */ +goog.dom.fullscreen.EventType = { + /** Dispatched by the Document when the fullscreen status changes. */ + CHANGE: goog.userAgent.WEBKIT ? + 'webkitfullscreenchange' : + 'mozfullscreenchange' +}; + + +/** + * Determines if full screen is supported. + * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being + * queried. If not provided, use the current DOM. + * @return {boolean} True iff full screen is supported. + */ +goog.dom.fullscreen.isSupported = function(opt_domHelper) { + var doc = goog.dom.fullscreen.getDocument_(opt_domHelper); + var body = doc.body; + return !!body.webkitRequestFullScreen || + (!!body.mozRequestFullScreen && doc.mozFullScreenEnabled); +}; + + +/** + * Requests putting the element in full screen. + * @param {!Element} element The element to put full screen. + */ +goog.dom.fullscreen.requestFullScreen = function(element) { + if (element.webkitRequestFullScreen) { + element.webkitRequestFullScreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } +}; + + +/** + * Requests putting the element in full screen with full keyboard access. + * @param {!Element} element The element to put full screen. + */ +goog.dom.fullscreen.requestFullScreenWithKeys = function( + element) { + if (element.mozRequestFullScreenWithKeys) { + element.mozRequestFullScreenWithKeys(); + } else if (element.webkitRequestFullScreen && + element.ALLOW_KEYBOARD_INPUT && + goog.userAgent.product.CHROME) { + // Safari has the ALLOW_KEYBOARD_INPUT property but using it gives an error. + element.webkitRequestFullScreen(element.ALLOW_KEYBOARD_INPUT); + } else { + goog.dom.fullscreen.requestFullScreen(element); + } +}; + + +/** + * Exits full screen. + * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being + * queried. If not provided, use the current DOM. + */ +goog.dom.fullscreen.exitFullScreen = function(opt_domHelper) { + var doc = goog.dom.fullscreen.getDocument_(opt_domHelper); + if (doc.webkitCancelFullScreen) { + doc.webkitCancelFullScreen(); + } else if (doc.mozCancelFullScreen) { + doc.mozCancelFullScreen(); + } +}; + + +/** + * Determines if the document is full screen. + * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being + * queried. If not provided, use the current DOM. + * @return {boolean} Whether the document is full screen. + */ +goog.dom.fullscreen.isFullScreen = function(opt_domHelper) { + var doc = goog.dom.fullscreen.getDocument_(opt_domHelper); + return !!doc.webkitIsFullScreen || !!doc.mozFullScreen; +}; + + +/** + * Gets the document object of the dom. + * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being + * queried. If not provided, use the current DOM. + * @return {!Document} The dom document. + * @private + */ +goog.dom.fullscreen.getDocument_ = function(opt_domHelper) { + return opt_domHelper ? + opt_domHelper.getDocument() : + goog.dom.getDomHelper().getDocument(); +}; diff --git a/master/closure-library/closure/goog/dom/iframe.js b/master/closure-library/closure/goog/dom/iframe.js new file mode 100644 index 0000000000..71b3df4fa2 --- /dev/null +++ b/master/closure-library/closure/goog/dom/iframe.js @@ -0,0 +1,129 @@ +// Copyright 2008 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 Utilities for creating and working with iframes + * cross-browser. + * @author gboyer@google.com (Garry Boyer) + */ + + +goog.provide('goog.dom.iframe'); + +goog.require('goog.dom'); + + +/** + * Safe source for a blank iframe. + * + * Intentionally not about:blank, which gives mixed content warnings in IE6 + * over HTTPS. + * + * @type {string} + */ +goog.dom.iframe.BLANK_SOURCE = 'javascript:""'; + + +/** + * Styles to help ensure an undecorated iframe. + * @type {string} + * @private + */ +goog.dom.iframe.STYLES_ = 'border:0;vertical-align:bottom;'; + + +/** + * Creates a completely blank iframe element. + * + * The iframe will not caused mixed-content warnings for IE6 under HTTPS. + * The iframe will also have no borders or padding, so that the styled width + * and height will be the actual width and height of the iframe. + * + * This function currently only attempts to create a blank iframe. There + * are no guarantees to the contents of the iframe or whether it is rendered + * in quirks mode. + * + * @param {goog.dom.DomHelper} domHelper The dom helper to use. + * @param {string=} opt_styles CSS styles for the iframe. + * @return {!HTMLIFrameElement} A completely blank iframe. + */ +goog.dom.iframe.createBlank = function(domHelper, opt_styles) { + return /** @type {!HTMLIFrameElement} */ (domHelper.createDom('iframe', { + 'frameborder': 0, + // Since iframes are inline elements, we must align to bottom to + // compensate for the line descent. + 'style': goog.dom.iframe.STYLES_ + (opt_styles || ''), + 'src': goog.dom.iframe.BLANK_SOURCE + })); +}; + + +/** + * Writes the contents of a blank iframe that has already been inserted + * into the document. + * @param {!HTMLIFrameElement} iframe An iframe with no contents, such as + * one created by goog.dom.iframe.createBlank, but already appended to + * a parent document. + * @param {string} content Content to write to the iframe, from doctype to + * the HTML close tag. + */ +goog.dom.iframe.writeContent = function(iframe, content) { + var doc = goog.dom.getFrameContentDocument(iframe); + doc.open(); + doc.write(content); + doc.close(); +}; + + +// TODO(gboyer): Provide a higher-level API for the most common use case, so +// that you can just provide a list of stylesheets and some content HTML. +/** + * Creates a same-domain iframe containing preloaded content. + * + * This is primarily useful for DOM sandboxing. One use case is to embed + * a trusted Javascript app with potentially conflicting CSS styles. The + * second case is to reduce the cost of layout passes by the browser -- for + * example, you can perform sandbox sizing of characters in an iframe while + * manipulating a heavy DOM in the main window. The iframe and parent frame + * can access each others' properties and functions without restriction. + * + * @param {!Element} parentElement The parent element in which to append the + * iframe. + * @param {string=} opt_headContents Contents to go into the iframe's head. + * @param {string=} opt_bodyContents Contents to go into the iframe's body. + * @param {string=} opt_styles CSS styles for the iframe itself, before adding + * to the parent element. + * @param {boolean=} opt_quirks Whether to use quirks mode (false by default). + * @return {HTMLIFrameElement} An iframe that has the specified contents. + */ +goog.dom.iframe.createWithContent = function( + parentElement, opt_headContents, opt_bodyContents, opt_styles, opt_quirks) { + var domHelper = goog.dom.getDomHelper(parentElement); + // Generate the HTML content. + var contentBuf = []; + + if (!opt_quirks) { + contentBuf.push(''); + } + contentBuf.push('', opt_headContents, '', + opt_bodyContents, ''); + + var iframe = goog.dom.iframe.createBlank(domHelper, opt_styles); + + // Cannot manipulate iframe content until it is in a document. + parentElement.appendChild(iframe); + goog.dom.iframe.writeContent(iframe, contentBuf.join('')); + + return iframe; +}; diff --git a/master/closure-library/closure/goog/dom/iter.js b/master/closure-library/closure/goog/dom/iter.js new file mode 100644 index 0000000000..0224af3ec4 --- /dev/null +++ b/master/closure-library/closure/goog/dom/iter.js @@ -0,0 +1,127 @@ +// Copyright 2008 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 Iterators over DOM nodes. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.iter.AncestorIterator'); +goog.provide('goog.dom.iter.ChildIterator'); +goog.provide('goog.dom.iter.SiblingIterator'); + +goog.require('goog.iter.Iterator'); +goog.require('goog.iter.StopIteration'); + + + +/** + * Iterator over a Node's siblings. + * @param {Node} node The node to start with. + * @param {boolean=} opt_includeNode Whether to return the given node as the + * first return value from next. + * @param {boolean=} opt_reverse Whether to traverse siblings in reverse + * document order. + * @constructor + * @extends {goog.iter.Iterator} + */ +goog.dom.iter.SiblingIterator = function(node, opt_includeNode, opt_reverse) { + /** + * The current node, or null if iteration is finished. + * @type {Node} + * @private + */ + this.node_ = node; + + /** + * Whether to iterate in reverse. + * @type {boolean} + * @private + */ + this.reverse_ = !!opt_reverse; + + if (node && !opt_includeNode) { + this.next(); + } +}; +goog.inherits(goog.dom.iter.SiblingIterator, goog.iter.Iterator); + + +/** @override */ +goog.dom.iter.SiblingIterator.prototype.next = function() { + var node = this.node_; + if (!node) { + throw goog.iter.StopIteration; + } + this.node_ = this.reverse_ ? node.previousSibling : node.nextSibling; + return node; +}; + + + +/** + * Iterator over an Element's children. + * @param {Element} element The element to iterate over. + * @param {boolean=} opt_reverse Optionally traverse children from last to + * first. + * @param {number=} opt_startIndex Optional starting index. + * @constructor + * @extends {goog.dom.iter.SiblingIterator} + */ +goog.dom.iter.ChildIterator = function(element, opt_reverse, opt_startIndex) { + if (!goog.isDef(opt_startIndex)) { + opt_startIndex = opt_reverse && element.childNodes.length ? + element.childNodes.length - 1 : 0; + } + goog.dom.iter.SiblingIterator.call(this, element.childNodes[opt_startIndex], + true, opt_reverse); +}; +goog.inherits(goog.dom.iter.ChildIterator, goog.dom.iter.SiblingIterator); + + + +/** + * Iterator over a Node's ancestors, stopping after the document body. + * @param {Node} node The node to start with. + * @param {boolean=} opt_includeNode Whether to return the given node as the + * first return value from next. + * @constructor + * @extends {goog.iter.Iterator} + */ +goog.dom.iter.AncestorIterator = function(node, opt_includeNode) { + /** + * The current node, or null if iteration is finished. + * @type {Node} + * @private + */ + this.node_ = node; + + if (node && !opt_includeNode) { + this.next(); + } +}; +goog.inherits(goog.dom.iter.AncestorIterator, goog.iter.Iterator); + + +/** @override */ +goog.dom.iter.AncestorIterator.prototype.next = function() { + var node = this.node_; + if (!node) { + throw goog.iter.StopIteration; + } + this.node_ = node.parentNode; + return node; +}; + diff --git a/master/closure-library/closure/goog/dom/multirange.js b/master/closure-library/closure/goog/dom/multirange.js new file mode 100644 index 0000000000..4e2526960d --- /dev/null +++ b/master/closure-library/closure/goog/dom/multirange.js @@ -0,0 +1,519 @@ +// Copyright 2008 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 Utilities for working with W3C multi-part ranges. + * + * @author robbyw@google.com (Robby Walker) + */ + + +goog.provide('goog.dom.MultiRange'); +goog.provide('goog.dom.MultiRangeIterator'); + +goog.require('goog.array'); +goog.require('goog.debug.Logger'); +goog.require('goog.dom.AbstractMultiRange'); +goog.require('goog.dom.AbstractRange'); +goog.require('goog.dom.RangeIterator'); +goog.require('goog.dom.RangeType'); +goog.require('goog.dom.SavedRange'); +goog.require('goog.dom.TextRange'); +goog.require('goog.iter.StopIteration'); + + + +/** + * Creates a new multi part range with no properties. Do not use this + * constructor: use one of the goog.dom.Range.createFrom* methods instead. + * @constructor + * @extends {goog.dom.AbstractMultiRange} + */ +goog.dom.MultiRange = function() { + /** + * Array of browser sub-ranges comprising this multi-range. + * @type {Array.} + * @private + */ + this.browserRanges_ = []; + + /** + * Lazily initialized array of range objects comprising this multi-range. + * @type {Array.} + * @private + */ + this.ranges_ = []; + + /** + * Lazily computed sorted version of ranges_, sorted by start point. + * @type {Array.?} + * @private + */ + this.sortedRanges_ = null; + + /** + * Lazily computed container node. + * @type {Node} + * @private + */ + this.container_ = null; +}; +goog.inherits(goog.dom.MultiRange, goog.dom.AbstractMultiRange); + + +/** + * Creates a new range wrapper from the given browser selection object. Do not + * use this method directly - please use goog.dom.Range.createFrom* instead. + * @param {Selection} selection The browser selection object. + * @return {goog.dom.MultiRange} A range wrapper object. + */ +goog.dom.MultiRange.createFromBrowserSelection = function(selection) { + var range = new goog.dom.MultiRange(); + for (var i = 0, len = selection.rangeCount; i < len; i++) { + range.browserRanges_.push(selection.getRangeAt(i)); + } + return range; +}; + + +/** + * Creates a new range wrapper from the given browser ranges. Do not + * use this method directly - please use goog.dom.Range.createFrom* instead. + * @param {Array.} browserRanges The browser ranges. + * @return {goog.dom.MultiRange} A range wrapper object. + */ +goog.dom.MultiRange.createFromBrowserRanges = function(browserRanges) { + var range = new goog.dom.MultiRange(); + range.browserRanges_ = goog.array.clone(browserRanges); + return range; +}; + + +/** + * Creates a new range wrapper from the given goog.dom.TextRange objects. Do + * not use this method directly - please use goog.dom.Range.createFrom* instead. + * @param {Array.} textRanges The text range objects. + * @return {goog.dom.MultiRange} A range wrapper object. + */ +goog.dom.MultiRange.createFromTextRanges = function(textRanges) { + var range = new goog.dom.MultiRange(); + range.ranges_ = textRanges; + range.browserRanges_ = goog.array.map(textRanges, function(range) { + return range.getBrowserRangeObject(); + }); + return range; +}; + + +/** + * Logging object. + * @type {goog.debug.Logger} + * @private + */ +goog.dom.MultiRange.prototype.logger_ = + goog.debug.Logger.getLogger('goog.dom.MultiRange'); + + +// Method implementations + + +/** + * Clears cached values. Should be called whenever this.browserRanges_ is + * modified. + * @private + */ +goog.dom.MultiRange.prototype.clearCachedValues_ = function() { + this.ranges_ = []; + this.sortedRanges_ = null; + this.container_ = null; +}; + + +/** + * @return {goog.dom.MultiRange} A clone of this range. + * @override + */ +goog.dom.MultiRange.prototype.clone = function() { + return goog.dom.MultiRange.createFromBrowserRanges(this.browserRanges_); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getType = function() { + return goog.dom.RangeType.MULTI; +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getBrowserRangeObject = function() { + // NOTE(robbyw): This method does not make sense for multi-ranges. + if (this.browserRanges_.length > 1) { + this.logger_.warning( + 'getBrowserRangeObject called on MultiRange with more than 1 range'); + } + return this.browserRanges_[0]; +}; + + +/** @override */ +goog.dom.MultiRange.prototype.setBrowserRangeObject = function(nativeRange) { + // TODO(robbyw): Look in to adding setBrowserSelectionObject. + return false; +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getTextRangeCount = function() { + return this.browserRanges_.length; +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getTextRange = function(i) { + if (!this.ranges_[i]) { + this.ranges_[i] = goog.dom.TextRange.createFromBrowserRange( + this.browserRanges_[i]); + } + return this.ranges_[i]; +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getContainer = function() { + if (!this.container_) { + var nodes = []; + for (var i = 0, len = this.getTextRangeCount(); i < len; i++) { + nodes.push(this.getTextRange(i).getContainer()); + } + this.container_ = goog.dom.findCommonAncestor.apply(null, nodes); + } + return this.container_; +}; + + +/** + * @return {Array.} An array of sub-ranges, sorted by start + * point. + */ +goog.dom.MultiRange.prototype.getSortedRanges = function() { + if (!this.sortedRanges_) { + this.sortedRanges_ = this.getTextRanges(); + this.sortedRanges_.sort(function(a, b) { + var aStartNode = a.getStartNode(); + var aStartOffset = a.getStartOffset(); + var bStartNode = b.getStartNode(); + var bStartOffset = b.getStartOffset(); + + if (aStartNode == bStartNode && aStartOffset == bStartOffset) { + return 0; + } + + return goog.dom.Range.isReversed(aStartNode, aStartOffset, bStartNode, + bStartOffset) ? 1 : -1; + }); + } + return this.sortedRanges_; +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getStartNode = function() { + return this.getSortedRanges()[0].getStartNode(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getStartOffset = function() { + return this.getSortedRanges()[0].getStartOffset(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getEndNode = function() { + // NOTE(robbyw): This may return the wrong node if any subranges overlap. + return goog.array.peek(this.getSortedRanges()).getEndNode(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getEndOffset = function() { + // NOTE(robbyw): This may return the wrong value if any subranges overlap. + return goog.array.peek(this.getSortedRanges()).getEndOffset(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.isRangeInDocument = function() { + return goog.array.every(this.getTextRanges(), function(range) { + return range.isRangeInDocument(); + }); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.isCollapsed = function() { + return this.browserRanges_.length == 0 || + this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getText = function() { + return goog.array.map(this.getTextRanges(), function(range) { + return range.getText(); + }).join(''); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getHtmlFragment = function() { + return this.getValidHtml(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getValidHtml = function() { + // NOTE(robbyw): This does not behave well if the sub-ranges overlap. + return goog.array.map(this.getTextRanges(), function(range) { + return range.getValidHtml(); + }).join(''); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.getPastableHtml = function() { + // TODO(robbyw): This should probably do something smart like group TR and TD + // selections in to the same table. + return this.getValidHtml(); +}; + + +/** @override */ +goog.dom.MultiRange.prototype.__iterator__ = function(opt_keys) { + return new goog.dom.MultiRangeIterator(this); +}; + + +// RANGE ACTIONS + + +/** @override */ +goog.dom.MultiRange.prototype.select = function() { + var selection = goog.dom.AbstractRange.getBrowserSelectionForWindow( + this.getWindow()); + selection.removeAllRanges(); + for (var i = 0, len = this.getTextRangeCount(); i < len; i++) { + selection.addRange(this.getTextRange(i).getBrowserRangeObject()); + } +}; + + +/** @override */ +goog.dom.MultiRange.prototype.removeContents = function() { + goog.array.forEach(this.getTextRanges(), function(range) { + range.removeContents(); + }); +}; + + +// SAVE/RESTORE + + +/** @override */ +goog.dom.MultiRange.prototype.saveUsingDom = function() { + return new goog.dom.DomSavedMultiRange_(this); +}; + + +// RANGE MODIFICATION + + +/** + * Collapses this range to a single point, either the first or last point + * depending on the parameter. This will result in the number of ranges in this + * multi range becoming 1. + * @param {boolean} toAnchor Whether to collapse to the anchor. + * @override + */ +goog.dom.MultiRange.prototype.collapse = function(toAnchor) { + if (!this.isCollapsed()) { + var range = toAnchor ? this.getTextRange(0) : this.getTextRange( + this.getTextRangeCount() - 1); + + this.clearCachedValues_(); + range.collapse(toAnchor); + this.ranges_ = [range]; + this.sortedRanges_ = [range]; + this.browserRanges_ = [range.getBrowserRangeObject()]; + } +}; + + +// SAVED RANGE OBJECTS + + + +/** + * A SavedRange implementation using DOM endpoints. + * @param {goog.dom.MultiRange} range The range to save. + * @constructor + * @extends {goog.dom.SavedRange} + * @private + */ +goog.dom.DomSavedMultiRange_ = function(range) { + /** + * Array of saved ranges. + * @type {Array.} + * @private + */ + this.savedRanges_ = goog.array.map(range.getTextRanges(), function(range) { + return range.saveUsingDom(); + }); +}; +goog.inherits(goog.dom.DomSavedMultiRange_, goog.dom.SavedRange); + + +/** + * @return {goog.dom.MultiRange} The restored range. + * @override + */ +goog.dom.DomSavedMultiRange_.prototype.restoreInternal = function() { + var ranges = goog.array.map(this.savedRanges_, function(savedRange) { + return savedRange.restore(); + }); + return goog.dom.MultiRange.createFromTextRanges(ranges); +}; + + +/** @override */ +goog.dom.DomSavedMultiRange_.prototype.disposeInternal = function() { + goog.dom.DomSavedMultiRange_.superClass_.disposeInternal.call(this); + + goog.array.forEach(this.savedRanges_, function(savedRange) { + savedRange.dispose(); + }); + delete this.savedRanges_; +}; + + +// RANGE ITERATION + + + +/** + * Subclass of goog.dom.TagIterator that iterates over a DOM range. It + * adds functions to determine the portion of each text node that is selected. + * + * @param {goog.dom.MultiRange} range The range to traverse. + * @constructor + * @extends {goog.dom.RangeIterator} + */ +goog.dom.MultiRangeIterator = function(range) { + if (range) { + this.iterators_ = goog.array.map( + range.getSortedRanges(), + function(r) { + return goog.iter.toIterator(r); + }); + } + + goog.dom.RangeIterator.call( + this, range ? this.getStartNode() : null, false); +}; +goog.inherits(goog.dom.MultiRangeIterator, goog.dom.RangeIterator); + + +/** + * The list of range iterators left to traverse. + * @type {Array.?} + * @private + */ +goog.dom.MultiRangeIterator.prototype.iterators_ = null; + + +/** + * The index of the current sub-iterator being traversed. + * @type {number} + * @private + */ +goog.dom.MultiRangeIterator.prototype.currentIdx_ = 0; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.getStartTextOffset = function() { + return this.iterators_[this.currentIdx_].getStartTextOffset(); +}; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.getEndTextOffset = function() { + return this.iterators_[this.currentIdx_].getEndTextOffset(); +}; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.getStartNode = function() { + return this.iterators_[0].getStartNode(); +}; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.getEndNode = function() { + return goog.array.peek(this.iterators_).getEndNode(); +}; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.isLast = function() { + return this.iterators_[this.currentIdx_].isLast(); +}; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.next = function() { + /** @preserveTry */ + try { + var it = this.iterators_[this.currentIdx_]; + var next = it.next(); + this.setPosition(it.node, it.tagType, it.depth); + return next; + } catch (ex) { + if (ex !== goog.iter.StopIteration || + this.iterators_.length - 1 == this.currentIdx_) { + throw ex; + } else { + // In case we got a StopIteration, increment counter and try again. + this.currentIdx_++; + return this.next(); + } + } +}; + + +/** @override */ +goog.dom.MultiRangeIterator.prototype.copyFrom = function(other) { + this.iterators_ = goog.array.clone(other.iterators_); + goog.dom.MultiRangeIterator.superClass_.copyFrom.call(this, other); +}; + + +/** + * @return {goog.dom.MultiRangeIterator} An identical iterator. + * @override + */ +goog.dom.MultiRangeIterator.prototype.clone = function() { + var copy = new goog.dom.MultiRangeIterator(null); + copy.copyFrom(this); + return copy; +}; diff --git a/master/closure-library/closure/goog/dom/nodeiterator.js b/master/closure-library/closure/goog/dom/nodeiterator.js new file mode 100644 index 0000000000..22453a021e --- /dev/null +++ b/master/closure-library/closure/goog/dom/nodeiterator.js @@ -0,0 +1,86 @@ +// Copyright 2008 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 Iterator subclass for DOM tree traversal. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.NodeIterator'); + +goog.require('goog.dom.TagIterator'); + + + +/** + * A DOM tree traversal iterator. + * + * Starting with the given node, the iterator walks the DOM in order, reporting + * events for each node. The iterator acts as a prefix iterator: + * + *
+ * <div>1<span>2</span>3</div>
+ * 
+ * + * Will return the following nodes: + * + * [div, 1, span, 2, 3] + * + * With the following depths + * + * [1, 1, 2, 2, 1] + * + * Imagining | represents iterator position, the traversal stops at + * each of the following locations: + * + *
<div>|1|<span>|2|</span>3|</div>
+ * + * The iterator can also be used in reverse mode, which will return the nodes + * and states in the opposite order. The depths will be slightly different + * since, like in normal mode, the depth is computed *after* the last move. + * + * Lastly, it is possible to create an iterator that is unconstrained, meaning + * that it will continue iterating until the end of the document instead of + * until exiting the start node. + * + * @param {Node=} opt_node The start node. Defaults to an empty iterator. + * @param {boolean=} opt_reversed Whether to traverse the tree in reverse. + * @param {boolean=} opt_unconstrained Whether the iterator is not constrained + * to the starting node and its children. + * @param {number=} opt_depth The starting tree depth. + * @constructor + * @extends {goog.dom.TagIterator} + */ +goog.dom.NodeIterator = function(opt_node, opt_reversed, + opt_unconstrained, opt_depth) { + goog.dom.TagIterator.call(this, opt_node, opt_reversed, opt_unconstrained, + null, opt_depth); +}; +goog.inherits(goog.dom.NodeIterator, goog.dom.TagIterator); + + +/** + * Moves to the next position in the DOM tree. + * @return {Node} Returns the next node, or throws a goog.iter.StopIteration + * exception if the end of the iterator's range has been reached. + * @override + */ +goog.dom.NodeIterator.prototype.next = function() { + do { + goog.dom.NodeIterator.superClass_.next.call(this); + } while (this.isEndTag()); + + return this.node; +}; diff --git a/master/closure-library/closure/goog/dom/nodeoffset.js b/master/closure-library/closure/goog/dom/nodeoffset.js new file mode 100644 index 0000000000..084d4b0766 --- /dev/null +++ b/master/closure-library/closure/goog/dom/nodeoffset.js @@ -0,0 +1,112 @@ +// 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 Object to store the offset from one node to another in a way + * that works on any similar DOM structure regardless of whether it is the same + * actual nodes. + * + */ + +goog.provide('goog.dom.NodeOffset'); + +goog.require('goog.Disposable'); +goog.require('goog.dom.TagName'); + + + +/** + * Object to store the offset from one node to another in a way that works on + * any similar DOM structure regardless of whether it is the same actual nodes. + * @param {Node} node The node to get the offset for. + * @param {Node} baseNode The node to calculate the offset from. + * @extends {goog.Disposable} + * @constructor + */ +goog.dom.NodeOffset = function(node, baseNode) { + goog.Disposable.call(this); + + /** + * A stack of childNode offsets. + * @type {Array.} + * @private + */ + this.offsetStack_ = []; + + /** + * A stack of childNode names. + * @type {Array.} + * @private + */ + this.nameStack_ = []; + + while (node && node.nodeName != goog.dom.TagName.BODY && node != baseNode) { + // Compute the sibling offset. + var siblingOffset = 0; + var sib = node.previousSibling; + while (sib) { + sib = sib.previousSibling; + ++siblingOffset; + } + this.offsetStack_.unshift(siblingOffset); + this.nameStack_.unshift(node.nodeName); + + node = node.parentNode; + } +}; +goog.inherits(goog.dom.NodeOffset, goog.Disposable); + + +/** + * @return {string} A string representation of this object. + * @override + */ +goog.dom.NodeOffset.prototype.toString = function() { + var strs = []; + var name; + for (var i = 0; name = this.nameStack_[i]; i++) { + strs.push(this.offsetStack_[i] + ',' + name); + } + return strs.join('\n'); +}; + + +/** + * Walk the dom and find the node relative to baseNode. Returns null on + * failure. + * @param {Node} baseNode The node to start walking from. Should be equivalent + * to the node passed in to the constructor, in that it should have the + * same contents. + * @return {Node} The node relative to baseNode, or null on failure. + */ +goog.dom.NodeOffset.prototype.findTargetNode = function(baseNode) { + var name; + var curNode = baseNode; + for (var i = 0; name = this.nameStack_[i]; ++i) { + curNode = curNode.childNodes[this.offsetStack_[i]]; + + // Sanity check and make sure the element names match. + if (!curNode || curNode.nodeName != name) { + return null; + } + } + return curNode; +}; + + +/** @override */ +goog.dom.NodeOffset.prototype.disposeInternal = function() { + delete this.offsetStack_; + delete this.nameStack_; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/abstractpattern.js b/master/closure-library/closure/goog/dom/pattern/abstractpattern.js new file mode 100644 index 0000000000..6015b09c5e --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/abstractpattern.js @@ -0,0 +1,60 @@ +// Copyright 2007 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 DOM pattern base class. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.AbstractPattern'); + +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Base pattern class for DOM matching. + * + * @constructor + */ +goog.dom.pattern.AbstractPattern = function() { +}; + + +/** + * The first node matched by this pattern. + * @type {Node} + */ +goog.dom.pattern.AbstractPattern.prototype.matchedNode = null; + + +/** + * Reset any internal state this pattern keeps. + */ +goog.dom.pattern.AbstractPattern.prototype.reset = function() { + // The base implementation does nothing. +}; + + +/** + * Test whether this pattern matches the given token. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} {@code MATCH} if the pattern matches. + */ +goog.dom.pattern.AbstractPattern.prototype.matchToken = function(token, type) { + return goog.dom.pattern.MatchType.NO_MATCH; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/allchildren.js b/master/closure-library/closure/goog/dom/pattern/allchildren.js new file mode 100644 index 0000000000..86f8cdf9e3 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/allchildren.js @@ -0,0 +1,75 @@ +// Copyright 2007 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 DOM pattern to match any children of a tag. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.AllChildren'); + +goog.require('goog.dom.pattern.AbstractPattern'); +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Pattern object that matches any nodes at or below the current tree depth. + * + * @constructor + * @extends {goog.dom.pattern.AbstractPattern} + */ +goog.dom.pattern.AllChildren = function() { +}; +goog.inherits(goog.dom.pattern.AllChildren, goog.dom.pattern.AbstractPattern); + + +/** + * Tracks the matcher's depth to detect the end of the tag. + * + * @type {number} + * @private + */ +goog.dom.pattern.AllChildren.prototype.depth_ = 0; + + +/** + * Test whether the given token is on the same level. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the + * same level or deeper and {@code BACKTRACK_MATCH} if not. + * @override + */ +goog.dom.pattern.AllChildren.prototype.matchToken = function(token, type) { + this.depth_ += type; + + if (this.depth_ >= 0) { + return goog.dom.pattern.MatchType.MATCHING; + } else { + this.depth_ = 0; + return goog.dom.pattern.MatchType.BACKTRACK_MATCH; + } +}; + + +/** + * Reset any internal state this pattern keeps. + * @override + */ +goog.dom.pattern.AllChildren.prototype.reset = function() { + this.depth_ = 0; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/callback/callback.js b/master/closure-library/closure/goog/dom/pattern/callback/callback.js new file mode 100644 index 0000000000..7d7aa60c33 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/callback/callback.js @@ -0,0 +1,82 @@ +// Copyright 2007 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 Useful callback functions for the DOM matcher. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.callback'); + +goog.require('goog.dom'); +goog.require('goog.dom.TagWalkType'); +goog.require('goog.iter'); + + +/** + * Callback function for use in {@link goog.dom.pattern.Matcher.addPattern} + * that removes the matched node from the tree. Should be used in conjunciton + * with a {@link goog.dom.pattern.StartTag} pattern. + * + * @param {Node} node The node matched by the pattern. + * @param {goog.dom.TagIterator} position The position where the match + * finished. + * @return {boolean} Returns true to indicate tree changes were made. + */ +goog.dom.pattern.callback.removeNode = function(node, position) { + // Find out which position would be next. + position.setPosition(node, goog.dom.TagWalkType.END_TAG); + + goog.iter.nextOrValue(position, null); + + // Remove the node. + goog.dom.removeNode(node); + + // Correct for the depth change. + position.depth -= 1; + + // Indicate that we made position/tree changes. + return true; +}; + + +/** + * Callback function for use in {@link goog.dom.pattern.Matcher.addPattern} + * that removes the matched node from the tree and replaces it with its + * children. Should be used in conjunction with a + * {@link goog.dom.pattern.StartTag} pattern. + * + * @param {Element} node The node matched by the pattern. + * @param {goog.dom.TagIterator} position The position where the match + * finished. + * @return {boolean} Returns true to indicate tree changes were made. + */ +goog.dom.pattern.callback.flattenElement = function(node, position) { + // Find out which position would be next. + position.setPosition(node, node.firstChild ? + goog.dom.TagWalkType.START_TAG : + goog.dom.TagWalkType.END_TAG); + + goog.iter.nextOrValue(position, null); + + // Flatten the node. + goog.dom.flattenElement(node); + + // Correct for the depth change. + position.depth -= 1; + + // Indicate that we made position/tree changes. + return true; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/callback/counter.js b/master/closure-library/closure/goog/dom/pattern/callback/counter.js new file mode 100644 index 0000000000..a354de05f1 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/callback/counter.js @@ -0,0 +1,72 @@ +// Copyright 2007 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 Callback object that counts matches. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.callback.Counter'); + + + +/** + * Callback class for counting matches. + * @constructor + */ +goog.dom.pattern.callback.Counter = function() { +}; + + +/** + * The count of objects matched so far. + * + * @type {number} + */ +goog.dom.pattern.callback.Counter.prototype.count = 0; + + +/** + * The callback function. Suitable as a callback for + * {@link goog.dom.pattern.Matcher}. + * @type {Function} + * @private + */ +goog.dom.pattern.callback.Counter.prototype.callback_ = null; + + +/** + * Get a bound callback function that is suitable as a callback for + * {@link goog.dom.pattern.Matcher}. + * + * @return {Function} A callback function. + */ +goog.dom.pattern.callback.Counter.prototype.getCallback = function() { + if (!this.callback_) { + this.callback_ = goog.bind(function() { + this.count++; + return false; + }, this); + } + return this.callback_; +}; + + +/** + * Reset the counter. + */ +goog.dom.pattern.callback.Counter.prototype.reset = function() { + this.count = 0; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/callback/test.js b/master/closure-library/closure/goog/dom/pattern/callback/test.js new file mode 100644 index 0000000000..30a58c1615 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/callback/test.js @@ -0,0 +1,77 @@ +// Copyright 2007 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 Callback object that tests if a pattern matches at least once. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.callback.Test'); + +goog.require('goog.iter.StopIteration'); + + + +/** + * Callback class for testing for at least one match. + * @constructor + */ +goog.dom.pattern.callback.Test = function() { +}; + + +/** + * Whether or not the pattern matched. + * + * @type {boolean} + */ +goog.dom.pattern.callback.Test.prototype.matched = false; + + +/** + * The callback function. Suitable as a callback for + * {@link goog.dom.pattern.Matcher}. + * @type {Function} + * @private + */ +goog.dom.pattern.callback.Test.prototype.callback_ = null; + + +/** + * Get a bound callback function that is suitable as a callback for + * {@link goog.dom.pattern.Matcher}. + * + * @return {Function} A callback function. + */ +goog.dom.pattern.callback.Test.prototype.getCallback = function() { + if (!this.callback_) { + this.callback_ = goog.bind(function(node, position) { + // Mark our match. + this.matched = true; + + // Stop searching. + throw goog.iter.StopIteration; + }, this); + } + return this.callback_; +}; + + +/** + * Reset the counter. + */ +goog.dom.pattern.callback.Test.prototype.reset = function() { + this.matched = false; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/childmatches.js b/master/closure-library/closure/goog/dom/pattern/childmatches.js new file mode 100644 index 0000000000..72f1b51f33 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/childmatches.js @@ -0,0 +1,154 @@ +// Copyright 2007 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 DOM pattern to match any children of a tag, and + * specifically collect those that match a child pattern. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.ChildMatches'); + +goog.require('goog.dom.pattern.AllChildren'); +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Pattern object that matches any nodes at or below the current tree depth. + * + * @param {goog.dom.pattern.AbstractPattern} childPattern Pattern to collect + * child matches of. + * @param {number=} opt_minimumMatches Enforce a minimum nuber of matches. + * Defaults to 0. + * @constructor + * @extends {goog.dom.pattern.AllChildren} + */ +goog.dom.pattern.ChildMatches = function(childPattern, opt_minimumMatches) { + this.childPattern_ = childPattern; + this.matches = []; + this.minimumMatches_ = opt_minimumMatches || 0; + goog.dom.pattern.AllChildren.call(this); +}; +goog.inherits(goog.dom.pattern.ChildMatches, goog.dom.pattern.AllChildren); + + +/** + * Array of matched child nodes. + * + * @type {Array.} + */ +goog.dom.pattern.ChildMatches.prototype.matches; + + +/** + * Minimum number of matches. + * + * @type {number} + * @private + */ +goog.dom.pattern.ChildMatches.prototype.minimumMatches_ = 0; + + +/** + * The child pattern to collect matches from. + * + * @type {goog.dom.pattern.AbstractPattern} + * @private + */ +goog.dom.pattern.ChildMatches.prototype.childPattern_; + + +/** + * Whether the pattern has recently matched or failed to match and will need to + * be reset when starting a new round of matches. + * + * @type {boolean} + * @private + */ +goog.dom.pattern.ChildMatches.prototype.needsReset_ = false; + + +/** + * Test whether the given token is on the same level. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the + * same level or deeper and {@code BACKTRACK_MATCH} if not. + * @override + */ +goog.dom.pattern.ChildMatches.prototype.matchToken = function(token, type) { + // Defer resets so we maintain our matches array until the last possible time. + if (this.needsReset_) { + this.reset(); + } + + // Call the super-method to ensure we stay in the child tree. + var status = + goog.dom.pattern.AllChildren.prototype.matchToken.apply(this, arguments); + + switch (status) { + case goog.dom.pattern.MatchType.MATCHING: + var backtrack = false; + + switch (this.childPattern_.matchToken(token, type)) { + case goog.dom.pattern.MatchType.BACKTRACK_MATCH: + backtrack = true; + case goog.dom.pattern.MatchType.MATCH: + // Collect the match. + this.matches.push(this.childPattern_.matchedNode); + break; + + default: + // Keep trying if we haven't hit a terminal state. + break; + } + + if (backtrack) { + // The only interesting result is a MATCH, since BACKTRACK_MATCH means + // we are hitting an infinite loop on something like a Repeat(0). + if (this.childPattern_.matchToken(token, type) == + goog.dom.pattern.MatchType.MATCH) { + this.matches.push(this.childPattern_.matchedNode); + } + } + return goog.dom.pattern.MatchType.MATCHING; + + case goog.dom.pattern.MatchType.BACKTRACK_MATCH: + // TODO(robbyw): this should return something like BACKTRACK_NO_MATCH + // when we don't meet our minimum. + this.needsReset_ = true; + return (this.matches.length >= this.minimumMatches_) ? + goog.dom.pattern.MatchType.BACKTRACK_MATCH : + goog.dom.pattern.MatchType.NO_MATCH; + + default: + this.needsReset_ = true; + return status; + } +}; + + +/** + * Reset any internal state this pattern keeps. + * @override + */ +goog.dom.pattern.ChildMatches.prototype.reset = function() { + this.needsReset_ = false; + this.matches.length = 0; + this.childPattern_.reset(); + goog.dom.pattern.AllChildren.prototype.reset.call(this); +}; diff --git a/master/closure-library/closure/goog/dom/pattern/endtag.js b/master/closure-library/closure/goog/dom/pattern/endtag.js new file mode 100644 index 0000000000..75f995266d --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/endtag.js @@ -0,0 +1,53 @@ +// Copyright 2007 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 DOM pattern to match the end of a tag. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.EndTag'); + +goog.require('goog.dom.TagWalkType'); +goog.require('goog.dom.pattern.Tag'); + + + +/** + * Pattern object that matches a closing tag. + * + * @param {string|RegExp} tag Name of the tag. Also will accept a regular + * expression to match against the tag name. + * @param {Object=} opt_attrs Optional map of attribute names to desired values. + * This pattern will only match when all attributes are present and match + * the string or regular expression value provided here. + * @param {Object=} opt_styles Optional map of CSS style names to desired + * values. This pattern will only match when all styles are present and + * match the string or regular expression value provided here. + * @param {Function=} opt_test Optional function that takes the element as a + * parameter and returns true if this pattern should match it. + * @constructor + * @extends {goog.dom.pattern.Tag} + */ +goog.dom.pattern.EndTag = function(tag, opt_attrs, opt_styles, opt_test) { + goog.dom.pattern.Tag.call( + this, + tag, + goog.dom.TagWalkType.END_TAG, + opt_attrs, + opt_styles, + opt_test); +}; +goog.inherits(goog.dom.pattern.EndTag, goog.dom.pattern.Tag); diff --git a/master/closure-library/closure/goog/dom/pattern/fulltag.js b/master/closure-library/closure/goog/dom/pattern/fulltag.js new file mode 100644 index 0000000000..1fa2230319 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/fulltag.js @@ -0,0 +1,93 @@ +// Copyright 2007 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 DOM pattern to match a tag and all of its children. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.FullTag'); + +goog.require('goog.dom.pattern.MatchType'); +goog.require('goog.dom.pattern.StartTag'); +goog.require('goog.dom.pattern.Tag'); + + + +/** + * Pattern object that matches a full tag including all its children. + * + * @param {string|RegExp} tag Name of the tag. Also will accept a regular + * expression to match against the tag name. + * @param {Object=} opt_attrs Optional map of attribute names to desired values. + * This pattern will only match when all attributes are present and match + * the string or regular expression value provided here. + * @param {Object=} opt_styles Optional map of CSS style names to desired + * values. This pattern will only match when all styles are present and + * match the string or regular expression value provided here. + * @param {Function=} opt_test Optional function that takes the element as a + * parameter and returns true if this pattern should match it. + * @constructor + * @extends {goog.dom.pattern.StartTag} + */ +goog.dom.pattern.FullTag = function(tag, opt_attrs, opt_styles, opt_test) { + goog.dom.pattern.StartTag.call( + this, + tag, + opt_attrs, + opt_styles, + opt_test); +}; +goog.inherits(goog.dom.pattern.FullTag, goog.dom.pattern.StartTag); + + +/** + * Tracks the matcher's depth to detect the end of the tag. + * + * @type {number} + * @private + */ +goog.dom.pattern.FullTag.prototype.depth_ = 0; + + +/** + * Test whether the given token is a start tag token which matches the tag name, + * style, and attributes provided in the constructor. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} MATCH at the end of our + * tag, MATCHING if we are within the tag, and + * NO_MATCH if the starting tag does not match. + * @override + */ +goog.dom.pattern.FullTag.prototype.matchToken = function(token, type) { + if (!this.depth_) { + // If we have not yet started, make sure we match as a StartTag. + if (goog.dom.pattern.Tag.prototype.matchToken.call(this, token, type)) { + this.depth_ = type; + return goog.dom.pattern.MatchType.MATCHING; + + } else { + return goog.dom.pattern.MatchType.NO_MATCH; + } + } else { + this.depth_ += type; + + return this.depth_ ? + goog.dom.pattern.MatchType.MATCHING : + goog.dom.pattern.MatchType.MATCH; + } +}; diff --git a/master/closure-library/closure/goog/dom/pattern/matcher.js b/master/closure-library/closure/goog/dom/pattern/matcher.js new file mode 100644 index 0000000000..c0c87a3d27 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/matcher.js @@ -0,0 +1,150 @@ +// Copyright 2007 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 DOM pattern matcher. Allows for simple searching of DOM + * using patterns descended from {@link goog.dom.pattern.AbstractPattern}. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.Matcher'); + +goog.require('goog.dom.TagIterator'); +goog.require('goog.dom.pattern.MatchType'); +goog.require('goog.iter'); + + +// TODO(robbyw): Allow for backtracks of size > 1. + + + +/** + * Given a set of patterns and a root node, this class tests the patterns in + * parallel. + * + * It is not (yet) a smart matcher - it doesn't do any advanced backtracking. + * Given the pattern DIV, SPAN the matcher will not match + * DIV, DIV, SPAN because it starts matching at the first + * DIV, fails to match SPAN at the second, and never + * backtracks to try again. + * + * It is also possible to have a set of complex patterns that when matched in + * parallel will miss some possible matches. Running multiple times will catch + * all matches eventually. + * + * @constructor + */ +goog.dom.pattern.Matcher = function() { + this.patterns_ = []; + this.callbacks_ = []; +}; + + +/** + * Array of patterns to attempt to match in parallel. + * + * @type {Array.} + * @private + */ +goog.dom.pattern.Matcher.prototype.patterns_; + + +/** + * Array of callbacks to call when a pattern is matched. The indexing is the + * same as the {@link #patterns_} array. + * + * @type {Array.} + * @private + */ +goog.dom.pattern.Matcher.prototype.callbacks_; + + +/** + * Adds a pattern to be matched. The callback can return an object whose keys + * are processing instructions. + * + * @param {goog.dom.pattern.AbstractPattern} pattern The pattern to add. + * @param {Function} callback Function to call when a match is found. Uses + * the above semantics. + */ +goog.dom.pattern.Matcher.prototype.addPattern = function(pattern, callback) { + this.patterns_.push(pattern); + this.callbacks_.push(callback); +}; + + +/** + * Resets all the patterns. + * + * @private + */ +goog.dom.pattern.Matcher.prototype.reset_ = function() { + for (var i = 0, len = this.patterns_.length; i < len; i++) { + this.patterns_[i].reset(); + } +}; + + +/** + * Test the given node against all patterns. + * + * @param {goog.dom.TagIterator} position A position in a node walk that is + * located at the token to process. + * @return {boolean} Whether a pattern modified the position or tree + * and its callback resulted in DOM structure or position modification. + * @private + */ +goog.dom.pattern.Matcher.prototype.matchToken_ = function(position) { + for (var i = 0, len = this.patterns_.length; i < len; i++) { + var pattern = this.patterns_[i]; + switch (pattern.matchToken(position.node, position.tagType)) { + case goog.dom.pattern.MatchType.MATCH: + case goog.dom.pattern.MatchType.BACKTRACK_MATCH: + var callback = this.callbacks_[i]; + + // Callbacks are allowed to modify the current position, but must + // return true if the do. + if (callback(pattern.matchedNode, position, pattern)) { + return true; + } + + default: + // Do nothing. + break; + } + } + + return false; +}; + + +/** + * Match the set of patterns against a match tree. + * + * @param {Node} node The root node of the tree to match. + */ +goog.dom.pattern.Matcher.prototype.match = function(node) { + var position = new goog.dom.TagIterator(node); + + this.reset_(); + + goog.iter.forEach(position, function() { + while (this.matchToken_(position)) { + // Since we've moved, our old pattern statuses don't make sense any more. + // Reset them. + this.reset_(); + } + }, this); +}; diff --git a/master/closure-library/closure/goog/dom/pattern/nodetype.js b/master/closure-library/closure/goog/dom/pattern/nodetype.js new file mode 100644 index 0000000000..b13bbe18c8 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/nodetype.js @@ -0,0 +1,58 @@ +// Copyright 2008 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 DOM pattern to match a node of the given type. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.NodeType'); + +goog.require('goog.dom.pattern.AbstractPattern'); +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Pattern object that matches any node of the given type. + * @param {goog.dom.NodeType} nodeType The node type to match. + * @constructor + * @extends {goog.dom.pattern.AbstractPattern} + */ +goog.dom.pattern.NodeType = function(nodeType) { + /** + * The node type to match. + * @type {goog.dom.NodeType} + * @private + */ + this.nodeType_ = nodeType; +}; +goog.inherits(goog.dom.pattern.NodeType, goog.dom.pattern.AbstractPattern); + + +/** + * Test whether the given token is a text token which matches the string or + * regular expression provided in the constructor. + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} MATCH if the pattern + * matches, NO_MATCH otherwise. + * @override + */ +goog.dom.pattern.NodeType.prototype.matchToken = function(token, type) { + return token.nodeType == this.nodeType_ ? + goog.dom.pattern.MatchType.MATCH : + goog.dom.pattern.MatchType.NO_MATCH; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/pattern.js b/master/closure-library/closure/goog/dom/pattern/pattern.js new file mode 100644 index 0000000000..19f4d1b794 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/pattern.js @@ -0,0 +1,93 @@ +// Copyright 2007 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 DOM patterns. Allows for description of complex DOM patterns + * using regular expression like constructs. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern'); +goog.provide('goog.dom.pattern.MatchType'); + + +/** + * Regular expression for breaking text nodes. + * @type {RegExp} + */ +goog.dom.pattern.BREAKING_TEXTNODE_RE = /^\s*$/; + + +/** + * Utility function to match a string against either a string or a regular + * expression. + * + * @param {string|RegExp} obj Either a string or a regular expression. + * @param {string} str The string to match. + * @return {boolean} Whether the strings are equal, or if the string matches + * the regular expression. + */ +goog.dom.pattern.matchStringOrRegex = function(obj, str) { + if (goog.isString(obj)) { + // Match a string + return str == obj; + } else { + // Match a regular expression + return !!(str && str.match(obj)); + } +}; + + +/** + * Utility function to match a DOM attribute against either a string or a + * regular expression. Conforms to the interface spec for + * {@link goog.object#every}. + * + * @param {string|RegExp} elem Either a string or a regular expression. + * @param {string} index The attribute name to match. + * @param {Object} orig The original map of matches to test. + * @return {boolean} Whether the strings are equal, or if the attribute matches + * the regular expression. + * @this {Element} Called using goog.object every on an Element. + */ +goog.dom.pattern.matchStringOrRegexMap = function(elem, index, orig) { + return goog.dom.pattern.matchStringOrRegex(elem, + index in this ? this[index] : + (this.getAttribute ? this.getAttribute(index) : null)); +}; + + +/** + * When matched to a token, a pattern may return any of the following statuses: + *
    + *
  1. NO_MATCH - The pattern does not match. This is the only + * value that evaluates to false in a boolean context. + *
  2. MATCHING - The token is part of an incomplete match. + *
  3. MATCH - The token completes a match. + *
  4. BACKTRACK_MATCH - The token does not match, but indicates + * the end of a repetitive match. For instance, in regular expressions, + * the pattern /a+/ would match 'aaaaaaaab'. + * Every 'a' token would give a status of + * MATCHING while the 'b' token would give a + * status of BACKTRACK_MATCH. + *
+ * @enum {number} + */ +goog.dom.pattern.MatchType = { + NO_MATCH: 0, + MATCHING: 1, + MATCH: 2, + BACKTRACK_MATCH: 3 +}; diff --git a/master/closure-library/closure/goog/dom/pattern/repeat.js b/master/closure-library/closure/goog/dom/pattern/repeat.js new file mode 100644 index 0000000000..5a47de0b08 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/repeat.js @@ -0,0 +1,190 @@ +// Copyright 2007 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 DOM pattern to match a tag and all of its children. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.Repeat'); + +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.pattern.AbstractPattern'); +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Pattern object that matches a repetition of another pattern. + * @param {goog.dom.pattern.AbstractPattern} pattern The pattern to + * repetitively match. + * @param {number=} opt_minimum The minimum number of times to match. Defaults + * to 0. + * @param {number=} opt_maximum The maximum number of times to match. Defaults + * to unlimited. + * @constructor + * @extends {goog.dom.pattern.AbstractPattern} + */ +goog.dom.pattern.Repeat = function(pattern, + opt_minimum, + opt_maximum) { + this.pattern_ = pattern; + this.minimum_ = opt_minimum || 0; + this.maximum_ = opt_maximum || null; + this.matches = []; +}; +goog.inherits(goog.dom.pattern.Repeat, goog.dom.pattern.AbstractPattern); + + +/** + * Pattern to repetitively match. + * + * @type {goog.dom.pattern.AbstractPattern} + * @private + */ +goog.dom.pattern.Repeat.prototype.pattern_; + + +/** + * Minimum number of times to match the pattern. + * + * @private + */ +goog.dom.pattern.Repeat.prototype.minimum_ = 0; + + +/** + * Optional maximum number of times to match the pattern. A {@code null} value + * will be treated as infinity. + * + * @type {?number} + * @private + */ +goog.dom.pattern.Repeat.prototype.maximum_ = 0; + + +/** + * Number of times the pattern has matched. + * + * @type {number} + */ +goog.dom.pattern.Repeat.prototype.count = 0; + + +/** + * Whether the pattern has recently matched or failed to match and will need to + * be reset when starting a new round of matches. + * + * @type {boolean} + * @private + */ +goog.dom.pattern.Repeat.prototype.needsReset_ = false; + + +/** + * The matched nodes. + * + * @type {Array.} + */ +goog.dom.pattern.Repeat.prototype.matches; + + +/** + * Test whether the given token continues a repeated series of matches of the + * pattern given in the constructor. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} MATCH if the pattern + * matches, BACKTRACK_MATCH if the pattern does not match + * but already had accumulated matches, MATCHING if the pattern + * starts a match, and NO_MATCH if the pattern does not match. + * @suppress {missingProperties} See the broken line below. + * @override + */ +goog.dom.pattern.Repeat.prototype.matchToken = function(token, type) { + // Reset if we're starting a new match + if (this.needsReset_) { + this.reset(); + } + + // If the option is set, ignore any whitespace only text nodes + if (token.nodeType == goog.dom.NodeType.TEXT && + token.nodeValue.match(/^\s+$/)) { + return goog.dom.pattern.MatchType.MATCHING; + } + + switch (this.pattern_.matchToken(token, type)) { + case goog.dom.pattern.MatchType.MATCH: + // Record the first token we match. + if (this.count == 0) { + this.matchedNode = token; + } + + // Mark the match + this.count++; + + // Add to the list + this.matches.push(this.pattern_.matchedNode); + + // Check if this match hits our maximum + if (this.maximum_ !== null && this.count == this.maximum_) { + this.needsReset_ = true; + return goog.dom.pattern.MatchType.MATCH; + } else { + return goog.dom.pattern.MatchType.MATCHING; + } + + case goog.dom.pattern.MatchType.MATCHING: + // This can happen when our child pattern is a sequence or a repetition. + return goog.dom.pattern.MatchType.MATCHING; + + case goog.dom.pattern.MatchType.BACKTRACK_MATCH: + // This happens if our child pattern is repetitive too. + // TODO(robbyw): Backtrack further if necessary. + this.count++; + + // NOTE(nicksantos): This line of code is broken. this.patterns_ doesn't + // exist, and this.currentPosition_ doesn't exit. When this is fixed, + // remove the missingProperties suppression above. + if (this.currentPosition_ == this.patterns_.length) { + this.needsReset_ = true; + return goog.dom.pattern.MatchType.BACKTRACK_MATCH; + } else { + // Retry the same token on the next iteration of the child pattern. + return this.matchToken(token, type); + } + + default: + this.needsReset_ = true; + if (this.count >= this.minimum_) { + return goog.dom.pattern.MatchType.BACKTRACK_MATCH; + } else { + return goog.dom.pattern.MatchType.NO_MATCH; + } + } +}; + + +/** + * Reset any internal state this pattern keeps. + * @override + */ +goog.dom.pattern.Repeat.prototype.reset = function() { + this.pattern_.reset(); + this.count = 0; + this.needsReset_ = false; + this.matches.length = 0; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/sequence.js b/master/closure-library/closure/goog/dom/pattern/sequence.js new file mode 100644 index 0000000000..df40fd6f61 --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/sequence.js @@ -0,0 +1,141 @@ +// Copyright 2007 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 DOM pattern to match a sequence of other patterns. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.Sequence'); + +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.pattern.AbstractPattern'); +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Pattern object that matches a sequence of other patterns. + * + * @param {Array.} patterns Ordered array of + * patterns to match. + * @param {boolean=} opt_ignoreWhitespace Optional flag to ignore text nodes + * consisting entirely of whitespace. The default is to not ignore them. + * @constructor + * @extends {goog.dom.pattern.AbstractPattern} + */ +goog.dom.pattern.Sequence = function(patterns, opt_ignoreWhitespace) { + this.patterns = patterns; + this.ignoreWhitespace_ = !!opt_ignoreWhitespace; +}; +goog.inherits(goog.dom.pattern.Sequence, goog.dom.pattern.AbstractPattern); + + +/** + * Ordered array of patterns to match. + * + * @type {Array.} + */ +goog.dom.pattern.Sequence.prototype.patterns; + + +/** + * Position in the patterns array we have reached by successful matches. + * + * @type {number} + * @private + */ +goog.dom.pattern.Sequence.prototype.currentPosition_ = 0; + + +/** + * Whether or not to ignore whitespace only Text nodes. + * + * @type {boolean} + * @private + */ +goog.dom.pattern.Sequence.prototype.ignoreWhitespace_ = false; + + +/** + * Test whether the given token starts, continues, or finishes the sequence + * of patterns given in the constructor. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} MATCH if the pattern + * matches, MATCHING if the pattern starts a match, and + * NO_MATCH if the pattern does not match. + * @override + */ +goog.dom.pattern.Sequence.prototype.matchToken = function(token, type) { + // If the option is set, ignore any whitespace only text nodes + if (this.ignoreWhitespace_ && token.nodeType == goog.dom.NodeType.TEXT && + goog.dom.pattern.BREAKING_TEXTNODE_RE.test(token.nodeValue)) { + return goog.dom.pattern.MatchType.MATCHING; + } + + switch (this.patterns[this.currentPosition_].matchToken(token, type)) { + case goog.dom.pattern.MatchType.MATCH: + // Record the first token we match. + if (this.currentPosition_ == 0) { + this.matchedNode = token; + } + + // Move forward one position. + this.currentPosition_++; + + // Check if this is the last position. + if (this.currentPosition_ == this.patterns.length) { + this.reset(); + return goog.dom.pattern.MatchType.MATCH; + } else { + return goog.dom.pattern.MatchType.MATCHING; + } + + case goog.dom.pattern.MatchType.MATCHING: + // This can happen when our child pattern is a sequence or a repetition. + return goog.dom.pattern.MatchType.MATCHING; + + case goog.dom.pattern.MatchType.BACKTRACK_MATCH: + // This means a repetitive match succeeded 1 token ago. + // TODO(robbyw): Backtrack further if necessary. + this.currentPosition_++; + + if (this.currentPosition_ == this.patterns.length) { + this.reset(); + return goog.dom.pattern.MatchType.BACKTRACK_MATCH; + } else { + // Retry the same token on the next pattern. + return this.matchToken(token, type); + } + + default: + this.reset(); + return goog.dom.pattern.MatchType.NO_MATCH; + } +}; + + +/** + * Reset any internal state this pattern keeps. + * @override + */ +goog.dom.pattern.Sequence.prototype.reset = function() { + if (this.patterns[this.currentPosition_]) { + this.patterns[this.currentPosition_].reset(); + } + this.currentPosition_ = 0; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/starttag.js b/master/closure-library/closure/goog/dom/pattern/starttag.js new file mode 100644 index 0000000000..4ce01135ea --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/starttag.js @@ -0,0 +1,53 @@ +// Copyright 2007 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 DOM pattern to match the start of a tag. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.StartTag'); + +goog.require('goog.dom.TagWalkType'); +goog.require('goog.dom.pattern.Tag'); + + + +/** + * Pattern object that matches an opening tag. + * + * @param {string|RegExp} tag Name of the tag. Also will accept a regular + * expression to match against the tag name. + * @param {Object=} opt_attrs Optional map of attribute names to desired values. + * This pattern will only match when all attributes are present and match + * the string or regular expression value provided here. + * @param {Object=} opt_styles Optional map of CSS style names to desired + * values. This pattern will only match when all styles are present and + * match the string or regular expression value provided here. + * @param {Function=} opt_test Optional function that takes the element as a + * parameter and returns true if this pattern should match it. + * @constructor + * @extends {goog.dom.pattern.Tag} + */ +goog.dom.pattern.StartTag = function(tag, opt_attrs, opt_styles, opt_test) { + goog.dom.pattern.Tag.call( + this, + tag, + goog.dom.TagWalkType.START_TAG, + opt_attrs, + opt_styles, + opt_test); +}; +goog.inherits(goog.dom.pattern.StartTag, goog.dom.pattern.Tag); diff --git a/master/closure-library/closure/goog/dom/pattern/tag.js b/master/closure-library/closure/goog/dom/pattern/tag.js new file mode 100644 index 0000000000..d04ccd3a3f --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/tag.js @@ -0,0 +1,150 @@ +// Copyright 2007 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 DOM pattern to match a tag. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.Tag'); + +goog.require('goog.dom.pattern'); +goog.require('goog.dom.pattern.AbstractPattern'); +goog.require('goog.dom.pattern.MatchType'); +goog.require('goog.object'); + + + +/** + * Pattern object that matches an tag. + * + * @param {string|RegExp} tag Name of the tag. Also will accept a regular + * expression to match against the tag name. + * @param {goog.dom.TagWalkType} type Type of token to match. + * @param {Object=} opt_attrs Optional map of attribute names to desired values. + * This pattern will only match when all attributes are present and match + * the string or regular expression value provided here. + * @param {Object=} opt_styles Optional map of CSS style names to desired + * values. This pattern will only match when all styles are present and + * match the string or regular expression value provided here. + * @param {Function=} opt_test Optional function that takes the element as a + * parameter and returns true if this pattern should match it. + * @constructor + * @extends {goog.dom.pattern.AbstractPattern} + */ +goog.dom.pattern.Tag = function(tag, type, opt_attrs, opt_styles, opt_test) { + if (goog.isString(tag)) { + this.tag_ = tag.toUpperCase(); + } else { + this.tag_ = tag; + } + + this.type_ = type; + + this.attrs_ = opt_attrs || null; + this.styles_ = opt_styles || null; + this.test_ = opt_test || null; +}; +goog.inherits(goog.dom.pattern.Tag, goog.dom.pattern.AbstractPattern); + + +/** + * The tag to match. + * + * @type {string|RegExp} + * @private + */ +goog.dom.pattern.Tag.prototype.tag_; + + +/** + * The type of token to match. + * + * @type {goog.dom.TagWalkType} + * @private + */ +goog.dom.pattern.Tag.prototype.type_; + + +/** + * The attributes to test for. + * + * @type {Object} + * @private + */ +goog.dom.pattern.Tag.prototype.attrs_ = null; + + +/** + * The styles to test for. + * + * @type {Object} + * @private + */ +goog.dom.pattern.Tag.prototype.styles_ = null; + + +/** + * Function that takes the element as a parameter and returns true if this + * pattern should match it. + * + * @type {Function} + * @private + */ +goog.dom.pattern.Tag.prototype.test_ = null; + + +/** + * Test whether the given token is a tag token which matches the tag name, + * style, and attributes provided in the constructor. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} MATCH if the pattern + * matches, NO_MATCH otherwise. + * @override + */ +goog.dom.pattern.Tag.prototype.matchToken = function(token, type) { + // Check the direction and tag name. + if (type == this.type_ && + goog.dom.pattern.matchStringOrRegex(this.tag_, token.nodeName)) { + // Check the attributes. + if (this.attrs_ && + !goog.object.every( + this.attrs_, + goog.dom.pattern.matchStringOrRegexMap, + token)) { + return goog.dom.pattern.MatchType.NO_MATCH; + } + // Check the styles. + if (this.styles_ && + !goog.object.every( + this.styles_, + goog.dom.pattern.matchStringOrRegexMap, + token.style)) { + return goog.dom.pattern.MatchType.NO_MATCH; + } + + if (this.test_ && !this.test_(token)) { + return goog.dom.pattern.MatchType.NO_MATCH; + } + + // If we reach this point, we have a match and should save it. + this.matchedNode = token; + return goog.dom.pattern.MatchType.MATCH; + } + + return goog.dom.pattern.MatchType.NO_MATCH; +}; diff --git a/master/closure-library/closure/goog/dom/pattern/text.js b/master/closure-library/closure/goog/dom/pattern/text.js new file mode 100644 index 0000000000..5b625ab84e --- /dev/null +++ b/master/closure-library/closure/goog/dom/pattern/text.js @@ -0,0 +1,70 @@ +// Copyright 2007 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 DOM pattern to match a text node. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.pattern.Text'); + +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.pattern'); +goog.require('goog.dom.pattern.AbstractPattern'); +goog.require('goog.dom.pattern.MatchType'); + + + +/** + * Pattern object that matches text by exact matching or regular expressions. + * + * @param {string|RegExp} match String or regular expression to match against. + * @constructor + * @extends {goog.dom.pattern.AbstractPattern} + */ +goog.dom.pattern.Text = function(match) { + this.match_ = match; +}; +goog.inherits(goog.dom.pattern.Text, goog.dom.pattern.AbstractPattern); + + +/** + * The text or regular expression to match. + * + * @type {string|RegExp} + * @private + */ +goog.dom.pattern.Text.prototype.match_; + + +/** + * Test whether the given token is a text token which matches the string or + * regular expression provided in the constructor. + * + * @param {Node} token Token to match against. + * @param {goog.dom.TagWalkType} type The type of token. + * @return {goog.dom.pattern.MatchType} MATCH if the pattern + * matches, NO_MATCH otherwise. + * @override + */ +goog.dom.pattern.Text.prototype.matchToken = function(token, type) { + if (token.nodeType == goog.dom.NodeType.TEXT && + goog.dom.pattern.matchStringOrRegex(this.match_, token.nodeValue)) { + this.matchedNode = token; + return goog.dom.pattern.MatchType.MATCH; + } + + return goog.dom.pattern.MatchType.NO_MATCH; +}; diff --git a/master/closure-library/closure/goog/dom/range.js b/master/closure-library/closure/goog/dom/range.js new file mode 100644 index 0000000000..4df2a20874 --- /dev/null +++ b/master/closure-library/closure/goog/dom/range.js @@ -0,0 +1,226 @@ +// Copyright 2007 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 Utilities for working with ranges in HTML documents. + * + * @author robbyw@google.com (Robby Walker) + * @author ojan@google.com (Ojan Vafai) + * @author jparent@google.com (Julie Parent) + */ + +goog.provide('goog.dom.Range'); + +goog.require('goog.dom'); +goog.require('goog.dom.AbstractRange'); +goog.require('goog.dom.ControlRange'); +goog.require('goog.dom.MultiRange'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.TextRange'); +goog.require('goog.userAgent'); + + +/** + * Create a new selection from the given browser window's current selection. + * Note that this object does not auto-update if the user changes their + * selection and should be used as a snapshot. + * @param {Window=} opt_win The window to get the selection of. Defaults to the + * window this class was defined in. + * @return {goog.dom.AbstractRange?} A range wrapper object, or null if there + * was an error. + */ +goog.dom.Range.createFromWindow = function(opt_win) { + var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow( + opt_win || window); + return sel && goog.dom.Range.createFromBrowserSelection(sel); +}; + + +/** + * Create a new range wrapper from the given browser selection object. Note + * that this object does not auto-update if the user changes their selection and + * should be used as a snapshot. + * @param {!Object} selection The browser selection object. + * @return {goog.dom.AbstractRange?} A range wrapper object or null if there + * was an error. + */ +goog.dom.Range.createFromBrowserSelection = function(selection) { + var range; + var isReversed = false; + if (selection.createRange) { + /** @preserveTry */ + try { + range = selection.createRange(); + } catch (e) { + // Access denied errors can be thrown here in IE if the selection was + // a flash obj or if there are cross domain issues + return null; + } + } else if (selection.rangeCount) { + if (selection.rangeCount > 1) { + return goog.dom.MultiRange.createFromBrowserSelection( + /** @type {Selection} */ (selection)); + } else { + range = selection.getRangeAt(0); + isReversed = goog.dom.Range.isReversed(selection.anchorNode, + selection.anchorOffset, selection.focusNode, selection.focusOffset); + } + } else { + return null; + } + + return goog.dom.Range.createFromBrowserRange(range, isReversed); +}; + + +/** + * Create a new range wrapper from the given browser range object. + * @param {Range|TextRange} range The browser range object. + * @param {boolean=} opt_isReversed Whether the focus node is before the anchor + * node. + * @return {goog.dom.AbstractRange} A range wrapper object. + */ +goog.dom.Range.createFromBrowserRange = function(range, opt_isReversed) { + // Create an IE control range when appropriate. + return goog.dom.AbstractRange.isNativeControlRange(range) ? + goog.dom.ControlRange.createFromBrowserRange(range) : + goog.dom.TextRange.createFromBrowserRange(range, opt_isReversed); +}; + + +/** + * Create a new range wrapper that selects the given node's text. + * @param {Node} node The node to select. + * @param {boolean=} opt_isReversed Whether the focus node is before the anchor + * node. + * @return {goog.dom.AbstractRange} A range wrapper object. + */ +goog.dom.Range.createFromNodeContents = function(node, opt_isReversed) { + return goog.dom.TextRange.createFromNodeContents(node, opt_isReversed); +}; + + +/** + * Create a new range wrapper that represents a caret at the given node, + * accounting for the given offset. This always creates a TextRange, regardless + * of whether node is an image node or other control range type node. + * @param {Node} node The node to place a caret at. + * @param {number} offset The offset within the node to place the caret at. + * @return {goog.dom.AbstractRange} A range wrapper object. + */ +goog.dom.Range.createCaret = function(node, offset) { + return goog.dom.TextRange.createFromNodes(node, offset, node, offset); +}; + + +/** + * Create a new range wrapper that selects the area between the given nodes, + * accounting for the given offsets. + * @param {Node} startNode The node to start with. + * @param {number} startOffset The offset within the node to start. + * @param {Node} endNode The node to end with. + * @param {number} endOffset The offset within the node to end. + * @return {goog.dom.AbstractRange} A range wrapper object. + */ +goog.dom.Range.createFromNodes = function(startNode, startOffset, endNode, + endOffset) { + return goog.dom.TextRange.createFromNodes(startNode, startOffset, endNode, + endOffset); +}; + + +/** + * Clears the window's selection. + * @param {Window=} opt_win The window to get the selection of. Defaults to the + * window this class was defined in. + */ +goog.dom.Range.clearSelection = function(opt_win) { + var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow( + opt_win || window); + if (!sel) { + return; + } + if (sel.empty) { + // We can't just check that the selection is empty, becuase IE + // sometimes gets confused. + try { + sel.empty(); + } catch (e) { + // Emptying an already empty selection throws an exception in IE + } + } else { + try { + sel.removeAllRanges(); + } catch (e) { + // This throws in IE9 if the range has been invalidated; for example, if + // the user clicked on an element which disappeared during the event + // handler. + } + } +}; + + +/** + * Tests if the window has a selection. + * @param {Window=} opt_win The window to check the selection of. Defaults to + * the window this class was defined in. + * @return {boolean} Whether the window has a selection. + */ +goog.dom.Range.hasSelection = function(opt_win) { + var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow( + opt_win || window); + return !!sel && (goog.userAgent.IE ? sel.type != 'None' : !!sel.rangeCount); +}; + + +/** + * Returns whether the focus position occurs before the anchor position. + * @param {Node} anchorNode The node to start with. + * @param {number} anchorOffset The offset within the node to start. + * @param {Node} focusNode The node to end with. + * @param {number} focusOffset The offset within the node to end. + * @return {boolean} Whether the focus position occurs before the anchor + * position. + */ +goog.dom.Range.isReversed = function(anchorNode, anchorOffset, focusNode, + focusOffset) { + if (anchorNode == focusNode) { + return focusOffset < anchorOffset; + } + var child; + if (anchorNode.nodeType == goog.dom.NodeType.ELEMENT && anchorOffset) { + child = anchorNode.childNodes[anchorOffset]; + if (child) { + anchorNode = child; + anchorOffset = 0; + } else if (goog.dom.contains(anchorNode, focusNode)) { + // If focus node is contained in anchorNode, it must be before the + // end of the node. Hence we are reversed. + return true; + } + } + if (focusNode.nodeType == goog.dom.NodeType.ELEMENT && focusOffset) { + child = focusNode.childNodes[focusOffset]; + if (child) { + focusNode = child; + focusOffset = 0; + } else if (goog.dom.contains(focusNode, anchorNode)) { + // If anchor node is contained in focusNode, it must be before the + // end of the node. Hence we are not reversed. + return false; + } + } + return (goog.dom.compareNodeOrder(anchorNode, focusNode) || + anchorOffset - focusOffset) > 0; +}; diff --git a/master/closure-library/closure/goog/dom/rangeendpoint.js b/master/closure-library/closure/goog/dom/rangeendpoint.js new file mode 100644 index 0000000000..f8d0fe446c --- /dev/null +++ b/master/closure-library/closure/goog/dom/rangeendpoint.js @@ -0,0 +1,32 @@ +// Copyright 2007 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 Simple struct for endpoints of a range. + * + * @author robbyw@google.com (Robby Walker) + */ + + +goog.provide('goog.dom.RangeEndpoint'); + + +/** + * Constants for selection endpoints. + * @enum {number} + */ +goog.dom.RangeEndpoint = { + START: 1, + END: 0 +}; diff --git a/master/closure-library/closure/goog/dom/savedcaretrange.js b/master/closure-library/closure/goog/dom/savedcaretrange.js new file mode 100644 index 0000000000..31d313461f --- /dev/null +++ b/master/closure-library/closure/goog/dom/savedcaretrange.js @@ -0,0 +1,203 @@ +// Copyright 2008 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 API for saving and restoring ranges as HTML carets. + * + * @author nicksantos@google.com (Nick Santos) + */ + + +goog.provide('goog.dom.SavedCaretRange'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.dom.SavedRange'); +goog.require('goog.dom.TagName'); +goog.require('goog.string'); + + + +/** + * A struct for holding context about saved selections. + * This can be used to preserve the selection and restore while the DOM is + * manipulated, or through an asynchronous call. Use goog.dom.Range factory + * methods to obtain an {@see goog.dom.AbstractRange} instance, and use + * {@see goog.dom.AbstractRange#saveUsingCarets} to obtain a SavedCaretRange. + * For editor ranges under content-editable elements or design-mode iframes, + * prefer using {@see goog.editor.range.saveUsingNormalizedCarets}. + * @param {goog.dom.AbstractRange} range The range being saved. + * @constructor + * @extends {goog.dom.SavedRange} + */ +goog.dom.SavedCaretRange = function(range) { + goog.dom.SavedRange.call(this); + + /** + * The DOM id of the caret at the start of the range. + * @type {string} + * @private + */ + this.startCaretId_ = goog.string.createUniqueString(); + + /** + * The DOM id of the caret at the end of the range. + * @type {string} + * @private + */ + this.endCaretId_ = goog.string.createUniqueString(); + + /** + * A DOM helper for storing the current document context. + * @type {goog.dom.DomHelper} + * @private + */ + this.dom_ = goog.dom.getDomHelper(range.getDocument()); + + range.surroundWithNodes(this.createCaret_(true), this.createCaret_(false)); +}; +goog.inherits(goog.dom.SavedCaretRange, goog.dom.SavedRange); + + +/** + * Gets the range that this SavedCaretRage represents, without selecting it + * or removing the carets from the DOM. + * @return {goog.dom.AbstractRange?} An abstract range. + */ +goog.dom.SavedCaretRange.prototype.toAbstractRange = function() { + var range = null; + var startCaret = this.getCaret(true); + var endCaret = this.getCaret(false); + if (startCaret && endCaret) { + range = goog.dom.Range.createFromNodes(startCaret, 0, endCaret, 0); + } + return range; +}; + + +/** + * Gets carets. + * @param {boolean} start If true, returns the start caret. Otherwise, get the + * end caret. + * @return {Element} The start or end caret in the given document. + */ +goog.dom.SavedCaretRange.prototype.getCaret = function(start) { + return this.dom_.getElement(start ? this.startCaretId_ : this.endCaretId_); +}; + + +/** + * Removes the carets from the current restoration document. + * @param {goog.dom.AbstractRange=} opt_range A range whose offsets have already + * been adjusted for caret removal; it will be adjusted if it is also + * affected by post-removal operations, such as text node normalization. + * @return {goog.dom.AbstractRange|undefined} The adjusted range, if opt_range + * was provided. + */ +goog.dom.SavedCaretRange.prototype.removeCarets = function(opt_range) { + goog.dom.removeNode(this.getCaret(true)); + goog.dom.removeNode(this.getCaret(false)); + return opt_range; +}; + + +/** + * Sets the document where the range will be restored. + * @param {!Document} doc An HTML document. + */ +goog.dom.SavedCaretRange.prototype.setRestorationDocument = function(doc) { + this.dom_.setDocument(doc); +}; + + +/** + * Reconstruct the selection from the given saved range. Removes carets after + * restoring the selection. If restore does not dispose this saved range, it may + * only be restored a second time if innerHTML or some other mechanism is used + * to restore the carets to the dom. + * @return {goog.dom.AbstractRange?} Restored selection. + * @override + * @protected + */ +goog.dom.SavedCaretRange.prototype.restoreInternal = function() { + var range = null; + var startCaret = this.getCaret(true); + var endCaret = this.getCaret(false); + if (startCaret && endCaret) { + var startNode = startCaret.parentNode; + var startOffset = goog.array.indexOf(startNode.childNodes, startCaret); + var endNode = endCaret.parentNode; + var endOffset = goog.array.indexOf(endNode.childNodes, endCaret); + if (endNode == startNode) { + // Compensate for the start caret being removed. + endOffset -= 1; + } + range = goog.dom.Range.createFromNodes(startNode, startOffset, + endNode, endOffset); + range = this.removeCarets(range); + range.select(); + } else { + // If only one caret was found, remove it. + this.removeCarets(); + } + return range; +}; + + +/** + * Dispose the saved range and remove the carets from the DOM. + * @override + * @protected + */ +goog.dom.SavedCaretRange.prototype.disposeInternal = function() { + this.removeCarets(); + this.dom_ = null; +}; + + +/** + * Creates a caret element. + * @param {boolean} start If true, creates the start caret. Otherwise, + * creates the end caret. + * @return {Element} The new caret element. + * @private + */ +goog.dom.SavedCaretRange.prototype.createCaret_ = function(start) { + return this.dom_.createDom(goog.dom.TagName.SPAN, + {'id': start ? this.startCaretId_ : this.endCaretId_}); +}; + + +/** + * A regex that will match all saved range carets in a string. + * @type {RegExp} + */ +goog.dom.SavedCaretRange.CARET_REGEX = /<\/span>/ig; + + +/** + * Returns whether two strings of html are equal, ignoring any saved carets. + * Thus two strings of html whose only difference is the id of their saved + * carets will be considered equal, since they represent html with the + * same selection. + * @param {string} str1 The first string. + * @param {string} str2 The second string. + * @return {boolean} Whether two strings of html are equal, ignoring any + * saved carets. + */ +goog.dom.SavedCaretRange.htmlEqual = function(str1, str2) { + return str1 == str2 || + str1.replace(goog.dom.SavedCaretRange.CARET_REGEX, '') == + str2.replace(goog.dom.SavedCaretRange.CARET_REGEX, ''); +}; diff --git a/master/closure-library/closure/goog/dom/savedrange.js b/master/closure-library/closure/goog/dom/savedrange.js new file mode 100644 index 0000000000..4f356d3cf1 --- /dev/null +++ b/master/closure-library/closure/goog/dom/savedrange.js @@ -0,0 +1,74 @@ +// Copyright 2007 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 generic interface for saving and restoring ranges. + * + * @author robbyw@google.com (Robby Walker) + */ + + +goog.provide('goog.dom.SavedRange'); + +goog.require('goog.Disposable'); +goog.require('goog.debug.Logger'); + + + +/** + * Abstract interface for a saved range. + * @constructor + * @extends {goog.Disposable} + */ +goog.dom.SavedRange = function() { + goog.Disposable.call(this); +}; +goog.inherits(goog.dom.SavedRange, goog.Disposable); + + +/** + * Logging object. + * @type {goog.debug.Logger} + * @private + */ +goog.dom.SavedRange.logger_ = + goog.debug.Logger.getLogger('goog.dom.SavedRange'); + + +/** + * Restores the range and by default disposes of the saved copy. Take note: + * this means the by default SavedRange objects are single use objects. + * @param {boolean=} opt_stayAlive Whether this SavedRange should stay alive + * (not be disposed) after restoring the range. Defaults to false (dispose). + * @return {goog.dom.AbstractRange} The restored range. + */ +goog.dom.SavedRange.prototype.restore = function(opt_stayAlive) { + if (this.isDisposed()) { + goog.dom.SavedRange.logger_.severe( + 'Disposed SavedRange objects cannot be restored.'); + } + + var range = this.restoreInternal(); + if (!opt_stayAlive) { + this.dispose(); + } + return range; +}; + + +/** + * Internal method to restore the saved range. + * @return {goog.dom.AbstractRange} The restored range. + */ +goog.dom.SavedRange.prototype.restoreInternal = goog.abstractMethod; diff --git a/master/closure-library/closure/goog/dom/selection.js b/master/closure-library/closure/goog/dom/selection.js new file mode 100644 index 0000000000..6d6f69e14f --- /dev/null +++ b/master/closure-library/closure/goog/dom/selection.js @@ -0,0 +1,470 @@ +// Copyright 2006 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 Utilities for working with selections in input boxes and text + * areas. + * + * @see ../demos/dom_selection.html + */ + + +goog.provide('goog.dom.selection'); + +goog.require('goog.string'); +goog.require('goog.userAgent'); + + +/** + * Sets the place where the selection should start inside a textarea or a text + * input + * @param {Element} textfield A textarea or text input. + * @param {number} pos The position to set the start of the selection at. + */ +goog.dom.selection.setStart = function(textfield, pos) { + if (goog.dom.selection.useSelectionProperties_(textfield)) { + textfield.selectionStart = pos; + } else if (goog.userAgent.IE) { + // destructuring assignment would have been sweet + var tmp = goog.dom.selection.getRangeIe_(textfield); + var range = tmp[0]; + var selectionRange = tmp[1]; + + if (range.inRange(selectionRange)) { + pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos); + + range.collapse(true); + range.move('character', pos); + range.select(); + } + } +}; + + +/** + * Return the place where the selection starts inside a textarea or a text + * input + * @param {Element} textfield A textarea or text input. + * @return {number} The position where the selection starts or 0 if it was + * unable to find the position or no selection exists. Note that we can't + * reliably tell the difference between an element that has no selection and + * one where it starts at 0. + */ +goog.dom.selection.getStart = function(textfield) { + return goog.dom.selection.getEndPoints_(textfield, true)[0]; +}; + + +/** + * Returns the start and end points of the selection within a textarea in IE. + * IE treats newline characters as \r\n characters, and we need to check for + * these characters at the edge of our selection, to ensure that we return the + * right cursor position. + * @param {TextRange} range Complete range object, e.g., "Hello\r\n". + * @param {TextRange} selRange Selected range object. + * @param {boolean} getOnlyStart Value indicating if only start + * cursor position is to be returned. In IE, obtaining the end position + * involves extra work, hence we have this parameter for calls which need + * only start position. + * @return {Array.} An array with the start and end positions where the + * selection starts and ends or [0,0] if it was unable to find the + * positions or no selection exists. Note that we can't reliably tell the + * difference between an element that has no selection and one where + * it starts and ends at 0. If getOnlyStart was true, we return + * -1 as end offset. + * @private + */ +goog.dom.selection.getEndPointsTextareaIe_ = function( + range, selRange, getOnlyStart) { + // Create a duplicate of the selected range object to perform our actions + // against. Example of selectionRange = "" (assuming that the cursor is + // just after the \r\n combination) + var selectionRange = selRange.duplicate(); + + // Text before the selection start, e.g.,"Hello" (notice how range.text + // excludes the \r\n sequence) + var beforeSelectionText = range.text; + // Text before the selection start, e.g., "Hello" (this will later include + // the \r\n sequences also) + var untrimmedBeforeSelectionText = beforeSelectionText; + // Text within the selection , e.g. "" assuming that the cursor is just after + // the \r\n combination. + var selectionText = selectionRange.text; + // Text within the selection, e.g., "" (this will later include the \r\n + // sequences also) + var untrimmedSelectionText = selectionText; + + // Boolean indicating whether we are done dealing with the text before the + // selection's beginning. + var isRangeEndTrimmed = false; + // Go over the range until it becomes a 0-lengthed range or until the range + // text starts changing when we move the end back by one character. + // If after moving the end back by one character, the text remains the same, + // then we need to add a "\r\n" at the end to get the actual text. + while (!isRangeEndTrimmed) { + if (range.compareEndPoints('StartToEnd', range) == 0) { + isRangeEndTrimmed = true; + } else { + range.moveEnd('character', -1); + if (range.text == beforeSelectionText) { + // If the start position of the cursor was after a \r\n string, + // we would skip over it in one go with the moveEnd call, but + // range.text will still show "Hello" (because of the IE range.text + // bug) - this implies that we should add a \r\n to our + // untrimmedBeforeSelectionText string. + untrimmedBeforeSelectionText += '\r\n'; + } else { + isRangeEndTrimmed = true; + } + } + } + + if (getOnlyStart) { + // We return -1 as end, since the caller is only interested in the start + // value. + return [untrimmedBeforeSelectionText.length, -1]; + } + // Boolean indicating whether we are done dealing with the text inside the + // selection. + var isSelectionRangeEndTrimmed = false; + // Go over the selected range until it becomes a 0-lengthed range or until + // the range text starts changing when we move the end back by one character. + // If after moving the end back by one character, the text remains the same, + // then we need to add a "\r\n" at the end to get the actual text. + while (!isSelectionRangeEndTrimmed) { + if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) { + isSelectionRangeEndTrimmed = true; + } else { + selectionRange.moveEnd('character', -1); + if (selectionRange.text == selectionText) { + // If the selection was not empty, and the end point of the selection + // was just after a \r\n, we would have skipped it in one go with the + // moveEnd call, and this implies that we should add a \r\n to the + // untrimmedSelectionText string. + untrimmedSelectionText += '\r\n'; + } else { + isSelectionRangeEndTrimmed = true; + } + } + } + return [ + untrimmedBeforeSelectionText.length, + untrimmedBeforeSelectionText.length + untrimmedSelectionText.length]; +}; + + +/** + * Returns the start and end points of the selection inside a textarea or a + * text input. + * @param {Element} textfield A textarea or text input. + * @return {Array.} An array with the start and end positions where the + * selection starts and ends or [0,0] if it was unable to find the + * positions or no selection exists. Note that we can't reliably tell the + * difference between an element that has no selection and one where + * it starts and ends at 0. + */ +goog.dom.selection.getEndPoints = function(textfield) { + return goog.dom.selection.getEndPoints_(textfield, false); +}; + + +/** + * Returns the start and end points of the selection inside a textarea or a + * text input. + * @param {Element} textfield A textarea or text input. + * @param {boolean} getOnlyStart Value indicating if only start + * cursor position is to be returned. In IE, obtaining the end position + * involves extra work, hence we have this parameter. In FF, there is not + * much extra effort involved. + * @return {Array.} An array with the start and end positions where the + * selection starts and ends or [0,0] if it was unable to find the + * positions or no selection exists. Note that we can't reliably tell the + * difference between an element that has no selection and one where + * it starts and ends at 0. If getOnlyStart was true, we return + * -1 as end offset. + * @private + */ +goog.dom.selection.getEndPoints_ = function(textfield, getOnlyStart) { + var startPos = 0; + var endPos = 0; + if (goog.dom.selection.useSelectionProperties_(textfield)) { + startPos = textfield.selectionStart; + endPos = getOnlyStart ? -1 : textfield.selectionEnd; + } else if (goog.userAgent.IE) { + var tmp = goog.dom.selection.getRangeIe_(textfield); + var range = tmp[0]; + var selectionRange = tmp[1]; + + if (range.inRange(selectionRange)) { + range.setEndPoint('EndToStart', selectionRange); + if (textfield.type == 'textarea') { + return goog.dom.selection.getEndPointsTextareaIe_( + range, selectionRange, getOnlyStart); + } + startPos = range.text.length; + if (!getOnlyStart) { + endPos = range.text.length + selectionRange.text.length; + } else { + endPos = -1; // caller did not ask for end position + } + } + } + return [startPos, endPos]; +}; + + +/** + * Sets the place where the selection should end inside a text area or a text + * input + * @param {Element} textfield A textarea or text input. + * @param {number} pos The position to end the selection at. + */ +goog.dom.selection.setEnd = function(textfield, pos) { + if (goog.dom.selection.useSelectionProperties_(textfield)) { + textfield.selectionEnd = pos; + } else if (goog.userAgent.IE) { + var tmp = goog.dom.selection.getRangeIe_(textfield); + var range = tmp[0]; + var selectionRange = tmp[1]; + + if (range.inRange(selectionRange)) { + // Both the current position and the start cursor position need + // to be canonicalized to take care of possible \r\n miscounts. + pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos); + var startCursorPos = goog.dom.selection.canonicalizePositionIe_( + textfield, goog.dom.selection.getStart(textfield)); + + selectionRange.collapse(true); + selectionRange.moveEnd('character', pos - startCursorPos); + selectionRange.select(); + } + } +}; + + +/** + * Returns the place where the selection ends inside a textarea or a text input + * @param {Element} textfield A textarea or text input. + * @return {number} The position where the selection ends or 0 if it was + * unable to find the position or no selection exists. + */ +goog.dom.selection.getEnd = function(textfield) { + return goog.dom.selection.getEndPoints_(textfield, false)[1]; +}; + + +/** + * Sets the cursor position within a textfield. + * @param {Element} textfield A textarea or text input. + * @param {number} pos The position within the text field. + */ +goog.dom.selection.setCursorPosition = function(textfield, pos) { + if (goog.dom.selection.useSelectionProperties_(textfield)) { + // Mozilla directly supports this + textfield.selectionStart = pos; + textfield.selectionEnd = pos; + + } else if (goog.userAgent.IE) { + pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos); + + // IE has textranges. A textfield's textrange encompasses the + // entire textfield's text by default + var sel = textfield.createTextRange(); + + sel.collapse(true); + sel.move('character', pos); + sel.select(); + } +}; + + +/** + * Sets the selected text inside a textarea or a text input + * @param {Element} textfield A textarea or text input. + * @param {string} text The text to change the selection to. + */ +goog.dom.selection.setText = function(textfield, text) { + if (goog.dom.selection.useSelectionProperties_(textfield)) { + var value = textfield.value; + var oldSelectionStart = textfield.selectionStart; + var before = value.substr(0, oldSelectionStart); + var after = value.substr(textfield.selectionEnd); + textfield.value = before + text + after; + textfield.selectionStart = oldSelectionStart; + textfield.selectionEnd = oldSelectionStart + text.length; + } else if (goog.userAgent.IE) { + var tmp = goog.dom.selection.getRangeIe_(textfield); + var range = tmp[0]; + var selectionRange = tmp[1]; + + if (!range.inRange(selectionRange)) { + return; + } + // When we set the selection text the selection range is collapsed to the + // end. We therefore duplicate the current selection so we know where it + // started. Once we've set the selection text we move the start of the + // selection range to the old start + var range2 = selectionRange.duplicate(); + selectionRange.text = text; + selectionRange.setEndPoint('StartToStart', range2); + selectionRange.select(); + } else { + throw Error('Cannot set the selection end'); + } +}; + + +/** + * Returns the selected text inside a textarea or a text input + * @param {Element} textfield A textarea or text input. + * @return {string} The selected text. + */ +goog.dom.selection.getText = function(textfield) { + if (goog.dom.selection.useSelectionProperties_(textfield)) { + var s = textfield.value; + return s.substring(textfield.selectionStart, textfield.selectionEnd); + } + + if (goog.userAgent.IE) { + var tmp = goog.dom.selection.getRangeIe_(textfield); + var range = tmp[0]; + var selectionRange = tmp[1]; + + if (!range.inRange(selectionRange)) { + return ''; + } else if (textfield.type == 'textarea') { + return goog.dom.selection.getSelectionRangeText_(selectionRange); + } + return selectionRange.text; + } + + throw Error('Cannot get the selection text'); +}; + + +/** + * Returns the selected text within a textarea in IE. + * IE treats newline characters as \r\n characters, and we need to check for + * these characters at the edge of our selection, to ensure that we return the + * right string. + * @param {TextRange} selRange Selected range object. + * @return {string} Selected text in the textarea. + * @private + */ +goog.dom.selection.getSelectionRangeText_ = function(selRange) { + // Create a duplicate of the selected range object to perform our actions + // against. Suppose the text in the textarea is "Hello\r\nWorld" and the + // selection encompasses the "o\r\n" bit, initial selectionRange will be "o" + // (assuming that the cursor is just after the \r\n combination) + var selectionRange = selRange.duplicate(); + + // Text within the selection , e.g. "o" assuming that the cursor is just after + // the \r\n combination. + var selectionText = selectionRange.text; + // Text within the selection, e.g., "o" (this will later include the \r\n + // sequences also) + var untrimmedSelectionText = selectionText; + + // Boolean indicating whether we are done dealing with the text inside the + // selection. + var isSelectionRangeEndTrimmed = false; + // Go over the selected range until it becomes a 0-lengthed range or until + // the range text starts changing when we move the end back by one character. + // If after moving the end back by one character, the text remains the same, + // then we need to add a "\r\n" at the end to get the actual text. + while (!isSelectionRangeEndTrimmed) { + if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) { + isSelectionRangeEndTrimmed = true; + } else { + selectionRange.moveEnd('character', -1); + if (selectionRange.text == selectionText) { + // If the selection was not empty, and the end point of the selection + // was just after a \r\n, we would have skipped it in one go with the + // moveEnd call, and this implies that we should add a \r\n to the + // untrimmedSelectionText string. + untrimmedSelectionText += '\r\n'; + } else { + isSelectionRangeEndTrimmed = true; + } + } + } + return untrimmedSelectionText; +}; + + +/** + * Helper function for returning the range for an object as well as the + * selection range + * @private + * @param {Element} el The element to get the range for. + * @return {Array.} Range of object and selection range in two + * element array. + */ +goog.dom.selection.getRangeIe_ = function(el) { + var doc = el.ownerDocument || el.document; + + var selectionRange = doc.selection.createRange(); + // el.createTextRange() doesn't work on textareas + var range; + + if (el.type == 'textarea') { + range = doc.body.createTextRange(); + range.moveToElementText(el); + } else { + range = el.createTextRange(); + } + + return [range, selectionRange]; +}; + + +/** + * Helper function for canonicalizing a position inside a textfield in IE. + * Deals with the issue that \r\n counts as 2 characters, but + * move('character', n) passes over both characters in one move. + * @private + * @param {Element} textfield The text element. + * @param {number} pos The position desired in that element. + * @return {number} The canonicalized position that will work properly with + * move('character', pos). + */ +goog.dom.selection.canonicalizePositionIe_ = function(textfield, pos) { + if (textfield.type == 'textarea') { + // We do this only for textarea because it is the only one which can + // have a \r\n (input cannot have this). + var value = textfield.value.substring(0, pos); + pos = goog.string.canonicalizeNewlines(value).length; + } + return pos; +}; + + +/** + * Helper function to determine whether it's okay to use + * selectionStart/selectionEnd. + * + * @param {Element} el The element to check for. + * @return {boolean} Whether it's okay to use the selectionStart and + * selectionEnd properties on {@code el}. + * @private + */ +goog.dom.selection.useSelectionProperties_ = function(el) { + try { + return typeof el.selectionStart == 'number'; + } catch (e) { + // Firefox throws an exception if you try to access selectionStart + // on an element with display: none. + return false; + } +}; diff --git a/master/closure-library/closure/goog/dom/tagiterator.js b/master/closure-library/closure/goog/dom/tagiterator.js new file mode 100644 index 0000000000..cd7787d6d9 --- /dev/null +++ b/master/closure-library/closure/goog/dom/tagiterator.js @@ -0,0 +1,367 @@ +// Copyright 2008 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 Iterator subclass for DOM tree traversal. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.TagIterator'); +goog.provide('goog.dom.TagWalkType'); + +goog.require('goog.dom.NodeType'); +goog.require('goog.iter.Iterator'); +goog.require('goog.iter.StopIteration'); + + +/** + * There are three types of token: + *
    + *
  1. {@code START_TAG} - The beginning of a tag. + *
  2. {@code OTHER} - Any non-element node position. + *
  3. {@code END_TAG} - The end of a tag. + *
+ * Users of this enumeration can rely on {@code START_TAG + END_TAG = 0} and + * that {@code OTHER = 0}. + * + * @enum {number} + */ +goog.dom.TagWalkType = { + START_TAG: 1, + OTHER: 0, + END_TAG: -1 +}; + + + +/** + * A DOM tree traversal iterator. + * + * Starting with the given node, the iterator walks the DOM in order, reporting + * events for the start and end of Elements, and the presence of text nodes. For + * example: + * + *
+ * <div>1<span>2</span>3</div>
+ * 
+ * + * Will return the following nodes: + * + * [div, 1, span, 2, span, 3, div] + * + * With the following states: + * + * [START, OTHER, START, OTHER, END, OTHER, END] + * + * And the following depths + * + * [1, 1, 2, 2, 1, 1, 0] + * + * Imagining | represents iterator position, the traversal stops at + * each of the following locations: + * + *
+ * <div>|1|<span>|2|</span>|3|</div>|
+ * 
+ * + * The iterator can also be used in reverse mode, which will return the nodes + * and states in the opposite order. The depths will be slightly different + * since, like in normal mode, the depth is computed *after* the given node. + * + * Lastly, it is possible to create an iterator that is unconstrained, meaning + * that it will continue iterating until the end of the document instead of + * until exiting the start node. + * + * @param {Node=} opt_node The start node. If unspecified or null, defaults to + * an empty iterator. + * @param {boolean=} opt_reversed Whether to traverse the tree in reverse. + * @param {boolean=} opt_unconstrained Whether the iterator is not constrained + * to the starting node and its children. + * @param {goog.dom.TagWalkType?=} opt_tagType The type of the position. + * Defaults to the start of the given node for forward iterators, and + * the end of the node for reverse iterators. + * @param {number=} opt_depth The starting tree depth. + * @constructor + * @extends {goog.iter.Iterator} + */ +goog.dom.TagIterator = function(opt_node, opt_reversed, + opt_unconstrained, opt_tagType, opt_depth) { + this.reversed = !!opt_reversed; + if (opt_node) { + this.setPosition(opt_node, opt_tagType); + } + this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0; + if (this.reversed) { + this.depth *= -1; + } + this.constrained = !opt_unconstrained; +}; +goog.inherits(goog.dom.TagIterator, goog.iter.Iterator); + + +/** + * The node this position is located on. + * @type {Node} + */ +goog.dom.TagIterator.prototype.node = null; + + +/** + * The type of this position. + * @type {goog.dom.TagWalkType} + */ +goog.dom.TagIterator.prototype.tagType = goog.dom.TagWalkType.OTHER; + + +/** + * The tree depth of this position relative to where the iterator started. The + * depth is considered to be the tree depth just past the current node, so if an + * iterator is at position
+ *     
|
+ *
+ * (i.e. the node is the div and the type is START_TAG) its depth will be 1. + * @type {number} + */ +goog.dom.TagIterator.prototype.depth; + + +/** + * Whether the node iterator is moving in reverse. + * @type {boolean} + */ +goog.dom.TagIterator.prototype.reversed; + + +/** + * Whether the iterator is constrained to the starting node and its children. + * @type {boolean} + */ +goog.dom.TagIterator.prototype.constrained; + + +/** + * Whether iteration has started. + * @type {boolean} + * @private + */ +goog.dom.TagIterator.prototype.started_ = false; + + +/** + * Set the position of the iterator. Overwrite the tree node and the position + * type which can be one of the {@link goog.dom.TagWalkType} token types. + * Only overwrites the tree depth when the parameter is specified. + * @param {Node} node The node to set the position to. + * @param {goog.dom.TagWalkType?=} opt_tagType The type of the position + * Defaults to the start of the given node. + * @param {number=} opt_depth The tree depth. + */ +goog.dom.TagIterator.prototype.setPosition = function(node, + opt_tagType, opt_depth) { + this.node = node; + + if (node) { + if (goog.isNumber(opt_tagType)) { + this.tagType = opt_tagType; + } else { + // Auto-determine the proper type + this.tagType = this.node.nodeType != goog.dom.NodeType.ELEMENT ? + goog.dom.TagWalkType.OTHER : + this.reversed ? goog.dom.TagWalkType.END_TAG : + goog.dom.TagWalkType.START_TAG; + } + } + + if (goog.isNumber(opt_depth)) { + this.depth = opt_depth; + } +}; + + +/** + * Replace this iterator's values with values from another. The two iterators + * must be of the same type. + * @param {goog.dom.TagIterator} other The iterator to copy. + * @protected + */ +goog.dom.TagIterator.prototype.copyFrom = function(other) { + this.node = other.node; + this.tagType = other.tagType; + this.depth = other.depth; + this.reversed = other.reversed; + this.constrained = other.constrained; +}; + + +/** + * @return {goog.dom.TagIterator} A copy of this iterator. + */ +goog.dom.TagIterator.prototype.clone = function() { + return new goog.dom.TagIterator(this.node, this.reversed, + !this.constrained, this.tagType, this.depth); +}; + + +/** + * Skip the current tag. + */ +goog.dom.TagIterator.prototype.skipTag = function() { + var check = this.reversed ? goog.dom.TagWalkType.END_TAG : + goog.dom.TagWalkType.START_TAG; + if (this.tagType == check) { + this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1); + this.depth += this.tagType * (this.reversed ? -1 : 1); + } +}; + + +/** + * Restart the current tag. + */ +goog.dom.TagIterator.prototype.restartTag = function() { + var check = this.reversed ? goog.dom.TagWalkType.START_TAG : + goog.dom.TagWalkType.END_TAG; + if (this.tagType == check) { + this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1); + this.depth += this.tagType * (this.reversed ? -1 : 1); + } +}; + + +/** + * Move to the next position in the DOM tree. + * @return {Node} Returns the next node, or throws a goog.iter.StopIteration + * exception if the end of the iterator's range has been reached. + * @override + */ +goog.dom.TagIterator.prototype.next = function() { + var node; + + if (this.started_) { + if (!this.node || this.constrained && this.depth == 0) { + throw goog.iter.StopIteration; + } + node = this.node; + + var startType = this.reversed ? goog.dom.TagWalkType.END_TAG : + goog.dom.TagWalkType.START_TAG; + + if (this.tagType == startType) { + // If we have entered the tag, test if there are any children to move to. + var child = this.reversed ? node.lastChild : node.firstChild; + if (child) { + this.setPosition(child); + } else { + // If not, move on to exiting this tag. + this.setPosition(node, + /** @type {goog.dom.TagWalkType} */ (startType * -1)); + } + } else { + var sibling = this.reversed ? node.previousSibling : node.nextSibling; + if (sibling) { + // Try to move to the next node. + this.setPosition(sibling); + } else { + // If no such node exists, exit our parent. + this.setPosition(node.parentNode, + /** @type {goog.dom.TagWalkType} */ (startType * -1)); + } + } + + this.depth += this.tagType * (this.reversed ? -1 : 1); + } else { + this.started_ = true; + } + + // Check the new position for being last, and return it if it's not. + node = this.node; + if (!this.node) { + throw goog.iter.StopIteration; + } + return node; +}; + + +/** + * @return {boolean} Whether next has ever been called on this iterator. + * @protected + */ +goog.dom.TagIterator.prototype.isStarted = function() { + return this.started_; +}; + + +/** + * @return {boolean} Whether this iterator's position is a start tag position. + */ +goog.dom.TagIterator.prototype.isStartTag = function() { + return this.tagType == goog.dom.TagWalkType.START_TAG; +}; + + +/** + * @return {boolean} Whether this iterator's position is an end tag position. + */ +goog.dom.TagIterator.prototype.isEndTag = function() { + return this.tagType == goog.dom.TagWalkType.END_TAG; +}; + + +/** + * @return {boolean} Whether this iterator's position is not at an element node. + */ +goog.dom.TagIterator.prototype.isNonElement = function() { + return this.tagType == goog.dom.TagWalkType.OTHER; +}; + + +/** + * Test if two iterators are at the same position - i.e. if the node and tagType + * is the same. This will still return true if the two iterators are moving in + * opposite directions or have different constraints. + * @param {goog.dom.TagIterator} other The iterator to compare to. + * @return {boolean} Whether the two iterators are at the same position. + */ +goog.dom.TagIterator.prototype.equals = function(other) { + // Nodes must be equal, and we must either have reached the end of our tree + // or be at the same position. + return other.node == this.node && (!this.node || + other.tagType == this.tagType); +}; + + +/** + * Replace the current node with the list of nodes. Reset the iterator so that + * it visits the first of the nodes next. + * @param {...Object} var_args A list of nodes to replace the current node with. + * If the first argument is array-like, it will be used, otherwise all the + * arguments are assumed to be nodes. + */ +goog.dom.TagIterator.prototype.splice = function(var_args) { + // Reset the iterator so that it iterates over the first replacement node in + // the arguments on the next iteration. + var node = this.node; + this.restartTag(); + this.reversed = !this.reversed; + goog.dom.TagIterator.prototype.next.call(this); + this.reversed = !this.reversed; + + // Replace the node with the arguments. + var arr = goog.isArrayLike(arguments[0]) ? arguments[0] : arguments; + for (var i = arr.length - 1; i >= 0; i--) { + goog.dom.insertSiblingAfter(arr[i], node); + } + goog.dom.removeNode(node); +}; diff --git a/master/closure-library/closure/goog/dom/tagname.js b/master/closure-library/closure/goog/dom/tagname.js new file mode 100644 index 0000000000..77a9b475a9 --- /dev/null +++ b/master/closure-library/closure/goog/dom/tagname.js @@ -0,0 +1,159 @@ +// Copyright 2007 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 Defines the goog.dom.TagName enum. This enumerates + * all HTML tag names specified in either the the W3C HTML 4.01 index of + * elements or the HTML5 draft specification. + * + * References: + * http://www.w3.org/TR/html401/index/elements.html + * http://dev.w3.org/html5/spec/section-index.html + * + */ +goog.provide('goog.dom.TagName'); + + +/** + * Enum of all html tag names specified by the W3C HTML4.01 and HTML5 + * specifications. + * @enum {string} + */ +goog.dom.TagName = { + A: 'A', + ABBR: 'ABBR', + ACRONYM: 'ACRONYM', + ADDRESS: 'ADDRESS', + APPLET: 'APPLET', + AREA: 'AREA', + ARTICLE: 'ARTICLE', + ASIDE: 'ASIDE', + AUDIO: 'AUDIO', + B: 'B', + BASE: 'BASE', + BASEFONT: 'BASEFONT', + BDI: 'BDI', + BDO: 'BDO', + BIG: 'BIG', + BLOCKQUOTE: 'BLOCKQUOTE', + BODY: 'BODY', + BR: 'BR', + BUTTON: 'BUTTON', + CANVAS: 'CANVAS', + CAPTION: 'CAPTION', + CENTER: 'CENTER', + CITE: 'CITE', + CODE: 'CODE', + COL: 'COL', + COLGROUP: 'COLGROUP', + COMMAND: 'COMMAND', + DATA: 'DATA', + DATALIST: 'DATALIST', + DD: 'DD', + DEL: 'DEL', + DETAILS: 'DETAILS', + DFN: 'DFN', + DIALOG: 'DIALOG', + DIR: 'DIR', + DIV: 'DIV', + DL: 'DL', + DT: 'DT', + EM: 'EM', + EMBED: 'EMBED', + FIELDSET: 'FIELDSET', + FIGCAPTION: 'FIGCAPTION', + FIGURE: 'FIGURE', + FONT: 'FONT', + FOOTER: 'FOOTER', + FORM: 'FORM', + FRAME: 'FRAME', + FRAMESET: 'FRAMESET', + H1: 'H1', + H2: 'H2', + H3: 'H3', + H4: 'H4', + H5: 'H5', + H6: 'H6', + HEAD: 'HEAD', + HEADER: 'HEADER', + HGROUP: 'HGROUP', + HR: 'HR', + HTML: 'HTML', + I: 'I', + IFRAME: 'IFRAME', + IMG: 'IMG', + INPUT: 'INPUT', + INS: 'INS', + ISINDEX: 'ISINDEX', + KBD: 'KBD', + KEYGEN: 'KEYGEN', + LABEL: 'LABEL', + LEGEND: 'LEGEND', + LI: 'LI', + LINK: 'LINK', + MAP: 'MAP', + MARK: 'MARK', + MATH: 'MATH', + MENU: 'MENU', + META: 'META', + METER: 'METER', + NAV: 'NAV', + NOFRAMES: 'NOFRAMES', + NOSCRIPT: 'NOSCRIPT', + OBJECT: 'OBJECT', + OL: 'OL', + OPTGROUP: 'OPTGROUP', + OPTION: 'OPTION', + OUTPUT: 'OUTPUT', + P: 'P', + PARAM: 'PARAM', + PRE: 'PRE', + PROGRESS: 'PROGRESS', + Q: 'Q', + RP: 'RP', + RT: 'RT', + RUBY: 'RUBY', + S: 'S', + SAMP: 'SAMP', + SCRIPT: 'SCRIPT', + SECTION: 'SECTION', + SELECT: 'SELECT', + SMALL: 'SMALL', + SOURCE: 'SOURCE', + SPAN: 'SPAN', + STRIKE: 'STRIKE', + STRONG: 'STRONG', + STYLE: 'STYLE', + SUB: 'SUB', + SUMMARY: 'SUMMARY', + SUP: 'SUP', + SVG: 'SVG', + TABLE: 'TABLE', + TBODY: 'TBODY', + TD: 'TD', + TEXTAREA: 'TEXTAREA', + TFOOT: 'TFOOT', + TH: 'TH', + THEAD: 'THEAD', + TIME: 'TIME', + TITLE: 'TITLE', + TR: 'TR', + TRACK: 'TRACK', + TT: 'TT', + U: 'U', + UL: 'UL', + VAR: 'VAR', + VIDEO: 'VIDEO', + WBR: 'WBR' +}; diff --git a/master/closure-library/closure/goog/dom/textrange.js b/master/closure-library/closure/goog/dom/textrange.js new file mode 100644 index 0000000000..1be6b5770d --- /dev/null +++ b/master/closure-library/closure/goog/dom/textrange.js @@ -0,0 +1,614 @@ +// Copyright 2007 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 Utilities for working with text ranges in HTML documents. + * + * @author robbyw@google.com (Robby Walker) + * @author ojan@google.com (Ojan Vafai) + * @author jparent@google.com (Julie Parent) + */ + + +goog.provide('goog.dom.TextRange'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.dom.AbstractRange'); +goog.require('goog.dom.RangeType'); +goog.require('goog.dom.SavedRange'); +goog.require('goog.dom.TagName'); +goog.require('goog.dom.TextRangeIterator'); +goog.require('goog.dom.browserrange'); +goog.require('goog.string'); +goog.require('goog.userAgent'); + + + +/** + * Create a new text selection with no properties. Do not use this constructor: + * use one of the goog.dom.Range.createFrom* methods instead. + * @constructor + * @extends {goog.dom.AbstractRange} + */ +goog.dom.TextRange = function() { +}; +goog.inherits(goog.dom.TextRange, goog.dom.AbstractRange); + + +/** + * Create a new range wrapper from the given browser range object. Do not use + * this method directly - please use goog.dom.Range.createFrom* instead. + * @param {Range|TextRange} range The browser range object. + * @param {boolean=} opt_isReversed Whether the focus node is before the anchor + * node. + * @return {goog.dom.TextRange} A range wrapper object. + */ +goog.dom.TextRange.createFromBrowserRange = function(range, opt_isReversed) { + return goog.dom.TextRange.createFromBrowserRangeWrapper_( + goog.dom.browserrange.createRange(range), opt_isReversed); +}; + + +/** + * Create a new range wrapper from the given browser range wrapper. + * @param {goog.dom.browserrange.AbstractRange} browserRange The browser range + * wrapper. + * @param {boolean=} opt_isReversed Whether the focus node is before the anchor + * node. + * @return {goog.dom.TextRange} A range wrapper object. + * @private + */ +goog.dom.TextRange.createFromBrowserRangeWrapper_ = function(browserRange, + opt_isReversed) { + var range = new goog.dom.TextRange(); + + // Initialize the range as a browser range wrapper type range. + range.browserRangeWrapper_ = browserRange; + range.isReversed_ = !!opt_isReversed; + + return range; +}; + + +/** + * Create a new range wrapper that selects the given node's text. Do not use + * this method directly - please use goog.dom.Range.createFrom* instead. + * @param {Node} node The node to select. + * @param {boolean=} opt_isReversed Whether the focus node is before the anchor + * node. + * @return {goog.dom.TextRange} A range wrapper object. + */ +goog.dom.TextRange.createFromNodeContents = function(node, opt_isReversed) { + return goog.dom.TextRange.createFromBrowserRangeWrapper_( + goog.dom.browserrange.createRangeFromNodeContents(node), + opt_isReversed); +}; + + +/** + * Create a new range wrapper that selects the area between the given nodes, + * accounting for the given offsets. Do not use this method directly - please + * use goog.dom.Range.createFrom* instead. + * @param {Node} anchorNode The node to start with. + * @param {number} anchorOffset The offset within the node to start. + * @param {Node} focusNode The node to end with. + * @param {number} focusOffset The offset within the node to end. + * @return {goog.dom.TextRange} A range wrapper object. + */ +goog.dom.TextRange.createFromNodes = function(anchorNode, anchorOffset, + focusNode, focusOffset) { + var range = new goog.dom.TextRange(); + range.isReversed_ = goog.dom.Range.isReversed(anchorNode, anchorOffset, + focusNode, focusOffset); + + // Avoid selecting BRs directly + if (anchorNode.tagName == 'BR') { + var parent = anchorNode.parentNode; + anchorOffset = goog.array.indexOf(parent.childNodes, anchorNode); + anchorNode = parent; + } + + if (focusNode.tagName == 'BR') { + var parent = focusNode.parentNode; + focusOffset = goog.array.indexOf(parent.childNodes, focusNode); + focusNode = parent; + } + + // Initialize the range as a W3C style range. + if (range.isReversed_) { + range.startNode_ = focusNode; + range.startOffset_ = focusOffset; + range.endNode_ = anchorNode; + range.endOffset_ = anchorOffset; + } else { + range.startNode_ = anchorNode; + range.startOffset_ = anchorOffset; + range.endNode_ = focusNode; + range.endOffset_ = focusOffset; + } + + return range; +}; + + +// Representation 1: a browser range wrapper. + + +/** + * The browser specific range wrapper. This can be null if one of the other + * representations of the range is specified. + * @type {goog.dom.browserrange.AbstractRange?} + * @private + */ +goog.dom.TextRange.prototype.browserRangeWrapper_ = null; + + +// Representation 2: two endpoints specified as nodes + offsets + + +/** + * The start node of the range. This can be null if one of the other + * representations of the range is specified. + * @type {Node} + * @private + */ +goog.dom.TextRange.prototype.startNode_ = null; + + +/** + * The start offset of the range. This can be null if one of the other + * representations of the range is specified. + * @type {?number} + * @private + */ +goog.dom.TextRange.prototype.startOffset_ = null; + + +/** + * The end node of the range. This can be null if one of the other + * representations of the range is specified. + * @type {Node} + * @private + */ +goog.dom.TextRange.prototype.endNode_ = null; + + +/** + * The end offset of the range. This can be null if one of the other + * representations of the range is specified. + * @type {?number} + * @private + */ +goog.dom.TextRange.prototype.endOffset_ = null; + + +/** + * Whether the focus node is before the anchor node. + * @type {boolean} + * @private + */ +goog.dom.TextRange.prototype.isReversed_ = false; + + +// Method implementations + + +/** + * @return {goog.dom.TextRange} A clone of this range. + * @override + */ +goog.dom.TextRange.prototype.clone = function() { + var range = new goog.dom.TextRange(); + range.browserRangeWrapper_ = this.browserRangeWrapper_; + range.startNode_ = this.startNode_; + range.startOffset_ = this.startOffset_; + range.endNode_ = this.endNode_; + range.endOffset_ = this.endOffset_; + range.isReversed_ = this.isReversed_; + + return range; +}; + + +/** @override */ +goog.dom.TextRange.prototype.getType = function() { + return goog.dom.RangeType.TEXT; +}; + + +/** @override */ +goog.dom.TextRange.prototype.getBrowserRangeObject = function() { + return this.getBrowserRangeWrapper_().getBrowserRange(); +}; + + +/** @override */ +goog.dom.TextRange.prototype.setBrowserRangeObject = function(nativeRange) { + // Test if it's a control range by seeing if a control range only method + // exists. + if (goog.dom.AbstractRange.isNativeControlRange(nativeRange)) { + return false; + } + this.browserRangeWrapper_ = goog.dom.browserrange.createRange( + nativeRange); + this.clearCachedValues_(); + return true; +}; + + +/** + * Clear all cached values. + * @private + */ +goog.dom.TextRange.prototype.clearCachedValues_ = function() { + this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null; +}; + + +/** @override */ +goog.dom.TextRange.prototype.getTextRangeCount = function() { + return 1; +}; + + +/** @override */ +goog.dom.TextRange.prototype.getTextRange = function(i) { + return this; +}; + + +/** + * @return {goog.dom.browserrange.AbstractRange} The range wrapper object. + * @private + */ +goog.dom.TextRange.prototype.getBrowserRangeWrapper_ = function() { + return this.browserRangeWrapper_ || + (this.browserRangeWrapper_ = goog.dom.browserrange.createRangeFromNodes( + this.getStartNode(), this.getStartOffset(), + this.getEndNode(), this.getEndOffset())); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getContainer = function() { + return this.getBrowserRangeWrapper_().getContainer(); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getStartNode = function() { + return this.startNode_ || + (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode()); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getStartOffset = function() { + return this.startOffset_ != null ? this.startOffset_ : + (this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset()); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getEndNode = function() { + return this.endNode_ || + (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode()); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getEndOffset = function() { + return this.endOffset_ != null ? this.endOffset_ : + (this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset()); +}; + + +/** + * Moves a TextRange to the provided nodes and offsets. + * @param {Node} startNode The node to start with. + * @param {number} startOffset The offset within the node to start. + * @param {Node} endNode The node to end with. + * @param {number} endOffset The offset within the node to end. + * @param {boolean} isReversed Whether the range is reversed. + */ +goog.dom.TextRange.prototype.moveToNodes = function(startNode, startOffset, + endNode, endOffset, + isReversed) { + this.startNode_ = startNode; + this.startOffset_ = startOffset; + this.endNode_ = endNode; + this.endOffset_ = endOffset; + this.isReversed_ = isReversed; + this.browserRangeWrapper_ = null; +}; + + +/** @override */ +goog.dom.TextRange.prototype.isReversed = function() { + return this.isReversed_; +}; + + +/** @override */ +goog.dom.TextRange.prototype.containsRange = function(otherRange, + opt_allowPartial) { + var otherRangeType = otherRange.getType(); + if (otherRangeType == goog.dom.RangeType.TEXT) { + return this.getBrowserRangeWrapper_().containsRange( + otherRange.getBrowserRangeWrapper_(), opt_allowPartial); + } else if (otherRangeType == goog.dom.RangeType.CONTROL) { + var elements = otherRange.getElements(); + var fn = opt_allowPartial ? goog.array.some : goog.array.every; + return fn(elements, function(el) { + return this.containsNode(el, opt_allowPartial); + }, this); + } + return false; +}; + + +/** + * Tests if the given node is in a document. + * @param {Node} node The node to check. + * @return {boolean} Whether the given node is in the given document. + */ +goog.dom.TextRange.isAttachedNode = function(node) { + if (goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) { + var returnValue = false; + /** @preserveTry */ + try { + returnValue = node.parentNode; + } catch (e) { + // IE sometimes throws Invalid Argument errors when a node is detached. + // Note: trying to return a value from the above try block can cause IE + // to crash. It is necessary to use the local returnValue + } + return !!returnValue; + } else { + return goog.dom.contains(node.ownerDocument.body, node); + } +}; + + +/** @override */ +goog.dom.TextRange.prototype.isRangeInDocument = function() { + // Ensure any cached nodes are in the document. IE also allows ranges to + // become detached, so we check if the range is still in the document as + // well for IE. + return (!this.startNode_ || + goog.dom.TextRange.isAttachedNode(this.startNode_)) && + (!this.endNode_ || + goog.dom.TextRange.isAttachedNode(this.endNode_)) && + (!(goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) || + this.getBrowserRangeWrapper_().isRangeInDocument()); +}; + + +/** @override */ +goog.dom.TextRange.prototype.isCollapsed = function() { + return this.getBrowserRangeWrapper_().isCollapsed(); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getText = function() { + return this.getBrowserRangeWrapper_().getText(); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getHtmlFragment = function() { + // TODO(robbyw): Generalize the code in browserrange so it is static and + // just takes an iterator. This would mean we don't always have to create a + // browser range. + return this.getBrowserRangeWrapper_().getHtmlFragment(); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getValidHtml = function() { + return this.getBrowserRangeWrapper_().getValidHtml(); +}; + + +/** @override */ +goog.dom.TextRange.prototype.getPastableHtml = function() { + // TODO(robbyw): Get any attributes the table or tr has. + + var html = this.getValidHtml(); + + if (html.match(/^\s*'; + } else if (html.match(/^\s*'; + } else if (html.match(/^\s*'; + } else if (html.match(/^\s*', html, ''); + } + + return html; +}; + + +/** + * Returns a TextRangeIterator over the contents of the range. Regardless of + * the direction of the range, the iterator will move in document order. + * @param {boolean=} opt_keys Unused for this iterator. + * @return {goog.dom.TextRangeIterator} An iterator over tags in the range. + * @override + */ +goog.dom.TextRange.prototype.__iterator__ = function(opt_keys) { + return new goog.dom.TextRangeIterator(this.getStartNode(), + this.getStartOffset(), this.getEndNode(), this.getEndOffset()); +}; + + +// RANGE ACTIONS + + +/** @override */ +goog.dom.TextRange.prototype.select = function() { + this.getBrowserRangeWrapper_().select(this.isReversed_); +}; + + +/** @override */ +goog.dom.TextRange.prototype.removeContents = function() { + this.getBrowserRangeWrapper_().removeContents(); + this.clearCachedValues_(); +}; + + +/** + * Surrounds the text range with the specified element (on Mozilla) or with a + * clone of the specified element (on IE). Returns a reference to the + * surrounding element if the operation was successful; returns null if the + * operation failed. + * @param {Element} element The element with which the selection is to be + * surrounded. + * @return {Element} The surrounding element (same as the argument on Mozilla, + * but not on IE), or null if unsuccessful. + */ +goog.dom.TextRange.prototype.surroundContents = function(element) { + var output = this.getBrowserRangeWrapper_().surroundContents(element); + this.clearCachedValues_(); + return output; +}; + + +/** @override */ +goog.dom.TextRange.prototype.insertNode = function(node, before) { + var output = this.getBrowserRangeWrapper_().insertNode(node, before); + this.clearCachedValues_(); + return output; +}; + + +/** @override */ +goog.dom.TextRange.prototype.surroundWithNodes = function(startNode, endNode) { + this.getBrowserRangeWrapper_().surroundWithNodes(startNode, endNode); + this.clearCachedValues_(); +}; + + +// SAVE/RESTORE + + +/** @override */ +goog.dom.TextRange.prototype.saveUsingDom = function() { + return new goog.dom.DomSavedTextRange_(this); +}; + + +// RANGE MODIFICATION + + +/** @override */ +goog.dom.TextRange.prototype.collapse = function(toAnchor) { + var toStart = this.isReversed() ? !toAnchor : toAnchor; + + if (this.browserRangeWrapper_) { + this.browserRangeWrapper_.collapse(toStart); + } + + if (toStart) { + this.endNode_ = this.startNode_; + this.endOffset_ = this.startOffset_; + } else { + this.startNode_ = this.endNode_; + this.startOffset_ = this.endOffset_; + } + + // Collapsed ranges can't be reversed + this.isReversed_ = false; +}; + + +// SAVED RANGE OBJECTS + + + +/** + * A SavedRange implementation using DOM endpoints. + * @param {goog.dom.AbstractRange} range The range to save. + * @constructor + * @extends {goog.dom.SavedRange} + * @private + */ +goog.dom.DomSavedTextRange_ = function(range) { + /** + * The anchor node. + * @type {Node} + * @private + */ + this.anchorNode_ = range.getAnchorNode(); + + /** + * The anchor node offset. + * @type {number} + * @private + */ + this.anchorOffset_ = range.getAnchorOffset(); + + /** + * The focus node. + * @type {Node} + * @private + */ + this.focusNode_ = range.getFocusNode(); + + /** + * The focus node offset. + * @type {number} + * @private + */ + this.focusOffset_ = range.getFocusOffset(); +}; +goog.inherits(goog.dom.DomSavedTextRange_, goog.dom.SavedRange); + + +/** + * @return {goog.dom.AbstractRange} The restored range. + * @override + */ +goog.dom.DomSavedTextRange_.prototype.restoreInternal = function() { + return goog.dom.Range.createFromNodes(this.anchorNode_, this.anchorOffset_, + this.focusNode_, this.focusOffset_); +}; + + +/** @override */ +goog.dom.DomSavedTextRange_.prototype.disposeInternal = function() { + goog.dom.DomSavedTextRange_.superClass_.disposeInternal.call(this); + + this.anchorNode_ = null; + this.focusNode_ = null; +}; diff --git a/master/closure-library/closure/goog/dom/textrangeiterator.js b/master/closure-library/closure/goog/dom/textrangeiterator.js new file mode 100644 index 0000000000..b8d49b8565 --- /dev/null +++ b/master/closure-library/closure/goog/dom/textrangeiterator.js @@ -0,0 +1,244 @@ +// Copyright 2007 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 Iterator between two DOM text range positions. + * + * @author robbyw@google.com (Robby Walker) + */ + +goog.provide('goog.dom.TextRangeIterator'); + +goog.require('goog.array'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.RangeIterator'); +goog.require('goog.dom.TagName'); +goog.require('goog.iter.StopIteration'); + + + +/** + * Subclass of goog.dom.TagIterator that iterates over a DOM range. It + * adds functions to determine the portion of each text node that is selected. + * + * @param {Node} startNode The starting node position. + * @param {number} startOffset The offset in to startNode. If startNode is + * an element, indicates an offset in to childNodes. If startNode is a + * text node, indicates an offset in to nodeValue. + * @param {Node} endNode The ending node position. + * @param {number} endOffset The offset in to endNode. If endNode is + * an element, indicates an offset in to childNodes. If endNode is a + * text node, indicates an offset in to nodeValue. + * @param {boolean=} opt_reverse Whether to traverse nodes in reverse. + * @constructor + * @extends {goog.dom.RangeIterator} + */ +goog.dom.TextRangeIterator = function(startNode, startOffset, endNode, + endOffset, opt_reverse) { + var goNext; + + if (startNode) { + this.startNode_ = startNode; + this.startOffset_ = startOffset; + this.endNode_ = endNode; + this.endOffset_ = endOffset; + + // Skip to the offset nodes - being careful to special case BRs since these + // have no children but still can appear as the startContainer of a range. + if (startNode.nodeType == goog.dom.NodeType.ELEMENT && + startNode.tagName != goog.dom.TagName.BR) { + var startChildren = startNode.childNodes; + var candidate = startChildren[startOffset]; + if (candidate) { + this.startNode_ = candidate; + this.startOffset_ = 0; + } else { + if (startChildren.length) { + this.startNode_ = + /** @type {Node} */ (goog.array.peek(startChildren)); + } + goNext = true; + } + } + + if (endNode.nodeType == goog.dom.NodeType.ELEMENT) { + this.endNode_ = endNode.childNodes[endOffset]; + if (this.endNode_) { + this.endOffset_ = 0; + } else { + // The offset was past the last element. + this.endNode_ = endNode; + } + } + } + + goog.dom.RangeIterator.call(this, opt_reverse ? this.endNode_ : + this.startNode_, opt_reverse); + + if (goNext) { + try { + this.next(); + } catch (e) { + if (e != goog.iter.StopIteration) { + throw e; + } + } + } +}; +goog.inherits(goog.dom.TextRangeIterator, goog.dom.RangeIterator); + + +/** + * The first node in the selection. + * @type {Node} + * @private + */ +goog.dom.TextRangeIterator.prototype.startNode_ = null; + + +/** + * The last node in the selection. + * @type {Node} + * @private + */ +goog.dom.TextRangeIterator.prototype.endNode_ = null; + + +/** + * The offset within the first node in the selection. + * @type {number} + * @private + */ +goog.dom.TextRangeIterator.prototype.startOffset_ = 0; + + +/** + * The offset within the last node in the selection. + * @type {number} + * @private + */ +goog.dom.TextRangeIterator.prototype.endOffset_ = 0; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.getStartTextOffset = function() { + // Offsets only apply to text nodes. If our current node is the start node, + // return the saved offset. Otherwise, return 0. + return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : + this.node == this.startNode_ ? this.startOffset_ : 0; +}; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.getEndTextOffset = function() { + // Offsets only apply to text nodes. If our current node is the end node, + // return the saved offset. Otherwise, return the length of the node. + return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : + this.node == this.endNode_ ? this.endOffset_ : this.node.nodeValue.length; +}; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.getStartNode = function() { + return this.startNode_; +}; + + +/** + * Change the start node of the iterator. + * @param {Node} node The new start node. + */ +goog.dom.TextRangeIterator.prototype.setStartNode = function(node) { + if (!this.isStarted()) { + this.setPosition(node); + } + + this.startNode_ = node; + this.startOffset_ = 0; +}; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.getEndNode = function() { + return this.endNode_; +}; + + +/** + * Change the end node of the iterator. + * @param {Node} node The new end node. + */ +goog.dom.TextRangeIterator.prototype.setEndNode = function(node) { + this.endNode_ = node; + this.endOffset_ = 0; +}; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.isLast = function() { + return this.isStarted() && this.node == this.endNode_ && + (!this.endOffset_ || !this.isStartTag()); +}; + + +/** + * Move to the next position in the selection. + * Throws {@code goog.iter.StopIteration} when it passes the end of the range. + * @return {Node} The node at the next position. + * @override + */ +goog.dom.TextRangeIterator.prototype.next = function() { + if (this.isLast()) { + throw goog.iter.StopIteration; + } + + // Call the super function. + return goog.dom.TextRangeIterator.superClass_.next.call(this); +}; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.skipTag = function() { + goog.dom.TextRangeIterator.superClass_.skipTag.apply(this); + + // If the node we are skipping contains the end node, we just skipped past + // the end, so we stop the iteration. + if (goog.dom.contains(this.node, this.endNode_)) { + throw goog.iter.StopIteration; + } +}; + + +/** @override */ +goog.dom.TextRangeIterator.prototype.copyFrom = function(other) { + this.startNode_ = other.startNode_; + this.endNode_ = other.endNode_; + this.startOffset_ = other.startOffset_; + this.endOffset_ = other.endOffset_; + this.isReversed_ = other.isReversed_; + + goog.dom.TextRangeIterator.superClass_.copyFrom.call(this, other); +}; + + +/** + * @return {goog.dom.TextRangeIterator} An identical iterator. + * @override + */ +goog.dom.TextRangeIterator.prototype.clone = function() { + var copy = new goog.dom.TextRangeIterator(this.startNode_, + this.startOffset_, this.endNode_, this.endOffset_, this.isReversed_); + copy.copyFrom(this); + return copy; +}; diff --git a/master/closure-library/closure/goog/dom/viewportsizemonitor.js b/master/closure-library/closure/goog/dom/viewportsizemonitor.js new file mode 100644 index 0000000000..8bc2423b39 --- /dev/null +++ b/master/closure-library/closure/goog/dom/viewportsizemonitor.js @@ -0,0 +1,233 @@ +// Copyright 2007 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 Utility class that monitors viewport size changes. + * + * @author attila@google.com (Attila Bodis) + * @see ../demos/viewportsizemonitor.html + */ + +goog.provide('goog.dom.ViewportSizeMonitor'); + +goog.require('goog.dom'); +goog.require('goog.events'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('goog.math.Size'); +goog.require('goog.userAgent'); + + + +/** + * This class can be used to monitor changes in the viewport size. Instances + * dispatch a {@link goog.events.EventType.RESIZE} event when the viewport size + * changes. Handlers can call {@link goog.dom.ViewportSizeMonitor#getSize} to + * get the new viewport size. + * + * Use this class if you want to execute resize/reflow logic each time the + * user resizes the browser window. This class is guaranteed to only dispatch + * {@code RESIZE} events when the pixel dimensions of the viewport change. + * (Internet Explorer fires resize events if any element on the page is resized, + * even if the viewport dimensions are unchanged, which can lead to infinite + * resize loops.) + * + * Example usage: + *
+ *    var vsm = new goog.dom.ViewportSizeMonitor();
+ *    goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
+ *      alert('Viewport size changed to ' + vsm.getSize());
+ *    });
+ *  
+ * + * Manually verified on IE6, IE7, FF2, Opera 9, and WebKit. {@code getSize} + * doesn't always return the correct viewport height on Safari 2.0.4. + * + * @param {Window=} opt_window The window to monitor; defaults to the window in + * which this code is executing. + * @constructor + * @extends {goog.events.EventTarget} + */ +goog.dom.ViewportSizeMonitor = function(opt_window) { + goog.events.EventTarget.call(this); + + // Default the window to the current window if unspecified. + this.window_ = opt_window || window; + + // Listen for window resize events. + this.listenerKey_ = goog.events.listen(this.window_, + goog.events.EventType.RESIZE, this.handleResize_, false, this); + + // Set the initial size. + this.size_ = goog.dom.getViewportSize(this.window_); + + if (this.isPollingRequired_()) { + this.windowSizePollInterval_ = window.setInterval( + goog.bind(this.checkForSizeChange_, this), + goog.dom.ViewportSizeMonitor.WINDOW_SIZE_POLL_RATE); + } +}; +goog.inherits(goog.dom.ViewportSizeMonitor, goog.events.EventTarget); + + +/** + * Returns a viewport size monitor for the given window. A new one is created + * if it doesn't exist already. This prevents the unnecessary creation of + * multiple spooling monitors for a window. + * @param {Window=} opt_window The window to monitor; defaults to the window in + * which this code is executing. + * @return {goog.dom.ViewportSizeMonitor} Monitor for the given window. + */ +goog.dom.ViewportSizeMonitor.getInstanceForWindow = function(opt_window) { + var currentWindow = opt_window || window; + var uid = goog.getUid(currentWindow); + + return goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] = + goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] || + new goog.dom.ViewportSizeMonitor(currentWindow); +}; + + +/** + * Removes and disposes a viewport size monitor for the given window if one + * exists. + * @param {Window=} opt_window The window whose monitor should be removed; + * defaults to the window in which this code is executing. + */ +goog.dom.ViewportSizeMonitor.removeInstanceForWindow = function(opt_window) { + var uid = goog.getUid(opt_window || window); + + goog.dispose(goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]); + delete goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]; +}; + + +/** + * Map of window hash code to viewport size monitor for that window, if + * created. + * @type {Object.} + * @private + */ +goog.dom.ViewportSizeMonitor.windowInstanceMap_ = {}; + + +/** + * Rate in milliseconds at which to poll the window size on browsers that + * need polling. + * @type {number} + */ +goog.dom.ViewportSizeMonitor.WINDOW_SIZE_POLL_RATE = 500; + + +/** + * Event listener key for window the window resize handler, as returned by + * {@link goog.events.listen}. + * @type {?number} + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.listenerKey_ = null; + + +/** + * The window to monitor. Defaults to the window in which the code is running. + * @type {Window} + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.window_ = null; + + +/** + * The most recently recorded size of the viewport, in pixels. + * @type {goog.math.Size?} + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.size_ = null; + + +/** + * Identifier for the interval used for polling the window size on Windows + * Safari. + * @type {?number} + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.windowSizePollInterval_ = null; + + +/** + * Checks if polling is required for this user agent. Opera only requires + * polling when the page is loaded within an IFRAME. + * @return {boolean} Whether polling is required. + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.isPollingRequired_ = function() { + return goog.userAgent.WEBKIT && goog.userAgent.WINDOWS || + goog.userAgent.OPERA && this.window_.self != this.window_.top; +}; + + +/** + * Returns the most recently recorded size of the viewport, in pixels. May + * return null if no window resize event has been handled yet. + * @return {goog.math.Size} The viewport dimensions, in pixels. + */ +goog.dom.ViewportSizeMonitor.prototype.getSize = function() { + // Return a clone instead of the original to preserve encapsulation. + return this.size_ ? this.size_.clone() : null; +}; + + +/** @override */ +goog.dom.ViewportSizeMonitor.prototype.disposeInternal = function() { + goog.dom.ViewportSizeMonitor.superClass_.disposeInternal.call(this); + + if (this.listenerKey_) { + goog.events.unlistenByKey(this.listenerKey_); + this.listenerKey_ = null; + } + + if (this.windowSizePollInterval_) { + window.clearInterval(this.windowSizePollInterval_); + this.windowSizePollInterval_ = null; + } + + this.window_ = null; + this.size_ = null; +}; + + +/** + * Handles window resize events by measuring the dimensions of the + * viewport and dispatching a {@link goog.events.EventType.RESIZE} event if the + * current dimensions are different from the previous ones. + * @param {goog.events.Event} event The window resize event to handle. + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.handleResize_ = function(event) { + this.checkForSizeChange_(); +}; + + +/** + * Measures the dimensions of the viewport and dispatches a + * {@link goog.events.EventType.RESIZE} event if the current dimensions are + * different from the previous ones. + * @private + */ +goog.dom.ViewportSizeMonitor.prototype.checkForSizeChange_ = function() { + var size = goog.dom.getViewportSize(this.window_); + if (!goog.math.Size.equals(size, this.size_)) { + this.size_ = size; + this.dispatchEvent(goog.events.EventType.RESIZE); + } +}; diff --git a/master/closure-library/closure/goog/dom/xml.js b/master/closure-library/closure/goog/dom/xml.js new file mode 100644 index 0000000000..a5ab4f8db2 --- /dev/null +++ b/master/closure-library/closure/goog/dom/xml.js @@ -0,0 +1,204 @@ +// Copyright 2006 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 + * XML utilities. + * + */ + +goog.provide('goog.dom.xml'); + +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); + + +/** + * Max XML size for MSXML2. Used to prevent potential DoS attacks. + * @type {number} + */ +goog.dom.xml.MAX_XML_SIZE_KB = 2 * 1024; // In kB + + +/** + * Max XML size for MSXML2. Used to prevent potential DoS attacks. + * @type {number} + */ +goog.dom.xml.MAX_ELEMENT_DEPTH = 256; // Same default as MSXML6. + + +/** + * Creates an XML document appropriate for the current JS runtime + * @param {string=} opt_rootTagName The root tag name. + * @param {string=} opt_namespaceUri Namespace URI of the document element. + * @return {Document} The new document. + */ +goog.dom.xml.createDocument = function(opt_rootTagName, opt_namespaceUri) { + if (opt_namespaceUri && !opt_rootTagName) { + throw Error("Can't create document with namespace and no root tag"); + } + if (document.implementation && document.implementation.createDocument) { + return document.implementation.createDocument(opt_namespaceUri || '', + opt_rootTagName || '', + null); + } else if (typeof ActiveXObject != 'undefined') { + var doc = goog.dom.xml.createMsXmlDocument_(); + if (doc) { + if (opt_rootTagName) { + doc.appendChild(doc.createNode(goog.dom.NodeType.ELEMENT, + opt_rootTagName, + opt_namespaceUri || '')); + } + return doc; + } + } + throw Error('Your browser does not support creating new documents'); +}; + + +/** + * Creates an XML document from a string + * @param {string} xml The text. + * @return {Document} XML document from the text. + */ +goog.dom.xml.loadXml = function(xml) { + if (typeof DOMParser != 'undefined') { + return new DOMParser().parseFromString(xml, 'application/xml'); + } else if (typeof ActiveXObject != 'undefined') { + var doc = goog.dom.xml.createMsXmlDocument_(); + doc.loadXML(xml); + return doc; + } + throw Error('Your browser does not support loading xml documents'); +}; + + +/** + * Serializes an XML document or subtree to string. + * @param {Document|Element} xml The document or the root node of the subtree. + * @return {string} The serialized XML. + */ +goog.dom.xml.serialize = function(xml) { + // Compatible with Firefox, Opera and WebKit. + if (typeof XMLSerializer != 'undefined') { + return new XMLSerializer().serializeToString(xml); + } + // Compatible with Internet Explorer. + var text = xml.xml; + if (text) { + return text; + } + throw Error('Your browser does not support serializing XML documents'); +}; + + +/** + * Selects a single node using an Xpath expression and a root node + * @param {Node} node The root node. + * @param {string} path Xpath selector. + * @return {Node} The selected node, or null if no matching node. + */ +goog.dom.xml.selectSingleNode = function(node, path) { + if (typeof node.selectSingleNode != 'undefined') { + var doc = goog.dom.getOwnerDocument(node); + if (typeof doc.setProperty != 'undefined') { + doc.setProperty('SelectionLanguage', 'XPath'); + } + return node.selectSingleNode(path); + } else if (document.implementation.hasFeature('XPath', '3.0')) { + var doc = goog.dom.getOwnerDocument(node); + var resolver = doc.createNSResolver(doc.documentElement); + var result = doc.evaluate(path, node, resolver, + XPathResult.FIRST_ORDERED_NODE_TYPE, null); + return result.singleNodeValue; + } + return null; +}; + + +/** + * Selects multiple nodes using an Xpath expression and a root node + * @param {Node} node The root node. + * @param {string} path Xpath selector. + * @return {(NodeList,Array.)} The selected nodes, or empty array if no + * matching nodes. + */ +goog.dom.xml.selectNodes = function(node, path) { + if (typeof node.selectNodes != 'undefined') { + var doc = goog.dom.getOwnerDocument(node); + if (typeof doc.setProperty != 'undefined') { + doc.setProperty('SelectionLanguage', 'XPath'); + } + return node.selectNodes(path); + } else if (document.implementation.hasFeature('XPath', '3.0')) { + var doc = goog.dom.getOwnerDocument(node); + var resolver = doc.createNSResolver(doc.documentElement); + var nodes = doc.evaluate(path, node, resolver, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + var results = []; + var count = nodes.snapshotLength; + for (var i = 0; i < count; i++) { + results.push(nodes.snapshotItem(i)); + } + return results; + } else { + return []; + } +}; + + +/** + * Sets multiple attributes on an element. Differs from goog.dom.setProperties + * in that it exclusively uses the element's setAttributes method. Use this + * when you need to ensure that the exact property is available as an attribute + * and can be read later by the native getAttribute method. + * @param {!Element} element XML or DOM element to set attributes on. + * @param {!Object.} attributes Map of property:value pairs. + */ +goog.dom.xml.setAttributes = function(element, attributes) { + for (var key in attributes) { + if (attributes.hasOwnProperty(key)) { + element.setAttribute(key, attributes[key]); + } + } +}; + + +/** + * Creates an instance of the MSXML2.DOMDocument. + * @return {Document} The new document. + * @private + */ +goog.dom.xml.createMsXmlDocument_ = function() { + var doc = new ActiveXObject('MSXML2.DOMDocument'); + if (doc) { + // Prevent potential vulnerabilities exposed by MSXML2, see + // http://b/1707300 and http://wiki/Main/ISETeamXMLAttacks for details. + doc.resolveExternals = false; + doc.validateOnParse = false; + // Add a try catch block because accessing these properties will throw an + // error on unsupported MSXML versions. This affects Windows machines + // running IE6 or IE7 that are on XP SP2 or earlier without MSXML updates. + // See http://msdn.microsoft.com/en-us/library/ms766391(VS.85).aspx for + // specific details on which MSXML versions support these properties. + try { + doc.setProperty('ProhibitDTD', true); + doc.setProperty('MaxXMLSize', goog.dom.xml.MAX_XML_SIZE_KB); + doc.setProperty('MaxElementDepth', goog.dom.xml.MAX_ELEMENT_DEPTH); + } catch (e) { + // No-op. + } + } + return doc; +}; diff --git a/master/closure-library/closure/goog/editor/browserfeature.js b/master/closure-library/closure/goog/editor/browserfeature.js new file mode 100644 index 0000000000..678dd04df1 --- /dev/null +++ b/master/closure-library/closure/goog/editor/browserfeature.js @@ -0,0 +1,266 @@ +// 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 Trogedit constants for browser features and quirks that should + * be used by the rich text editor. + */ + +goog.provide('goog.editor.BrowserFeature'); + +goog.require('goog.editor.defines'); +goog.require('goog.userAgent'); +goog.require('goog.userAgent.product'); +goog.require('goog.userAgent.product.isVersion'); + + +/** + * Maps browser quirks to boolean values, detailing what the current + * browser supports. + * @type {Object} + */ +goog.editor.BrowserFeature = { + // Whether this browser uses the IE TextRange object. + HAS_IE_RANGES: goog.userAgent.IE && !goog.userAgent.isDocumentMode(9), + + // Whether this browser uses the W3C standard Range object. + // Assumes IE higher versions will be compliance with W3C standard. + HAS_W3C_RANGES: goog.userAgent.GECKO || goog.userAgent.WEBKIT || + goog.userAgent.OPERA || + (goog.userAgent.IE && goog.userAgent.isDocumentMode(9)), + + // Has the contentEditable attribute, which makes nodes editable. + // + // NOTE(nicksantos): FF3 has contentEditable, but there are 3 major reasons + // why we don't use it: + // 1) In FF3, we listen for key events on the document, and we'd have to + // filter them properly. See TR_Browser.USE_DOCUMENT_FOR_KEY_EVENTS. + // 2) In FF3, we listen for focus/blur events on the document, which + // simply doesn't make sense in contentEditable. focus/blur + // on contentEditable elements still has some quirks, which we're + // talking to Firefox-team about. + // 3) We currently use Mutation events in FF3 to detect changes, + // and these are dispatched on the document only. + // If we ever hope to support FF3/contentEditable, all 3 of these issues + // will need answers. Most just involve refactoring at our end. + HAS_CONTENT_EDITABLE: goog.userAgent.IE || goog.userAgent.WEBKIT || + goog.userAgent.OPERA || + (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 && + goog.userAgent.GECKO && goog.userAgent.isVersion('1.9')), + + // Whether to use mutation event types to detect changes + // in the field contents. + USE_MUTATION_EVENTS: goog.userAgent.GECKO, + + // Whether the browser has a functional DOMSubtreeModified event. + // TODO(user): Enable for all FF3 once we're confident this event fires + // reliably. Currently it's only enabled if using contentEditable in FF as + // we have no other choice in that case but to use this event. + HAS_DOM_SUBTREE_MODIFIED_EVENT: goog.userAgent.WEBKIT || + (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 && + goog.userAgent.GECKO && goog.userAgent.isVersion('1.9')), + + // Whether nodes can be copied from one document to another + HAS_DOCUMENT_INDEPENDENT_NODES: goog.userAgent.GECKO, + + // Whether the cursor goes before or inside the first block element on + // focus, e.g.,

foo

. FF will put the cursor before the + // paragraph on focus, which is wrong. + PUTS_CURSOR_BEFORE_FIRST_BLOCK_ELEMENT_ON_FOCUS: goog.userAgent.GECKO, + + // Whether the selection of one frame is cleared when another frame + // is focused. + CLEARS_SELECTION_WHEN_FOCUS_LEAVES: + goog.userAgent.IE || goog.userAgent.WEBKIT || goog.userAgent.OPERA, + + // Whether "unselectable" is supported as an element style. + HAS_UNSELECTABLE_STYLE: goog.userAgent.GECKO || goog.userAgent.WEBKIT, + + // Whether this browser's "FormatBlock" command does not suck. + FORMAT_BLOCK_WORKS_FOR_BLOCKQUOTES: goog.userAgent.GECKO || + goog.userAgent.WEBKIT || goog.userAgent.OPERA, + + // Whether this browser's "FormatBlock" command may create multiple + // blockquotes. + CREATES_MULTIPLE_BLOCKQUOTES: + (goog.userAgent.WEBKIT && !goog.userAgent.isVersion('534.16')) || + goog.userAgent.OPERA, + + // Whether this browser's "FormatBlock" command will wrap blockquotes + // inside of divs, instead of replacing divs with blockquotes. + WRAPS_BLOCKQUOTE_IN_DIVS: goog.userAgent.OPERA, + + // Whether the readystatechange event is more reliable than load. + PREFERS_READY_STATE_CHANGE_EVENT: goog.userAgent.IE, + + // Whether hitting the tab key will fire a keypress event. + // see http://www.quirksmode.org/js/keys.html + TAB_FIRES_KEYPRESS: !goog.userAgent.IE, + + // Has a standards mode quirk where width=100% doesn't do the right thing, + // but width=99% does. + // TODO(user|user): This should be fixable by less hacky means + NEEDS_99_WIDTH_IN_STANDARDS_MODE: goog.userAgent.IE, + + // Whether keyboard events only reliably fire on the document. + // On Gecko without contentEditable, keyboard events only fire reliably on the + // document element. With contentEditable, the field itself is focusable, + // which means that it will fire key events. + USE_DOCUMENT_FOR_KEY_EVENTS: goog.userAgent.GECKO && + !goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3, + + // Whether this browser shows non-standard attributes in innerHTML. + SHOWS_CUSTOM_ATTRS_IN_INNER_HTML: goog.userAgent.IE, + + // Whether this browser shrinks empty nodes away to nothing. + // (If so, we need to insert some space characters into nodes that + // shouldn't be collapsed) + COLLAPSES_EMPTY_NODES: + goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA, + + // Whether we must convert and tags to , . + CONVERT_TO_B_AND_I_TAGS: goog.userAgent.GECKO || goog.userAgent.OPERA, + + // Whether this browser likes to tab through images in contentEditable mode, + // and we like to disable this feature. + TABS_THROUGH_IMAGES: goog.userAgent.IE, + + // Whether this browser unescapes urls when you extract it from the href tag. + UNESCAPES_URLS_WITHOUT_ASKING: goog.userAgent.IE && + !goog.userAgent.isVersion('7.0'), + + // Whether this browser supports execCommand("styleWithCSS") to toggle between + // inserting html tags or inline styling for things like bold, italic, etc. + HAS_STYLE_WITH_CSS: + goog.userAgent.GECKO && goog.userAgent.isVersion('1.8') || + goog.userAgent.WEBKIT || goog.userAgent.OPERA, + + // Whether clicking on an editable link will take you to that site. + FOLLOWS_EDITABLE_LINKS: goog.userAgent.WEBKIT, + + // Whether this browser has document.activeElement available. + HAS_ACTIVE_ELEMENT: + goog.userAgent.IE || goog.userAgent.OPERA || + goog.userAgent.GECKO && goog.userAgent.isVersion('1.9'), + + // Whether this browser supports the setCapture method on DOM elements. + HAS_SET_CAPTURE: goog.userAgent.IE, + + // Whether this browser can't set background color when the selection + // is collapsed. + EATS_EMPTY_BACKGROUND_COLOR: goog.userAgent.GECKO || + goog.userAgent.WEBKIT && !goog.userAgent.isVersion('527'), + + // Whether this browser supports the "focusin" or "DOMFocusIn" event + // consistently. + // NOTE(nicksantos): FF supports DOMFocusIn, but doesn't seem to do so + // consistently. + SUPPORTS_FOCUSIN: goog.userAgent.IE || goog.userAgent.OPERA, + + // Whether clicking on an image will cause the selection to move to the image. + // Note: Gecko moves the selection, but it won't always go to the image. + // For example, if the image is wrapped in a div, and you click on the img, + // anchorNode = focusNode = div, anchorOffset = 0, focusOffset = 1, so this + // is another way of "selecting" the image, but there are too many special + // cases like this so we will do the work manually. + SELECTS_IMAGES_ON_CLICK: goog.userAgent.IE || goog.userAgent.OPERA, + + // Whether this browser moves '); + + // + // Hidefocus is needed to ensure that IE7 doesn't show the dotted, focus + // border when you tab into the field. + html.push('', bodyHtml, ''); + + return html.join(''); +}; + + +/** + * Write the initial iframe content in normal mode. + * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about + * the field. + * @param {string} bodyHtml The HTML to insert as the iframe body. + * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about + * the field, if needed. + * @param {HTMLIFrameElement} iframe The iframe. + */ +goog.editor.icontent.writeNormalInitialBlendedIframe = + function(info, bodyHtml, style, iframe) { + // Firefox blended needs to inherit all the css from the original page. + // Firefox standards mode needs to set extra style for images. + if (info.blended_) { + var field = style.wrapper_; + // If there is padding on the original field, then the iFrame will be + // positioned inside the padding by default. We don't want this, as it + // causes the contents to appear to shift, and also causes the + // scrollbars to appear inside the padding. + // + // To compensate, we set the iframe margins to offset the padding. + var paddingBox = goog.style.getPaddingBox(field); + if (paddingBox.top || paddingBox.left || + paddingBox.right || paddingBox.bottom) { + goog.style.setStyle(iframe, 'margin', + (-paddingBox.top) + 'px ' + + (-paddingBox.right) + 'px ' + + (-paddingBox.bottom) + 'px ' + + (-paddingBox.left) + 'px'); + } + } + + goog.editor.icontent.writeNormalInitialIframe( + info, bodyHtml, style, iframe); +}; + + +/** + * Write the initial iframe content in normal mode. + * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about + * the field. + * @param {string} bodyHtml The HTML to insert as the iframe body. + * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about + * the field, if needed. + * @param {HTMLIFrameElement} iframe The iframe. + */ +goog.editor.icontent.writeNormalInitialIframe = + function(info, bodyHtml, style, iframe) { + + var html = goog.editor.icontent.getInitialIframeContent_( + info, bodyHtml, style); + + var doc = goog.dom.getFrameContentDocument(iframe); + doc.open(); + doc.write(html); + doc.close(); +}; + + +/** + * Write the initial iframe content in IE/HTTPS mode. + * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about + * the field. + * @param {Document} doc The iframe document. + * @param {string} bodyHtml The HTML to insert as the iframe body. + */ +goog.editor.icontent.writeHttpsInitialIframe = function(info, doc, bodyHtml) { + var body = doc.body; + + // For HTTPS we already have a document with a doc type and a body element + // and don't want to create a new history entry which can cause data loss if + // the user clicks the back button. + if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) { + body.contentEditable = true; + } + body.className = 'editable'; + body.setAttribute('g_editable', true); + body.hideFocus = true; + body.id = info.fieldId_; + + goog.style.setStyle(body, info.extraStyles_); + body.innerHTML = bodyHtml; +}; + diff --git a/master/closure-library/closure/goog/editor/link.js b/master/closure-library/closure/goog/editor/link.js new file mode 100644 index 0000000000..6d89a64441 --- /dev/null +++ b/master/closure-library/closure/goog/editor/link.js @@ -0,0 +1,344 @@ +// Copyright 2007 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 utility class for managing editable links. + * + * @author nicksantos@google.com (Nick Santos) + */ + +goog.provide('goog.editor.Link'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.Range'); +goog.require('goog.editor.BrowserFeature'); +goog.require('goog.editor.Command'); +goog.require('goog.editor.node'); +goog.require('goog.editor.range'); +goog.require('goog.string'); +goog.require('goog.string.Unicode'); +goog.require('goog.uri.utils'); +goog.require('goog.uri.utils.ComponentIndex'); + + + +/** + * Wrap an editable link. + * @param {HTMLAnchorElement} anchor The anchor element. + * @param {boolean} isNew Whether this is a new link. + * @constructor + */ +goog.editor.Link = function(anchor, isNew) { + /** + * The link DOM element. + * @type {HTMLAnchorElement} + * @private + */ + this.anchor_ = anchor; + + /** + * Whether this link represents a link just added to the document. + * @type {boolean} + * @private + */ + this.isNew_ = isNew; + + + /** + * Any extra anchors created by the browser from a selection in the same + * operation that created the primary link + * @type {!Array.} + * @private + */ + this.extraAnchors_ = []; +}; + + +/** + * @return {HTMLAnchorElement} The anchor element. + */ +goog.editor.Link.prototype.getAnchor = function() { + return this.anchor_; +}; + + +/** + * @return {!Array.} The extra anchor elements, if any, + * created by the browser from a selection. + */ +goog.editor.Link.prototype.getExtraAnchors = function() { + return this.extraAnchors_; +}; + + +/** + * @return {string} The inner text for the anchor. + */ +goog.editor.Link.prototype.getCurrentText = function() { + if (!this.currentText_) { + this.currentText_ = goog.dom.getRawTextContent(this.getAnchor()); + } + return this.currentText_; +}; + + +/** + * @return {boolean} Whether the link is new. + */ +goog.editor.Link.prototype.isNew = function() { + return this.isNew_; +}; + + +/** + * Set the url without affecting the isNew() status of the link. + * @param {string} url A URL. + */ +goog.editor.Link.prototype.initializeUrl = function(url) { + this.getAnchor().href = url; +}; + + +/** + * Removes the link, leaving its contents in the document. Note that this + * object will no longer be usable/useful after this call. + */ +goog.editor.Link.prototype.removeLink = function() { + goog.dom.flattenElement(this.anchor_); + this.anchor_ = null; + while (this.extraAnchors_.length) { + goog.dom.flattenElement(/** @type {Element} */(this.extraAnchors_.pop())); + } +}; + + +/** + * Change the link. + * @param {string} newText New text for the link. If the link contains all its + * text in one descendent, newText will only replace the text in that + * one node. Otherwise, we'll change the innerHTML of the whole + * link to newText. + * @param {string} newUrl A new URL. + */ +goog.editor.Link.prototype.setTextAndUrl = function(newText, newUrl) { + var anchor = this.getAnchor(); + anchor.href = newUrl; + + // If the text did not change, don't update link text. + var currentText = this.getCurrentText(); + if (newText != currentText) { + var leaf = goog.editor.node.getLeftMostLeaf(anchor); + if (leaf.nodeType == goog.dom.NodeType.TEXT) { + leaf = leaf.parentNode; + } + + if (goog.dom.getRawTextContent(leaf) != currentText) { + leaf = anchor; + } + + goog.dom.removeChildren(leaf); + + var domHelper = goog.dom.getDomHelper(leaf); + goog.dom.appendChild(leaf, domHelper.createTextNode(newText)); + + // The text changed, so force getCurrentText to recompute. + this.currentText_ = null; + } + + this.isNew_ = false; +}; + + +/** + * Places the cursor to the right of the anchor. + * Note that this is different from goog.editor.range's placeCursorNextTo + * in that it specifically handles the placement of a cursor in browsers + * that trap you in links, by adding a space when necessary and placing the + * cursor after that space. + */ +goog.editor.Link.prototype.placeCursorRightOf = function() { + var anchor = this.getAnchor(); + // If the browser gets stuck in a link if we place the cursor next to it, + // we'll place the cursor after a space instead. + if (goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS) { + var spaceNode; + var nextSibling = anchor.nextSibling; + + // Check if there is already a space after the link. Only handle the + // simple case - the next node is a text node that starts with a space. + if (nextSibling && + nextSibling.nodeType == goog.dom.NodeType.TEXT && + (goog.string.startsWith(nextSibling.data, goog.string.Unicode.NBSP) || + goog.string.startsWith(nextSibling.data, ' '))) { + spaceNode = nextSibling; + } else { + // If there isn't an obvious space to use, create one after the link. + var dh = goog.dom.getDomHelper(anchor); + spaceNode = dh.createTextNode(goog.string.Unicode.NBSP); + goog.dom.insertSiblingAfter(spaceNode, anchor); + } + + // Move the selection after the space. + var range = goog.dom.Range.createCaret(spaceNode, 1); + range.select(); + } else { + goog.editor.range.placeCursorNextTo(anchor, false); + } +}; + + +/** + * Updates the cursor position and link bubble for this link. + * @param {goog.editor.Field} field The field in which the link is created. + * @param {string} url The link url. + * @private + */ +goog.editor.Link.prototype.updateLinkDisplay_ = function(field, url) { + this.initializeUrl(url); + this.placeCursorRightOf(); + field.execCommand(goog.editor.Command.UPDATE_LINK_BUBBLE); +}; + + +/** + * After link creation, finish creating the link depending on the type + * of link being created. + * @param {goog.editor.Field} field The field where this link is being created. + */ +goog.editor.Link.prototype.finishLinkCreation = function(field) { + var text = this.getCurrentText(); + if (goog.editor.Link.isLikelyUrl(text)) { + if (text.search(/:/) < 0) { + text = 'http://' + goog.string.trimLeft(text); + } + this.updateLinkDisplay_(field, text); + } else if (goog.editor.Link.isLikelyEmailAddress(text)) { + text = 'mailto:' + text; + this.updateLinkDisplay_(field, text); + } else { + field.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, this); + } +}; + + +/** + * Initialize a new link. + * @param {HTMLAnchorElement} anchor The anchor element. + * @param {string} url The initial URL. + * @param {string=} opt_target The target. + * @param {Array.=} opt_extraAnchors Extra anchors created + * by the browser when parsing a selection. + * @return {goog.editor.Link} The link. + */ +goog.editor.Link.createNewLink = function(anchor, url, opt_target, + opt_extraAnchors) { + var link = new goog.editor.Link(anchor, true); + link.initializeUrl(url); + + if (opt_target) { + anchor.target = opt_target; + } + if (opt_extraAnchors) { + link.extraAnchors_ = opt_extraAnchors; + } + + return link; +}; + + +/** + * Returns true if str could be a URL, false otherwise + * + * Ex: TR_Util.isLikelyUrl_("http://www.google.com") == true + * TR_Util.isLikelyUrl_("www.google.com") == true + * + * @param {string} str String to check if it looks like a URL. + * @return {boolean} Whether str could be a URL. + */ +goog.editor.Link.isLikelyUrl = function(str) { + // Whitespace means this isn't a domain. + if (/\s/.test(str)) { + return false; + } + + if (goog.editor.Link.isLikelyEmailAddress(str)) { + return false; + } + + // Add a scheme if the url doesn't have one - this helps the parser. + var addedScheme = false; + if (!/^[^:\/?#.]+:/.test(str)) { + str = 'http://' + str; + addedScheme = true; + } + + // Parse the domain. + var parts = goog.uri.utils.split(str); + + // Relax the rules for special schemes. + var scheme = parts[goog.uri.utils.ComponentIndex.SCHEME]; + if (goog.array.indexOf(['mailto', 'aim'], scheme) != -1) { + return true; + } + + // Require domains to contain a '.', unless the domain is fully qualified. + var domain = parts[goog.uri.utils.ComponentIndex.DOMAIN]; + if (!domain || (addedScheme && domain.indexOf('.') == -1)) { + return false; + } + + // Require http and ftp paths to start with '/'. + var path = parts[goog.uri.utils.ComponentIndex.PATH]; + return !path || path.indexOf('/') == 0; +}; + + +/** + * Regular expression that matches strings that could be an email address. + * @type {RegExp} + * @private + */ +goog.editor.Link.LIKELY_EMAIL_ADDRESS_ = new RegExp( + '^' + // Test from start of string + '[\\w-]+(\\.[\\w-]+)*' + // Dot-delimited alphanumerics and dashes (name) + '\\@' + // @ + '([\\w-]+\\.)+' + // Alphanumerics, dashes and dots (domain) + '(\\d+|\\w\\w+)$', // Domain ends in at least one number or 2 letters + 'i'); + + +/** + * Returns true if str could be an email address, false otherwise + * + * Ex: goog.editor.Link.isLikelyEmailAddress_("some word") == false + * goog.editor.Link.isLikelyEmailAddress_("foo@foo.com") == true + * + * @param {string} str String to test for being email address. + * @return {boolean} Whether "str" looks like an email address. + */ +goog.editor.Link.isLikelyEmailAddress = function(str) { + return goog.editor.Link.LIKELY_EMAIL_ADDRESS_.test(str); +}; + + +/** + * Determines whether or not a url is an email link. + * @param {string} url A url. + * @return {boolean} Whether the url is a mailto link. + */ +goog.editor.Link.isMailto = function(url) { + return !!url && goog.string.startsWith(url, 'mailto:'); +}; diff --git a/master/closure-library/closure/goog/editor/node.js b/master/closure-library/closure/goog/editor/node.js new file mode 100644 index 0000000000..b58ebb50ba --- /dev/null +++ b/master/closure-library/closure/goog/editor/node.js @@ -0,0 +1,457 @@ +// 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 Utilties for working with DOM nodes related to rich text + * editing. Many of these are not general enough to go into goog.dom. + * + */ + +goog.provide('goog.editor.node'); + +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.TagName'); +goog.require('goog.dom.iter.ChildIterator'); +goog.require('goog.dom.iter.SiblingIterator'); +goog.require('goog.iter'); +goog.require('goog.object'); +goog.require('goog.string'); +goog.require('goog.string.Unicode'); + + +/** + * Names of all block-level tags + * @type {Object} + * @private + */ +goog.editor.node.BLOCK_TAG_NAMES_ = goog.object.createSet( + goog.dom.TagName.ADDRESS, + goog.dom.TagName.ARTICLE, + goog.dom.TagName.ASIDE, + goog.dom.TagName.BLOCKQUOTE, + goog.dom.TagName.BODY, + goog.dom.TagName.CAPTION, + goog.dom.TagName.CENTER, + goog.dom.TagName.COL, + goog.dom.TagName.COLGROUP, + goog.dom.TagName.DETAILS, + goog.dom.TagName.DIR, + goog.dom.TagName.DIV, + goog.dom.TagName.DL, + goog.dom.TagName.DD, + goog.dom.TagName.DT, + goog.dom.TagName.FIELDSET, + goog.dom.TagName.FIGCAPTION, + goog.dom.TagName.FIGURE, + goog.dom.TagName.FOOTER, + goog.dom.TagName.FORM, + goog.dom.TagName.H1, + goog.dom.TagName.H2, + goog.dom.TagName.H3, + goog.dom.TagName.H4, + goog.dom.TagName.H5, + goog.dom.TagName.H6, + goog.dom.TagName.HEADER, + goog.dom.TagName.HGROUP, + goog.dom.TagName.HR, + goog.dom.TagName.ISINDEX, + goog.dom.TagName.OL, + goog.dom.TagName.LI, + goog.dom.TagName.MAP, + goog.dom.TagName.MENU, + goog.dom.TagName.NAV, + goog.dom.TagName.OPTGROUP, + goog.dom.TagName.OPTION, + goog.dom.TagName.P, + goog.dom.TagName.PRE, + goog.dom.TagName.SECTION, + goog.dom.TagName.SUMMARY, + goog.dom.TagName.TABLE, + goog.dom.TagName.TBODY, + goog.dom.TagName.TD, + goog.dom.TagName.TFOOT, + goog.dom.TagName.TH, + goog.dom.TagName.THEAD, + goog.dom.TagName.TR, + goog.dom.TagName.UL); + + +/** + * Names of tags that have intrinsic content. + * TODO(robbyw): What about object, br, input, textarea, button, isindex, + * hr, keygen, select, table, tr, td? + * @type {Object} + * @private + */ +goog.editor.node.NON_EMPTY_TAGS_ = goog.object.createSet( + goog.dom.TagName.IMG, goog.dom.TagName.IFRAME, goog.dom.TagName.EMBED); + + +/** + * Check if the node is in a standards mode document. + * @param {Node} node The node to test. + * @return {boolean} Whether the node is in a standards mode document. + */ +goog.editor.node.isStandardsMode = function(node) { + return goog.dom.getDomHelper(node).isCss1CompatMode(); +}; + + +/** + * Get the right-most non-ignorable leaf node of the given node. + * @param {Node} parent The parent ndoe. + * @return {Node} The right-most non-ignorable leaf node. + */ +goog.editor.node.getRightMostLeaf = function(parent) { + var temp; + while (temp = goog.editor.node.getLastChild(parent)) { + parent = temp; + } + return parent; +}; + + +/** + * Get the left-most non-ignorable leaf node of the given node. + * @param {Node} parent The parent ndoe. + * @return {Node} The left-most non-ignorable leaf node. + */ +goog.editor.node.getLeftMostLeaf = function(parent) { + var temp; + while (temp = goog.editor.node.getFirstChild(parent)) { + parent = temp; + } + return parent; +}; + + +/** + * Version of firstChild that skips nodes that are entirely + * whitespace and comments. + * @param {Node} parent The reference node. + * @return {Node} The first child of sibling that is important according to + * goog.editor.node.isImportant, or null if no such node exists. + */ +goog.editor.node.getFirstChild = function(parent) { + return goog.editor.node.getChildHelper_(parent, false); +}; + + +/** + * Version of lastChild that skips nodes that are entirely whitespace or + * comments. (Normally lastChild is a property of all DOM nodes that gives the + * last of the nodes contained directly in the reference node.) + * @param {Node} parent The reference node. + * @return {Node} The last child of sibling that is important according to + * goog.editor.node.isImportant, or null if no such node exists. + */ +goog.editor.node.getLastChild = function(parent) { + return goog.editor.node.getChildHelper_(parent, true); +}; + + +/** + * Version of previoussibling that skips nodes that are entirely + * whitespace or comments. (Normally previousSibling is a property + * of all DOM nodes that gives the sibling node, the node that is + * a child of the same parent, that occurs immediately before the + * reference node.) + * @param {Node} sibling The reference node. + * @return {Node} The closest previous sibling to sibling that is + * important according to goog.editor.node.isImportant, or null if no such + * node exists. + */ +goog.editor.node.getPreviousSibling = function(sibling) { + return /** @type {Node} */ (goog.editor.node.getFirstValue_( + goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling, false, true), + goog.editor.node.isImportant))); +}; + + +/** + * Version of nextSibling that skips nodes that are entirely whitespace or + * comments. + * @param {Node} sibling The reference node. + * @return {Node} The closest next sibling to sibling that is important + * according to goog.editor.node.isImportant, or null if no + * such node exists. + */ +goog.editor.node.getNextSibling = function(sibling) { + return /** @type {Node} */ (goog.editor.node.getFirstValue_( + goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling), + goog.editor.node.isImportant))); +}; + + +/** + * Internal helper for lastChild/firstChild that skips nodes that are entirely + * whitespace or comments. + * @param {Node} parent The reference node. + * @param {boolean} isReversed Whether children should be traversed forward + * or backward. + * @return {Node} The first/last child of sibling that is important according + * to goog.editor.node.isImportant, or null if no such node exists. + * @private + */ +goog.editor.node.getChildHelper_ = function(parent, isReversed) { + return (!parent || parent.nodeType != goog.dom.NodeType.ELEMENT) ? null : + /** @type {Node} */ (goog.editor.node.getFirstValue_(goog.iter.filter( + new goog.dom.iter.ChildIterator( + /** @type {Element} */ (parent), isReversed), + goog.editor.node.isImportant))); +}; + + +/** + * Utility function that returns the first value from an iterator or null if + * the iterator is empty. + * @param {goog.iter.Iterator} iterator The iterator to get a value from. + * @return {*} The first value from the iterator. + * @private + */ +goog.editor.node.getFirstValue_ = function(iterator) { + /** @preserveTry */ + try { + return iterator.next(); + } catch (e) { + return null; + } +}; + + +/** + * Determine if a node should be returned by the iterator functions. + * @param {Node} node An object implementing the DOM1 Node interface. + * @return {boolean} Whether the node is an element, or a text node that + * is not all whitespace. + */ +goog.editor.node.isImportant = function(node) { + // Return true if the node is not either a TextNode or an ElementNode. + return node.nodeType == goog.dom.NodeType.ELEMENT || + node.nodeType == goog.dom.NodeType.TEXT && + !goog.editor.node.isAllNonNbspWhiteSpace(node); +}; + + +/** + * Determine whether a node's text content is entirely whitespace. + * @param {Node} textNode A node implementing the CharacterData interface (i.e., + * a Text, Comment, or CDATASection node. + * @return {boolean} Whether the text content of node is whitespace, + * otherwise false. + */ +goog.editor.node.isAllNonNbspWhiteSpace = function(textNode) { + return goog.string.isBreakingWhitespace(textNode.nodeValue); +}; + + +/** + * Returns true if the node contains only whitespace and is not and does not + * contain any images, iframes or embed tags. + * @param {Node} node The node to check. + * @param {boolean=} opt_prohibitSingleNbsp By default, this function treats a + * single nbsp as empty. Set this to true to treat this case as non-empty. + * @return {boolean} Whether the node contains only whitespace. + */ +goog.editor.node.isEmpty = function(node, opt_prohibitSingleNbsp) { + var nodeData = goog.dom.getRawTextContent(node); + + if (node.getElementsByTagName) { + for (var tag in goog.editor.node.NON_EMPTY_TAGS_) { + if (node.tagName == tag || node.getElementsByTagName(tag).length > 0) { + return false; + } + } + } + return (!opt_prohibitSingleNbsp && nodeData == goog.string.Unicode.NBSP) || + goog.string.isBreakingWhitespace(nodeData); +}; + + +/** + * Returns the length of the text in node if it is a text node, or the number + * of children of the node, if it is an element. Useful for range-manipulation + * code where you need to know the offset for the right side of the node. + * @param {Node} node The node to get the length of. + * @return {number} The length of the node. + */ +goog.editor.node.getLength = function(node) { + return node.length || node.childNodes.length; +}; + + +/** + * Search child nodes using a predicate function and return the first node that + * satisfies the condition. + * @param {Node} parent The parent node to search. + * @param {function(Node):boolean} hasProperty A function that takes a child + * node as a parameter and returns true if it meets the criteria. + * @return {?number} The index of the node found, or null if no node is found. + */ +goog.editor.node.findInChildren = function(parent, hasProperty) { + for (var i = 0, len = parent.childNodes.length; i < len; i++) { + if (hasProperty(parent.childNodes[i])) { + return i; + } + } + return null; +}; + + +/** + * Search ancestor nodes using a predicate function and returns the topmost + * ancestor in the chain of consecutive ancestors that satisfies the condition. + * + * @param {Node} node The node whose ancestors have to be searched. + * @param {function(Node): boolean} hasProperty A function that takes a parent + * node as a parameter and returns true if it meets the criteria. + * @return {Node} The topmost ancestor or null if no ancestor satisfies the + * predicate function. + */ +goog.editor.node.findHighestMatchingAncestor = function(node, hasProperty) { + var parent = node.parentNode; + var ancestor = null; + while (parent && hasProperty(parent)) { + ancestor = parent; + parent = parent.parentNode; + } + return ancestor; +}; + + +/** +* Checks if node is a block-level html element. The display css + * property is ignored. + * @param {Node} node The node to test. + * @return {boolean} Whether the node is a block-level node. + */ +goog.editor.node.isBlockTag = function(node) { + return !!goog.editor.node.BLOCK_TAG_NAMES_[node.tagName]; +}; + + +/** + * Skips siblings of a node that are empty text nodes. + * @param {Node} node A node. May be null. + * @return {Node} The node or the first sibling of the node that is not an + * empty text node. May be null. + */ +goog.editor.node.skipEmptyTextNodes = function(node) { + while (node && node.nodeType == goog.dom.NodeType.TEXT && + !node.nodeValue) { + node = node.nextSibling; + } + return node; +}; + + +/** + * Checks if an element is a top-level editable container (meaning that + * it itself is not editable, but all its child nodes are editable). + * @param {Node} element The element to test. + * @return {boolean} Whether the element is a top-level editable container. + */ +goog.editor.node.isEditableContainer = function(element) { + return element.getAttribute && + element.getAttribute('g_editable') == 'true'; +}; + + +/** + * Checks if a node is inside an editable container. + * @param {Node} node The node to test. + * @return {boolean} Whether the node is in an editable container. + */ +goog.editor.node.isEditable = function(node) { + return !!goog.dom.getAncestor(node, goog.editor.node.isEditableContainer); +}; + + +/** + * Finds the top-most DOM node inside an editable field that is an ancestor + * (or self) of a given DOM node and meets the specified criteria. + * @param {Node} node The DOM node where the search starts. + * @param {function(Node) : boolean} criteria A function that takes a DOM node + * as a parameter and returns a boolean to indicate whether the node meets + * the criteria or not. + * @return {Node} The DOM node if found, or null. + */ +goog.editor.node.findTopMostEditableAncestor = function(node, criteria) { + var targetNode = null; + while (node && !goog.editor.node.isEditableContainer(node)) { + if (criteria(node)) { + targetNode = node; + } + node = node.parentNode; + } + return targetNode; +}; + + +/** + * Splits off a subtree. + * @param {!Node} currentNode The starting splitting point. + * @param {Node=} opt_secondHalf The initial leftmost leaf the new subtree. + * If null, siblings after currentNode will be placed in the subtree, but + * no additional node will be. + * @param {Node=} opt_root The top of the tree where splitting stops at. + * @return {!Node} The new subtree. + */ +goog.editor.node.splitDomTreeAt = function(currentNode, + opt_secondHalf, opt_root) { + var parent; + while (currentNode != opt_root && (parent = currentNode.parentNode)) { + opt_secondHalf = goog.editor.node.getSecondHalfOfNode_(parent, currentNode, + opt_secondHalf); + currentNode = parent; + } + return /** @type {!Node} */(opt_secondHalf); +}; + + +/** + * Creates a clone of node, moving all children after startNode to it. + * When firstChild is not null or undefined, it is also appended to the clone + * as the first child. + * @param {!Node} node The node to clone. + * @param {!Node} startNode All siblings after this node will be moved to the + * clone. + * @param {Node|undefined} firstChild The first child of the new cloned element. + * @return {!Node} The cloned node that now contains the children after + * startNode. + * @private + */ +goog.editor.node.getSecondHalfOfNode_ = function(node, startNode, firstChild) { + var secondHalf = /** @type {!Node} */(node.cloneNode(false)); + while (startNode.nextSibling) { + goog.dom.appendChild(secondHalf, startNode.nextSibling); + } + if (firstChild) { + secondHalf.insertBefore(firstChild, secondHalf.firstChild); + } + return secondHalf; +}; + + +/** + * Appends all of oldNode's children to newNode. This removes all children from + * oldNode and appends them to newNode. oldNode is left with no children. + * @param {!Node} newNode Node to transfer children to. + * @param {Node} oldNode Node to transfer children from. + * @deprecated Use goog.dom.append directly instead. + */ +goog.editor.node.transferChildren = function(newNode, oldNode) { + goog.dom.append(newNode, oldNode.childNodes); +}; diff --git a/master/closure-library/closure/goog/editor/plugin.js b/master/closure-library/closure/goog/editor/plugin.js new file mode 100644 index 0000000000..6f45a2e173 --- /dev/null +++ b/master/closure-library/closure/goog/editor/plugin.js @@ -0,0 +1,463 @@ +// Copyright 2008 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. +// All Rights Reserved. + +/** + * @fileoverview Abstract API for TrogEdit plugins. + * + * @see ../demos/editor/editor.html + */ + +goog.provide('goog.editor.Plugin'); + +goog.require('goog.debug.Logger'); +// TODO(user): Remove the dependency on goog.editor.Command asap. Currently only +// needed for execCommand issues with links. +goog.require('goog.editor.Command'); +goog.require('goog.events.EventTarget'); +goog.require('goog.functions'); +goog.require('goog.object'); +goog.require('goog.reflect'); + + + +/** + * Abstract API for trogedit plugins. + * @constructor + * @extends {goog.events.EventTarget} + */ +goog.editor.Plugin = function() { + goog.events.EventTarget.call(this); + + /** + * Whether this plugin is enabled for the registered field object. + * @type {boolean} + * @private + */ + this.enabled_ = this.activeOnUneditableFields(); +}; +goog.inherits(goog.editor.Plugin, goog.events.EventTarget); + + +/** + * The field object this plugin is attached to. + * @type {goog.editor.Field} + * @protected + * @deprecated Use goog.editor.Plugin.getFieldObject and + * goog.editor.Plugin.setFieldObject. + */ +goog.editor.Plugin.prototype.fieldObject = null; + + +/** + * @return {goog.dom.DomHelper?} The dom helper object associated with the + * currently active field. + */ +goog.editor.Plugin.prototype.getFieldDomHelper = function() { + return this.getFieldObject() && this.getFieldObject().getEditableDomHelper(); +}; + + +/** + * Indicates if this plugin should be automatically disposed when the + * registered field is disposed. This should be changed to false for + * plugins used as multi-field plugins. + * @type {boolean} + * @private + */ +goog.editor.Plugin.prototype.autoDispose_ = true; + + +/** + * The logger for this plugin. + * @type {goog.debug.Logger} + * @protected + */ +goog.editor.Plugin.prototype.logger = + goog.debug.Logger.getLogger('goog.editor.Plugin'); + + +/** + * Sets the field object for use with this plugin. + * @return {goog.editor.Field} The editable field object. + * @protected + * @suppress {deprecated} Until fieldObject can be made private. + */ +goog.editor.Plugin.prototype.getFieldObject = function() { + return this.fieldObject; +}; + + +/** + * Sets the field object for use with this plugin. + * @param {goog.editor.Field} fieldObject The editable field object. + * @protected + * @suppress {deprecated} Until fieldObject can be made private. + */ +goog.editor.Plugin.prototype.setFieldObject = function(fieldObject) { + this.fieldObject = fieldObject; +}; + + +/** + * Registers the field object for use with this plugin. + * @param {goog.editor.Field} fieldObject The editable field object. + */ +goog.editor.Plugin.prototype.registerFieldObject = function(fieldObject) { + this.setFieldObject(fieldObject); +}; + + +/** + * Unregisters and disables this plugin for the current field object. + * @param {goog.editor.Field} fieldObj The field object. For single-field + * plugins, this parameter is ignored. + */ +goog.editor.Plugin.prototype.unregisterFieldObject = function(fieldObj) { + if (this.getFieldObject()) { + this.disable(this.getFieldObject()); + this.setFieldObject(null); + } +}; + + +/** + * Enables this plugin for the specified, registered field object. A field + * object should only be enabled when it is loaded. + * @param {goog.editor.Field} fieldObject The field object. + */ +goog.editor.Plugin.prototype.enable = function(fieldObject) { + if (this.getFieldObject() == fieldObject) { + this.enabled_ = true; + } else { + this.logger.severe('Trying to enable an unregistered field with ' + + 'this plugin.'); + } +}; + + +/** + * Disables this plugin for the specified, registered field object. + * @param {goog.editor.Field} fieldObject The field object. + */ +goog.editor.Plugin.prototype.disable = function(fieldObject) { + if (this.getFieldObject() == fieldObject) { + this.enabled_ = false; + } else { + this.logger.severe('Trying to disable an unregistered field ' + + 'with this plugin.'); + } +}; + + +/** + * Returns whether this plugin is enabled for the field object. + * + * @param {goog.editor.Field} fieldObject The field object. + * @return {boolean} Whether this plugin is enabled for the field object. + */ +goog.editor.Plugin.prototype.isEnabled = function(fieldObject) { + return this.getFieldObject() == fieldObject ? this.enabled_ : false; +}; + + +/** + * Set if this plugin should automatically be disposed when the registered + * field is disposed. + * @param {boolean} autoDispose Whether to autoDispose. + */ +goog.editor.Plugin.prototype.setAutoDispose = function(autoDispose) { + this.autoDispose_ = autoDispose; +}; + + +/** + * @return {boolean} Whether or not this plugin should automatically be disposed + * when it's registered field is disposed. + */ +goog.editor.Plugin.prototype.isAutoDispose = function() { + return this.autoDispose_; +}; + + +/** + * @return {boolean} If true, field will not disable the command + * when the field becomes uneditable. + */ +goog.editor.Plugin.prototype.activeOnUneditableFields = goog.functions.FALSE; + + +/** + * @param {string} command The command to check. + * @return {boolean} If true, field will not dispatch change events + * for commands of this type. This is useful for "seamless" plugins like + * dialogs and lorem ipsum. + */ +goog.editor.Plugin.prototype.isSilentCommand = goog.functions.FALSE; + + +/** @override */ +goog.editor.Plugin.prototype.disposeInternal = function() { + if (this.getFieldObject()) { + this.unregisterFieldObject(this.getFieldObject()); + } + + goog.editor.Plugin.superClass_.disposeInternal.call(this); +}; + + +/** + * @return {string} The ID unique to this plugin class. Note that different + * instances off the plugin share the same classId. + */ +goog.editor.Plugin.prototype.getTrogClassId; + + +/** + * An enum of operations that plugins may support. + * @enum {number} + */ +goog.editor.Plugin.Op = { + KEYDOWN: 1, + KEYPRESS: 2, + KEYUP: 3, + SELECTION: 4, + SHORTCUT: 5, + EXEC_COMMAND: 6, + QUERY_COMMAND: 7, + PREPARE_CONTENTS_HTML: 8, + CLEAN_CONTENTS_HTML: 10, + CLEAN_CONTENTS_DOM: 11 +}; + + +/** + * A map from plugin operations to the names of the methods that + * invoke those operations. + */ +goog.editor.Plugin.OPCODE = goog.object.transpose( + goog.reflect.object(goog.editor.Plugin, { + handleKeyDown: goog.editor.Plugin.Op.KEYDOWN, + handleKeyPress: goog.editor.Plugin.Op.KEYPRESS, + handleKeyUp: goog.editor.Plugin.Op.KEYUP, + handleSelectionChange: goog.editor.Plugin.Op.SELECTION, + handleKeyboardShortcut: goog.editor.Plugin.Op.SHORTCUT, + execCommand: goog.editor.Plugin.Op.EXEC_COMMAND, + queryCommandValue: goog.editor.Plugin.Op.QUERY_COMMAND, + prepareContentsHtml: goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, + cleanContentsHtml: goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, + cleanContentsDom: goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM + })); + + +/** + * A set of op codes that run even on disabled plugins. + */ +goog.editor.Plugin.IRREPRESSIBLE_OPS = goog.object.createSet( + goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, + goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, + goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM); + + +/** + * Handles keydown. It is run before handleKeyboardShortcut and if it returns + * true handleKeyboardShortcut will not be called. + * @param {!goog.events.BrowserEvent} e The browser event. + * @return {boolean} Whether the event was handled and thus should *not* be + * propagated to other plugins or handleKeyboardShortcut. + */ +goog.editor.Plugin.prototype.handleKeyDown; + + +/** + * Handles keypress. It is run before handleKeyboardShortcut and if it returns + * true handleKeyboardShortcut will not be called. + * @param {!goog.events.BrowserEvent} e The browser event. + * @return {boolean} Whether the event was handled and thus should *not* be + * propagated to other plugins or handleKeyboardShortcut. + */ +goog.editor.Plugin.prototype.handleKeyPress; + + +/** + * Handles keyup. + * @param {!goog.events.BrowserEvent} e The browser event. + * @return {boolean} Whether the event was handled and thus should *not* be + * propagated to other plugins. + */ +goog.editor.Plugin.prototype.handleKeyUp; + + +/** + * Handles selection change. + * @param {!goog.events.BrowserEvent=} opt_e The browser event. + * @param {!Node=} opt_target The node the selection changed to. + * @return {boolean} Whether the event was handled and thus should *not* be + * propagated to other plugins. + */ +goog.editor.Plugin.prototype.handleSelectionChange; + + +/** + * Handles keyboard shortcuts. Preferred to using handleKey* as it will use + * the proper event based on browser and will be more performant. If + * handleKeyPress/handleKeyDown returns true, this will not be called. If the + * plugin handles the shortcut, it is responsible for dispatching appropriate + * events (change, selection change at the time of this comment). If the plugin + * calls execCommand on the editable field, then execCommand already takes care + * of dispatching events. + * NOTE: For performance reasons this is only called when any key is pressed + * in conjunction with ctrl/meta keys OR when a small subset of keys (defined + * in goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_) are pressed without + * ctrl/meta keys. We specifically don't invoke it when altKey is pressed since + * alt key is used in many i8n UIs to enter certain characters. + * @param {!goog.events.BrowserEvent} e The browser event. + * @param {string} key The key pressed. + * @param {boolean} isModifierPressed Whether the ctrl/meta key was pressed or + * not. + * @return {boolean} Whether the event was handled and thus should *not* be + * propagated to other plugins. We also call preventDefault on the event if + * the return value is true. + */ +goog.editor.Plugin.prototype.handleKeyboardShortcut; + + +/** + * Handles execCommand. This default implementation handles dispatching + * BEFORECHANGE, CHANGE, and SELECTIONCHANGE events, and calls + * execCommandInternal to perform the actual command. Plugins that want to + * do their own event dispatching should override execCommand, otherwise + * it is preferred to only override execCommandInternal. + * + * This version of execCommand will only work for single field plugins. + * Multi-field plugins must override execCommand. + * + * @param {string} command The command to execute. + * @param {...*} var_args Any additional parameters needed to + * execute the command. + * @return {*} The result of the execCommand, if any. + */ +goog.editor.Plugin.prototype.execCommand = function(command, var_args) { + // TODO(user): Replace all uses of isSilentCommand with plugins that just + // override this base execCommand method. + var silent = this.isSilentCommand(command); + if (!silent) { + // Stop listening to mutation events in Firefox while text formatting + // is happening. This prevents us from trying to size the field in the + // middle of an execCommand, catching the field in a strange intermediary + // state where both replacement nodes and original nodes are appended to + // the dom. Note that change events get turned back on by + // fieldObj.dispatchChange. + if (goog.userAgent.GECKO) { + this.getFieldObject().stopChangeEvents(true, true); + } + + this.getFieldObject().dispatchBeforeChange(); + } + + try { + var result = this.execCommandInternal.apply(this, arguments); + } finally { + // If the above execCommandInternal call throws an exception, we still need + // to turn change events back on (see http://b/issue?id=1471355). + // NOTE: If if you add to or change the methods called in this finally + // block, please add them as expected calls to the unit test function + // testExecCommandException(). + if (!silent) { + // dispatchChange includes a call to startChangeEvents, which unwinds the + // call to stopChangeEvents made before the try block. + this.getFieldObject().dispatchChange(); + this.getFieldObject().dispatchSelectionChangeEvent(); + } + } + + return result; +}; + + +/** + * Handles execCommand. This default implementation does nothing, and is + * called by execCommand, which handles event dispatching. This method should + * be overriden by plugins that don't need to do their own event dispatching. + * If custom event dispatching is needed, execCommand shoul be overriden + * instead. + * + * @param {string} command The command to execute. + * @param {...*} var_args Any additional parameters needed to + * execute the command. + * @return {*} The result of the execCommand, if any. + * @protected + */ +goog.editor.Plugin.prototype.execCommandInternal; + + +/** + * Gets the state of this command if this plugin serves that command. + * @param {string} command The command to check. + * @return {*} The value of the command. + */ +goog.editor.Plugin.prototype.queryCommandValue; + + +/** + * Prepares the given HTML for editing. Strips out content that should not + * appear in an editor, and normalizes content as appropriate. The inverse + * of cleanContentsHtml. + * + * This op is invoked even on disabled plugins. + * + * @param {string} originalHtml The original HTML. + * @param {Object} styles A map of strings. If the plugin wants to add + * any styles to the field element, it should add them as key-value + * pairs to this object. + * @return {string} New HTML that's ok for editing. + */ +goog.editor.Plugin.prototype.prepareContentsHtml; + + +/** + * Cleans the contents of the node passed to it. The node contents are modified + * directly, and the modifications will subsequently be used, for operations + * such as saving the innerHTML of the editor etc. Since the plugins act on + * the DOM directly, this method can be very expensive. + * + * This op is invoked even on disabled plugins. + * + * @param {!Element} fieldCopy The copy of the editable field which + * needs to be cleaned up. + */ +goog.editor.Plugin.prototype.cleanContentsDom; + + +/** + * Cleans the html contents of Trogedit. Both cleanContentsDom and + * and cleanContentsHtml will be called on contents extracted from Trogedit. + * The inverse of prepareContentsHtml. + * + * This op is invoked even on disabled plugins. + * + * @param {string} originalHtml The trogedit HTML. + * @return {string} Cleaned-up HTML. + */ +goog.editor.Plugin.prototype.cleanContentsHtml; + + +/** + * Whether the string corresponds to a command this plugin handles. + * @param {string} command Command string to check. + * @return {boolean} Whether the plugin handles this type of command. + */ +goog.editor.Plugin.prototype.isSupportedCommand = function(command) { + return false; +}; diff --git a/master/closure-library/closure/goog/editor/plugins/abstractbubbleplugin.js b/master/closure-library/closure/goog/editor/plugins/abstractbubbleplugin.js new file mode 100644 index 0000000000..d02556db10 --- /dev/null +++ b/master/closure-library/closure/goog/editor/plugins/abstractbubbleplugin.js @@ -0,0 +1,535 @@ +// 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 Base class for bubble plugins. + */ + +goog.provide('goog.editor.plugins.AbstractBubblePlugin'); + +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.Range'); +goog.require('goog.dom.TagName'); +goog.require('goog.editor.Plugin'); +goog.require('goog.editor.style'); +goog.require('goog.events'); +goog.require('goog.events.EventHandler'); +goog.require('goog.events.EventType'); +goog.require('goog.functions'); +goog.require('goog.string.Unicode'); +goog.require('goog.ui.Component.EventType'); +goog.require('goog.ui.editor.Bubble'); +goog.require('goog.userAgent'); + + + +/** + * Base class for bubble plugins. This is used for to connect user behavior + * in the editor to a goog.ui.editor.Bubble UI element that allows + * the user to modify the properties of an element on their page (e.g. the alt + * text of an image tag). + * + * Subclasses should override the abstract method getBubbleTargetFromSelection() + * with code to determine if the current selection should activate the bubble + * type. The other abstract method createBubbleContents() should be overriden + * with code to create the inside markup of the bubble. The base class creates + * the rest of the bubble. + * + * @constructor + * @extends {goog.editor.Plugin} + */ +goog.editor.plugins.AbstractBubblePlugin = function() { + goog.base(this); + + /** + * Place to register events the plugin listens to. + * @type {goog.events.EventHandler} + * @protected + */ + this.eventRegister = new goog.events.EventHandler(this); +}; +goog.inherits(goog.editor.plugins.AbstractBubblePlugin, goog.editor.Plugin); + + +/** + * The css class name of option link elements. + * @type {string} + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.OPTION_LINK_CLASSNAME_ = + goog.getCssName('tr_option-link'); + + +/** + * The css class name of link elements. + * @type {string} + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.LINK_CLASSNAME_ = + goog.getCssName('tr_bubble_link'); + + +/** + * The constant string used to separate option links. + * @type {string} + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.DASH_NBSP_STRING = + goog.string.Unicode.NBSP + '-' + goog.string.Unicode.NBSP; + + +/** + * Default factory function for creating a bubble UI component. + * @param {!Element} parent The parent element for the bubble. + * @param {number} zIndex The z index to draw the bubble at. + * @return {!goog.ui.editor.Bubble} The new bubble component. + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.defaultBubbleFactory_ = function( + parent, zIndex) { + return new goog.ui.editor.Bubble(parent, zIndex); +}; + + +/** + * Factory function that creates a bubble UI component. It takes as parameters + * the bubble parent element and the z index to draw the bubble at. + * @type {function(!Element, number): !goog.ui.editor.Bubble} + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.bubbleFactory_ = + goog.editor.plugins.AbstractBubblePlugin.defaultBubbleFactory_; + + +/** + * Sets the bubble factory function. + * @param {function(!Element, number): !goog.ui.editor.Bubble} + * bubbleFactory Function that creates a bubble for the given bubble parent + * element and z index. + */ +goog.editor.plugins.AbstractBubblePlugin.setBubbleFactory = function( + bubbleFactory) { + goog.editor.plugins.AbstractBubblePlugin.bubbleFactory_ = bubbleFactory; +}; + + +/** + * Map from field id to shared bubble object. + * @type {Object.} + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.bubbleMap_ = {}; + + +/** + * The optional parent of the bubble. If null or not set, we will use the + * application document. This is useful when you have an editor embedded in + * a scrolling DIV. + * @type {Element|undefined} + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.bubbleParent_; + + +/** + * The id of the panel this plugin added to the shared bubble. Null when + * this plugin doesn't currently have a panel in a bubble. + * @type {string?} + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.panelId_ = null; + + +/** + * Sets the bubble parent. + * @param {Element} bubbleParent An element where the bubble will be + * anchored. If null, we will use the application document. This + * is useful when you have an editor embedded in a scrolling div. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.setBubbleParent = function( + bubbleParent) { + this.bubbleParent_ = bubbleParent; +}; + + +/** + * @return {goog.dom.DomHelper} The dom helper for the bubble window. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleDom = function() { + return this.dom_; +}; + + +/** @override */ +goog.editor.plugins.AbstractBubblePlugin.prototype.getTrogClassId = + goog.functions.constant('AbstractBubblePlugin'); + + +/** + * Returns the element whose properties the bubble manipulates. + * @return {Element} The target element. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.getTargetElement = + function() { + return this.targetElement_; +}; + + +/** @override */ +goog.editor.plugins.AbstractBubblePlugin.prototype.handleKeyUp = function(e) { + // For example, when an image is selected, pressing any key overwrites + // the image and the panel should be hidden. + // Therefore we need to track key presses when the bubble is showing. + if (this.isVisible()) { + this.handleSelectionChange(); + } + return false; +}; + + +/** + * Pops up a property bubble for the given selection if appropriate and closes + * open property bubbles if no longer needed. This should not be overridden. + * @override + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.handleSelectionChange = + function(opt_e, opt_target) { + var selectedElement; + if (opt_e) { + selectedElement = /** @type {Element} */ (opt_e.target); + } else if (opt_target) { + selectedElement = /** @type {Element} */ (opt_target); + } else { + var range = this.getFieldObject().getRange(); + if (range) { + var startNode = range.getStartNode(); + var endNode = range.getEndNode(); + var startOffset = range.getStartOffset(); + var endOffset = range.getEndOffset(); + // Sometimes in IE, the range will be collapsed, but think the end node + // and start node are different (although in the same visible position). + // In this case, favor the position IE thinks is the start node. + if (goog.userAgent.IE && range.isCollapsed() && startNode != endNode) { + range = goog.dom.Range.createCaret(startNode, startOffset); + } + if (startNode.nodeType == goog.dom.NodeType.ELEMENT && + startNode == endNode && startOffset == endOffset - 1) { + var element = startNode.childNodes[startOffset]; + if (element.nodeType == goog.dom.NodeType.ELEMENT) { + selectedElement = element; + } + } + } + selectedElement = selectedElement || range && range.getContainerElement(); + } + return this.handleSelectionChangeInternal(selectedElement); +}; + + +/** + * Pops up a property bubble for the given selection if appropriate and closes + * open property bubbles if no longer needed. + * @param {Element?} selectedElement The selected element. + * @return {boolean} Always false, allowing every bubble plugin to handle the + * event. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype. + handleSelectionChangeInternal = function(selectedElement) { + if (selectedElement) { + var bubbleTarget = this.getBubbleTargetFromSelection(selectedElement); + if (bubbleTarget) { + if (bubbleTarget != this.targetElement_ || !this.panelId_) { + // Make sure any existing panel of the same type is closed before + // creating a new one. + if (this.panelId_) { + this.closeBubble(); + } + this.createBubble(bubbleTarget); + } + return false; + } + } + + if (this.panelId_) { + this.closeBubble(); + } + + return false; +}; + + +/** + * Should be overriden by subclasses to return the bubble target element or + * null if an element of their required type isn't found. + * @param {Element} selectedElement The target of the selection change event or + * the parent container of the current entire selection. + * @return {Element?} The HTML bubble target element or null if no element of + * the required type is not found. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype. + getBubbleTargetFromSelection = goog.abstractMethod; + + +/** @override */ +goog.editor.plugins.AbstractBubblePlugin.prototype.disable = function(field) { + // When the field is made uneditable, dispose of the bubble. We do this + // because the next time the field is made editable again it may be in + // a different document / iframe. + if (field.isUneditable()) { + var bubble = goog.editor.plugins.AbstractBubblePlugin.bubbleMap_[field.id]; + if (bubble) { + bubble.dispose(); + delete goog.editor.plugins.AbstractBubblePlugin.bubbleMap_[field.id]; + } + } +}; + + +/** + * @return {goog.ui.editor.Bubble} The shared bubble object for the field this + * plugin is registered on. Creates it if necessary. + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.getSharedBubble_ = + function() { + var bubbleParent = /** @type {!Element} */ (this.bubbleParent_ || + this.getFieldObject().getAppWindow().document.body); + this.dom_ = goog.dom.getDomHelper(bubbleParent); + + var bubble = goog.editor.plugins.AbstractBubblePlugin.bubbleMap_[ + this.getFieldObject().id]; + if (!bubble) { + bubble = goog.editor.plugins.AbstractBubblePlugin.bubbleFactory_.call(null, + bubbleParent, + this.getFieldObject().getBaseZindex()); + goog.editor.plugins.AbstractBubblePlugin.bubbleMap_[ + this.getFieldObject().id] = bubble; + } + return bubble; +}; + + +/** + * Creates and shows the property bubble. + * @param {Element} targetElement The target element of the bubble. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.createBubble = function( + targetElement) { + var bubble = this.getSharedBubble_(); + if (!bubble.hasPanelOfType(this.getBubbleType())) { + this.targetElement_ = targetElement; + + this.panelId_ = bubble.addPanel(this.getBubbleType(), this.getBubbleTitle(), + targetElement, + goog.bind(this.createBubbleContents, this), + this.shouldPreferBubbleAboveElement()); + this.eventRegister.listen(bubble, goog.ui.Component.EventType.HIDE, + this.handlePanelClosed_); + this.onShow(); + } +}; + + +/** + * @return {string} The type of bubble shown by this plugin. Usually the tag + * name of the element this bubble targets. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleType = function() { + return ''; +}; + + +/** + * @return {string} The title for bubble shown by this plugin. Defaults to no + * title. Should be overridden by subclasses. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleTitle = function() { + return ''; +}; + + +/** + * @return {boolean} Whether the bubble should prefer placement above the + * target element. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype. + shouldPreferBubbleAboveElement = goog.functions.FALSE; + + +/** + * Should be overriden by subclasses to add the type specific contents to the + * bubble. + * @param {Element} bubbleContainer The container element of the bubble to + * which the contents should be added. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.createBubbleContents = + goog.abstractMethod; + + +/** + * Register the handler for the target's CLICK event. + * @param {Element} target The event source element. + * @param {Function} handler The event handler. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.registerClickHandler = + function(target, handler) { + this.eventRegister.listen(target, goog.events.EventType.CLICK, handler); +}; + + +/** + * Closes the bubble. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.closeBubble = function() { + if (this.panelId_) { + this.getSharedBubble_().removePanel(this.panelId_); + this.handlePanelClosed_(); + } +}; + + +/** + * Called after the bubble is shown. The default implementation does nothing. + * Override it to provide your own one. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.onShow = goog.nullFunction; + + +/** + * Handles when the bubble panel is closed. Invoked when the entire bubble is + * hidden and also directly when the panel is closed manually. + * @private + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.handlePanelClosed_ = + function() { + this.targetElement_ = null; + this.panelId_ = null; + this.eventRegister.removeAll(); +}; + + +/** + * @return {boolean} Whether the bubble is visible. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.isVisible = function() { + return !!this.panelId_; +}; + + +/** + * Reposition the property bubble. + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.reposition = function() { + var bubble = this.getSharedBubble_(); + if (bubble) { + bubble.reposition(); + } +}; + + +/** + * Helper method that creates option links (such as edit, test, remove) + * @param {string} id String id for the span id. + * @return {Element} The option link element. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.createLinkOption = function( + id) { + // Dash plus link are together in a span so we can hide/show them easily + return this.dom_.createDom(goog.dom.TagName.SPAN, + { + id: id, + className: + goog.editor.plugins.AbstractBubblePlugin.OPTION_LINK_CLASSNAME_ + }, + this.dom_.createTextNode( + goog.editor.plugins.AbstractBubblePlugin.DASH_NBSP_STRING)); +}; + + +/** + * Helper method that creates a link with text set to linkText and optionaly + * wires up a listener for the CLICK event or the link. + * @param {string} linkId The id of the link. + * @param {string} linkText Text of the link. + * @param {Function=} opt_onClick Optional function to call when the link is + * clicked. + * @param {Element=} opt_container If specified, location to insert link. If no + * container is specified, the old link is removed and replaced. + * @return {Element} The link element. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.createLink = function( + linkId, linkText, opt_onClick, opt_container) { + var link = this.createLinkHelper(linkId, linkText, false, opt_container); + if (opt_onClick) { + this.registerClickHandler(link, opt_onClick); + } + return link; +}; + + +/** + * Helper method to create a link to insert into the bubble. + * @param {string} linkId The id of the link. + * @param {string} linkText Text of the link. + * @param {boolean} isAnchor Set to true to create an actual anchor tag + * instead of a span. Actual links are right clickable (e.g. to open in + * a new window) and also update window status on hover. + * @param {Element=} opt_container If specified, location to insert link. If no + * container is specified, the old link is removed and replaced. + * @return {Element} The link element. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.createLinkHelper = function( + linkId, linkText, isAnchor, opt_container) { + var link = this.dom_.createDom( + isAnchor ? goog.dom.TagName.A : goog.dom.TagName.SPAN, + {className: goog.editor.plugins.AbstractBubblePlugin.LINK_CLASSNAME_}, + linkText); + this.setupLink(link, linkId, opt_container); + goog.editor.style.makeUnselectable(link, this.eventRegister); + return link; +}; + + +/** + * Inserts a link in the given container if it is specified or removes + * the old link with this id and replaces it with the new link + * @param {Element} link Html element to insert. + * @param {string} linkId Id of the link. + * @param {Element=} opt_container If specified, location to insert link. + * @protected + */ +goog.editor.plugins.AbstractBubblePlugin.prototype.setupLink = function( + link, linkId, opt_container) { + if (opt_container) { + opt_container.appendChild(link); + } else { + var oldLink = this.dom_.getElement(linkId); + if (oldLink) { + goog.dom.replaceNode(link, oldLink); + } + } + + link.id = linkId; +}; diff --git a/master/closure-library/closure/goog/editor/plugins/abstractdialogplugin.js b/master/closure-library/closure/goog/editor/plugins/abstractdialogplugin.js new file mode 100644 index 0000000000..5d24c2214f --- /dev/null +++ b/master/closure-library/closure/goog/editor/plugins/abstractdialogplugin.js @@ -0,0 +1,337 @@ +// Copyright 2008 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 abstract superclass for TrogEdit dialog plugins. Each + * Trogedit dialog has its own plugin. + * + * @author nicksantos@google.com (Nick Santos) + * @author marcosalmeida@google.com (Marcos Almeida) + */ + +goog.provide('goog.editor.plugins.AbstractDialogPlugin'); +goog.provide('goog.editor.plugins.AbstractDialogPlugin.EventType'); + +goog.require('goog.dom'); +goog.require('goog.dom.Range'); +goog.require('goog.editor.Field.EventType'); +goog.require('goog.editor.Plugin'); +goog.require('goog.editor.range'); +goog.require('goog.events'); +goog.require('goog.ui.editor.AbstractDialog.EventType'); + + +// *** Public interface ***************************************************** // + + + +/** + * An abstract superclass for a Trogedit plugin that creates exactly one + * dialog. By default dialogs are not reused -- each time execCommand is called, + * a new instance of the dialog object is created (and the old one disposed of). + * To enable reusing of the dialog object, subclasses should call + * setReuseDialog() after calling the superclass constructor. + * @param {string} command The command that this plugin handles. + * @constructor + * @extends {goog.editor.Plugin} + */ +goog.editor.plugins.AbstractDialogPlugin = function(command) { + goog.editor.Plugin.call(this); + this.command_ = command; +}; +goog.inherits(goog.editor.plugins.AbstractDialogPlugin, goog.editor.Plugin); + + +/** @override */ +goog.editor.plugins.AbstractDialogPlugin.prototype.isSupportedCommand = + function(command) { + return command == this.command_; +}; + + +/** + * Handles execCommand. Dialog plugins don't make any changes when they open a + * dialog, just when the dialog closes (because only modal dialogs are + * supported). Hence this method does not dispatch the change events that the + * superclass method does. + * @param {string} command The command to execute. + * @param {...*} var_args Any additional parameters needed to + * execute the command. + * @return {*} The result of the execCommand, if any. + * @override + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.execCommand = function( + command, var_args) { + return this.execCommandInternal.apply(this, arguments); +}; + + +// *** Events *************************************************************** // + + +/** + * Event type constants for events the dialog plugins fire. + * @enum {string} + */ +goog.editor.plugins.AbstractDialogPlugin.EventType = { + // This event is fired when a dialog has been opened. + OPENED: 'dialogOpened', + // This event is fired when a dialog has been closed. + CLOSED: 'dialogClosed' +}; + + +// *** Protected interface ************************************************** // + + +/** + * Creates a new instance of this plugin's dialog. Must be overridden by + * subclasses. + * @param {!goog.dom.DomHelper} dialogDomHelper The dom helper to be used to + * create the dialog. + * @param {*=} opt_arg The dialog specific argument. Concrete subclasses should + * declare a specific type. + * @return {goog.ui.editor.AbstractDialog} The newly created dialog. + * @protected + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.createDialog = + goog.abstractMethod; + + +/** + * Returns the current dialog that was created and opened by this plugin. + * @return {goog.ui.editor.AbstractDialog} The current dialog that was created + * and opened by this plugin. + * @protected + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.getDialog = function() { + return this.dialog_; +}; + + +/** + * Sets whether this plugin should reuse the same instance of the dialog each + * time execCommand is called or create a new one. This is intended for use by + * subclasses only, hence protected. + * @param {boolean} reuse Whether to reuse the dialog. + * @protected + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.setReuseDialog = + function(reuse) { + this.reuseDialog_ = reuse; +}; + + +/** + * Handles execCommand by opening the dialog. Dispatches + * {@link goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED} after the + * dialog is shown. + * @param {string} command The command to execute. + * @param {*=} opt_arg The dialog specific argument. Should be the same as + * {@link createDialog}. + * @return {*} Always returns true, indicating the dialog was shown. + * @protected + * @override + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.execCommandInternal = + function(command, opt_arg) { + // If this plugin should not reuse dialog instances, first dispose of the + // previous dialog. + if (!this.reuseDialog_) { + this.disposeDialog_(); + } + // If there is no dialog yet (or we aren't reusing the previous one), create + // one. + if (!this.dialog_) { + this.dialog_ = this.createDialog( + // TODO(user): Add Field.getAppDomHelper. (Note dom helper will + // need to be updated if setAppWindow is called by clients.) + goog.dom.getDomHelper(this.getFieldObject().getAppWindow()), + opt_arg); + } + + // Since we're opening a dialog, we need to clear the selection because the + // focus will be going to the dialog, and if we leave an selection in the + // editor while another selection is active in the dialog as the user is + // typing, some browsers will screw up the original selection. But first we + // save it so we can restore it when the dialog closes. + // getRange may return null if there is no selection in the field. + var tempRange = this.getFieldObject().getRange(); + // saveUsingDom() did not work as well as saveUsingNormalizedCarets(), + // not sure why. + this.savedRange_ = tempRange && goog.editor.range.saveUsingNormalizedCarets( + tempRange); + goog.dom.Range.clearSelection( + this.getFieldObject().getEditableDomHelper().getWindow()); + + // Listen for the dialog closing so we can clean up. + goog.events.listenOnce(this.dialog_, + goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE, + this.handleAfterHide, + false, + this); + + this.getFieldObject().setModalMode(true); + this.dialog_.show(); + this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED); + + // Since the selection has left the document, dispatch a selection + // change event. + this.getFieldObject().dispatchSelectionChangeEvent(); + + return true; +}; + + +/** + * Cleans up after the dialog has closed, including restoring the selection to + * what it was before the dialog was opened. If a subclass modifies the editable + * field's content such that the original selection is no longer valid (usually + * the case when the user clicks OK, and sometimes also on Cancel), it is that + * subclass' responsibility to place the selection in the desired place during + * the OK or Cancel (or other) handler. In that case, this method will leave the + * selection in place. + * @param {goog.events.Event} e The AFTER_HIDE event object. + * @protected + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.handleAfterHide = function( + e) { + this.getFieldObject().setModalMode(false); + this.restoreOriginalSelection(); + + if (!this.reuseDialog_) { + this.disposeDialog_(); + } + + this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.CLOSED); + + // Since the selection has returned to the document, dispatch a selection + // change event. + this.getFieldObject().dispatchSelectionChangeEvent(); + + // When the dialog closes due to pressing enter or escape, that happens on the + // keydown event. But the browser will still fire a keyup event after that, + // which is caught by the editable field and causes it to try to fire a + // selection change event. To avoid that, we "debounce" the selection change + // event, meaning the editable field will not fire that event if the keyup + // that caused it immediately after this dialog was hidden ("immediately" + // means a small number of milliseconds defined by the editable field). + this.getFieldObject().debounceEvent( + goog.editor.Field.EventType.SELECTIONCHANGE); +}; + + +/** + * Restores the selection in the editable field to what it was before the dialog + * was opened. This is not guaranteed to work if the contents of the field + * have changed. + * @protected + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.restoreOriginalSelection = + function() { + this.getFieldObject().focus(); + if (this.savedRange_) { + this.savedRange_.restore(); + this.savedRange_ = null; + } +}; + + +/** + * Cleans up the structure used to save the original selection before the dialog + * was opened. Should be used by subclasses that don't restore the original + * selection via restoreOriginalSelection. + * @protected + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.disposeOriginalSelection = + function() { + if (this.savedRange_) { + this.savedRange_.dispose(); + this.savedRange_ = null; + } +}; + + +/** @override */ +goog.editor.plugins.AbstractDialogPlugin.prototype.disposeInternal = + function() { + this.disposeDialog_(); + goog.base(this, 'disposeInternal'); +}; + + +// *** Private implementation *********************************************** // + + +/** + * The command that this plugin handles. + * @type {string} + * @private + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.command_; + + +/** + * The current dialog that was created and opened by this plugin. + * @type {goog.ui.editor.AbstractDialog} + * @private + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.dialog_; + + +/** + * Whether this plugin should reuse the same instance of the dialog each time + * execCommand is called or create a new one. + * @type {boolean} + * @private + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.reuseDialog_ = false; + + +/** + * Mutex to prevent recursive calls to disposeDialog_. + * @type {boolean} + * @private + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.isDisposingDialog_ = false; + + +/** + * SavedRange representing the selection before the dialog was opened. + * @type {goog.dom.SavedRange} + * @private + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.savedRange_; + + +/** + * Disposes of the dialog if needed. It is this abstract class' responsibility + * to dispose of the dialog. The "if needed" refers to the fact this method + * might be called twice (nested calls, not sequential) in the dispose flow, so + * if the dialog was already disposed once it should not be disposed again. + * @private + */ +goog.editor.plugins.AbstractDialogPlugin.prototype.disposeDialog_ = function() { + // Wrap disposing the dialog in a mutex. Otherwise disposing it would cause it + // to get hidden (if it is still open) and fire AFTER_HIDE, which in + // turn would cause the dialog to be disposed again (closure only flags an + // object as disposed after the dispose call chain completes, so it doesn't + // prevent recursive dispose calls). + if (this.dialog_ && !this.isDisposingDialog_) { + this.isDisposingDialog_ = true; + this.dialog_.dispose(); + this.dialog_ = null; + this.isDisposingDialog_ = false; + } +}; diff --git a/master/closure-library/closure/goog/editor/plugins/abstracttabhandler.js b/master/closure-library/closure/goog/editor/plugins/abstracttabhandler.js new file mode 100644 index 0000000000..e5668199d7 --- /dev/null +++ b/master/closure-library/closure/goog/editor/plugins/abstracttabhandler.js @@ -0,0 +1,78 @@ +// Copyright 2008 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 Abstract Editor plugin class to handle tab keys. Has one + * abstract method which should be overriden to handle a tab key press. + * + * @author robbyw@google.com (Robby Walker) + * @author ajp@google.com (Andy Perelson) + */ + +goog.provide('goog.editor.plugins.AbstractTabHandler'); + +goog.require('goog.editor.Plugin'); +goog.require('goog.events.KeyCodes'); + + + +/** + * Plugin to handle tab keys. Specific tab behavior defined by subclasses. + * + * @constructor + * @extends {goog.editor.Plugin} + */ +goog.editor.plugins.AbstractTabHandler = function() { + goog.editor.Plugin.call(this); +}; +goog.inherits(goog.editor.plugins.AbstractTabHandler, goog.editor.Plugin); + + +/** @override */ +goog.editor.plugins.AbstractTabHandler.prototype.getTrogClassId = + goog.abstractMethod; + + +/** @override */ +goog.editor.plugins.AbstractTabHandler.prototype.handleKeyboardShortcut = + function(e, key, isModifierPressed) { + // If a dialog doesn't have selectable field, Moz grabs the event and + // performs actions in editor window. This solves that problem and allows + // the event to be passed on to proper handlers. + if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) { + return false; + } + + // Don't handle Ctrl+Tab since the user is most likely trying to switch + // browser tabs. See bug 1305086. + // FF3 on Mac sends Ctrl-Tab to trogedit and we end up inserting a tab, but + // then it also switches the tabs. See bug 1511681. Note that we don't use + // isModifierPressed here since isModifierPressed is true only if metaKey + // is true on Mac. + if (e.keyCode == goog.events.KeyCodes.TAB && !e.metaKey && !e.ctrlKey) { + return this.handleTabKey(e); + } + + return false; +}; + + +/** + * Handle a tab key press. + * @param {goog.events.Event} e The key event. + * @return {boolean} Whether this event was handled by this plugin. + * @protected + */ +goog.editor.plugins.AbstractTabHandler.prototype.handleTabKey = + goog.abstractMethod; diff --git a/master/closure-library/closure/goog/editor/plugins/basictextformatter.js b/master/closure-library/closure/goog/editor/plugins/basictextformatter.js new file mode 100644 index 0000000000..973c078b8e --- /dev/null +++ b/master/closure-library/closure/goog/editor/plugins/basictextformatter.js @@ -0,0 +1,1748 @@ +// Copyright 2006 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 Functions to style text. + * + */ + +goog.provide('goog.editor.plugins.BasicTextFormatter'); +goog.provide('goog.editor.plugins.BasicTextFormatter.COMMAND'); + +goog.require('goog.array'); +goog.require('goog.debug.Logger'); +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.Range'); +goog.require('goog.dom.TagName'); +goog.require('goog.editor.BrowserFeature'); +goog.require('goog.editor.Command'); +goog.require('goog.editor.Link'); +goog.require('goog.editor.Plugin'); +goog.require('goog.editor.node'); +goog.require('goog.editor.range'); +goog.require('goog.editor.style'); +goog.require('goog.iter'); +goog.require('goog.iter.StopIteration'); +goog.require('goog.object'); +goog.require('goog.string'); +goog.require('goog.string.Unicode'); +goog.require('goog.style'); +goog.require('goog.ui.editor.messages'); +goog.require('goog.userAgent'); + + + +/** + * Functions to style text (e.g. underline, make bold, etc.) + * @constructor + * @extends {goog.editor.Plugin} + */ +goog.editor.plugins.BasicTextFormatter = function() { + goog.editor.Plugin.call(this); +}; +goog.inherits(goog.editor.plugins.BasicTextFormatter, goog.editor.Plugin); + + +/** @override */ +goog.editor.plugins.BasicTextFormatter.prototype.getTrogClassId = function() { + return 'BTF'; +}; + + +/** + * Logging object. + * @type {goog.debug.Logger} + * @protected + * @override + */ +goog.editor.plugins.BasicTextFormatter.prototype.logger = + goog.debug.Logger.getLogger('goog.editor.plugins.BasicTextFormatter'); + + +/** + * Commands implemented by this plugin. + * @enum {string} + */ +goog.editor.plugins.BasicTextFormatter.COMMAND = { + LINK: '+link', + FORMAT_BLOCK: '+formatBlock', + INDENT: '+indent', + OUTDENT: '+outdent', + STRIKE_THROUGH: '+strikeThrough', + HORIZONTAL_RULE: '+insertHorizontalRule', + SUBSCRIPT: '+subscript', + SUPERSCRIPT: '+superscript', + UNDERLINE: '+underline', + BOLD: '+bold', + ITALIC: '+italic', + FONT_SIZE: '+fontSize', + FONT_FACE: '+fontName', + FONT_COLOR: '+foreColor', + BACKGROUND_COLOR: '+backColor', + ORDERED_LIST: '+insertOrderedList', + UNORDERED_LIST: '+insertUnorderedList', + JUSTIFY_CENTER: '+justifyCenter', + JUSTIFY_FULL: '+justifyFull', + JUSTIFY_RIGHT: '+justifyRight', + JUSTIFY_LEFT: '+justifyLeft' +}; + + +/** + * Inverse map of execCommand strings to + * {@link goog.editor.plugins.BasicTextFormatter.COMMAND} constants. Used to + * determine whether a string corresponds to a command this plugin + * handles in O(1) time. + * @type {Object} + * @private + */ +goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_ = + goog.object.transpose(goog.editor.plugins.BasicTextFormatter.COMMAND); + + +/** + * Whether the string corresponds to a command this plugin handles. + * @param {string} command Command string to check. + * @return {boolean} Whether the string corresponds to a command + * this plugin handles. + * @override + */ +goog.editor.plugins.BasicTextFormatter.prototype.isSupportedCommand = function( + command) { + // TODO(user): restore this to simple check once table editing + // is moved out into its own plugin + return command in goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_; +}; + + +/** + * @return {goog.dom.AbstractRange} The closure range object that wraps the + * current user selection. + * @private + */ +goog.editor.plugins.BasicTextFormatter.prototype.getRange_ = function() { + return this.getFieldObject().getRange(); +}; + + +/** + * @return {Document} The document object associated with the currently active + * field. + * @private + */ +goog.editor.plugins.BasicTextFormatter.prototype.getDocument_ = function() { + return this.getFieldDomHelper().getDocument(); +}; + + +/** + * Execute a user-initiated command. + * @param {string} command Command to execute. + * @param {...*} var_args For color commands, this + * should be the hex color (with the #). For FORMAT_BLOCK, this should be + * the goog.editor.plugins.BasicTextFormatter.BLOCK_COMMAND. + * It will be unused for other commands. + * @return {Object|undefined} The result of the command. + * @override + */ +goog.editor.plugins.BasicTextFormatter.prototype.execCommandInternal = function( + command, var_args) { + var preserveDir, styleWithCss, needsFormatBlockDiv, hasDummySelection; + var result; + var opt_arg = arguments[1]; + + switch (command) { + case goog.editor.plugins.BasicTextFormatter.COMMAND.BACKGROUND_COLOR: + // Don't bother for no color selected, color picker is resetting itself. + if (!goog.isNull(opt_arg)) { + if (goog.editor.BrowserFeature.EATS_EMPTY_BACKGROUND_COLOR) { + this.applyBgColorManually_(opt_arg); + } else if (goog.userAgent.OPERA) { + // backColor will color the block level element instead of + // the selected span of text in Opera. + this.execCommandHelper_('hiliteColor', opt_arg); + } else { + this.execCommandHelper_(command, opt_arg); + } + } + break; + + case goog.editor.plugins.BasicTextFormatter.COMMAND.LINK: + result = this.toggleLink_(opt_arg); + break; + + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER: + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL: + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT: + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT: + this.justify_(command); + break; + + default: + if (goog.userAgent.IE && + command == + goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK && + opt_arg) { + // IE requires that the argument be in the form of an opening + // tag, like

, including angle brackets. WebKit will accept + // the arguemnt with or without brackets, and Firefox pre-3 supports + // only a fixed subset of tags with brackets, and prefers without. + // So we only add them IE only. + opt_arg = '<' + opt_arg + '>'; + } + + if (command == + goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR && + goog.isNull(opt_arg)) { + // If we don't have a color, then FONT_COLOR is a no-op. + break; + } + + switch (command) { + case goog.editor.plugins.BasicTextFormatter.COMMAND.INDENT: + case goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT: + if (goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) { + if (goog.userAgent.GECKO) { + styleWithCss = true; + } + if (goog.userAgent.OPERA) { + if (command == + goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT) { + // styleWithCSS actually sets negative margins on
+ // to outdent them. If the command is enabled without + // styleWithCSS flipped on, then the caret is in a blockquote so + // styleWithCSS must not be used. But if the command is not + // enabled, styleWithCSS should be used so that elements such as + // a
with a margin-left style can still be outdented. + // (Opera bug: CORE-21118) + styleWithCss = + !this.getDocument_().queryCommandEnabled('outdent'); + } else { + // Always use styleWithCSS for indenting. Otherwise, Opera will + // make separate
s around *each* indented line, + // which adds big default
margins between each + // indented line. + styleWithCss = true; + } + } + } + // Fall through. + + case goog.editor.plugins.BasicTextFormatter.COMMAND.ORDERED_LIST: + case goog.editor.plugins.BasicTextFormatter.COMMAND.UNORDERED_LIST: + if (goog.editor.BrowserFeature.LEAVES_P_WHEN_REMOVING_LISTS && + this.queryCommandStateInternal_(this.getDocument_(), + command)) { + // IE leaves behind P tags when unapplying lists. + // If we're not in P-mode, then we want divs + // So, unlistify, then convert the Ps into divs. + needsFormatBlockDiv = this.getFieldObject().queryCommandValue( + goog.editor.Command.DEFAULT_TAG) != goog.dom.TagName.P; + } else if (!goog.editor.BrowserFeature.CAN_LISTIFY_BR) { + // IE doesn't convert BRed line breaks into separate list items. + // So convert the BRs to divs, then do the listify. + this.convertBreaksToDivs_(); + } + + // This fix only works in Gecko. + if (goog.userAgent.GECKO && + goog.editor.BrowserFeature.FORGETS_FORMATTING_WHEN_LISTIFYING && + !this.queryCommandValue(command)) { + hasDummySelection |= this.beforeInsertListGecko_(); + } + // Fall through to preserveDir block + + case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK: + // Both FF & IE may lose directionality info. Save/restore it. + // TODO(user): Does Safari also need this? + // TODO (gmark, jparent): This isn't ideal because it uses a string + // literal, so if the plugin name changes, it would break. We need a + // better solution. See also other places in code that use + // this.getPluginByClassId('Bidi'). + preserveDir = !!this.getFieldObject().getPluginByClassId('Bidi'); + break; + + case goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT: + case goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT: + if (goog.editor.BrowserFeature.NESTS_SUBSCRIPT_SUPERSCRIPT) { + // This browser nests subscript and superscript when both are + // applied, instead of canceling out the first when applying the + // second. + this.applySubscriptSuperscriptWorkarounds_(command); + } + break; + + case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE: + case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD: + case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC: + // If we are applying the formatting, then we want to have + // styleWithCSS false so that we generate html tags (like ). If we + // are unformatting something, we want to have styleWithCSS true so + // that we can unformat both html tags and inline styling. + // TODO(user): What about WebKit and Opera? + styleWithCss = goog.userAgent.GECKO && + goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && + this.queryCommandValue(command); + break; + + case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR: + case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE: + // It is very expensive in FF (order of magnitude difference) to use + // font tags instead of styled spans. Whenever possible, + // force FF to use spans. + // Font size is very expensive too, but FF always uses font tags, + // regardless of which styleWithCSS value you use. + styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && + goog.userAgent.GECKO; + } + + /** + * Cases where we just use the default execCommand (in addition + * to the above fall-throughs) + * goog.editor.plugins.BasicTextFormatter.COMMAND.STRIKE_THROUGH: + * goog.editor.plugins.BasicTextFormatter.COMMAND.HORIZONTAL_RULE: + * goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT: + * goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT: + * goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE: + * goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD: + * goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC: + * goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE: + * goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE: + */ + this.execCommandHelper_(command, opt_arg, preserveDir, !!styleWithCss); + + if (hasDummySelection) { + this.getDocument_().execCommand('Delete', false, true); + } + + if (needsFormatBlockDiv) { + this.getDocument_().execCommand('FormatBlock', false, '
'); + } + } + // FF loses focus, so we have to set the focus back to the document or the + // user can't type after selecting from menu. In IE, focus is set correctly + // and resetting it here messes it up. + if (goog.userAgent.GECKO && !this.getFieldObject().inModalMode()) { + this.focusField_(); + } + return result; +}; + + +/** + * Focuses on the field. + * @private + */ +goog.editor.plugins.BasicTextFormatter.prototype.focusField_ = function() { + this.getFieldDomHelper().getWindow().focus(); +}; + + +/** + * Gets the command value. + * @param {string} command The command value to get. + * @return {string|boolean|null} The current value of the command in the given + * selection. NOTE: This return type list is not documented in MSDN or MDC + * and has been constructed from experience. Please update it + * if necessary. + * @override + */ +goog.editor.plugins.BasicTextFormatter.prototype.queryCommandValue = function( + command) { + var styleWithCss; + switch (command) { + case goog.editor.plugins.BasicTextFormatter.COMMAND.LINK: + return this.isNodeInState_(goog.dom.TagName.A); + + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER: + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL: + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT: + case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT: + return this.isJustification_(command); + + case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK: + // TODO(nicksantos): See if we can use queryCommandValue here. + return goog.editor.plugins.BasicTextFormatter.getSelectionBlockState_( + this.getFieldObject().getRange()); + + case goog.editor.plugins.BasicTextFormatter.COMMAND.INDENT: + case goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT: + case goog.editor.plugins.BasicTextFormatter.COMMAND.HORIZONTAL_RULE: + // TODO: See if there are reasonable results to return for + // these commands. + return false; + + case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE: + case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE: + case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR: + case goog.editor.plugins.BasicTextFormatter.COMMAND.BACKGROUND_COLOR: + // We use queryCommandValue here since we don't just want to know if a + // color/fontface/fontsize is applied, we want to know WHICH one it is. + return this.queryCommandValueInternal_(this.getDocument_(), command, + goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && + goog.userAgent.GECKO); + + case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE: + case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD: + case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC: + styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && + goog.userAgent.GECKO; + + default: + /** + * goog.editor.plugins.BasicTextFormatter.COMMAND.STRIKE_THROUGH + * goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT + * goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT + * goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE + * goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD + * goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC + * goog.editor.plugins.BasicTextFormatter.COMMAND.ORDERED_LIST + * goog.editor.plugins.BasicTextFormatter.COMMAND.UNORDERED_LIST + */ + // This only works for commands that use the default execCommand + return this.queryCommandStateInternal_(this.getDocument_(), command, + styleWithCss); + } +}; + + +/** + * @override + */ +goog.editor.plugins.BasicTextFormatter.prototype.prepareContentsHtml = + function(html) { + // If the browser collapses empty nodes and the field has only a script + // tag in it, then it will collapse this node. Which will mean the user + // can't click into it to edit it. + if (goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES && + html.match(/^\s* + + + diff --git a/master/examples/animation.js b/master/examples/animation.js new file mode 100644 index 0000000000..8f86dd3ec0 --- /dev/null +++ b/master/examples/animation.js @@ -0,0 +1,111 @@ +var london = ol.projection.transform( + new ol.Coordinate(-0.12755, 51.507222), 'EPSG:4326', 'EPSG:3857'); +var moscow = ol.projection.transform( + new ol.Coordinate(37.6178, 55.7517), 'EPSG:4326', 'EPSG:3857'); +var instanbul = ol.projection.transform( + new ol.Coordinate(28.9744, 41.0128), 'EPSG:4326', 'EPSG:3857'); +var rome = ol.projection.transform( + new ol.Coordinate(12.5, 41.9), 'EPSG:4326', 'EPSG:3857'); +var bern = ol.projection.transform( + new ol.Coordinate(7.4458, 46.95), 'EPSG:4326', 'EPSG:3857'); + +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.OpenStreetMap() + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: instanbul, + zoom: 6 + }) +}); + + +var rotateLeft = document.getElementById('rotate-left'); +rotateLeft.addEventListener('click', function() { + var rotateLeft = ol.animation.rotate({ + duration: 2000, + rotation: -4 * Math.PI + }); + map.addPreRenderFunction(rotateLeft); +}, false); +var rotateRight = document.getElementById('rotate-right'); +rotateRight.addEventListener('click', function() { + var rotateRight = ol.animation.rotate({ + duration: 2000, + rotation: 4 * Math.PI + }); + map.addPreRenderFunction(rotateRight); +}, false); + + +var panToLondon = document.getElementById('pan-to-london'); +panToLondon.addEventListener('click', function() { + var pan = ol.animation.pan({ + duration: 2000, + source: map.getView().getView2D().getCenter() + }); + map.addPreRenderFunction(pan); + map.getView().getView2D().setCenter(london); +}, false); + +var elasticToMoscow = document.getElementById('elastic-to-moscow'); +elasticToMoscow.addEventListener('click', function() { + var pan = ol.animation.pan({ + duration: 2000, + easing: ol.easing.elastic, + source: map.getView().getView2D().getCenter() + }); + map.addPreRenderFunction(pan); + map.getView().getView2D().setCenter(moscow); +}, false); + +var bounceToInstanbul = document.getElementById('bounce-to-instanbul'); +bounceToInstanbul.addEventListener('click', function() { + var pan = ol.animation.pan({ + duration: 2000, + easing: ol.easing.bounce, + source: map.getView().getView2D().getCenter() + }); + map.addPreRenderFunction(pan); + map.getView().getView2D().setCenter(instanbul); +}, false); + +var spinToRome = document.getElementById('spin-to-rome'); +spinToRome.addEventListener('click', function() { + var duration = 2000; + var start = +new Date(); + var pan = ol.animation.pan({ + duration: duration, + source: map.getView().getView2D().getCenter(), + start: start + }); + var rotate = ol.animation.rotate({ + duration: duration, + rotation: 2 * Math.PI, + start: start + }); + map.addPreRenderFunctions([pan, rotate]); + map.getView().getView2D().setCenter(rome); +}, false); + +var flyToBern = document.getElementById('fly-to-bern'); +flyToBern.addEventListener('click', function() { + var duration = 2000; + var start = +new Date(); + var pan = ol.animation.pan({ + duration: duration, + source: map.getView().getView2D().getCenter(), + start: start + }); + var bounce = ol.animation.bounce({ + duration: duration, + resolution: 4 * map.getView().getView2D().getResolution(), + start: start + }); + map.addPreRenderFunctions([pan, bounce]); + map.getView().getView2D().setCenter(bern); +}, false); diff --git a/master/examples/bing-maps-require.js b/master/examples/bing-maps-require.js new file mode 100644 index 0000000000..bfb9b043eb --- /dev/null +++ b/master/examples/bing-maps-require.js @@ -0,0 +1,7 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.BingMaps'); diff --git a/master/examples/bing-maps.html b/master/examples/bing-maps.html new file mode 100644 index 0000000000..1265dac5c3 --- /dev/null +++ b/master/examples/bing-maps.html @@ -0,0 +1,52 @@ + + + + + + + + + + Bing Maps example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Bing Maps example

+

Example of a Bing Maps layer.

+
+

See the bing-maps.js source to see how this is done.

+
+
bing, bing-maps
+
+ +
+ +
+ + + + + diff --git a/master/examples/bing-maps.js b/master/examples/bing-maps.js new file mode 100644 index 0000000000..b40f3630f3 --- /dev/null +++ b/master/examples/bing-maps.js @@ -0,0 +1,17 @@ +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.BingMaps({ + key: 'AgtFlPYDnymLEe9zJ5PCkghbNiFZE9aAtTy3mPaEnEBXqLHtFuTcKoZ-miMC3w7R', + style: 'AerialWithLabels' + }) + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: ol.projection.transform( + new ol.Coordinate(-123.1, 49.25), 'EPSG:4326', 'EPSG:3857'), + zoom: 8 + }) +}); diff --git a/master/examples/brightness-contrast-require.js b/master/examples/brightness-contrast-require.js new file mode 100644 index 0000000000..e5be57d974 --- /dev/null +++ b/master/examples/brightness-contrast-require.js @@ -0,0 +1,6 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.MapQuestOpenAerial'); diff --git a/master/examples/brightness-contrast.html b/master/examples/brightness-contrast.html new file mode 100644 index 0000000000..503a48ee27 --- /dev/null +++ b/master/examples/brightness-contrast.html @@ -0,0 +1,62 @@ + + + + + + + + + + Brightness/contrast example + + + + + +
+ +
+
+
+
+ + + +
+
+ + + +
+
+
+ +
+ +
+

Brightness/contrast example

+

Example of brightness/contrast control on the client (WebGL only).

+
+

See the brightness-contrast.js source to see how this is done.

+
+
brightness, contrast, webgl
+
+ +
+ +
+ + + + + diff --git a/master/examples/brightness-contrast.js b/master/examples/brightness-contrast.js new file mode 100644 index 0000000000..f94f2617a2 --- /dev/null +++ b/master/examples/brightness-contrast.js @@ -0,0 +1,39 @@ +var layer = new ol.layer.TileLayer({ + source: new ol.source.MapQuestOpenAerial() +}); + +var map = new ol.Map({ + layers: [layer], + renderer: ol.RendererHint.WEBGL, + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 2 + }) +}); + +var increaseBrightness = document.getElementById('increase-brightness'); +increaseBrightness.addEventListener('click', function() { + layer.setBrightness(layer.getBrightness() + 0.125); +}, false); +var resetBrightness = document.getElementById('reset-brightness'); +resetBrightness.addEventListener('click', function() { + layer.setBrightness(0); +}, false); +var decreaseBrightness = document.getElementById('decrease-brightness'); +decreaseBrightness.addEventListener('click', function() { + layer.setBrightness(layer.getBrightness() - 0.125); +}, false); + +var increaseContrast = document.getElementById('increase-contrast'); +increaseContrast.addEventListener('click', function() { + layer.setContrast(layer.getContrast() + 0.125); +}, false); +var resetContrast = document.getElementById('reset-contrast'); +resetContrast.addEventListener('click', function() { + layer.setContrast(1); +}, false); +var decreaseContrast = document.getElementById('decrease-contrast'); +decreaseContrast.addEventListener('click', function() { + layer.setContrast(layer.getContrast() - 0.125); +}, false); diff --git a/master/examples/canvas-tiles-require.js b/master/examples/canvas-tiles-require.js new file mode 100644 index 0000000000..2f0bf9dd89 --- /dev/null +++ b/master/examples/canvas-tiles-require.js @@ -0,0 +1,9 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.DebugTileSource'); +goog.require('ol.source.OpenStreetMap'); +goog.require('ol.tilegrid.XYZ'); diff --git a/master/examples/canvas-tiles.js b/master/examples/canvas-tiles.js index ecec31b88b..9fb07531b6 100644 --- a/master/examples/canvas-tiles.js +++ b/master/examples/canvas-tiles.js @@ -1,32 +1,20 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHint'); -goog.require('ol.View2D'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.projection'); -goog.require('ol.source.DebugTileSource'); -goog.require('ol.source.OpenStreetMap'); -goog.require('ol.tilegrid.XYZ'); - - -var layers = new ol.Collection([ +var layers = [ new ol.layer.TileLayer({ source: new ol.source.OpenStreetMap() }), new ol.layer.TileLayer({ source: new ol.source.DebugTileSource({ - projection: ol.projection.getFromCode('EPSG:3857'), + projection: 'EPSG:3857', tileGrid: new ol.tilegrid.XYZ({ maxZoom: 22 }) }) }) -]); +]; var webglMap = new ol.Map({ view: new ol.View2D({ - center: ol.projection.transformWithCodes( + center: ol.projection.transform( new ol.Coordinate(-0.1275, 51.507222), 'EPSG:4326', 'EPSG:3857'), zoom: 10 }), @@ -43,7 +31,7 @@ domMap.bindTo('layers', webglMap); domMap.bindTo('view', webglMap); var canvasMap = new ol.Map({ - renderer: ol.RendererHint.DOM, + renderer: ol.RendererHint.CANVAS, target: 'canvasMap' }); canvasMap.bindTo('layers', webglMap); diff --git a/master/examples/epsg-4326-require.js b/master/examples/epsg-4326-require.js new file mode 100644 index 0000000000..89e246c983 --- /dev/null +++ b/master/examples/epsg-4326-require.js @@ -0,0 +1,10 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.control.ScaleLine'); +goog.require('ol.control.ScaleLineUnits'); +goog.require('ol.control.defaults'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.TiledWMS'); diff --git a/master/examples/epsg-4326.js b/master/examples/epsg-4326.js index 5219ed456a..690ac451e2 100644 --- a/master/examples/epsg-4326.js +++ b/master/examples/epsg-4326.js @@ -1,16 +1,4 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHint'); -goog.require('ol.View2D'); -goog.require('ol.control.ScaleLineUnits'); -goog.require('ol.control.defaults'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.projection'); -goog.require('ol.source.TiledWMS'); - - -var layers = new ol.Collection([ +var layers = [ new ol.layer.TileLayer({ source: new ol.source.TiledWMS({ url: 'http://vmap0.tiles.osgeo.org/wms/vmap0', @@ -22,22 +10,20 @@ var layers = new ol.Collection([ } }) }) -]); +]; var map = new ol.Map({ - controls: ol.control.defaults({ - scaleLine: true, - // FIXME The typecast here is only needed if the example is compiled - scaleLineOptions: /** @type {ol.control.ScaleLineOptions} */ ({ + controls: ol.control.defaults({}, [ + new ol.control.ScaleLine({ units: ol.control.ScaleLineUnits.DEGREES }) - }), + ]), layers: layers, // The OSgeo server does not set cross origin headers, so we cannot use WebGL renderers: [ol.RendererHint.CANVAS, ol.RendererHint.DOM], target: 'map', view: new ol.View2D({ - projection: ol.projection.getFromCode('EPSG:4326'), + projection: 'EPSG:4326', center: new ol.Coordinate(0, 0), zoom: 2 }) diff --git a/master/examples/example-list.js b/master/examples/example-list.js index 4f046a24a5..7a51f352a9 100644 --- a/master/examples/example-list.js +++ b/master/examples/example-list.js @@ -1 +1 @@ -var info={"index": {"openaerial": {"0": 1, "3": 1}, "osm": {"1": 1}, "same": {"4": 1}, "layers": {"1": 1, "4": 1, "9": 1, "7": 2}, "note": {"1": 1}, "wms": {"8": 3, "9": 3, "10": 3}, "capabilities": {"8": 1}, "source": {"6": 1}, "black": {"1": 1}, "tiles": {"1": 2}, "watercolor": {"6": 1}, "grid": {"1": 1}, "tiled": {"9": 2, "10": 2}, "not": {"1": 1}, "using": {"9": 1}, "rotation": {"4": 1}, "transparent": {"7": 1}, "semi": {"7": 1}, "side": {"4": 4}, "ed": {"7": 1}, "national": {"9": 1}, "sync": {"4": 1, "7": 1}, "4326": {"2": 2}, "anchored": {"0": 3}, "full": {"3": 2}, "are": {"1": 2}, "fullscreen": {"3": 1}, "canvas": {"1": 3, "4": 1, "7": 1}, "overlay": {"0": 1}, "demonstrates": {"0": 1}, "popup": {"0": 1}, "screen": {"3": 2}, "ol3": {"1": 1}, "html5": {"1": 1}, "tilejson": {"7": 2}, "by": {"4": 2}, "bingmaps": {"7": 1}, "getcapabilities": {"8": 3}, "of": {"2": 1, "3": 1, "5": 1, "6": 1, "8": 1, "9": 1, "10": 1}, "base": {"7": 1}, "origin": {"1": 2}, "and": {"9": 1, "4": 1, "7": 2}, "projection": {"9": 3}, "simple": {"5": 3}, "parsing": {"8": 2}, "tilelayer": {"9": 1, "10": 1, "3": 1}, "coordinates": {"1": 3}, "mapquest": {"0": 1, "3": 1}, "epsg4326": {"2": 1}, "epsg": {"9": 1, "2": 2}, "top": {"1": 1}, "two": {"9": 1, "4": 1, "7": 1}, "custom": {"9": 1}, "pixelmap": {"9": 1}, "that": {"1": 1}, "normalized": {"1": 1}, "with": {"1": 1, "9": 1, "7": 1}, "example": {"0": 1, "1": 1, "2": 2, "3": 2, "4": 1, "5": 2, "6": 2, "7": 1, "8": 2, "9": 2, "10": 2}, "openstreetmap": {"1": 1, "5": 1}, "layer": {"10": 1, "7": 2}, "share": {"4": 1}, "21781": {"9": 1}, "an": {"1": 1}, "in": {"2": 1}, "webgl": {"4": 1, "7": 1}, "parks": {"9": 1}, "1": {"9": 2}, "maps": {"4": 1, "7": 2}, "tile": {"1": 3, "10": 1, "3": 1, "6": 1, "9": 1}, "stamen": {"6": 3}, "map": {"2": 1, "3": 1, "5": 1}, "elements": {"0": 3}, "object": {"4": 1}, "generated": {"1": 1}, "000": {"9": 2}, "on": {"1": 1}, "response": {"8": 1}, "a": {"2": 1, "3": 1, "5": 1, "6": 1, "7": 2, "8": 1, "10": 1}, "center": {"4": 1}, "dom": {"4": 1, "7": 1}, "bing": {"7": 2}, "bottom": {"1": 1}, "client": {"1": 1}, "the": {"1": 3, "4": 2, "9": 1}, "resolution": {"4": 1}, "left": {"1": 2}}, "examples": [{"author": "Frederic Junod", "tags": "anchored elements, overlay, popup, mapquest, openaerial", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "anchored-elements.html", "shortdesc": "Demonstrates anchored elements.", "title": "Anchored elements example", "example": "anchored-elements.html"}, {"author": "Frederic Junod", "tags": "layers, openstreetmap, canvas", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "canvas-tiles.html", "shortdesc": "The black grid tiles are generated on the client with an HTML5 canvas. Note that the tile coordinates are ol3 normalized tile coordinates (origin bottom left), not OSM tile coordinates (origin top left).", "title": "Canvas tiles example", "example": "canvas-tiles.html"}, {"author": "Frederic Junod", "tags": "epsg4326", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "epsg-4326.html", "shortdesc": "Example of a map in EPSG:4326.", "title": "EPSG:4326 example", "example": "epsg-4326.html"}, {"author": "Frederic Junod", "tags": "fullscreen, mapquest, openaerial, tile, tilelayer", "modified": "2013-03-06T17:31:46+0100", "classes": [], "link": "full-screen.html", "shortdesc": "Example of a full-screen map.", "title": "Full-screen example", "example": "full-screen.html"}, {"author": "Frederic Junod", "tags": "side-by-side, canvas, webgl, dom, sync, object", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "side-by-side.html", "shortdesc": "The two maps share the same center, resolution, rotation and layers.", "title": "Side-by-side example", "example": "side-by-side.html"}, {"author": "Frederic Junod", "tags": "simple, openstreetmap", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "simple.html", "shortdesc": "Example of a simple map.", "title": "Simple example", "example": "simple.html"}, {"author": "Frederic Junod", "tags": "stamen, watercolor", "modified": "2013-03-06T17:07:47+0100", "classes": [], "link": "stamen.html", "shortdesc": "Example of a Stamen tile source.", "title": "Stamen example", "example": "stamen.html"}, {"author": "Frederic Junod", "tags": "layers, tilejson, bing, bingmaps", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "two-layers.html", "shortdesc": "Sync'ed DOM, WebGL and Canvas maps with a Bing Maps base layer and a semi-transparent TileJSON layer.", "title": "Two layers example", "example": "two-layers.html"}, {"author": "Frederic Junod", "tags": "wms, capabilities, getcapabilities", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "wms-capabilities.html", "shortdesc": "Example of parsing a WMS GetCapabilities response.", "title": "WMS GetCapabilities parsing example", "example": "wms-capabilities.html"}, {"author": "Frederic Junod", "tags": "wms, tile, tilelayer, projection", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "wms-custom-proj.html", "shortdesc": "Example of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.", "title": "Tiled WMS with custom projection example", "example": "wms-custom-proj.html"}, {"author": "Frederic Junod", "tags": "wms, tile, tilelayer", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "wms.html", "shortdesc": "Example of a tiled WMS layer.", "title": "Tiled WMS example", "example": "wms.html"}]}; \ No newline at end of file +var info={"index": {"composed": {"16": 1}, "code": {"11": 4}, "labels": {"16": 2}, "rotated": {"11": 1}, "jpeg": {"6": 3}, "openaerial": {"0": 1, "7": 1}, "osm": {"4": 1}, "parks": {"19": 1}, "alt": {"11": 1}, "layers": {"16": 2, "19": 1, "4": 1, "14": 1}, "1": {"19": 2}, "wms": {"18": 3, "19": 3, "20": 3, "21": 3}, "coordinates": {"4": 3}, "to": {"11": 1}, "only": {"8": 1, "3": 1}, "black": {"4": 1}, "saturation": {"8": 3}, "watercolor": {"16": 2}, "grid": {"4": 1}, "tiled": {"19": 2, "21": 2}, "not": {"4": 1}, "using": {"19": 1}, "rotation": {"11": 2, "14": 1}, "parsing": {"18": 2}, "transparent": {"13": 3}, "and": {"19": 1, "14": 1}, "rotate": {"11": 1}, "semi": {"13": 2}, "brightness": {"3": 3}, "side": {"14": 4}, "national": {"19": 1}, "terrain": {"16": 2}, "sync": {"14": 1}, "4326": {"5": 2}, "anchored": {"0": 3}, "full": {"7": 2}, "export": {"6": 2}, "are": {"16": 1, "4": 2}, "fullscreen": {"7": 1}, "canvas": {"4": 3, "14": 3}, "scale": {"12": 3}, "overlay": {"0": 1}, "demonstrates": {"0": 1}, "outside": {"10": 1}, "exporting": {"6": 1}, "contrast": {"3": 3}, "popup": {"0": 1}, "screen": {"7": 2}, "ol3": {"4": 1}, "html5": {"4": 1}, "tilejson": {"17": 3, "13": 1}, "by": {"14": 2}, "on": {"8": 1, "3": 1, "4": 1}, "shift": {"11": 1}, "generated": {"4": 1}, "base": {"16": 1}, "origin": {"4": 2}, "openstreetmap": {"4": 1, "6": 1, "10": 1, "11": 1, "12": 1, "15": 1}, "projection": {"19": 3}, "simple": {"15": 3}, "image": {"20": 3, "6": 1}, "one": {"14": 3}, "tilelayer": {"19": 1, "21": 1, "7": 1}, "capabilities": {"18": 1}, "mapquest": {"0": 1, "9": 3, "13": 1, "7": 1}, "epsg4326": {"5": 1}, "use": {"11": 1}, "source": {"16": 1}, "epsg": {"19": 1, "5": 2}, "top": {"4": 1}, "three": {"14": 1}, "custom": {"19": 1}, "pixelmap": {"19": 1}, "hue": {"8": 3}, "that": {"4": 1}, "normalized": {"4": 1}, "line": {"12": 3}, "with": {"16": 1, "19": 1, "4": 1, "13": 1}, "single": {"20": 2}, "of": {"2": 1, "3": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1, "11": 1, "12": 1, "13": 1, "15": 1, "16": 1, "17": 1, "18": 1, "19": 1, "20": 1, "21": 1}, "example": {"0": 1, "1": 2, "2": 2, "3": 2, "4": 1, "5": 2, "6": 2, "7": 2, "8": 2, "9": 2, "10": 2, "11": 2, "12": 2, "13": 2, "14": 1, "15": 2, "16": 2, "17": 2, "18": 2, "19": 2, "20": 2, "21": 2}, "control": {"8": 1, "10": 1, "3": 1}, "layer": {"2": 1, "13": 2, "16": 1, "17": 1, "20": 1, "21": 1}, "share": {"14": 1}, "tiles": {"4": 2}, "21781": {"19": 1}, "an": {"4": 1}, "as": {"6": 1}, "in": {"5": 1}, "getcapabilities": {"18": 3}, "mouse": {"10": 3}, "webgl": {"8": 2, "3": 2, "14": 2}, "same": {"14": 1}, "note": {"4": 1}, "maps": {"2": 3, "14": 1}, "animation": {"1": 2}, "tile": {"16": 1, "19": 1, "4": 3, "21": 1, "7": 1}, "stamen": {"16": 3}, "map": {"5": 1, "6": 1, "7": 1, "9": 1, "10": 1, "11": 2, "13": 1, "15": 1}, "elements": {"0": 3}, "object": {"14": 1}, "drag": {"11": 1}, "000": {"19": 2}, "two": {"16": 2, "19": 1}, "animations": {"1": 1}, "response": {"18": 1}, "a": {"2": 1, "5": 1, "6": 2, "7": 1, "9": 1, "10": 1, "11": 1, "12": 1, "13": 2, "15": 1, "16": 1, "17": 1, "18": 1, "20": 1, "21": 1}, "center": {"14": 1}, "dom": {"14": 2}, "bing": {"2": 4}, "bottom": {"4": 1}, "client": {"8": 1, "3": 1, "4": 1}, "position": {"10": 3}, "the": {"3": 1, "4": 3, "8": 1, "10": 1, "11": 1, "14": 2, "16": 2, "19": 1}, "resolution": {"14": 1}, "left": {"4": 2}}, "examples": [{"author": "Frederic Junod", "tags": "anchored elements, overlay, popup, mapquest, openaerial", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "anchored-elements.html", "shortdesc": "Demonstrates anchored elements.", "title": "Anchored elements example", "example": "anchored-elements.html"}, {"author": "Tom Payne", "tags": "animation", "modified": "2013-03-07T02:56:28+0100", "classes": [], "link": "animation.html", "shortdesc": "Example animations.", "title": "Animation example", "example": "animation.html"}, {"author": "Tom Payne", "tags": "bing, bing-maps", "modified": "2013-03-06T20:13:45+0100", "classes": [], "link": "bing-maps.html", "shortdesc": "Example of a Bing Maps layer.", "title": "Bing Maps example", "example": "bing-maps.html"}, {"author": "Tom Payne", "tags": "brightness, contrast, webgl", "modified": "2013-03-07T01:53:52+0100", "classes": [], "link": "brightness-contrast.html", "shortdesc": "Example of brightness/contrast control on the client (WebGL only).", "title": "Brightness/contrast example", "example": "brightness-contrast.html"}, {"author": "Frederic Junod", "tags": "layers, openstreetmap, canvas", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "canvas-tiles.html", "shortdesc": "The black grid tiles are generated on the client with an HTML5 canvas. Note that the tile coordinates are ol3 normalized tile coordinates (origin bottom left), not OSM tile coordinates (origin top left).", "title": "Canvas tiles example", "example": "canvas-tiles.html"}, {"author": "Frederic Junod", "tags": "epsg4326", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "epsg-4326.html", "shortdesc": "Example of a map in EPSG:4326.", "title": "EPSG:4326 example", "example": "epsg-4326.html"}, {"author": "Tom Payne", "tags": "export-jpeg, openstreetmap", "modified": "2013-03-06T21:28:59+0100", "classes": [], "link": "export-jpeg.html", "shortdesc": "Example of exporting a map as a JPEG image.", "title": "Export JPEG example", "example": "export-jpeg.html"}, {"author": "Frederic Junod", "tags": "fullscreen, mapquest, openaerial, tile, tilelayer", "modified": "2013-03-06T17:31:46+0100", "classes": [], "link": "full-screen.html", "shortdesc": "Example of a full-screen map.", "title": "Full-screen example", "example": "full-screen.html"}, {"author": "Tom Payne", "tags": "hue, saturation, webgl", "modified": "2013-03-07T01:42:14+0100", "classes": [], "link": "hue-saturation.html", "shortdesc": "Example of hue/saturation control on the client (WebGL only).", "title": "Hue/saturation example", "example": "hue-saturation.html"}, {"author": "Tom Payne", "tags": "mapquest", "modified": "2013-03-07T00:46:09+0100", "classes": [], "link": "mapquest.html", "shortdesc": "Example of a MapQuest map.", "title": "MapQuest example", "example": "mapquest.html"}, {"author": "Tom Payne", "tags": "mouse-position, openstreetmap", "modified": "2013-03-06T20:45:08+0100", "classes": [], "link": "mouse-position.html", "shortdesc": "Example of a mouse position control, outside the map.", "title": "Mouse position example", "example": "mouse-position.html"}, {"author": "Tom Payne", "tags": "rotation, openstreetmap", "modified": "2013-03-09T21:48:33+0100", "classes": [], "link": "rotation.html", "shortdesc": "Example of a rotated map. Use Alt+Shift+drag to rotate the map.", "title": "Rotation example", "example": "rotation.html"}, {"author": "Tom Payne", "tags": "scale-line, openstreetmap", "modified": "2013-03-06T20:34:47+0100", "classes": [], "link": "scale-line.html", "shortdesc": "Example of a scale line.", "title": "Scale line example", "example": "scale-line.html"}, {"author": "Tom Payne", "tags": "transparent, mapquest, tilejson", "modified": "2013-03-09T17:18:41+0100", "classes": [], "link": "semi-transparent-layer.html", "shortdesc": "Example of a map with a semi-transparent layer.", "title": "Semi-transparent layer example", "example": "semi-transparent-layer.html"}, {"author": "Tom Payne", "tags": "side-by-side, canvas, webgl, dom, canvas, sync, object", "modified": "2013-03-07T03:15:19+0100", "classes": [], "link": "side-by-side.html", "shortdesc": "The three maps, one WebGL, one Canvas, one DOM, share the same center, resolution, rotation and layers.", "title": "Side-by-side example", "example": "side-by-side.html"}, {"author": "Frederic Junod", "tags": "simple, openstreetmap", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "simple.html", "shortdesc": "Example of a simple map.", "title": "Simple example", "example": "simple.html"}, {"author": "Tom Payne", "tags": "stamen, watercolor, terrain-labels, two-layers", "modified": "2013-03-06T21:08:06+0100", "classes": [], "link": "stamen.html", "shortdesc": "Example of a Stamen tile source. Two layers are composed: the watercolor base layer with the terrain labels.", "title": "Stamen example", "example": "stamen.html"}, {"author": "Tom Payne", "tags": "tilejson", "modified": "2013-03-06T20:21:07+0100", "classes": [], "link": "tilejson.html", "shortdesc": "Example of a TileJSON layer.", "title": "TileJSON example", "example": "tilejson.html"}, {"author": "Frederic Junod", "tags": "wms, capabilities, getcapabilities", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "wms-capabilities.html", "shortdesc": "Example of parsing a WMS GetCapabilities response.", "title": "WMS GetCapabilities parsing example", "example": "wms-capabilities.html"}, {"author": "Frederic Junod", "tags": "wms, tile, tilelayer, projection", "modified": "2013-03-06T15:12:01+0100", "classes": [], "link": "wms-custom-proj.html", "shortdesc": "Example of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.", "title": "Tiled WMS with custom projection example", "example": "wms-custom-proj.html"}, {"author": "\u00c9ric Lemoine", "tags": "wms, image", "modified": "2013-03-07T12:29:13+0100", "classes": [], "link": "wms-single-image.html", "shortdesc": "Example of a single image WMS layer.", "title": "Single image WMS example", "example": "wms-single-image.html"}, {"author": "\u00c9ric Lemoine", "tags": "wms, tile, tilelayer", "modified": "2013-03-07T11:59:09+0100", "classes": [], "link": "wms-tiled.html", "shortdesc": "Example of a tiled WMS layer.", "title": "Tiled WMS example", "example": "wms-tiled.html"}]}; \ No newline at end of file diff --git a/master/examples/example-list.xml b/master/examples/example-list.xml index 49b65ebbf0..8e1a123e30 100644 --- a/master/examples/example-list.xml +++ b/master/examples/example-list.xml @@ -1 +1 @@ -OpenLayers Exampleshttp://openlayers.github.com/ol3/master/examples/example-list.xml#2013-03-06T05:04:11Z2013-03-06T05:04:11ZFull-screen examplefullscreen, mapquest, openaerial, tile, tilelayerExample of a full-screen map.2013-03-06T17:31:46+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/full-screen.html#2013-03-06T17:31:46+0100Stamen examplestamen, watercolorExample of a Stamen tile source.2013-03-06T17:07:47+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/stamen.html#2013-03-06T17:07:47+0100Anchored elements exampleanchored elements, overlay, popup, mapquest, openaerialDemonstrates anchored elements.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/anchored-elements.html#2013-03-06T15:12:01+0100Canvas tiles examplelayers, openstreetmap, canvasThe black grid tiles are generated on the client with an HTML5 canvas. Note that the tile coordinates are ol3 normalized tile coordinates (origin bottom left), not OSM tile coordinates (origin top left).2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/canvas-tiles.html#2013-03-06T15:12:01+0100EPSG:4326 exampleepsg4326Example of a map in EPSG:4326.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/epsg-4326.html#2013-03-06T15:12:01+0100Side-by-side exampleside-by-side, canvas, webgl, dom, sync, objectThe two maps share the same center, resolution, rotation and layers.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/side-by-side.html#2013-03-06T15:12:01+0100Simple examplesimple, openstreetmapExample of a simple map.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/simple.html#2013-03-06T15:12:01+0100Two layers examplelayers, tilejson, bing, bingmapsSync'ed DOM, WebGL and Canvas maps with a Bing Maps base layer and a semi-transparent TileJSON layer.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/two-layers.html#2013-03-06T15:12:01+0100WMS GetCapabilities parsing examplewms, capabilities, getcapabilitiesExample of parsing a WMS GetCapabilities response.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/wms-capabilities.html#2013-03-06T15:12:01+0100Tiled WMS with custom projection examplewms, tile, tilelayer, projectionExample of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/wms-custom-proj.html#2013-03-06T15:12:01+0100Tiled WMS examplewms, tile, tilelayerExample of a tiled WMS layer.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/wms.html#2013-03-06T15:12:01+0100 \ No newline at end of file +OpenLayers Exampleshttp://openlayers.github.com/ol3/master/examples/example-list.xml#2013-03-11T12:33:00Z2013-03-11T12:33:00ZRotation examplerotation, openstreetmapExample of a rotated map. Use <code>Alt</code>+<code>Shift</code>+drag to rotate the map.2013-03-09T21:48:33+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/rotation.html#2013-03-09T21:48:33+0100Semi-transparent layer exampletransparent, mapquest, tilejsonExample of a map with a semi-transparent layer.2013-03-09T17:18:41+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/semi-transparent-layer.html#2013-03-09T17:18:41+0100Single image WMS examplewms, imageExample of a single image WMS layer.2013-03-07T12:29:13+0100Éric Lemoinehttp://openlayers.github.com/ol3/master/examples/wms-single-image.html#2013-03-07T12:29:13+0100Tiled WMS examplewms, tile, tilelayerExample of a tiled WMS layer.2013-03-07T11:59:09+0100Éric Lemoinehttp://openlayers.github.com/ol3/master/examples/wms-tiled.html#2013-03-07T11:59:09+0100Side-by-side exampleside-by-side, canvas, webgl, dom, canvas, sync, objectThe three maps, one WebGL, one Canvas, one DOM, share the same center, resolution, rotation and layers.2013-03-07T03:15:19+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/side-by-side.html#2013-03-07T03:15:19+0100Animation exampleanimationExample animations.2013-03-07T02:56:28+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/animation.html#2013-03-07T02:56:28+0100Brightness/contrast examplebrightness, contrast, webglExample of brightness/contrast control on the client (WebGL only).2013-03-07T01:53:52+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/brightness-contrast.html#2013-03-07T01:53:52+0100Hue/saturation examplehue, saturation, webglExample of hue/saturation control on the client (WebGL only).2013-03-07T01:42:14+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/hue-saturation.html#2013-03-07T01:42:14+0100MapQuest examplemapquestExample of a MapQuest map.2013-03-07T00:46:09+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/mapquest.html#2013-03-07T00:46:09+0100Export JPEG exampleexport-jpeg, openstreetmapExample of exporting a map as a JPEG image.2013-03-06T21:28:59+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/export-jpeg.html#2013-03-06T21:28:59+0100Stamen examplestamen, watercolor, terrain-labels, two-layersExample of a Stamen tile source. Two layers are composed: the watercolor base layer with the terrain labels.2013-03-06T21:08:06+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/stamen.html#2013-03-06T21:08:06+0100Mouse position examplemouse-position, openstreetmapExample of a mouse position control, outside the map.2013-03-06T20:45:08+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/mouse-position.html#2013-03-06T20:45:08+0100Scale line examplescale-line, openstreetmapExample of a scale line.2013-03-06T20:34:47+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/scale-line.html#2013-03-06T20:34:47+0100TileJSON exampletilejsonExample of a TileJSON layer.2013-03-06T20:21:07+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/tilejson.html#2013-03-06T20:21:07+0100Bing Maps examplebing, bing-mapsExample of a Bing Maps layer.2013-03-06T20:13:45+0100Tom Paynehttp://openlayers.github.com/ol3/master/examples/bing-maps.html#2013-03-06T20:13:45+0100Full-screen examplefullscreen, mapquest, openaerial, tile, tilelayerExample of a full-screen map.2013-03-06T17:31:46+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/full-screen.html#2013-03-06T17:31:46+0100Anchored elements exampleanchored elements, overlay, popup, mapquest, openaerialDemonstrates anchored elements.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/anchored-elements.html#2013-03-06T15:12:01+0100Canvas tiles examplelayers, openstreetmap, canvasThe black grid tiles are generated on the client with an HTML5 canvas. Note that the tile coordinates are ol3 normalized tile coordinates (origin bottom left), not OSM tile coordinates (origin top left).2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/canvas-tiles.html#2013-03-06T15:12:01+0100EPSG:4326 exampleepsg4326Example of a map in EPSG:4326.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/epsg-4326.html#2013-03-06T15:12:01+0100Simple examplesimple, openstreetmapExample of a simple map.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/simple.html#2013-03-06T15:12:01+0100WMS GetCapabilities parsing examplewms, capabilities, getcapabilitiesExample of parsing a WMS GetCapabilities response.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/wms-capabilities.html#2013-03-06T15:12:01+0100Tiled WMS with custom projection examplewms, tile, tilelayer, projectionExample of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.2013-03-06T15:12:01+0100Frederic Junodhttp://openlayers.github.com/ol3/master/examples/wms-custom-proj.html#2013-03-06T15:12:01+0100 \ No newline at end of file diff --git a/master/examples/export-jpeg-require.js b/master/examples/export-jpeg-require.js new file mode 100644 index 0000000000..cf2799bfd9 --- /dev/null +++ b/master/examples/export-jpeg-require.js @@ -0,0 +1,6 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.OpenStreetMap'); diff --git a/master/examples/export-jpeg.html b/master/examples/export-jpeg.html new file mode 100644 index 0000000000..cd7b4a4ec3 --- /dev/null +++ b/master/examples/export-jpeg.html @@ -0,0 +1,53 @@ + + + + + + + + + + Export JPEG example + + + + + +
+ +
+ +
+ +
+ +
+

Export JPEG example

+

Example of exporting a map as a JPEG image.

+
+

See the export-jpeg.js source to see how this is done.

+
+
export-jpeg, openstreetmap
+
+ +
+ +
+ + + + + diff --git a/master/examples/export-jpeg.js b/master/examples/export-jpeg.js new file mode 100644 index 0000000000..3b69a5f4e2 --- /dev/null +++ b/master/examples/export-jpeg.js @@ -0,0 +1,18 @@ +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.OpenStreetMap() + }) + ], + renderer: ol.RendererHint.CANVAS, + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 2 + }) +}); + +var exportJPEGElement = document.getElementById('export-jpeg'); +exportJPEGElement.addEventListener('click', function(e) { + e.target.href = map.getRenderer().getCanvas().toDataURL('image/jpeg'); +}, false); diff --git a/master/examples/full-screen-require.js b/master/examples/full-screen-require.js new file mode 100644 index 0000000000..04ee3aa6fc --- /dev/null +++ b/master/examples/full-screen-require.js @@ -0,0 +1,7 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.control.defaults'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.MapQuestOpenAerial'); diff --git a/master/examples/full-screen.js b/master/examples/full-screen.js index df668a44e4..7c08421637 100644 --- a/master/examples/full-screen.js +++ b/master/examples/full-screen.js @@ -1,21 +1,8 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHints'); -goog.require('ol.View2D'); -goog.require('ol.control.defaults'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.source.MapQuestOpenAerial'); - - var layer = new ol.layer.TileLayer({ source: new ol.source.MapQuestOpenAerial() }); var map = new ol.Map({ - controls: ol.control.defaults({ - scaleLine: true - }), - layers: new ol.Collection([layer]), + layers: [layer], renderers: ol.RendererHints.createFromQueryData(), target: 'map', view: new ol.View2D({ diff --git a/master/examples/hue-saturation-require.js b/master/examples/hue-saturation-require.js new file mode 100644 index 0000000000..7ee06b674f --- /dev/null +++ b/master/examples/hue-saturation-require.js @@ -0,0 +1,7 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.BingMaps'); diff --git a/master/examples/hue-saturation.html b/master/examples/hue-saturation.html new file mode 100644 index 0000000000..daf15a3013 --- /dev/null +++ b/master/examples/hue-saturation.html @@ -0,0 +1,62 @@ + + + + + + + + + + Hue/saturation example + + + + + +
+ +
+
+
+
+ + + +
+
+ + + +
+
+
+ +
+ +
+

Hue/saturation example

+

Example of hue/saturation control on the client (WebGL only).

+
+

See the hue-saturation.js source to see how this is done.

+
+
hue, saturation, webgl
+
+ +
+ +
+ + + + + diff --git a/master/examples/hue-saturation.js b/master/examples/hue-saturation.js new file mode 100644 index 0000000000..48dc84edef --- /dev/null +++ b/master/examples/hue-saturation.js @@ -0,0 +1,43 @@ +var layer = new ol.layer.TileLayer({ + source: new ol.source.BingMaps({ + key: 'AgtFlPYDnymLEe9zJ5PCkghbNiFZE9aAtTy3mPaEnEBXqLHtFuTcKoZ-miMC3w7R', + style: 'Aerial' + }) +}); + +var map = new ol.Map({ + layers: [layer], + renderer: ol.RendererHint.WEBGL, + target: 'map', + view: new ol.View2D({ + center: ol.projection.transform( + new ol.Coordinate(-9.375, 51.483333), 'EPSG:4326', 'EPSG:3857'), + zoom: 15 + }) +}); + +var increaseHue = document.getElementById('increase-hue'); +increaseHue.addEventListener('click', function() { + layer.setHue(layer.getHue() + 0.25); +}, false); +var resetHue = document.getElementById('reset-hue'); +resetHue.addEventListener('click', function() { + layer.setHue(0); +}, false); +var decreaseHue = document.getElementById('decrease-hue'); +decreaseHue.addEventListener('click', function() { + layer.setHue(layer.getHue() - 0.25); +}, false); + +var increaseSaturation = document.getElementById('increase-saturation'); +increaseSaturation.addEventListener('click', function() { + layer.setSaturation(layer.getSaturation() + 0.25); +}, false); +var resetSaturation = document.getElementById('reset-saturation'); +resetSaturation.addEventListener('click', function() { + layer.setSaturation(1); +}, false); +var decreaseSaturation = document.getElementById('decrease-saturation'); +decreaseSaturation.addEventListener('click', function() { + layer.setSaturation(layer.getSaturation() - 0.25); +}, false); diff --git a/master/examples/index.html b/master/examples/index.html index a466bec866..6c34d08113 100644 --- a/master/examples/index.html +++ b/master/examples/index.html @@ -167,7 +167,7 @@ }; - Simple example + OpenLayers 3 Examples diff --git a/master/examples/jquery.min.js b/master/examples/jquery.min.js new file mode 100644 index 0000000000..16ad06c5ac --- /dev/null +++ b/master/examples/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.2 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"":"")+""),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;e=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="
"+""+"
",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="
t
",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="
",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( +a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&j.push({elem:this,matches:d.slice(e)});for(k=0;k0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f +.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(;d1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===""&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/master/examples/loader.js b/master/examples/loader.js index 92cefa8e76..19c5d2ae04 100644 --- a/master/examples/loader.js +++ b/master/examples/loader.js @@ -1,17 +1,15 @@ /** - * * Loader to add ol.css, ol.js and the example-specific js file to the * documents. * * This loader is used for the hosted examples. It is used in place of the * development loader (examples/loader.js). * - * ol.css, ol.js, ol-simple.js, and ol-whitespace.js are built with - * Plovr/Closure. `build.py build` builds them. They are located in the - * ../build/ directory, relatively to this script. + * ol.css, ol.js, ol-simple.js, ol-whitespace.js, and ol-deps.js are built + * by OL3's build.py script. They are located in the ../build/ directory, + * relatively to this script. * - * The script should be named loader.js. So it needs to be renamed to - * loader.js from loader_hosted_examples.js. + * The script must be named loader.js. * * Usage: * @@ -59,17 +57,23 @@ var oljs = 'ol.js', mode; if ('mode' in pageParams) { mode = pageParams.mode.toLowerCase(); - if (mode != 'advanced') { + if (mode == 'debug') { + mode = 'raw'; + } + if (mode != 'advanced' && mode != 'raw') { oljs = 'ol-' + mode + '.js'; } } - document.write(''); - document.write('' + - ''); - document.write('' + - ''); + var scriptId = encodeURIComponent(scriptParams.id); + document.write(''); + if (mode != 'raw') { + document.write(''); + } else { + window.CLOSURE_NO_DEPS = true; // we've got our own deps file + document.write(''); + document.write(''); + document.write(''); + } + document.write(''); }()); diff --git a/master/examples/mapquest-require.js b/master/examples/mapquest-require.js new file mode 100644 index 0000000000..f071a3d10b --- /dev/null +++ b/master/examples/mapquest-require.js @@ -0,0 +1,7 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.MapQuestOSM'); diff --git a/master/examples/mapquest.html b/master/examples/mapquest.html new file mode 100644 index 0000000000..abc7b5057b --- /dev/null +++ b/master/examples/mapquest.html @@ -0,0 +1,52 @@ + + + + + + + + + + MapQuest example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

MapQuest example

+

Example of a MapQuest map.

+
+

See the mapquest.js source to see how this is done.

+
+
mapquest
+
+ +
+ +
+ + + + + diff --git a/master/examples/mapquest.js b/master/examples/mapquest.js new file mode 100644 index 0000000000..21ca6852dd --- /dev/null +++ b/master/examples/mapquest.js @@ -0,0 +1,14 @@ +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.MapQuestOSM() + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: ol.projection.transform( + new ol.Coordinate(139.6917, 35.689506), 'EPSG:4326', 'EPSG:3857'), + zoom: 9 + }) +}); diff --git a/master/examples/mouse-position-require.js b/master/examples/mouse-position-require.js new file mode 100644 index 0000000000..52f645eee6 --- /dev/null +++ b/master/examples/mouse-position-require.js @@ -0,0 +1,9 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.control.MousePosition'); +goog.require('ol.control.defaults'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.OpenStreetMap'); diff --git a/master/examples/mouse-position.html b/master/examples/mouse-position.html new file mode 100644 index 0000000000..9412d00c99 --- /dev/null +++ b/master/examples/mouse-position.html @@ -0,0 +1,53 @@ + + + + + + + + + + Mouse position example + + + + + +
+ +
+
+
+ +
+
+ +
+ +
+

Mouse position example

+

Example of a mouse position control, outside the map.

+
+

See the mouse-position.js source to see how this is done.

+
+
mouse-position, openstreetmap
+
+ +
+ +
+ + + + + diff --git a/master/examples/mouse-position.js b/master/examples/mouse-position.js new file mode 100644 index 0000000000..86dffb6f7f --- /dev/null +++ b/master/examples/mouse-position.js @@ -0,0 +1,21 @@ +var map = new ol.Map({ + controls: ol.control.defaults({}, [ + new ol.control.MousePosition({ + coordinateFormat: ol.Coordinate.toStringHDMS, + projection: 'EPSG:4326', + target: document.getElementById('mouse-position'), + undefinedHTML: ' ' + }) + ]), + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.OpenStreetMap() + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 2 + }) +}); diff --git a/master/examples/rotation-require.js b/master/examples/rotation-require.js new file mode 100644 index 0000000000..371bc68d69 --- /dev/null +++ b/master/examples/rotation-require.js @@ -0,0 +1,6 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.OpenStreetMap'); diff --git a/master/examples/rotation.html b/master/examples/rotation.html new file mode 100644 index 0000000000..004b0d3045 --- /dev/null +++ b/master/examples/rotation.html @@ -0,0 +1,52 @@ + + + + + + + + + + Rotation example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Rotation example

+

Example of a rotated map. Use Alt+Shift+drag to rotate the map.

+
+

See the rotation.js source to see how this is done.

+
+
rotation, openstreetmap
+
+ +
+ +
+ + + + + diff --git a/master/examples/rotation.js b/master/examples/rotation.js new file mode 100644 index 0000000000..bae7197ee5 --- /dev/null +++ b/master/examples/rotation.js @@ -0,0 +1,14 @@ +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.OpenStreetMap() + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(-25860000, 4130000), + rotation: Math.PI / 6, + zoom: 10 + }) +}); diff --git a/master/examples/scale-line-require.js b/master/examples/scale-line-require.js new file mode 100644 index 0000000000..d8e2509601 --- /dev/null +++ b/master/examples/scale-line-require.js @@ -0,0 +1,9 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.control.ScaleLine'); +goog.require('ol.control.ScaleLineUnits'); +goog.require('ol.control.defaults'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.OpenStreetMap'); diff --git a/master/examples/two-layers.html b/master/examples/scale-line.html similarity index 57% rename from master/examples/two-layers.html rename to master/examples/scale-line.html index 7e0e68044f..54d9d6cd42 100644 --- a/master/examples/two-layers.html +++ b/master/examples/scale-line.html @@ -7,7 +7,7 @@ - Two layers example + Scale line example @@ -26,37 +26,27 @@
-
-

Canvas

-
- export map as jpeg -
-
-

WebGL

-
-
-
-

DOM

-
+
+
-

Two layers example

-

Sync'ed DOM, WebGL and Canvas maps with a Bing Maps base layer and a semi-transparent TileJSON layer.

+

Scale line example

+

Example of a scale line.

-

See the two-layers.js source to see how this is done.

+

See the scale-line.js source to see how this is done.

-
layers, tilejson, bing, bingmaps
+
scale-line, openstreetmap
- + diff --git a/master/examples/scale-line.js b/master/examples/scale-line.js new file mode 100644 index 0000000000..9c3d483f39 --- /dev/null +++ b/master/examples/scale-line.js @@ -0,0 +1,18 @@ +var map = new ol.Map({ + controls: ol.control.defaults({}, [ + new ol.control.ScaleLine({ + units: ol.control.ScaleLineUnits.IMPERIAL + }) + ]), + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.OpenStreetMap() + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 2 + }) +}); diff --git a/master/examples/semi-transparent-layer-require.js b/master/examples/semi-transparent-layer-require.js new file mode 100644 index 0000000000..16f0d3a25d --- /dev/null +++ b/master/examples/semi-transparent-layer-require.js @@ -0,0 +1,8 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.MapQuestOpenAerial'); +goog.require('ol.source.TileJSON'); diff --git a/master/examples/semi-transparent-layer.html b/master/examples/semi-transparent-layer.html new file mode 100644 index 0000000000..a70a848f59 --- /dev/null +++ b/master/examples/semi-transparent-layer.html @@ -0,0 +1,52 @@ + + + + + + + + + + Semi-transparent layer example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Semi-transparent layer example

+

Example of a map with a semi-transparent layer.

+
+

See the semi-transparent-layer.js source to see how this is done.

+
+
transparent, mapquest, tilejson
+
+ +
+ +
+ + + + + diff --git a/master/examples/semi-transparent-layer.js b/master/examples/semi-transparent-layer.js new file mode 100644 index 0000000000..226f67f2b7 --- /dev/null +++ b/master/examples/semi-transparent-layer.js @@ -0,0 +1,19 @@ +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.MapQuestOpenAerial() + }), + new ol.layer.TileLayer({ + source: new ol.source.TileJSON({ + uri: 'http://api.tiles.mapbox.com/v3/mapbox.va-quake-aug.jsonp' + }) + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: ol.projection.transform( + new ol.Coordinate(-77.93255, 37.9555), 'EPSG:4326', 'EPSG:3857'), + zoom: 5 + }) +}); diff --git a/master/examples/side-by-side-require.js b/master/examples/side-by-side-require.js new file mode 100644 index 0000000000..aaede8a080 --- /dev/null +++ b/master/examples/side-by-side-require.js @@ -0,0 +1,11 @@ +goog.require('ol.Collection'); +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.animation'); +goog.require('ol.easing'); +goog.require('ol.interaction.Keyboard'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.MapQuestOpenAerial'); diff --git a/master/examples/side-by-side.html b/master/examples/side-by-side.html index 869eac70d0..c7544898ae 100644 --- a/master/examples/side-by-side.html +++ b/master/examples/side-by-side.html @@ -29,17 +29,14 @@

Canvas

-

WebGL

-

DOM

-
@@ -47,11 +44,11 @@

Side-by-side example

-

The two maps share the same center, resolution, rotation and layers.

+

The three maps, one WebGL, one Canvas, one DOM, share the same center, resolution, rotation and layers.

See the side-by-side.js source to see how this is done.

-
side-by-side, canvas, webgl, dom, sync, object
+
side-by-side, canvas, webgl, dom, canvas, sync, object
@@ -61,18 +58,10 @@
drag, arrow keys
Zoom
double-click, Shift+double-click, mouse wheel, +/- keys; Shift+drag
-
Rotate
-
Alt+Shift+drag, r to reset
-
Brightness/contrast
-
b/B/c/C keys (WebGL only)
-
Hue/saturation
-
h/H/s/S keys (WebGL only)
Opacity
o/O keys
Visibility
v/V keys
-
Animations
-
j/l/m/x/L/M/X keys
Reset
0 key
diff --git a/master/examples/side-by-side.js b/master/examples/side-by-side.js index 983c8e1528..fc5d8f9f7a 100644 --- a/master/examples/side-by-side.js +++ b/master/examples/side-by-side.js @@ -1,21 +1,6 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHint'); -goog.require('ol.View2D'); -goog.require('ol.animation'); -goog.require('ol.control.MousePosition'); -goog.require('ol.control.defaults'); -goog.require('ol.easing'); -goog.require('ol.interaction.Keyboard'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.projection'); -goog.require('ol.source.MapQuestOpenAerial'); - - -var LONDON = ol.projection.transformWithCodes( +var LONDON = ol.projection.transform( new ol.Coordinate(-0.12755, 51.507222), 'EPSG:4326', 'EPSG:3857'); -var MOSCOW = ol.projection.transformWithCodes( +var MOSCOW = ol.projection.transform( new ol.Coordinate(37.6178, 55.7517), 'EPSG:4326', 'EPSG:3857'); var layer = new ol.layer.TileLayer({ @@ -27,28 +12,14 @@ var view = new ol.View2D({ zoom: 1 }); -var domMousePosition = new ol.control.MousePosition({ - coordinateFormat: ol.Coordinate.toStringHDMS, - projection: ol.projection.getFromCode('EPSG:4326'), - target: document.getElementById('domMousePosition'), - undefinedHTML: ' ' -}); var domMap = new ol.Map({ - controls: ol.control.defaults({}, [domMousePosition]), layers: new ol.Collection([layer]), renderer: ol.RendererHint.DOM, target: 'domMap', view: view }); -var webglMousePosition = new ol.control.MousePosition({ - coordinateFormat: ol.Coordinate.toStringHDMS, - projection: ol.projection.getFromCode('EPSG:4326'), - target: document.getElementById('webglMousePosition'), - undefinedHTML: ' ' -}); var webglMap = new ol.Map({ - controls: ol.control.defaults({}, [webglMousePosition]), renderer: ol.RendererHint.WEBGL, target: 'webglMap' }); @@ -58,14 +29,7 @@ if (webglMap !== null) { } -var canvasMousePosition = new ol.control.MousePosition({ - coordinateFormat: ol.Coordinate.toStringHDMS, - projection: ol.projection.getFromCode('EPSG:4326'), - target: document.getElementById('canvasMousePosition'), - undefinedHtml: ' ' -}); var canvasMap = new ol.Map({ - controls: ol.control.defaults({}, [canvasMousePosition]), renderer: ol.RendererHint.CANVAS, target: 'canvasMap' }); @@ -76,144 +40,19 @@ if (canvasMap !== null) { var keyboardInteraction = new ol.interaction.Keyboard(); keyboardInteraction.addCallback('0', function() { - layer.setBrightness(0); - layer.setContrast(1); - layer.setHue(0); - layer.setSaturation(1); layer.setOpacity(1); layer.setVisible(true); }); -keyboardInteraction.addCallback('b', function() { - layer.setBrightness(layer.getBrightness() - 0.1); -}); -keyboardInteraction.addCallback('B', function() { - layer.setBrightness(layer.getBrightness() + 0.1); -}); -keyboardInteraction.addCallback('c', function() { - layer.setContrast(layer.getContrast() - 0.1); -}); -keyboardInteraction.addCallback('C', function() { - // contrast is unbounded, but for this example we clamp to 3 - layer.setContrast(Math.min(3, layer.getContrast() + 0.1)); -}); -keyboardInteraction.addCallback('h', function() { - layer.setHue(layer.getHue() - (Math.PI / 5)); -}); -keyboardInteraction.addCallback('H', function() { - layer.setHue(layer.getHue() + (Math.PI / 5)); -}); -keyboardInteraction.addCallback('j', function() { - var bounce = ol.animation.bounce({ - resolution: 2 * view.getResolution() - }); - domMap.addPreRenderFunction(bounce); - webglMap.addPreRenderFunction(bounce); - canvasMap.addPreRenderFunction(bounce); -}); -keyboardInteraction.addCallback('l', function() { - var pan = ol.animation.pan({ - source: view.getCenter(), - easing: ol.easing.elastic - }); - domMap.addPreRenderFunction(pan); - webglMap.addPreRenderFunction(pan); - canvasMap.addPreRenderFunction(pan); - view.setCenter(LONDON); -}); -keyboardInteraction.addCallback('L', function() { - var start = +new Date(); - var duration = 5000; - var bounce = ol.animation.bounce({ - resolution: 2 * view.getResolution(), - start: start, - duration: duration - }); - var pan = ol.animation.pan({ - source: view.getCenter(), - start: start, - duration: duration - }); - var rotate = ol.animation.rotate({ - rotation: 4 * Math.PI, - start: start, - duration: duration - }); - var preRenderFunctions = [bounce, pan, rotate]; - domMap.addPreRenderFunctions(preRenderFunctions); - webglMap.addPreRenderFunctions(preRenderFunctions); - canvasMap.addPreRenderFunctions(preRenderFunctions); - view.setCenter(LONDON); -}); -keyboardInteraction.addCallback('m', function() { - var pan = ol.animation.pan({ - source: view.getCenter(), - duration: 1000, - easing: ol.easing.bounce - }); - domMap.addPreRenderFunction(pan); - webglMap.addPreRenderFunction(pan); - canvasMap.addPreRenderFunction(pan); - view.setCenter(MOSCOW); -}); -keyboardInteraction.addCallback('M', function() { - var start = +new Date(); - var duration = 5000; - var bounce = ol.animation.bounce({ - resolution: 2 * view.getResolution(), - start: start, - duration: duration - }); - var pan = ol.animation.pan({ - source: view.getCenter(), - start: start, - duration: duration - }); - var rotate = ol.animation.rotate({ - rotation: -4 * Math.PI, - start: start, - duration: duration - }); - var preRenderFunctions = [bounce, pan, rotate]; - domMap.addPreRenderFunctions(preRenderFunctions); - webglMap.addPreRenderFunctions(preRenderFunctions); - canvasMap.addPreRenderFunctions(preRenderFunctions); - view.setCenter(MOSCOW); -}); keyboardInteraction.addCallback('o', function() { - layer.setOpacity(layer.getOpacity() - 0.1); + layer.setOpacity(layer.getOpacity() - 0.125); }); keyboardInteraction.addCallback('O', function() { - layer.setOpacity(layer.getOpacity() + 0.1); + layer.setOpacity(layer.getOpacity() + 0.125); }); keyboardInteraction.addCallback('r', function() { view.setRotation(0); }); -keyboardInteraction.addCallback('s', function() { - layer.setSaturation(layer.getSaturation() - 0.1); -}); -keyboardInteraction.addCallback('S', function() { - // saturation is unbounded, but for this example we clamp to 3 - layer.setSaturation(Math.min(3, layer.getSaturation() + 0.1)); -}); keyboardInteraction.addCallback('vV', function() { layer.setVisible(!layer.getVisible()); }); -keyboardInteraction.addCallback('x', function() { - var rotate = ol.animation.rotate({ - rotation: 4 * Math.PI, - duration: 2000 - }); - domMap.addPreRenderFunction(rotate); - webglMap.addPreRenderFunction(rotate); - canvasMap.addPreRenderFunction(rotate); -}); -keyboardInteraction.addCallback('X', function() { - var rotate = ol.animation.rotate({ - rotation: -4 * Math.PI, - duration: 2000 - }); - domMap.addPreRenderFunction(rotate); - webglMap.addPreRenderFunction(rotate); - canvasMap.addPreRenderFunction(rotate); -}); domMap.getInteractions().push(keyboardInteraction); diff --git a/master/examples/simple-require.js b/master/examples/simple-require.js new file mode 100644 index 0000000000..371bc68d69 --- /dev/null +++ b/master/examples/simple-require.js @@ -0,0 +1,6 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.OpenStreetMap'); diff --git a/master/examples/simple.js b/master/examples/simple.js index f71042eeb0..5cb998b4e4 100644 --- a/master/examples/simple.js +++ b/master/examples/simple.js @@ -1,18 +1,9 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHints'); -goog.require('ol.View2D'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.source.OpenStreetMap'); - - var map = new ol.Map({ - layers: new ol.Collection([ + layers: [ new ol.layer.TileLayer({ source: new ol.source.OpenStreetMap() }) - ]), + ], renderers: ol.RendererHints.createFromQueryData(), target: 'map', view: new ol.View2D({ diff --git a/master/examples/stamen-require.js b/master/examples/stamen-require.js new file mode 100644 index 0000000000..bbbac08e62 --- /dev/null +++ b/master/examples/stamen-require.js @@ -0,0 +1,7 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.Stamen'); diff --git a/master/examples/stamen.html b/master/examples/stamen.html index 811d378633..930c971209 100644 --- a/master/examples/stamen.html +++ b/master/examples/stamen.html @@ -35,11 +35,11 @@

Stamen example

-

Example of a Stamen tile source.

+

Example of a Stamen tile source. Two layers are composed: the watercolor base layer with the terrain labels.

See the stamen.js source to see how this is done.

-
stamen, watercolor
+
stamen, watercolor, terrain-labels, two-layers
diff --git a/master/examples/stamen.js b/master/examples/stamen.js index 233c04cdb8..df50b064e7 100644 --- a/master/examples/stamen.js +++ b/master/examples/stamen.js @@ -1,30 +1,21 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHints'); -goog.require('ol.View2D'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.source.Stamen'); - - -var layers = new ol.Collection([ - new ol.layer.TileLayer({ - source: new ol.source.Stamen({ - layer: 'watercolor' - }) - }), - new ol.layer.TileLayer({ - source: new ol.source.Stamen({ - layer: 'terrain-labels' - }) - }) -]); var map = new ol.Map({ - layers: layers, + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.Stamen({ + layer: 'watercolor' + }) + }), + new ol.layer.TileLayer({ + source: new ol.source.Stamen({ + layer: 'terrain-labels' + }) + }) + ], renderers: ol.RendererHints.createFromQueryData(), target: 'map', view: new ol.View2D({ - center: new ol.Coordinate(0, 0), - zoom: 3 + center: ol.projection.transform( + new ol.Coordinate(-122.416667, 37.783333), 'EPSG:4326', 'EPSG:3857'), + zoom: 12 }) }); diff --git a/master/examples/tilejson-require.js b/master/examples/tilejson-require.js new file mode 100644 index 0000000000..22b6d6a1d7 --- /dev/null +++ b/master/examples/tilejson-require.js @@ -0,0 +1,6 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.TileJSON'); diff --git a/master/examples/tilejson.html b/master/examples/tilejson.html new file mode 100644 index 0000000000..4e05014695 --- /dev/null +++ b/master/examples/tilejson.html @@ -0,0 +1,52 @@ + + + + + + + + + + TileJSON example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

TileJSON example

+

Example of a TileJSON layer.

+
+

See the tilejson.js source to see how this is done.

+
+
tilejson
+
+ +
+ +
+ + + + + diff --git a/master/examples/tilejson.js b/master/examples/tilejson.js new file mode 100644 index 0000000000..419b796c2c --- /dev/null +++ b/master/examples/tilejson.js @@ -0,0 +1,15 @@ +var map = new ol.Map({ + layers: [ + new ol.layer.TileLayer({ + source: new ol.source.TileJSON({ + uri: 'http://api.tiles.mapbox.com/v3/mapbox.geography-class.jsonp' + }) + }) + ], + renderers: ol.RendererHints.createFromQueryData(), + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 2 + }) +}); diff --git a/master/examples/two-layers.js b/master/examples/two-layers.js deleted file mode 100644 index e325376b7f..0000000000 --- a/master/examples/two-layers.js +++ /dev/null @@ -1,56 +0,0 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Map'); -goog.require('ol.RendererHint'); -goog.require('ol.View2D'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.projection'); -goog.require('ol.source.BingMaps'); -goog.require('ol.source.TileJSON'); - - -var layers = new ol.Collection([ - new ol.layer.TileLayer({ - source: new ol.source.BingMaps({ - key: 'AgtFlPYDnymLEe9zJ5PCkghbNiFZE9aAtTy3mPaEnEBXqLHtFuTcKoZ-miMC3w7R', - style: 'Aerial' - }) - }), - new ol.layer.TileLayer({ - source: new ol.source.TileJSON({ - uri: 'http://api.tiles.mapbox.com/v3/mapbox.va-quake-aug.jsonp' - }) - }) -]); - -var webglMap = new ol.Map({ - layers: layers, - renderer: ol.RendererHint.WEBGL, - target: 'webglMap', - view: new ol.View2D({ - center: ol.projection.transformWithCodes( - new ol.Coordinate(-77.93255, 37.9555), 'EPSG:4326', 'EPSG:3857'), - zoom: 5 - }) -}); - -var domMap = new ol.Map({ - renderer: ol.RendererHint.DOM, - target: 'domMap' -}); -domMap.bindTo('layers', webglMap); -domMap.bindTo('view', webglMap); - - -var canvasMap = new ol.Map({ - renderer: ol.RendererHint.CANVAS, - target: 'canvasMap' -}); -canvasMap.bindTo('layers', webglMap); -canvasMap.bindTo('view', webglMap); - -// Handle clicks on the "canvas-export" element. -var element = document.getElementById('canvas-export'); -element.addEventListener('click', function(e) { - e.target.href = canvasMap.getRenderer().getCanvas().toDataURL('image/jpeg'); -}, false); diff --git a/master/examples/wms-capabilities-require.js b/master/examples/wms-capabilities-require.js new file mode 100644 index 0000000000..504d6c437d --- /dev/null +++ b/master/examples/wms-capabilities-require.js @@ -0,0 +1 @@ +goog.require('ol.parser.ogc.WMSCapabilities'); diff --git a/master/examples/wms-capabilities.js b/master/examples/wms-capabilities.js index 8566372599..6ea9ee5bda 100644 --- a/master/examples/wms-capabilities.js +++ b/master/examples/wms-capabilities.js @@ -1,5 +1,3 @@ -goog.require('ol.parser.ogc.WMSCapabilities'); - var parser = new ol.parser.ogc.WMSCapabilities(), result; var url = 'data/ogcsample.xml'; diff --git a/master/examples/wms-custom-proj-require.js b/master/examples/wms-custom-proj-require.js new file mode 100644 index 0000000000..5632c4a6ad --- /dev/null +++ b/master/examples/wms-custom-proj-require.js @@ -0,0 +1,11 @@ +goog.require('ol.Attribution'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.Map'); +goog.require('ol.Projection'); +goog.require('ol.ProjectionUnits'); +goog.require('ol.RendererHints'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.projection'); +goog.require('ol.source.TiledWMS'); diff --git a/master/examples/wms-custom-proj.js b/master/examples/wms-custom-proj.js index 6aae577534..7c56ed62d5 100644 --- a/master/examples/wms-custom-proj.js +++ b/master/examples/wms-custom-proj.js @@ -1,26 +1,13 @@ -goog.require('ol.Attribution'); -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Extent'); -goog.require('ol.Map'); -goog.require('ol.Projection'); -goog.require('ol.ProjectionUnits'); -goog.require('ol.RendererHints'); -goog.require('ol.View2D'); -goog.require('ol.layer.ImageLayer'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.projection'); -goog.require('ol.source.SingleImageWMS'); -goog.require('ol.source.TiledWMS'); - - -var epsg21781 = new ol.Projection('EPSG:21781', ol.ProjectionUnits.METERS, - // Validity extent from http://spatialreference.org - new ol.Extent(485869.5728, 76443.1884, 837076.5648, 299941.7864)); +var epsg21781 = new ol.Projection({ + code: 'EPSG:21781', + units: ol.ProjectionUnits.METERS, + // Validity extent from http://spatialreference.org + extent: new ol.Extent(485869.5728, 76443.1884, 837076.5648, 299941.7864) +}); ol.projection.addProjection(epsg21781); var extent = new ol.Extent(420000, 30000, 900000, 350000); -var layers = new ol.Collection([ +var layers = [ new ol.layer.TileLayer({ source: new ol.source.TiledWMS({ url: 'http://wms.geo.admin.ch/', @@ -35,17 +22,18 @@ var layers = new ol.Collection([ extent: extent }) }), - new ol.layer.ImageLayer({ - source: new ol.source.SingleImageWMS({ + new ol.layer.TileLayer({ + source: new ol.source.TiledWMS({ url: 'http://wms.geo.admin.ch/', attributions: [new ol.Attribution( '© ' + '' + 'National parks / geo.admin.ch')], - params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'} + params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'}, + extent: extent }) }) -]); +]; var map = new ol.Map({ layers: layers, diff --git a/master/examples/wms-single-image-require.js b/master/examples/wms-single-image-require.js new file mode 100644 index 0000000000..d203e412b5 --- /dev/null +++ b/master/examples/wms-single-image-require.js @@ -0,0 +1,9 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.MapQuestOpenAerial'); +goog.require('ol.source.SingleImageWMS'); diff --git a/master/examples/wms-single-image.html b/master/examples/wms-single-image.html new file mode 100644 index 0000000000..6014aa59bf --- /dev/null +++ b/master/examples/wms-single-image.html @@ -0,0 +1,52 @@ + + + + + + + + + + Single image WMS example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Single image WMS example

+

Example of a single image WMS layer.

+
+

See the wms-single-image.js source to see how this is done.

+
+
wms, image
+
+ +
+ +
+ + + + + diff --git a/master/examples/wms-single-image.js b/master/examples/wms-single-image.js new file mode 100644 index 0000000000..a3e7a1f119 --- /dev/null +++ b/master/examples/wms-single-image.js @@ -0,0 +1,22 @@ +var layers = [ + new ol.layer.TileLayer({ + source: new ol.source.MapQuestOpenAerial() + }), + new ol.layer.ImageLayer({ + source: new ol.source.SingleImageWMS({ + url: 'http://demo.opengeo.org/geoserver/wms', + crossOrigin: null, + params: {'LAYERS': 'topp:states'}, + extent: new ol.Extent(-13884991, 2870341, -7455066, 6338219) + }) + }) +]; +var map = new ol.Map({ + renderer: ol.RendererHint.CANVAS, + layers: layers, + target: 'map', + view: new ol.View2D({ + center: new ol.Coordinate(-10997148, 4569099), + zoom: 4 + }) +}); diff --git a/master/examples/wms-tiled-require.js b/master/examples/wms-tiled-require.js new file mode 100644 index 0000000000..339a1ff5bc --- /dev/null +++ b/master/examples/wms-tiled-require.js @@ -0,0 +1,8 @@ +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.source.MapQuestOpenAerial'); +goog.require('ol.source.TiledWMS'); diff --git a/master/examples/wms.html b/master/examples/wms-tiled.html similarity index 88% rename from master/examples/wms.html rename to master/examples/wms-tiled.html index 75d0ae3f02..04dc1c40c3 100644 --- a/master/examples/wms.html +++ b/master/examples/wms-tiled.html @@ -37,7 +37,7 @@

Tiled WMS example

Example of a tiled WMS layer.

-

See the wms.js source to see how this is done.

+

See the wms-tiled.js source to see how this is done.

wms, tile, tilelayer
@@ -46,7 +46,7 @@ - + diff --git a/master/examples/wms.js b/master/examples/wms-tiled.js similarity index 62% rename from master/examples/wms.js rename to master/examples/wms-tiled.js index d71c133002..a5cea34a39 100644 --- a/master/examples/wms.js +++ b/master/examples/wms-tiled.js @@ -1,15 +1,4 @@ -goog.require('ol.Collection'); -goog.require('ol.Coordinate'); -goog.require('ol.Extent'); -goog.require('ol.Map'); -goog.require('ol.RendererHint'); -goog.require('ol.View2D'); -goog.require('ol.layer.TileLayer'); -goog.require('ol.source.MapQuestOpenAerial'); -goog.require('ol.source.TiledWMS'); - - -var layers = new ol.Collection([ +var layers = [ new ol.layer.TileLayer({ source: new ol.source.MapQuestOpenAerial() }), @@ -21,7 +10,7 @@ var layers = new ol.Collection([ extent: new ol.Extent(-13884991, 2870341, -7455066, 6338219) }) }) -]); +]; var map = new ol.Map({ renderer: ol.RendererHint.CANVAS, layers: layers, diff --git a/master/ol/ol/anchoredelement.exports b/master/ol/ol/anchoredelement.exports new file mode 100644 index 0000000000..29fbb3bfc8 --- /dev/null +++ b/master/ol/ol/anchoredelement.exports @@ -0,0 +1,7 @@ +@exportClass ol.AnchoredElement ol.AnchoredElementOptions + +@exportSymbol ol.AnchoredElementPositioning +@exportProperty ol.AnchoredElementPositioning.BOTTOM_LEFT +@exportProperty ol.AnchoredElementPositioning.BOTTOM_RIGHT +@exportProperty ol.AnchoredElementPositioning.TOP_LEFT +@exportProperty ol.AnchoredElementPositioning.TOP_RIGHT diff --git a/master/ol/ol/anchoredelement.js b/master/ol/ol/anchoredelement.js new file mode 100644 index 0000000000..14c60cd0fe --- /dev/null +++ b/master/ol/ol/anchoredelement.js @@ -0,0 +1,318 @@ +goog.provide('ol.AnchoredElement'); +goog.provide('ol.AnchoredElementPositioning'); +goog.provide('ol.AnchoredElementProperty'); + +goog.require('goog.dom'); +goog.require('goog.events'); +goog.require('goog.style'); +goog.require('ol.Coordinate'); +goog.require('ol.Map'); +goog.require('ol.MapEventType'); +goog.require('ol.Object'); + + +/** + * @enum {string} + */ +ol.AnchoredElementProperty = { + ELEMENT: 'element', + MAP: 'map', + POSITION: 'position', + POSITIONING: 'positioning' +}; + + +/** + * @enum {string} + */ +ol.AnchoredElementPositioning = { + BOTTOM_LEFT: 'bottom-left', + BOTTOM_RIGHT: 'bottom-right', + TOP_LEFT: 'top-left', + TOP_RIGHT: 'top-right' +}; + + + +/** + * @constructor + * @extends {ol.Object} + * @param {ol.AnchoredElementOptions} anchoredElementOptions Anchored element + * options. + */ +ol.AnchoredElement = function(anchoredElementOptions) { + + goog.base(this); + + /** + * @private + * @type {Element} + */ + this.element_ = goog.dom.createElement(goog.dom.TagName.DIV); + this.element_.style.position = 'absolute'; + + /** + * @private + * @type {{bottom_: string, + * left_: string, + * right_: string, + * top_: string, + * visible: boolean}} + */ + this.rendered_ = { + bottom_: '', + left_: '', + right_: '', + top_: '', + visible: true + }; + + goog.events.listen( + this, ol.Object.getChangedEventType(ol.AnchoredElementProperty.ELEMENT), + this.handleElementChanged, false, this); + + goog.events.listen( + this, ol.Object.getChangedEventType(ol.AnchoredElementProperty.MAP), + this.handleMapChanged, false, this); + + goog.events.listen( + this, ol.Object.getChangedEventType(ol.AnchoredElementProperty.POSITION), + this.handlePositionChanged, false, this); + + goog.events.listen( + this, + ol.Object.getChangedEventType(ol.AnchoredElementProperty.POSITIONING), + this.handlePositioningChanged, false, this); + + if (goog.isDef(anchoredElementOptions.element)) { + this.setElement(anchoredElementOptions.element); + } + if (goog.isDef(anchoredElementOptions.position)) { + this.setPosition(anchoredElementOptions.position); + } + if (goog.isDef(anchoredElementOptions.positioning)) { + this.setPositioning(anchoredElementOptions.positioning); + } + if (goog.isDef(anchoredElementOptions.map)) { + this.setMap(anchoredElementOptions.map); + } + +}; +goog.inherits(ol.AnchoredElement, ol.Object); + + +/** + * @return {Element|undefined} Element. + */ +ol.AnchoredElement.prototype.getElement = function() { + return /** @type {Element|undefined} */ ( + this.get(ol.AnchoredElementProperty.ELEMENT)); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'getElement', + ol.AnchoredElement.prototype.getElement); + + +/** + * @return {ol.Map|undefined} Map. + */ +ol.AnchoredElement.prototype.getMap = function() { + return /** @type {ol.Map|undefined} */ ( + this.get(ol.AnchoredElementProperty.MAP)); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'getMap', + ol.AnchoredElement.prototype.getMap); + + +/** + * @return {ol.Coordinate|undefined} Position. + */ +ol.AnchoredElement.prototype.getPosition = function() { + return /** @type {ol.Coordinate|undefined} */ ( + this.get(ol.AnchoredElementProperty.POSITION)); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'getPosition', + ol.AnchoredElement.prototype.getPosition); + + +/** + * @return {ol.AnchoredElementPositioning|undefined} Positioning. + */ +ol.AnchoredElement.prototype.getPositioning = function() { + return /** @type {ol.AnchoredElementPositioning|undefined} */ ( + this.get(ol.AnchoredElementProperty.POSITIONING)); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'getPositioning', + ol.AnchoredElement.prototype.getPositioning); + + +/** + * @protected + */ +ol.AnchoredElement.prototype.handleElementChanged = function() { + goog.dom.removeChildren(this.element_); + var element = this.getElement(); + if (goog.isDefAndNotNull(element)) { + goog.dom.append(/** @type {!Node} */ (this.element_), element); + } +}; + + +/** + * @protected + */ +ol.AnchoredElement.prototype.handleMapChanged = function() { + if (!goog.isNull(this.mapPostrenderListenerKey_)) { + goog.dom.removeNode(this.element_); + goog.events.unlistenByKey(this.mapPostrenderListenerKey_); + this.mapPostrenderListenerKey_ = null; + } + var map = this.getMap(); + if (goog.isDefAndNotNull(map)) { + this.mapPostrenderListenerKey_ = goog.events.listen(map, + ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this); + this.updatePixelPosition_(); + goog.dom.append( + /** @type {!Node} */ (map.getOverlayContainer()), this.element_); + } +}; + + +/** + * @protected + */ +ol.AnchoredElement.prototype.handleMapPostrender = function() { + this.updatePixelPosition_(); +}; + + +/** + * @protected + */ +ol.AnchoredElement.prototype.handlePositionChanged = function() { + this.updatePixelPosition_(); +}; + + +/** + * @protected + */ +ol.AnchoredElement.prototype.handlePositioningChanged = function() { + this.updatePixelPosition_(); +}; + + +/** + * @param {Element|undefined} element Element. + */ +ol.AnchoredElement.prototype.setElement = function(element) { + this.set(ol.AnchoredElementProperty.ELEMENT, element); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'setElement', + ol.AnchoredElement.prototype.setElement); + + +/** + * @param {ol.Map|undefined} map Map. + */ +ol.AnchoredElement.prototype.setMap = function(map) { + this.set(ol.AnchoredElementProperty.MAP, map); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'setMap', + ol.AnchoredElement.prototype.setMap); + + +/** + * @param {ol.Coordinate|undefined} position Position. + */ +ol.AnchoredElement.prototype.setPosition = function(position) { + this.set(ol.AnchoredElementProperty.POSITION, position); +}; +goog.exportProperty( + ol.AnchoredElement.prototype, + 'setPosition', + ol.AnchoredElement.prototype.setPosition); + + +/** + * @param {ol.AnchoredElementPositioning|undefined} positioning Positioning. + */ +ol.AnchoredElement.prototype.setPositioning = function(positioning) { + this.set(ol.AnchoredElementProperty.POSITIONING, positioning); +}; + + +/** + * @private + */ +ol.AnchoredElement.prototype.updatePixelPosition_ = function() { + + var map = this.getMap(); + var position = this.getPosition(); + if (!goog.isDef(map) || !map.isDef() || !goog.isDef(position)) { + if (this.rendered_.visible) { + goog.style.showElement(this.element_, false); + this.rendered_.visible = false; + } + return; + } + + var pixel = map.getPixelFromCoordinate(position); + var mapSize = map.getSize(); + goog.asserts.assert(goog.isDef(mapSize)); + var style = this.element_.style; + var positioning = this.getPositioning(); + if (positioning == ol.AnchoredElementPositioning.BOTTOM_RIGHT || + positioning == ol.AnchoredElementPositioning.TOP_RIGHT) { + if (this.rendered_.left_ !== '') { + this.rendered_.left_ = style.left = ''; + } + var right = Math.round(mapSize.width - pixel.x) + 'px'; + if (this.rendered_.right_ != right) { + this.rendered_.right_ = style.right = right; + } + } else { + if (this.rendered_.right_ !== '') { + this.rendered_.right_ = style.right = ''; + } + var left = Math.round(pixel.x) + 'px'; + if (this.rendered_.left_ != left) { + this.rendered_.left_ = style.left = left; + } + } + if (positioning == ol.AnchoredElementPositioning.TOP_LEFT || + positioning == ol.AnchoredElementPositioning.TOP_RIGHT) { + if (this.rendered_.bottom_ !== '') { + this.rendered_.bottom_ = style.bottom = ''; + } + var top = Math.round(pixel.y) + 'px'; + if (this.rendered_.top_ != top) { + this.rendered_.top_ = style.top = top; + } + } else { + if (this.rendered_.top_ !== '') { + this.rendered_.top_ = style.top = ''; + } + var bottom = Math.round(mapSize.height - pixel.y) + 'px'; + if (this.rendered_.bottom_ != bottom) { + this.rendered_.bottom_ = style.bottom = bottom; + } + } + + if (!this.rendered_.visible) { + goog.style.showElement(this.element_, true); + this.rendered_.visible = true; + } + +}; diff --git a/master/ol/ol/animation.exports b/master/ol/ol/animation.exports new file mode 100644 index 0000000000..4a8819704d --- /dev/null +++ b/master/ol/ol/animation.exports @@ -0,0 +1,5 @@ +@exportSymbol ol.animation +@exportProperty ol.animation.bounce +@exportProperty ol.animation.pan +@exportProperty ol.animation.rotate +@exportProperty ol.animation.zoom diff --git a/master/ol/ol/animation.js b/master/ol/ol/animation.js new file mode 100644 index 0000000000..7c0b4dffdf --- /dev/null +++ b/master/ol/ol/animation.js @@ -0,0 +1,130 @@ +// FIXME works for View2D only + +goog.provide('ol.animation'); + +goog.require('ol.PreRenderFunction'); +goog.require('ol.ViewHint'); +goog.require('ol.easing'); + + +/** + * @param {ol.animation.BounceOptions} options Options. + * @return {ol.PreRenderFunction} Pre-render function. + */ +ol.animation.bounce = function(options) { + var resolution = options.resolution; + var start = goog.isDef(options.start) ? options.start : goog.now(); + var duration = goog.isDef(options.duration) ? options.duration : 1000; + var easing = goog.isDef(options.easing) ? + options.easing : ol.easing.upAndDown; + return function(map, frameState) { + if (frameState.time < start) { + frameState.animate = true; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else if (frameState.time < start + duration) { + var delta = easing((frameState.time - start) / duration); + var deltaResolution = resolution - frameState.view2DState.resolution; + frameState.animate = true; + frameState.view2DState.resolution += delta * deltaResolution; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else { + return false; + } + }; +}; + + +/** + * @param {ol.animation.PanOptions} options Options. + * @return {ol.PreRenderFunction} Pre-render function. + */ +ol.animation.pan = function(options) { + var source = options.source; + var start = goog.isDef(options.start) ? options.start : goog.now(); + var sourceX = source.x; + var sourceY = source.y; + var duration = goog.isDef(options.duration) ? options.duration : 1000; + var easing = goog.isDef(options.easing) ? + options.easing : ol.easing.inAndOut; + return function(map, frameState) { + if (frameState.time < start) { + frameState.animate = true; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else if (frameState.time < start + duration) { + var delta = 1 - easing((frameState.time - start) / duration); + var deltaX = sourceX - frameState.view2DState.center.x; + var deltaY = sourceY - frameState.view2DState.center.y; + frameState.animate = true; + frameState.view2DState.center.x += delta * deltaX; + frameState.view2DState.center.y += delta * deltaY; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else { + return false; + } + }; +}; + + +/** + * @param {ol.animation.RotateOptions} options Options. + * @return {ol.PreRenderFunction} Pre-render function. + */ +ol.animation.rotate = function(options) { + var sourceRotation = options.rotation; + var start = goog.isDef(options.start) ? options.start : goog.now(); + var duration = goog.isDef(options.duration) ? options.duration : 1000; + var easing = goog.isDef(options.easing) ? + options.easing : ol.easing.inAndOut; + + return function(map, frameState) { + if (frameState.time < start) { + frameState.animate = true; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else if (frameState.time < start + duration) { + var delta = 1 - easing((frameState.time - start) / duration); + var deltaRotation = + sourceRotation - frameState.view2DState.rotation; + frameState.animate = true; + frameState.view2DState.rotation += delta * deltaRotation; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else { + return false; + } + }; +}; + + +/** + * @param {ol.animation.ZoomOptions} options Options. + * @return {ol.PreRenderFunction} Pre-render function. + */ +ol.animation.zoom = function(options) { + var sourceResolution = options.resolution; + var start = goog.isDef(options.start) ? options.start : goog.now(); + var duration = goog.isDef(options.duration) ? options.duration : 1000; + var easing = goog.isDef(options.easing) ? + options.easing : ol.easing.inAndOut; + return function(map, frameState) { + if (frameState.time < start) { + frameState.animate = true; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else if (frameState.time < start + duration) { + var delta = 1 - easing((frameState.time - start) / duration); + var deltaResolution = + sourceResolution - frameState.view2DState.resolution; + frameState.animate = true; + frameState.view2DState.resolution += delta * deltaResolution; + frameState.viewHints[ol.ViewHint.ANIMATING] += 1; + return true; + } else { + return false; + } + }; +}; diff --git a/master/ol/ol/array.js b/master/ol/ol/array.js new file mode 100644 index 0000000000..2a1ce13de4 --- /dev/null +++ b/master/ol/ol/array.js @@ -0,0 +1,59 @@ +goog.provide('ol.array'); + +goog.require('goog.array'); + + +/** + * @param {Array.} arr Array. + * @param {number} target Target. + * @return {number} Index. + */ +ol.array.binaryFindNearest = function(arr, target) { + var index = goog.array.binarySearch(arr, target, function(a, b) { + return b - a; + }); + if (index >= 0) { + return index; + } else if (index == -1) { + return 0; + } else if (index == -arr.length - 1) { + return arr.length - 1; + } else { + var left = -index - 2; + var right = -index - 1; + if (arr[left] - target < target - arr[right]) { + return left; + } else { + return right; + } + } +}; + + +/** + * @param {Array.} arr Array. + * @param {number} target Target. + * @return {number} Index. + */ +ol.array.linearFindNearest = function(arr, target) { + var n = arr.length; + if (arr[0] <= target) { + return 0; + } else if (target <= arr[n - 1]) { + return n - 1; + } else { + var i; + for (i = 1; i < n; ++i) { + if (arr[i] == target) { + return i; + } else if (arr[i] < target) { + if (arr[i - 1] - target < target - arr[i]) { + return i - 1; + } else { + return i; + } + } + } + return n - 1; + } +}; diff --git a/master/ol/ol/attribution.exports b/master/ol/ol/attribution.exports new file mode 100644 index 0000000000..053c0abeae --- /dev/null +++ b/master/ol/ol/attribution.exports @@ -0,0 +1 @@ +@exportSymbol ol.Attribution diff --git a/master/ol/ol/attribution.js b/master/ol/ol/attribution.js new file mode 100644 index 0000000000..cc353c36df --- /dev/null +++ b/master/ol/ol/attribution.js @@ -0,0 +1,58 @@ +goog.provide('ol.Attribution'); + +goog.require('ol.TileRange'); + + + +/** + * @constructor + * @param {string} html HTML. + * @param {Object.>=} opt_tileRanges Tile ranges. + */ +ol.Attribution = function(html, opt_tileRanges) { + + /** + * @private + * @type {string} + */ + this.html_ = html; + + /** + * @private + * @type {Object.>} + */ + this.tileRanges_ = opt_tileRanges || null; + +}; + + +/** + * @return {string} HTML. + */ +ol.Attribution.prototype.getHTML = function() { + return this.html_; +}; + + +/** + * @param {Object.} tileRanges Tile ranges. + * @return {boolean} Intersects any tile range. + */ +ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges) { + if (goog.isNull(this.tileRanges_)) { + return true; + } + var i, tileRange, z; + for (z in tileRanges) { + if (!(z in this.tileRanges_)) { + continue; + } + tileRange = tileRanges[z]; + for (i = 0; i < this.tileRanges_[z].length; ++i) { + if (this.tileRanges_[z][i].intersects(tileRange)) { + return true; + } + } + } + return false; +}; diff --git a/master/ol/ol/browserfeature.js b/master/ol/ol/browserfeature.js new file mode 100644 index 0000000000..46e40e6394 --- /dev/null +++ b/master/ol/ol/browserfeature.js @@ -0,0 +1,20 @@ +goog.provide('ol.BrowserFeature'); + + +/** + * @define {boolean} Assume touch. + */ +ol.ASSUME_TOUCH = false; + + +/** + * @type {Object} + */ +ol.BrowserFeature = { + /** + * @type {boolean} True if browser supports touch events + */ + HAS_TOUCH: ol.ASSUME_TOUCH || + (document && 'ontouchstart' in document.documentElement) || + !!(window.navigator.msPointerEnabled) +}; diff --git a/master/ol/ol/canvas/canvas.js b/master/ol/ol/canvas/canvas.js new file mode 100644 index 0000000000..71085aa721 --- /dev/null +++ b/master/ol/ol/canvas/canvas.js @@ -0,0 +1,22 @@ +goog.provide('ol.canvas'); + +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); + + +/** + * @const + * @type {boolean} Is supported. + */ +ol.canvas.SUPPORTED = (function() { + if (!('HTMLCanvasElement' in goog.global)) { + return false; + } + try { + var canvas = /** @type {HTMLCanvasElement} */ + (goog.dom.createElement(goog.dom.TagName.CANVAS)); + return !goog.isNull(canvas.getContext('2d')); + } catch (e) { + return false; + } +})(); diff --git a/master/ol/ol/collection.exports b/master/ol/ol/collection.exports new file mode 100644 index 0000000000..11b7e20c8f --- /dev/null +++ b/master/ol/ol/collection.exports @@ -0,0 +1,11 @@ +@exportSymbol ol.Collection +@exportProperty ol.Collection.prototype.clear +@exportProperty ol.Collection.prototype.forEach +@exportProperty ol.Collection.prototype.getAt +@exportProperty ol.Collection.prototype.getLength +@exportProperty ol.Collection.prototype.insertAt +@exportProperty ol.Collection.prototype.pop +@exportProperty ol.Collection.prototype.push +@exportProperty ol.Collection.prototype.remove +@exportProperty ol.Collection.prototype.removeAt +@exportProperty ol.Collection.prototype.setAt diff --git a/master/ol/ol/collection.js b/master/ol/ol/collection.js new file mode 100644 index 0000000000..08d3340188 --- /dev/null +++ b/master/ol/ol/collection.js @@ -0,0 +1,220 @@ + +/** + * An implementation of Google Maps' MVCArray. + * @see https://developers.google.com/maps/documentation/javascript/reference + */ + +goog.provide('ol.Collection'); +goog.provide('ol.CollectionEvent'); +goog.provide('ol.CollectionEventType'); + +goog.require('goog.array'); +goog.require('goog.events.Event'); +goog.require('ol.Object'); + + +/** + * @enum {string} + */ +ol.CollectionEventType = { + ADD: 'add', + REMOVE: 'remove' +}; + + + +/** + * @constructor + * @extends {goog.events.Event} + * @param {ol.CollectionEventType} type Type. + * @param {*=} opt_elem Element. + * @param {Object=} opt_target Target. + */ +ol.CollectionEvent = function(type, opt_elem, opt_target) { + + goog.base(this, type, opt_target); + + /** + * @type {*} + */ + this.elem = opt_elem; + +}; +goog.inherits(ol.CollectionEvent, goog.events.Event); + + +/** + * @enum {string} + */ +ol.CollectionProperty = { + LENGTH: 'length' +}; + + + +/** + * @constructor + * @extends {ol.Object} + * @param {Array=} opt_array Array. + */ +ol.Collection = function(opt_array) { + + goog.base(this); + + /** + * @private + * @type {Array} + */ + this.array_ = opt_array || []; + + this.updateLength_(); + +}; +goog.inherits(ol.Collection, ol.Object); + + +/** + * Remove all elements from the collection. + */ +ol.Collection.prototype.clear = function() { + while (this.getLength() > 0) { + this.pop(); + } +}; + + +/** + * @param {Array} arr Array. + */ +ol.Collection.prototype.extend = function(arr) { + var i; + for (i = 0; i < arr.length; ++i) { + this.push(arr[i]); + } +}; + + +/** + * @param {Function} f Function. + * @param {Object=} opt_obj Object. + */ +ol.Collection.prototype.forEach = function(f, opt_obj) { + goog.array.forEach(this.array_, f, opt_obj); +}; + + +/** + * @return {Array} Array. + */ +ol.Collection.prototype.getArray = function() { + return this.array_; +}; + + +/** + * @param {number} index Index. + * @return {*} Element. + */ +ol.Collection.prototype.getAt = function(index) { + return this.array_[index]; +}; + + +/** + * @return {number} Length. + */ +ol.Collection.prototype.getLength = function() { + return /** @type {number} */ (this.get(ol.CollectionProperty.LENGTH)); +}; + + +/** + * @param {number} index Index. + * @param {*} elem Element. + */ +ol.Collection.prototype.insertAt = function(index, elem) { + goog.array.insertAt(this.array_, elem, index); + this.updateLength_(); + this.dispatchEvent( + new ol.CollectionEvent(ol.CollectionEventType.ADD, elem, this)); +}; + + +/** + * @return {*} Element. + */ +ol.Collection.prototype.pop = function() { + return this.removeAt(this.getLength() - 1); +}; + + +/** + * @param {*} elem Element. + * @return {number} Length. + */ +ol.Collection.prototype.push = function(elem) { + var n = this.array_.length; + this.insertAt(n, elem); + return n; +}; + + +/** + * Removes the first occurence of elem from the collection. + * @param {*} elem Element. + * @return {*} The removed element or undefined if elem was not found. + */ +ol.Collection.prototype.remove = function(elem) { + var i; + for (i = 0; i < this.array_.length; ++i) { + if (this.array_[i] === elem) { + return this.removeAt(i); + } + } + return undefined; +}; + + +/** + * @param {number} index Index. + * @return {*} Value. + */ +ol.Collection.prototype.removeAt = function(index) { + var prev = this.array_[index]; + goog.array.removeAt(this.array_, index); + this.updateLength_(); + this.dispatchEvent( + new ol.CollectionEvent(ol.CollectionEventType.REMOVE, prev, this)); + return prev; +}; + + +/** + * @param {number} index Index. + * @param {*} elem Element. + */ +ol.Collection.prototype.setAt = function(index, elem) { + var n = this.getLength(); + if (index < n) { + var prev = this.array_[index]; + this.array_[index] = elem; + this.dispatchEvent( + new ol.CollectionEvent(ol.CollectionEventType.REMOVE, prev, this)); + this.dispatchEvent( + new ol.CollectionEvent(ol.CollectionEventType.ADD, elem, this)); + } else { + var j; + for (j = n; j < index; ++j) { + this.insertAt(j, undefined); + } + this.insertAt(index, elem); + } +}; + + +/** + * @private + */ +ol.Collection.prototype.updateLength_ = function() { + this.set(ol.CollectionProperty.LENGTH, this.array_.length); +}; diff --git a/master/ol/ol/color.js b/master/ol/ol/color.js new file mode 100644 index 0000000000..368e23fdda --- /dev/null +++ b/master/ol/ol/color.js @@ -0,0 +1,62 @@ +goog.provide('ol.Color'); + +goog.require('goog.color'); +goog.require('goog.math'); + + + +/** + * @constructor + * @param {number} r Red, 0 to 255. + * @param {number} g Green, 0 to 255. + * @param {number} b Blue, 0 to 255. + * @param {number} a Alpha, 0 (fully transparent) to 1 (fully opaque). + */ +ol.Color = function(r, g, b, a) { + + /** + * @type {number} + */ + this.r = goog.math.clamp(r, 0, 255); + + /** + * @type {number} + */ + this.g = goog.math.clamp(g, 0, 255); + + /** + * @type {number} + */ + this.b = goog.math.clamp(b, 0, 255); + + /** + * @type {number} + */ + this.a = goog.math.clamp(a, 0, 1); + +}; + + +/** + * @param {string} str String. + * @param {number=} opt_a Alpha. + * @return {ol.Color} Color. + */ +ol.Color.createFromString = function(str, opt_a) { + var rgb = goog.color.hexToRgb(goog.color.parse(str).hex); + var a = opt_a || 255; + return new ol.Color(rgb[0], rgb[1], rgb[2], a); +}; + + +/** + * @param {ol.Color} color1 Color 1. + * @param {ol.Color} color2 Color 2. + * @return {boolean} Equals. + */ +ol.Color.equals = function(color1, color2) { + return (color1.r == color2.r && + color1.g == color2.g && + color1.b == color2.b && + color1.a == color2.a); +}; diff --git a/master/ol/ol/constraints.js b/master/ol/ol/constraints.js new file mode 100644 index 0000000000..81b3e4cd57 --- /dev/null +++ b/master/ol/ol/constraints.js @@ -0,0 +1,27 @@ +goog.provide('ol.Constraints'); + +goog.require('ol.ResolutionConstraintType'); +goog.require('ol.RotationConstraintType'); + + + +/** + * @constructor + * @param {ol.ResolutionConstraintType} resolutionConstraint + * Resolution constraint. + * @param {ol.RotationConstraintType} rotationConstraint + * Rotation constraint. + */ +ol.Constraints = function(resolutionConstraint, rotationConstraint) { + + /** + * @type {ol.ResolutionConstraintType} + */ + this.resolution = resolutionConstraint; + + /** + * @type {ol.RotationConstraintType} + */ + this.rotation = rotationConstraint; + +}; diff --git a/master/ol/ol/control/attribution.exports b/master/ol/ol/control/attribution.exports new file mode 100644 index 0000000000..57e5bdb9d8 --- /dev/null +++ b/master/ol/ol/control/attribution.exports @@ -0,0 +1,3 @@ +@exportClass ol.control.Attribution ol.control.AttributionOptions +@exportProperty ol.control.Attribution.prototype.setMap + diff --git a/master/ol/ol/control/attributioncontrol.js b/master/ol/ol/control/attributioncontrol.js new file mode 100644 index 0000000000..23c5b6d241 --- /dev/null +++ b/master/ol/ol/control/attributioncontrol.js @@ -0,0 +1,208 @@ +// FIXME handle date line wrap + +goog.provide('ol.control.Attribution'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.object'); +goog.require('goog.style'); +goog.require('ol.Attribution'); +goog.require('ol.FrameState'); +goog.require('ol.MapEvent'); +goog.require('ol.MapEventType'); +goog.require('ol.TileRange'); +goog.require('ol.control.Control'); +goog.require('ol.source.Source'); + + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {ol.control.AttributionOptions=} opt_options Options. + */ +ol.control.Attribution = function(opt_options) { + + var options = goog.isDef(opt_options) ? opt_options : {}; + + this.ulElement_ = goog.dom.createElement(goog.dom.TagName.UL); + + var element = goog.dom.createDom(goog.dom.TagName.DIV, { + 'class': 'ol-attribution ol-unselectable' + }, this.ulElement_); + + goog.base(this, { + element: element, + map: options.map, + target: options.target + }); + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + + /** + * @private + * @type {Object.} + */ + this.attributionElements_ = {}; + + /** + * @private + * @type {Object.} + */ + this.attributionElementRenderedVisible_ = {}; + + /** + * @private + * @type {Array.} + */ + this.listenerKeys_ = null; + +}; +goog.inherits(ol.control.Attribution, ol.control.Control); + + +/** + * @param {?Object.>} usedTiles Used + * tiles. + * @param {Object.} sources Sources. + * @return {Object.} Attributions. + */ +ol.control.Attribution.prototype.getTileSourceAttributions = + function(usedTiles, sources) { + /** @type {Object.} */ + var attributions = {}; + var i, tileRanges, tileSource, tileSourceAttribution, + tileSourceAttributionKey, tileSourceAttributions, tileSourceKey, z; + for (tileSourceKey in usedTiles) { + goog.asserts.assert(tileSourceKey in sources); + tileSource = sources[tileSourceKey]; + tileSourceAttributions = tileSource.getAttributions(); + if (goog.isNull(tileSourceAttributions)) { + continue; + } + tileRanges = usedTiles[tileSourceKey]; + for (i = 0; i < tileSourceAttributions.length; ++i) { + tileSourceAttribution = tileSourceAttributions[i]; + tileSourceAttributionKey = goog.getUid(tileSourceAttribution).toString(); + if (tileSourceAttributionKey in attributions) { + continue; + } + if (tileSourceAttribution.intersectsAnyTileRange(tileRanges)) { + attributions[tileSourceAttributionKey] = tileSourceAttribution; + } + } + } + return attributions; +}; + + +/** + * @param {ol.MapEvent} mapEvent Map event. + */ +ol.control.Attribution.prototype.handleMapPostrender = function(mapEvent) { + this.updateElement_(mapEvent.frameState); +}; + + +/** + * @inheritDoc + */ +ol.control.Attribution.prototype.setMap = function(map) { + if (!goog.isNull(this.listenerKeys_)) { + goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); + this.listenerKeys_ = null; + } + goog.base(this, 'setMap', map); + if (!goog.isNull(map)) { + this.listenerKeys_ = [ + goog.events.listen(map, ol.MapEventType.POSTRENDER, + this.handleMapPostrender, false, this) + ]; + } +}; + + +/** + * @private + * @param {?ol.FrameState} frameState Frame state. + */ +ol.control.Attribution.prototype.updateElement_ = function(frameState) { + + if (goog.isNull(frameState)) { + if (this.renderedVisible_) { + goog.style.showElement(this.element, false); + this.renderedVisible_ = false; + } + return; + } + + var map = this.getMap(); + + /** @type {Object.} */ + var attributionsToRemove = {}; + /** @type {Object.} */ + var sources = {}; + var layers = map.getLayers(); + if (goog.isDef(layers)) { + layers.forEach(function(layer) { + var source = layer.getSource(); + sources[goog.getUid(source).toString()] = source; + var attributions = source.getAttributions(); + if (!goog.isNull(attributions)) { + var attribution, i; + for (i = 0; i < attributions.length; ++i) { + attribution = attributions[i]; + attributionKey = goog.getUid(attribution).toString(); + attributionsToRemove[attributionKey] = true; + } + } + }); + } + + /** @type {Object.} */ + var attributions = goog.object.clone(frameState.attributions); + var tileSourceAttributions = this.getTileSourceAttributions( + frameState.usedTiles, sources); + goog.object.extend(attributions, tileSourceAttributions); + + /** @type {Array.} */ + var attributionKeys = + goog.array.map(goog.object.getKeys(attributions), Number); + goog.array.sort(attributionKeys); + var i, attributionElement, attributionKey; + for (i = 0; i < attributionKeys.length; ++i) { + attributionKey = attributionKeys[i].toString(); + if (attributionKey in this.attributionElements_) { + if (!this.attributionElementRenderedVisible_[attributionKey]) { + goog.style.showElement(this.attributionElements_[attributionKey], true); + this.attributionElementRenderedVisible_[attributionKey] = true; + } + } else { + attributionElement = goog.dom.createElement(goog.dom.TagName.LI); + attributionElement.innerHTML = attributions[attributionKey].getHTML(); + goog.dom.appendChild(this.ulElement_, attributionElement); + this.attributionElements_[attributionKey] = attributionElement; + this.attributionElementRenderedVisible_[attributionKey] = true; + } + delete attributionsToRemove[attributionKey]; + } + + for (attributionKey in attributionsToRemove) { + goog.dom.removeNode(this.attributionElements_[attributionKey]); + delete this.attributionElements_[attributionKey]; + delete this.attributionElementRenderedVisible_[attributionKey]; + } + + var renderVisible = !goog.array.isEmpty(attributionKeys); + if (this.renderedVisible_ != renderVisible) { + goog.style.showElement(this.element, renderVisible); + this.renderedVisible_ = renderVisible; + } + +}; diff --git a/master/ol/ol/control/control.js b/master/ol/ol/control/control.js new file mode 100644 index 0000000000..461847c340 --- /dev/null +++ b/master/ol/ol/control/control.js @@ -0,0 +1,89 @@ +goog.provide('ol.control.Control'); +goog.provide('ol.control.ControlOptions'); + +goog.require('goog.Disposable'); + + +/** + * @typedef {{element: (Element|undefined), + * map: (ol.Map|undefined), + * target: (Element|undefined)}} + */ +ol.control.ControlOptions; + + + +/** + * A thing which is painted over the map to provide a means for interaction + * (buttons) of show annotations (status bars). + * + * @constructor + * @extends {goog.Disposable} + * @param {ol.control.ControlOptions} controlOptions Control options. + */ +ol.control.Control = function(controlOptions) { + + goog.base(this); + + /** + * @protected + * @type {Element} + */ + this.element = goog.isDef(controlOptions.element) ? + controlOptions.element : null; + + /** + * @private + * @type {Element|undefined} + */ + this.target_ = controlOptions.target; + + /** + * @private + * @type {ol.Map} + */ + this.map_ = null; + + if (goog.isDef(controlOptions.map)) { + this.setMap(controlOptions.map); + } + +}; +goog.inherits(ol.control.Control, goog.Disposable); + + +/** + * @inheritDoc + */ +ol.control.Control.prototype.disposeInternal = function() { + goog.dom.removeNode(this.element); + goog.base(this, 'disposeInternal'); +}; + + +/** + * @return {ol.Map} Map. + */ +ol.control.Control.prototype.getMap = function() { + return this.map_; +}; + + +/** + * Removes the control from its current map and attaches it to the new map. + * Subtypes might also wish set up event handlers to get notified about changes + * to the map here. + * + * @param {ol.Map} map Map. + */ +ol.control.Control.prototype.setMap = function(map) { + if (!goog.isNull(this.map_)) { + goog.dom.removeNode(this.element); + } + this.map_ = map; + if (!goog.isNull(this.map_)) { + var target = goog.isDef(this.target_) ? + this.target_ : map.getOverlayContainer(); + goog.dom.appendChild(target, this.element); + } +}; diff --git a/master/ol/ol/control/defaults.exports b/master/ol/ol/control/defaults.exports new file mode 100644 index 0000000000..0023131772 --- /dev/null +++ b/master/ol/ol/control/defaults.exports @@ -0,0 +1 @@ +@exportSymbol ol.control.defaults ol.control.defaults diff --git a/master/ol/ol/control/defaults.js b/master/ol/ol/control/defaults.js new file mode 100644 index 0000000000..90980c182b --- /dev/null +++ b/master/ol/ol/control/defaults.js @@ -0,0 +1,42 @@ +goog.provide('ol.control.defaults'); + +goog.require('goog.array'); +goog.require('ol.control.Attribution'); +goog.require('ol.control.Zoom'); + + +/** + * @param {ol.control.DefaultsOptions=} opt_options Options. + * @param {Array.=} opt_controls Additional controls. + * @return {Array.} Controls. + */ +ol.control.defaults = function(opt_options, opt_controls) { + + var options = goog.isDef(opt_options) ? opt_options : {}; + + /** @type {Array.} */ + var controls = []; + + var attributionControl = goog.isDef(options.attribution) ? + options.attribution : true; + if (attributionControl) { + var attributionControlOptions = goog.isDef(options.attributionOptions) ? + options.attributionOptions : undefined; + controls.push(new ol.control.Attribution(attributionControlOptions)); + } + + var zoomControl = goog.isDef(options.zoom) ? + options.zoom : true; + if (zoomControl) { + var zoomControlOptions = goog.isDef(options.zoomControlOptions) ? + options.zoomControlOptions : undefined; + controls.push(new ol.control.Zoom(zoomControlOptions)); + } + + if (goog.isDef(opt_controls)) { + goog.array.extend(controls, opt_controls); + } + + return controls; + +}; diff --git a/master/ol/ol/control/dragboxcontrol.js b/master/ol/ol/control/dragboxcontrol.js new file mode 100644 index 0000000000..5fcbc51596 --- /dev/null +++ b/master/ol/ol/control/dragboxcontrol.js @@ -0,0 +1,95 @@ +goog.provide('ol.control.DragBox'); + +goog.require('goog.asserts'); +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.style'); +goog.require('ol.Coordinate'); +goog.require('ol.MapBrowserEvent'); +goog.require('ol.MapBrowserEvent.EventType'); +goog.require('ol.Pixel'); +goog.require('ol.Size'); +goog.require('ol.control.Control'); + + +/** + * @typedef {{map: (ol.Map|undefined), + * startCoordinate: ol.Coordinate}} + */ +ol.control.DragBoxOptions; + + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {ol.control.DragBoxOptions} dragBoxOptions Drag box options. + */ +ol.control.DragBox = function(dragBoxOptions) { + + var element = goog.dom.createDom(goog.dom.TagName.DIV, 'ol-dragbox'); + + /** + * @type {ol.Pixel|undefined} + * @private + */ + this.startPixel_ = null; + + /** + * @private + * @type {ol.Coordinate} + */ + this.startCoordinate_ = dragBoxOptions.startCoordinate; + + /** + * @private + * @type {?number} + */ + this.dragListenKey_ = null; + + goog.base(this, { + element: element, + map: dragBoxOptions.map + }); + +}; +goog.inherits(ol.control.DragBox, ol.control.Control); + + +/** + * @inheritDoc + */ +ol.control.DragBox.prototype.setMap = function(map) { + if (!goog.isNull(this.dragListenKey_)) { + goog.events.unlistenByKey(this.dragListenKey_); + this.dragListenKey_ = null; + } + if (!goog.isNull(map)) { + this.startPixel_ = map.getPixelFromCoordinate(this.startCoordinate_); + goog.asserts.assert(goog.isDef(this.startPixel_)); + goog.style.setPosition(this.element, this.startPixel_); + goog.style.setBorderBoxSize(this.element, new ol.Size(0, 0)); + this.dragListenKey_ = goog.events.listen( + map, ol.MapBrowserEvent.EventType.DRAG, this.updateBox_, false, this); + } + goog.base(this, 'setMap', map); +}; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle. + * @private + */ +ol.control.DragBox.prototype.updateBox_ = function(mapBrowserEvent) { + var map = this.getMap(); + var coordinate = mapBrowserEvent.getCoordinate(); + goog.asserts.assert(goog.isDef(coordinate)); + var currentPixel = map.getPixelFromCoordinate(coordinate); + goog.style.setPosition(this.element, new ol.Pixel( + Math.min(currentPixel.x, this.startPixel_.x), + Math.min(currentPixel.y, this.startPixel_.y))); + goog.style.setBorderBoxSize(this.element, new ol.Size( + Math.abs(currentPixel.x - this.startPixel_.x), + Math.abs(currentPixel.y - this.startPixel_.y))); +}; diff --git a/master/ol/ol/control/mouseposition.exports b/master/ol/ol/control/mouseposition.exports new file mode 100644 index 0000000000..e29f9caa13 --- /dev/null +++ b/master/ol/ol/control/mouseposition.exports @@ -0,0 +1,3 @@ +@exportClass ol.control.MousePosition ol.control.MousePositionOptions +@exportProperty ol.control.MousePosition.prototype.setMap + diff --git a/master/ol/ol/control/mousepositioncontrol.js b/master/ol/ol/control/mousepositioncontrol.js new file mode 100644 index 0000000000..206be35210 --- /dev/null +++ b/master/ol/ol/control/mousepositioncontrol.js @@ -0,0 +1,196 @@ +// FIXME should listen on appropriate pane, once it is defined +// FIXME works for View2D only + +goog.provide('ol.control.MousePosition'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('goog.style'); +goog.require('ol.Coordinate'); +goog.require('ol.CoordinateFormatType'); +goog.require('ol.MapEvent'); +goog.require('ol.MapEventType'); +goog.require('ol.Pixel'); +goog.require('ol.Projection'); +goog.require('ol.TransformFunction'); +goog.require('ol.control.Control'); +goog.require('ol.projection'); + + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {ol.control.MousePositionOptions=} opt_options Options. + */ +ol.control.MousePosition = function(opt_options) { + + var options = goog.isDef(opt_options) ? opt_options : {}; + + var element = goog.dom.createDom(goog.dom.TagName.DIV, { + 'class': 'ol-mouse-position' + }); + + goog.base(this, { + element: element, + map: options.map, + target: options.target + }); + + /** + * @private + * @type {ol.Projection} + */ + this.projection_ = ol.projection.get(options.projection); + + /** + * @private + * @type {ol.CoordinateFormatType|undefined} + */ + this.coordinateFormat_ = options.coordinateFormat; + + /** + * @private + * @type {string} + */ + this.undefinedHTML_ = goog.isDef(options.undefinedHTML) ? + options.undefinedHTML : ''; + + /** + * @private + * @type {string} + */ + this.renderedHTML_ = element.innerHTML; + + /** + * @private + * @type {ol.Projection} + */ + this.mapProjection_ = null; + + /** + * @private + * @type {ol.TransformFunction} + */ + this.transform_ = ol.projection.identityTransform; + + /** + * @private + * @type {ol.Projection} + */ + this.renderedProjection_ = null; + + /** + * @private + * @type {ol.Pixel} + */ + this.lastMouseMovePixel_ = null; + + /** + * @private + * @type {Array.} + */ + this.listenerKeys_ = null; + +}; +goog.inherits(ol.control.MousePosition, ol.control.Control); + + +/** + * @param {ol.MapEvent} mapEvent Map event. + * @protected + */ +ol.control.MousePosition.prototype.handleMapPostrender = function(mapEvent) { + var frameState = mapEvent.frameState; + if (goog.isNull(frameState)) { + this.mapProjection_ = null; + } else { + this.mapProjection_ = frameState.view2DState.projection; + } + this.updateHTML_(this.lastMouseMovePixel_); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @protected + */ +ol.control.MousePosition.prototype.handleMouseMove = function(browserEvent) { + var map = this.getMap(); + var eventPosition = goog.style.getRelativePosition( + browserEvent, map.getViewport()); + var pixel = new ol.Pixel(eventPosition.x, eventPosition.y); + this.updateHTML_(pixel); + this.lastMouseMovePixel_ = pixel; +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @protected + */ +ol.control.MousePosition.prototype.handleMouseOut = function(browserEvent) { + this.updateHTML_(null); + this.lastMouseMovePixel_ = null; +}; + + +/** + * @inheritDoc + */ +ol.control.MousePosition.prototype.setMap = function(map) { + if (!goog.isNull(this.listenerKeys_)) { + goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); + this.listenerKeys_ = null; + } + goog.base(this, 'setMap', map); + if (!goog.isNull(map)) { + var viewport = map.getViewport(); + this.listenerKeys_ = [ + goog.events.listen(viewport, goog.events.EventType.MOUSEMOVE, + this.handleMouseMove, false, this), + goog.events.listen(viewport, goog.events.EventType.MOUSEOUT, + this.handleMouseOut, false, this), + goog.events.listen(map, ol.MapEventType.POSTRENDER, + this.handleMapPostrender, false, this) + ]; + } +}; + + +/** + * @param {?ol.Pixel} pixel Pixel. + * @private + */ +ol.control.MousePosition.prototype.updateHTML_ = function(pixel) { + var html = this.undefinedHTML_; + if (!goog.isNull(pixel)) { + if (this.renderedProjection_ != this.mapProjection_) { + if (!goog.isNull(this.projection_)) { + this.transform_ = ol.projection.getTransformFromProjections( + this.mapProjection_, this.projection_); + } else { + this.transform_ = ol.projection.identityTransform; + } + this.renderedProjection_ = this.mapProjection_; + } + var map = this.getMap(); + var coordinate = map.getCoordinateFromPixel(pixel); + if (!goog.isNull(coordinate)) { + var vertex = [coordinate.x, coordinate.y]; + vertex = this.transform_(vertex, vertex); + coordinate = new ol.Coordinate(vertex[0], vertex[1]); + if (goog.isDef(this.coordinateFormat_)) { + html = this.coordinateFormat_(coordinate); + } else { + html = coordinate.toString(); + } + } + } + if (!goog.isDef(this.renderedHTML_) || html != this.renderedHTML_) { + this.element.innerHTML = html; + this.renderedHTML_ = html; + } +}; diff --git a/master/ol/ol/control/scaleline.exports b/master/ol/ol/control/scaleline.exports new file mode 100644 index 0000000000..6d0cbe1cd1 --- /dev/null +++ b/master/ol/ol/control/scaleline.exports @@ -0,0 +1,9 @@ +@exportClass ol.control.ScaleLine ol.control.ScaleLineOptions +@exportProperty ol.control.ScaleLine.prototype.setMap + +@exportSymbol ol.control.ScaleLineUnits +@exportProperty ol.control.ScaleLineUnits.DEGREES +@exportProperty ol.control.ScaleLineUnits.IMPERIAL +@exportProperty ol.control.ScaleLineUnits.NAUTICAL +@exportProperty ol.control.ScaleLineUnits.METRIC +@exportProperty ol.control.ScaleLineUnits.US diff --git a/master/ol/ol/control/scalelinecontrol.js b/master/ol/ol/control/scalelinecontrol.js new file mode 100644 index 0000000000..8ba1ae5032 --- /dev/null +++ b/master/ol/ol/control/scalelinecontrol.js @@ -0,0 +1,285 @@ +goog.provide('ol.control.ScaleLine'); +goog.provide('ol.control.ScaleLineUnits'); + +goog.require('goog.dom'); +goog.require('goog.style'); +goog.require('ol.FrameState'); +goog.require('ol.MapEvent'); +goog.require('ol.MapEventType'); +goog.require('ol.ProjectionUnits'); +goog.require('ol.TransformFunction'); +goog.require('ol.control.Control'); +goog.require('ol.projection'); +goog.require('ol.sphere.NORMAL'); + + +/** + * @enum {string} + */ +ol.control.ScaleLineUnits = { + DEGREES: 'degrees', + IMPERIAL: 'imperial', + NAUTICAL: 'nautical', + METRIC: 'metric', + US: 'us' +}; + + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {ol.control.ScaleLineOptions=} opt_options Options. + */ +ol.control.ScaleLine = function(opt_options) { + + var options = opt_options || {}; + + /** + * @private + * @type {Element} + */ + this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV, { + 'class': 'ol-scale-line-inner' + }); + + /** + * @private + * @type {Element} + */ + this.element_ = goog.dom.createDom(goog.dom.TagName.DIV, { + 'class': 'ol-scale-line ol-unselectable' + }, this.innerElement_); + + /** + * @private + * @type {number} + */ + this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64; + + /** + * @private + * @type {ol.control.ScaleLineUnits} + */ + this.units_ = goog.isDef(options.units) ? + options.units : ol.control.ScaleLineUnits.METRIC; + + /** + * @private + * @type {Array.} + */ + this.listenerKeys_ = null; + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = false; + + /** + * @private + * @type {number|undefined} + */ + this.renderedWidth_; + + /** + * @private + * @type {string} + */ + this.renderedHTML_ = ''; + + /** + * @private + * @type {?ol.TransformFunction} + */ + this.toEPSG4326_ = null; + + goog.base(this, { + element: this.element_, + map: options.map, + target: options.target + }); + +}; +goog.inherits(ol.control.ScaleLine, ol.control.Control); + + +/** + * @const + * @type {Array.} + */ +ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5]; + + +/** + * @param {ol.MapEvent} mapEvent Map event. + */ +ol.control.ScaleLine.prototype.handleMapPostrender = function(mapEvent) { + var frameState = mapEvent.frameState; + this.updateElement_(mapEvent.frameState); +}; + + +/** + * @inheritDoc + */ +ol.control.ScaleLine.prototype.setMap = function(map) { + if (!goog.isNull(this.listenerKeys_)) { + goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); + this.listenerKeys_ = null; + } + goog.base(this, 'setMap', map); + if (!goog.isNull(map)) { + this.listenerKeys_ = [ + goog.events.listen(map, ol.MapEventType.POSTRENDER, + this.handleMapPostrender, false, this) + ]; + } +}; + + +/** + * @param {?ol.FrameState} frameState Frame state. + * @private + */ +ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { + + if (goog.isNull(frameState)) { + if (this.renderedVisible_) { + goog.style.showElement(this.element_, false); + this.renderedVisible_ = false; + } + return; + } + + var view2DState = frameState.view2DState; + var center = view2DState.center; + var projection = view2DState.projection; + var pointResolution = + projection.getPointResolution(view2DState.resolution, center); + var projectionUnits = projection.getUnits(); + + var cosLatitude; + if (projectionUnits == ol.ProjectionUnits.DEGREES && + (this.units_ == ol.control.ScaleLineUnits.METRIC || + this.units_ == ol.control.ScaleLineUnits.IMPERIAL)) { + + // Convert pointResolution from degrees to meters + this.toEPSG4326_ = null; + cosLatitude = Math.cos(goog.math.toRadians(center.y)); + pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180; + projectionUnits = ol.ProjectionUnits.METERS; + + } else if ((projectionUnits == ol.ProjectionUnits.FEET || + projectionUnits == ol.ProjectionUnits.METERS) && + this.units_ == ol.control.ScaleLineUnits.DEGREES) { + + // Convert pointResolution from meters or feet to degrees + if (goog.isNull(this.toEPSG4326_)) { + this.toEPSG4326_ = ol.projection.getTransformFromProjections( + projection, ol.projection.get('EPSG:4326')); + } + var vertex = [center.x, center.y]; + vertex = this.toEPSG4326_(vertex, vertex, 2); + cosLatitude = Math.cos(goog.math.toRadians(vertex[1])); + var radius = ol.sphere.NORMAL.radius; + if (projectionUnits == ol.ProjectionUnits.FEET) { + radius /= 0.3048; + } + pointResolution *= 180 / (Math.PI * cosLatitude * radius); + projectionUnits = ol.ProjectionUnits.DEGREES; + + } else { + + this.toEPSG4326_ = null; + + } + + goog.asserts.assert( + ((this.units_ == ol.control.ScaleLineUnits.METRIC || + this.units_ == ol.control.ScaleLineUnits.IMPERIAL) && + projectionUnits == ol.ProjectionUnits.METERS) || + (this.units_ == ol.control.ScaleLineUnits.DEGREES && + projectionUnits == ol.ProjectionUnits.DEGREES)); + + var nominalCount = this.minWidth_ * pointResolution; + var suffix = ''; + if (this.units_ == ol.control.ScaleLineUnits.DEGREES) { + if (nominalCount < 1 / 60) { + suffix = '\u2033'; // seconds + pointResolution *= 3600; + } else if (nominalCount < 1) { + suffix = '\u2032'; // minutes + pointResolution *= 60; + } else { + suffix = '\u00b0'; // degrees + } + } else if (this.units_ == ol.control.ScaleLineUnits.IMPERIAL) { + if (nominalCount < 0.9144) { + suffix = 'in'; + pointResolution /= 0.0254; + } else if (nominalCount < 1609.344) { + suffix = 'ft'; + pointResolution /= 0.3048; + } else { + suffix = 'mi'; + pointResolution /= 1609.344; + } + } else if (this.units_ == ol.control.ScaleLineUnits.NAUTICAL) { + pointResolution /= 1852; + suffix = 'nm'; + } else if (this.units_ == ol.control.ScaleLineUnits.METRIC) { + if (nominalCount < 1) { + suffix = 'mm'; + pointResolution *= 1000; + } else if (nominalCount < 1000) { + suffix = 'm'; + } else { + suffix = 'km'; + pointResolution /= 1000; + } + } else if (this.units_ == ol.control.ScaleLineUnits.US) { + if (nominalCount < 0.9144) { + suffix = 'in'; + pointResolution *= 39.37; + } else if (nominalCount < 1609.344) { + suffix = 'ft'; + pointResolution /= 0.30480061; + } else { + suffix = 'mi'; + pointResolution /= 1609.3472; + } + } else { + goog.asserts.assert(false); + } + + var i = 3 * Math.floor( + Math.log(this.minWidth_ * pointResolution) / Math.log(10)); + var count, width; + while (true) { + count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] * + Math.pow(10, Math.floor(i / 3)); + width = Math.round(count / pointResolution); + if (width >= this.minWidth_) { + break; + } + ++i; + } + + var html = count + suffix; + if (this.renderedHTML_ != html) { + this.innerElement_.innerHTML = html; + this.renderedHTML_ = html; + } + + if (this.renderedWidth_ != width) { + this.innerElement_.style.width = width + 'px'; + this.renderedWidth_ = width; + } + + if (!this.renderedVisible_) { + goog.style.showElement(this.element_, true); + this.renderedVisible_ = true; + } + +}; diff --git a/master/ol/ol/control/zoom.exports b/master/ol/ol/control/zoom.exports new file mode 100644 index 0000000000..91cb9a7fbe --- /dev/null +++ b/master/ol/ol/control/zoom.exports @@ -0,0 +1,2 @@ +@exportClass ol.control.Zoom ol.control.ZoomOptions +@exportProperty ol.control.Zoom.prototype.setMap diff --git a/master/ol/ol/control/zoomcontrol.js b/master/ol/ol/control/zoomcontrol.js new file mode 100644 index 0000000000..ca3d316378 --- /dev/null +++ b/master/ol/ol/control/zoomcontrol.js @@ -0,0 +1,92 @@ +// FIXME works for View2D only + +goog.provide('ol.control.Zoom'); + +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('ol.control.Control'); + + +/** + * @define {number} Zoom duration. + */ +ol.control.ZOOM_DURATION = 250; + + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {ol.control.ZoomOptions=} opt_options Options. + */ +ol.control.Zoom = function(opt_options) { + + var options = goog.isDef(opt_options) ? opt_options : {}; + + var inElement = goog.dom.createDom(goog.dom.TagName.A, { + 'href': '#zoomIn', + 'class': 'ol-zoom-in' + }); + goog.events.listen(inElement, [ + goog.events.EventType.TOUCHEND, + goog.events.EventType.CLICK + ], this.handleIn_, false, this); + + var outElement = goog.dom.createDom(goog.dom.TagName.A, { + 'href': '#zoomOut', + 'class': 'ol-zoom-out' + }); + goog.events.listen(outElement, [ + goog.events.EventType.TOUCHEND, + goog.events.EventType.CLICK + ], this.handleOut_, false, this); + + var element = goog.dom.createDom( + goog.dom.TagName.DIV, 'ol-zoom ol-unselectable', inElement, outElement); + + goog.base(this, { + element: element, + map: options.map, + target: options.target + }); + + /** + * @type {number} + * @private + */ + this.delta_ = goog.isDef(options.delta) ? options.delta : 1; + +}; +goog.inherits(ol.control.Zoom, ol.control.Control); + + +/** + * @param {goog.events.BrowserEvent} browserEvent The browser event to handle. + * @private + */ +ol.control.Zoom.prototype.handleIn_ = function(browserEvent) { + // prevent #zoomIn anchor from getting appended to the url + browserEvent.preventDefault(); + var map = this.getMap(); + map.requestRenderFrame(); + // FIXME works for View2D only + map.getView().zoomByDelta(map, this.delta_, undefined, + ol.control.ZOOM_DURATION); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent The browser event to handle. + * @private + */ +ol.control.Zoom.prototype.handleOut_ = function(browserEvent) { + // prevent #zoomOut anchor from getting appended to the url + browserEvent.preventDefault(); + var map = this.getMap(); + map.requestRenderFrame(); + // FIXME works for View2D only + map.getView().zoomByDelta(map, -this.delta_, undefined, + ol.control.ZOOM_DURATION); +}; diff --git a/master/ol/ol/coordinate.exports b/master/ol/ol/coordinate.exports new file mode 100644 index 0000000000..1dec787cd7 --- /dev/null +++ b/master/ol/ol/coordinate.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.Coordinate +@exportProperty ol.Coordinate.toStringHDMS diff --git a/master/ol/ol/coordinate.js b/master/ol/ol/coordinate.js new file mode 100644 index 0000000000..dcf4832038 --- /dev/null +++ b/master/ol/ol/coordinate.js @@ -0,0 +1,106 @@ +goog.provide('ol.Coordinate'); +goog.provide('ol.CoordinateFormatType'); + +goog.require('goog.math'); +goog.require('goog.math.Vec2'); + + +/** + * @typedef {function((ol.Coordinate|undefined)): string} + */ +ol.CoordinateFormatType; + + + +/** + * Two dimensional coordinate which does not know its projection. + * + * @constructor + * @extends {goog.math.Vec2} + * @param {number} x X. + * @param {number} y Y. + */ +ol.Coordinate = function(x, y) { + goog.base(this, x, y); +}; +goog.inherits(ol.Coordinate, goog.math.Vec2); + + +/** + * @const + * @type {ol.Coordinate} + */ +ol.Coordinate.ZERO = new ol.Coordinate(0, 0); + + +/** + * @param {number=} opt_precision Precision. + * @return {ol.CoordinateFormatType} Coordinate format. + */ +ol.Coordinate.createStringXY = function(opt_precision) { + return function(coordinate) { + return ol.Coordinate.toStringXY(coordinate, opt_precision); + }; +}; + + +/** + * @private + * @param {number} degrees Degrees. + * @param {string} hemispheres Hemispheres. + * @return {string} String. + */ +ol.Coordinate.degreesToStringHDMS_ = function(degrees, hemispheres) { + var normalizedDegrees = goog.math.modulo(degrees + 180, 360) - 180; + var x = Math.abs(Math.round(3600 * normalizedDegrees)); + return Math.floor(x / 3600) + '\u00b0 ' + + Math.floor((x / 60) % 60) + '\u2032 ' + + Math.floor(x % 60) + '\u2033 ' + + hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0); +}; + + +/** + * @param {ol.Coordinate|undefined} coordinate Coordinate. + * @return {string} Hemisphere, degrees, minutes and seconds. + */ +ol.Coordinate.toStringHDMS = function(coordinate) { + if (goog.isDef(coordinate)) { + return ol.Coordinate.degreesToStringHDMS_(coordinate.y, 'NS') + ' ' + + ol.Coordinate.degreesToStringHDMS_(coordinate.x, 'EW'); + } else { + return ''; + } +}; + + +/** + * @param {ol.Coordinate|undefined} coordinate Coordinate. + * @param {number=} opt_precision Precision. + * @return {string} XY. + */ +ol.Coordinate.toStringXY = function(coordinate, opt_precision) { + if (goog.isDef(coordinate)) { + var precision = opt_precision || 0; + return coordinate.x.toFixed(precision) + ', ' + + coordinate.y.toFixed(precision); + } else { + return ''; + } +}; + + +/** + * Create an ol.Coordinate from an Array and take into account axis order. + * @param {Array} array The array with coordinates. + * @param {string} axis the axis info. + * @return {ol.Coordinate} The coordinate created. + */ +ol.Coordinate.fromProjectedArray = function(array, axis) { + var firstAxis = axis.charAt(0); + if (firstAxis === 'n' || firstAxis === 's') { + return new ol.Coordinate(array[1], array[0]); + } else { + return new ol.Coordinate(array[0], array[1]); + } +}; diff --git a/master/ol/ol/dom/dom.js b/master/ol/ol/dom/dom.js new file mode 100644 index 0000000000..7fc85d93aa --- /dev/null +++ b/master/ol/ol/dom/dom.js @@ -0,0 +1,86 @@ +// FIXME add tests for browser features (Modernizr?) +// FIXME implement Matrix Filter for IE < 9 + +goog.provide('ol.dom'); +goog.provide('ol.dom.BrowserFeature'); + +goog.require('goog.vec.Mat4'); + + +/** + * @enum {boolean} + */ +ol.dom.BrowserFeature = { + CAN_USE_CSS_TRANSFORM: false, + CAN_USE_CSS_TRANSFORM3D: true, + CAN_USE_MATRIX_FILTER: false +}; + + +/** + * @param {Element} element Element. + * @param {string} value Value. + */ +ol.dom.setTransform = function(element, value) { + var style = element.style; + style.WebkitTransform = value; + style.MozTransform = value; + style.OTransform = value; + style.transform = value; +}; + + +/** + * @param {Element} element Element. + * @param {goog.vec.Mat4.AnyType} transform Matrix. + * @param {number=} opt_precision Precision. + */ +ol.dom.transformElement2D = function(element, transform, opt_precision) { + // using matrix() causes gaps in Chrome and Firefox on Mac OS X, so prefer + // matrix3d() + var i; + if (ol.dom.BrowserFeature.CAN_USE_CSS_TRANSFORM3D) { + var value3D; + if (goog.isDef(opt_precision)) { + /** @type {Array.} */ + var strings3D = new Array(16); + for (i = 0; i < 16; ++i) { + strings3D[i] = transform[i].toFixed(opt_precision); + } + value3D = strings3D.join(','); + } else { + value3D = transform.join(','); + } + ol.dom.setTransform(element, 'matrix3d(' + value3D + ')'); + } else if (ol.dom.BrowserFeature.CAN_USE_CSS_TRANSFORM) { + /** @type {Array.} */ + var transform2D = [ + goog.vec.Mat4.getElement(transform, 0, 0), + goog.vec.Mat4.getElement(transform, 1, 0), + goog.vec.Mat4.getElement(transform, 0, 1), + goog.vec.Mat4.getElement(transform, 1, 1), + goog.vec.Mat4.getElement(transform, 0, 3), + goog.vec.Mat4.getElement(transform, 1, 3) + ]; + var value2D; + if (goog.isDef(opt_precision)) { + /** @type {Array.} */ + var strings2D = new Array(6); + for (i = 0; i < 6; ++i) { + strings2D[i] = transform2D[i].toFixed(opt_precision); + } + value2D = strings2D.join(','); + } else { + value2D = transform2D.join(','); + } + ol.dom.setTransform(element, 'matrix(' + value2D + ')'); + } else if (ol.dom.BrowserFeature.CAN_USE_MATRIX_FILTER) { + // http://msdn.microsoft.com/en-us/library/ms533014%28VS.85,loband%29.aspx + goog.asserts.assert(false); // FIXME + } else { + // FIXME check this code! + var style = element.style; + style.left = Math.round(goog.vec.Mat4.getElement(transform, 0, 3)) + 'px'; + style.top = Math.round(goog.vec.Mat4.getElement(transform, 1, 3)) + 'px'; + } +}; diff --git a/master/ol/ol/easing.exports b/master/ol/ol/easing.exports new file mode 100644 index 0000000000..9ea3bdc094 --- /dev/null +++ b/master/ol/ol/easing.exports @@ -0,0 +1,8 @@ +@exportSymbol ol.easing +@exportProperty ol.easing.bounce +@exportProperty ol.easing.easeIn +@exportProperty ol.easing.easeOut +@exportProperty ol.easing.elastic +@exportProperty ol.easing.inAndOut +@exportProperty ol.easing.linear +@exportProperty ol.easing.upAndDown diff --git a/master/ol/ol/easing.js b/master/ol/ol/easing.js new file mode 100644 index 0000000000..9e829f3a93 --- /dev/null +++ b/master/ol/ol/easing.js @@ -0,0 +1,83 @@ +goog.provide('ol.easing'); + +goog.require('goog.fx.easing'); + + +/** + * from https://raw.github.com/DmitryBaranovskiy/raphael/master/raphael.js + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.bounce = function(t) { + var s = 7.5625, p = 2.75, l; + if (t < (1 / p)) { + l = s * t * t; + } else { + if (t < (2 / p)) { + t -= (1.5 / p); + l = s * t * t + 0.75; + } else { + if (t < (2.5 / p)) { + t -= (2.25 / p); + l = s * t * t + 0.9375; + } else { + t -= (2.625 / p); + l = s * t * t + 0.984375; + } + } + } + return l; +}; + + +/** + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.easeIn = goog.fx.easing.easeIn; + + +/** + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.easeOut = goog.fx.easing.easeOut; + + +/** + * from https://raw.github.com/DmitryBaranovskiy/raphael/master/raphael.js + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.elastic = function(t) { + return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * (2 * Math.PI) / 0.3) + 1; +}; + + +/** + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.inAndOut = goog.fx.easing.inAndOut; + + +/** + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.linear = function(t) { + return t; +}; + + +/** + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + */ +ol.easing.upAndDown = function(t) { + if (t < 0.5) { + return ol.easing.inAndOut(2 * t); + } else { + return 1 - ol.easing.inAndOut(2 * (t - 0.5)); + } +}; diff --git a/master/ol/ol/ellipsoid.js b/master/ol/ol/ellipsoid.js new file mode 100644 index 0000000000..1669c7de5f --- /dev/null +++ b/master/ol/ol/ellipsoid.js @@ -0,0 +1,170 @@ +goog.provide('ol.Ellipsoid'); + +goog.require('goog.math'); +goog.require('ol.Coordinate'); + + + +/** + * @constructor + * @param {number} a Major radius. + * @param {number} flattening Flattening. + */ +ol.Ellipsoid = function(a, flattening) { + + /** + * @type {number} + */ + this.a = a; + + /** + * @type {number} + */ + this.flattening = flattening; + + /** + * @type {number} + */ + this.b = this.a * (1 - this.flattening); + +}; + + +/** + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 1. + * @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence. + * @param {number=} opt_maxIterations Maximum iterations. + * @return {{distance: number, initialBearing: number, finalBearing: number}} + * Vincenty. + */ +ol.Ellipsoid.prototype.vincenty = + function(c1, c2, opt_minDeltaLambda, opt_maxIterations) { + var minDeltaLambda = goog.isDef(opt_minDeltaLambda) ? + opt_minDeltaLambda : 1e-12; + var maxIterations = goog.isDef(opt_maxIterations) ? + opt_maxIterations : 100; + var f = this.flattening; + var lat1 = goog.math.toRadians(c1.y); + var lat2 = goog.math.toRadians(c2.y); + var deltaLon = goog.math.toRadians(c2.x - c1.x); + var U1 = Math.atan((1 - f) * Math.tan(lat1)); + var cosU1 = Math.cos(U1); + var sinU1 = Math.sin(U1); + var U2 = Math.atan((1 - f) * Math.tan(lat2)); + var cosU2 = Math.cos(U2); + var sinU2 = Math.sin(U2); + var lambda = deltaLon; + var cosSquaredAlpha, sinAlpha; + var cosLambda, deltaLambda = Infinity, sinLambda; + var cos2SigmaM, cosSigma, sigma, sinSigma; + var i; + for (i = maxIterations; i > 0; --i) { + cosLambda = Math.cos(lambda); + sinLambda = Math.sin(lambda); + var x = cosU2 * sinLambda; + var y = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda; + sinSigma = Math.sqrt(x * x + y * y); + if (sinSigma === 0) { + return { + distance: 0, + initialBearing: 0, + finalBearing: 0 + }; + } + cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda; + sigma = Math.atan2(sinSigma, cosSigma); + sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma; + cosSquaredAlpha = 1 - sinAlpha * sinAlpha; + cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSquaredAlpha; + if (isNaN(cos2SigmaM)) { + cos2SigmaM = 0; + } + var C = f / 16 * cosSquaredAlpha * (4 + f * (4 - 3 * cosSquaredAlpha)); + var lambdaPrime = deltaLon + (1 - C) * f * sinAlpha * (sigma + + C * sinSigma * (cos2SigmaM + + C * cosSigma * (2 * cos2SigmaM * cos2SigmaM - 1))); + deltaLambda = Math.abs(lambdaPrime - lambda); + lambda = lambdaPrime; + if (deltaLambda < minDeltaLambda) { + break; + } + } + if (i === 0) { + return { + distance: NaN, + finalBearing: NaN, + initialBearing: NaN + }; + } + var aSquared = this.a * this.a; + var bSquared = this.b * this.b; + var uSquared = cosSquaredAlpha * (aSquared - bSquared) / bSquared; + var A = 1 + uSquared / 16384 * + (4096 + uSquared * (uSquared * (320 - 175 * uSquared) - 768)); + var B = uSquared / 1024 * + (256 + uSquared * (uSquared * (74 - 47 * uSquared) - 128)); + var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * + (cosSigma * (2 * cos2SigmaM * cos2SigmaM - 1) - + B / 6 * cos2SigmaM * (4 * sinSigma * sinSigma - 3) * + (4 * cos2SigmaM * cos2SigmaM - 3))); + cosLambda = Math.cos(lambda); + sinLambda = Math.sin(lambda); + var alpha1 = Math.atan2(cosU2 * sinLambda, + cosU1 * sinU2 - sinU1 * cosU2 * cosLambda); + var alpha2 = Math.atan2(cosU1 * sinLambda, + cosU1 * sinU2 * cosLambda - sinU1 * cosU2); + return { + distance: this.b * A * (sigma - deltaSigma), + initialBearing: goog.math.toDegrees(alpha1), + finalBearing: goog.math.toDegrees(alpha2) + }; +}; + + +/** + * Returns the distance from c1 to c2 using Vincenty. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 1. + * @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence. + * @param {number=} opt_maxIterations Maximum iterations. + * @return {number} Vincenty distance. + */ +ol.Ellipsoid.prototype.vincentyDistance = + function(c1, c2, opt_minDeltaLambda, opt_maxIterations) { + var vincenty = this.vincenty(c1, c2, opt_minDeltaLambda, opt_maxIterations); + return vincenty.distance; +}; + + +/** + * Returns the final bearing from c1 to c2 using Vincenty. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 1. + * @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence. + * @param {number=} opt_maxIterations Maximum iterations. + * @return {number} Initial bearing. + */ +ol.Ellipsoid.prototype.vincentyFinalBearing = + function(c1, c2, opt_minDeltaLambda, opt_maxIterations) { + var vincenty = this.vincenty(c1, c2, opt_minDeltaLambda, opt_maxIterations); + return vincenty.finalBearing; +}; + + +/** + * Returns the initial bearing from c1 to c2 using Vincenty. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 1. + * @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence. + * @param {number=} opt_maxIterations Maximum iterations. + * @return {number} Initial bearing. + */ +ol.Ellipsoid.prototype.vincentyInitialBearing = + function(c1, c2, opt_minDeltaLambda, opt_maxIterations) { + var vincenty = this.vincenty(c1, c2, opt_minDeltaLambda, opt_maxIterations); + return vincenty.initialBearing; +}; diff --git a/master/ol/ol/ellipsoid/wgs84.js b/master/ol/ol/ellipsoid/wgs84.js new file mode 100644 index 0000000000..e5244b80d7 --- /dev/null +++ b/master/ol/ol/ellipsoid/wgs84.js @@ -0,0 +1,10 @@ +goog.provide('ol.ellipsoid.WGS84'); + +goog.require('ol.Ellipsoid'); + + +/** + * @const + * @type {ol.Ellipsoid} + */ +ol.ellipsoid.WGS84 = new ol.Ellipsoid(6378137, 1 / 298.257223563); diff --git a/master/ol/ol/extent.exports b/master/ol/ol/extent.exports new file mode 100644 index 0000000000..b52ee8007a --- /dev/null +++ b/master/ol/ol/extent.exports @@ -0,0 +1,3 @@ +@exportSymbol ol.Extent +@exportProperty ol.Extent.prototype.getHeight +@exportProperty ol.Extent.prototype.getWidth diff --git a/master/ol/ol/extent.js b/master/ol/ol/extent.js new file mode 100644 index 0000000000..5595382e7c --- /dev/null +++ b/master/ol/ol/extent.js @@ -0,0 +1,117 @@ +goog.provide('ol.Extent'); + +goog.require('ol.Coordinate'); +goog.require('ol.Rectangle'); +goog.require('ol.TransformFunction'); + + + +/** + * Rectangular extent which is not rotated. An extent does not know its + * projection. + * + * @constructor + * @extends {ol.Rectangle} + * @param {number} minX Minimum X. + * @param {number} minY Minimum Y. + * @param {number} maxX Maximum X. + * @param {number} maxY Maximum Y. + */ +ol.Extent = function(minX, minY, maxX, maxY) { + goog.base(this, minX, minY, maxX, maxY); +}; +goog.inherits(ol.Extent, ol.Rectangle); + + +/** + * Builds an extent that includes all given coordinates. + * + * @param {...ol.Coordinate} var_args Coordinates. + * @return {!ol.Extent} Bounding extent. + */ +ol.Extent.boundingExtent = function(var_args) { + var coordinate0 = arguments[0]; + var extent = new ol.Extent(coordinate0.x, coordinate0.y, + coordinate0.x, coordinate0.y); + var i; + for (i = 1; i < arguments.length; ++i) { + var coordinate = arguments[i]; + extent.minX = Math.min(extent.minX, coordinate.x); + extent.minY = Math.min(extent.minY, coordinate.y); + extent.maxX = Math.max(extent.maxX, coordinate.x); + extent.maxY = Math.max(extent.maxY, coordinate.y); + } + return extent; +}; + + +/** + * Checks if the passed coordinate is contained or on the edge + * of the extent. + * + * @param {ol.Coordinate} coordinate Coordinate. + * @return {boolean} Contains. + */ +ol.Extent.prototype.containsCoordinate = function(coordinate) { + return this.minX <= coordinate.x && coordinate.x <= this.maxX && + this.minY <= coordinate.y && coordinate.y <= this.maxY; +}; + + +/** + * Checks if the passed extent is contained or on the edge of the + * extent. + * + * @param {ol.Extent} extent Extent. + * @return {boolean} Contains. + */ +ol.Extent.prototype.containsExtent = function(extent) { + return this.minX <= extent.minX && extent.maxX <= this.maxX && + this.minY <= extent.minY && extent.maxY <= this.maxY; +}; + + +/** + * @return {ol.Coordinate} Bottom left coordinate. + */ +ol.Extent.prototype.getBottomLeft = function() { + return new ol.Coordinate(this.minX, this.minY); +}; + + +/** + * @return {ol.Coordinate} Bottom right coordinate. + */ +ol.Extent.prototype.getBottomRight = function() { + return new ol.Coordinate(this.maxX, this.minY); +}; + + +/** + * @return {ol.Coordinate} Top left coordinate. + */ +ol.Extent.prototype.getTopLeft = function() { + return new ol.Coordinate(this.minX, this.maxY); +}; + + +/** + * @return {ol.Coordinate} Top right coordinate. + */ +ol.Extent.prototype.getTopRight = function() { + return new ol.Coordinate(this.maxX, this.maxY); +}; + + +/** + * @param {ol.TransformFunction} transformFn Transform function. + * @return {ol.Extent} Extent. + */ +ol.Extent.prototype.transform = function(transformFn) { + var input = [this.minX, this.minY, this.maxX, this.maxY]; + input = transformFn(input, input, 2); + return new ol.Extent(Math.min(input[0], input[2]), + Math.min(input[1], input[3]), + Math.max(input[0], input[2]), + Math.max(input[1], input[3])); +}; diff --git a/master/ol/ol/framestate.js b/master/ol/ol/framestate.js new file mode 100644 index 0000000000..a4c97039a0 --- /dev/null +++ b/master/ol/ol/framestate.js @@ -0,0 +1,50 @@ +// FIXME add view3DState +// FIXME factor out common code between usedTiles and wantedTiles + +goog.provide('ol.FrameState'); +goog.provide('ol.PostRenderFunction'); +goog.provide('ol.PreRenderFunction'); + +goog.require('goog.vec.Mat4'); +goog.require('ol.Attribution'); +goog.require('ol.Color'); +goog.require('ol.Extent'); +goog.require('ol.Size'); +goog.require('ol.TileQueue'); +goog.require('ol.TileRange'); +goog.require('ol.View2DState'); +goog.require('ol.layer.Layer'); +goog.require('ol.layer.LayerState'); + + +/** + * @typedef {{animate: boolean, + * attributions: Object., + * backgroundColor: ol.Color, + * coordinateToPixelMatrix: goog.vec.Mat4.Number, + * extent: (null|ol.Extent), + * layersArray: Array., + * layerStates: Object., + * pixelToCoordinateMatrix: goog.vec.Mat4.Number, + * postRenderFunctions: Array., + * size: ol.Size, + * tileQueue: ol.TileQueue, + * time: number, + * usedTiles: Object.>, + * view2DState: ol.View2DState, + * viewHints: Array., + * wantedTiles: Object.>}} + */ +ol.FrameState; + + +/** + * @typedef {function(ol.Map, ?ol.FrameState): boolean} + */ +ol.PostRenderFunction; + + +/** + * @typedef {function(ol.Map, ?ol.FrameState): boolean} + */ +ol.PreRenderFunction; diff --git a/master/ol/ol/geolocation.exports b/master/ol/ol/geolocation.exports new file mode 100644 index 0000000000..adc26edc01 --- /dev/null +++ b/master/ol/ol/geolocation.exports @@ -0,0 +1 @@ +@exportSymbol ol.Geolocation diff --git a/master/ol/ol/geolocation.js b/master/ol/ol/geolocation.js new file mode 100644 index 0000000000..74edb40540 --- /dev/null +++ b/master/ol/ol/geolocation.js @@ -0,0 +1,312 @@ +// FIXME handle geolocation not supported +// FIXME handle geolocation errors + +goog.provide('ol.Geolocation'); +goog.provide('ol.GeolocationProperty'); + +goog.require('goog.functions'); +goog.require('goog.math'); +goog.require('ol.Coordinate'); +goog.require('ol.Object'); +goog.require('ol.Projection'); +goog.require('ol.projection'); + + +/** + * @enum {string} + */ +ol.GeolocationProperty = { + ACCURACY: 'accuracy', + ALTITUDE: 'altitude', + ALTITUDE_ACCURACY: 'altitudeAccuracy', + HEADING: 'heading', + POSITION: 'position', + PROJECTION: 'projection', + SPEED: 'speed', + TRACKING: 'tracking', + TRACKING_OPTIONS: 'trackingOptions' +}; + + + +/** + * @constructor + * @extends {ol.Object} + */ +ol.Geolocation = function() { + + goog.base(this); + + /** + * The unprojected (EPSG:4326) device position. + * @private + * @type {ol.Coordinate} + */ + this.position_ = null; + + /** + * @private + * @type {number|undefined} + */ + this.watchId_; + + this.setTracking(false); + + goog.events.listen( + this, ol.Object.getChangedEventType(ol.GeolocationProperty.PROJECTION), + this.handleProjectionChanged_, false, this); + goog.events.listen( + this, ol.Object.getChangedEventType(ol.GeolocationProperty.TRACKING), + this.handleTrackingChanged_, false, this); +}; +goog.inherits(ol.Geolocation, ol.Object); + + +/** + * @inheritDoc + */ +ol.Geolocation.prototype.disposeInternal = function() { + this.setTracking(false); + goog.base(this, 'disposeInternal'); +}; + + +/** + * @private + */ +ol.Geolocation.prototype.handleProjectionChanged_ = function() { + var projection = this.getProjection(); + if (goog.isDefAndNotNull(projection)) { + this.transformFn_ = ol.projection.getTransformFromProjections( + ol.projection.get('EPSG:4326'), projection); + if (!goog.isNull(this.position_)) { + var vertex = [this.position_.x, this.position_.y]; + vertex = this.transformFn_(vertex, vertex, 2); + this.set(ol.GeolocationProperty.POSITION, + new ol.Coordinate(vertex[0], vertex[1])); + } + } +}; + + +/** + * @private + */ +ol.Geolocation.prototype.handleTrackingChanged_ = function() { + if (ol.Geolocation.SUPPORTED) { + var tracking = this.getTracking(); + if (tracking && !goog.isDef(this.watchId_)) { + this.watchId_ = navigator.geolocation.watchPosition( + goog.bind(this.positionChange_, this), + goog.bind(this.positionError_, this), + this.getTrackingOptions()); + } else if (!tracking && goog.isDef(this.watchId_)) { + navigator.geolocation.clearWatch(this.watchId_); + this.watchId_ = undefined; + } + } +}; + + +/** + * @const + * @type {boolean} Is supported. + */ +ol.Geolocation.SUPPORTED = 'geolocation' in navigator; + + +/** + * @private + * @param {GeolocationPosition} position position event. + */ +ol.Geolocation.prototype.positionChange_ = function(position) { + var coords = position.coords; + this.set(ol.GeolocationProperty.ACCURACY, coords.accuracy); + this.set(ol.GeolocationProperty.ALTITUDE, + goog.isNull(coords.altitude) ? undefined : coords.altitude); + this.set(ol.GeolocationProperty.ALTITUDE_ACCURACY, + goog.isNull(coords.altitudeAccuracy) ? + undefined : coords.altitudeAccuracy); + this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ? + undefined : goog.math.toRadians(coords.heading)); + this.position_ = new ol.Coordinate(coords.longitude, coords.latitude); + var vertex = [coords.longitude, coords.latitude]; + vertex = this.transformFn_(vertex, vertex, 2); + this.set(ol.GeolocationProperty.POSITION, + new ol.Coordinate(vertex[0], vertex[1])); + this.set(ol.GeolocationProperty.SPEED, + goog.isNull(coords.speed) ? undefined : coords.speed); +}; + + +/** + * @private + * @param {GeolocationPositionError} error error object. + */ +ol.Geolocation.prototype.positionError_ = function(error) { +}; + + +/** + * The accuracy of the position in meters. + * @return {number|undefined} accuracy. + */ +ol.Geolocation.prototype.getAccuracy = function() { + return /** @type {number} */ ( + this.get(ol.GeolocationProperty.ACCURACY)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getAccuracy', + ol.Geolocation.prototype.getAccuracy); + + +/** + * @return {number|undefined} Altitude. + */ +ol.Geolocation.prototype.getAltitude = function() { + return /** @type {number|undefined} */ ( + this.get(ol.GeolocationProperty.ALTITUDE)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getAltitude', + ol.Geolocation.prototype.getAltitude); + + +/** + * @return {number|undefined} Altitude accuracy. + */ +ol.Geolocation.prototype.getAltitudeAccuracy = function() { + return /** @type {number|undefined} */ ( + this.get(ol.GeolocationProperty.ALTITUDE_ACCURACY)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getAltitudeAccuracy', + ol.Geolocation.prototype.getAltitudeAccuracy); + + +/** + * @return {number|undefined} Heading. + */ +ol.Geolocation.prototype.getHeading = function() { + return /** @type {number|undefined} */ ( + this.get(ol.GeolocationProperty.HEADING)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getHeading', + ol.Geolocation.prototype.getHeading); + + +/** + * The position of the device. + * @return {ol.Coordinate|undefined} position. + */ +ol.Geolocation.prototype.getPosition = function() { + return /** @type {ol.Coordinate} */ ( + this.get(ol.GeolocationProperty.POSITION)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getPosition', + ol.Geolocation.prototype.getPosition); + + +/** + * @return {ol.Projection|undefined} projection. + */ +ol.Geolocation.prototype.getProjection = function() { + return /** @type {ol.Projection} */ ( + this.get(ol.GeolocationProperty.PROJECTION)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getProjection', + ol.Geolocation.prototype.getProjection); + + +/** + * @return {number|undefined} Speed. + */ +ol.Geolocation.prototype.getSpeed = function() { + return /** @type {number|undefined} */ ( + this.get(ol.GeolocationProperty.SPEED)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getSpeed', + ol.Geolocation.prototype.getSpeed); + + +/** + * @return {boolean|undefined} tracking. + */ +ol.Geolocation.prototype.getTracking = function() { + return /** @type {boolean} */ ( + this.get(ol.GeolocationProperty.TRACKING)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getTracking', + ol.Geolocation.prototype.getTracking); + + +/** + * @return {GeolocationPositionOptions|undefined} tracking options. + */ +ol.Geolocation.prototype.getTrackingOptions = function() { + return /** @type {GeolocationPositionOptions} */ ( + this.get(ol.GeolocationProperty.TRACKING_OPTIONS)); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'getTrackingOptions', + ol.Geolocation.prototype.getTrackingOptions); + + +/** + * @param {ol.Projection} projection Projection. + */ +ol.Geolocation.prototype.setProjection = function(projection) { + this.set(ol.GeolocationProperty.PROJECTION, projection); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'setProjection', + ol.Geolocation.prototype.setProjection); + + +/** + * @param {boolean} tracking Enable or disable tracking. + */ +ol.Geolocation.prototype.setTracking = function(tracking) { + this.set(ol.GeolocationProperty.TRACKING, tracking); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'setTracking', + ol.Geolocation.prototype.setTracking); + + +/** + * @param {GeolocationPositionOptions} options Tracking options. + */ +ol.Geolocation.prototype.setTrackingOptions = function(options) { + this.set(ol.GeolocationProperty.TRACKING_OPTIONS, options); +}; +goog.exportProperty( + ol.Geolocation.prototype, + 'setTrackingOptions', + ol.Geolocation.prototype.setTrackingOptions); + + +/** + * @private + * @param {Array.} input Input coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output coordinate values. + */ +ol.Geolocation.prototype.transformFn_ = goog.functions.identity; diff --git a/master/ol/ol/image.js b/master/ol/ol/image.js new file mode 100644 index 0000000000..41d5e6fc88 --- /dev/null +++ b/master/ol/ol/image.js @@ -0,0 +1,203 @@ +goog.provide('ol.Image'); +goog.provide('ol.ImageState'); + +goog.require('goog.array'); +goog.require('goog.events'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); + + +/** + * @enum {number} + */ +ol.ImageState = { + IDLE: 0, + LOADING: 1, + LOADED: 2, + ERROR: 3 +}; + + + +/** + * @constructor + * @extends {goog.events.EventTarget} + * @param {ol.Extent} extent Extent. + * @param {number} resolution Resolution. + * @param {string} src Image source URI. + * @param {?string} crossOrigin Cross origin. + * @param {Array.} attributions Attributions. + */ +ol.Image = function(extent, resolution, src, crossOrigin, attributions) { + + /** + * @private + * @type {Array.} + */ + this.attributions_ = attributions; + + /** + * @private + * @type {ol.Extent} + */ + this.extent_ = extent; + + /** + * @private + * @type {string} + */ + this.src_ = src; + + /** + * @private + * @type {number} + */ + this.resolution_ = resolution; + + /** + * @private + * @type {Image} + */ + this.image_ = new Image(); + if (!goog.isNull(crossOrigin)) { + this.image_.crossOrigin = crossOrigin; + } + + /** + * @private + * @type {Object.} + */ + this.imageByContext_ = {}; + + /** + * @private + * @type {Array.} + */ + this.imageListenerKeys_ = null; + + /** + * @protected + * @type {ol.ImageState} + */ + this.state = ol.ImageState.IDLE; +}; +goog.inherits(ol.Image, goog.events.EventTarget); + + +/** + * @protected + */ +ol.Image.prototype.dispatchChangeEvent = function() { + this.dispatchEvent(goog.events.EventType.CHANGE); +}; + + +/** + * @return {Array.} Attributions. + */ +ol.Image.prototype.getAttributions = function() { + return this.attributions_; +}; + + +/** + * @return {ol.Extent} Extent. + */ +ol.Image.prototype.getExtent = function() { + return this.extent_; +}; + + +/** + * @param {Object=} opt_context Object. + * @return {HTMLCanvasElement|Image|HTMLVideoElement} Image. + */ +ol.Image.prototype.getImageElement = function(opt_context) { + if (goog.isDef(opt_context)) { + var image; + var key = goog.getUid(opt_context); + if (key in this.imageByContext_) { + return this.imageByContext_[key]; + } else if (goog.object.isEmpty(this.imageByContext_)) { + image = this.image_; + } else { + image = /** @type {Image} */ (this.image_.cloneNode(false)); + } + this.imageByContext_[key] = image; + return image; + } else { + return this.image_; + } +}; + + +/** + * @return {number} Resolution. + */ +ol.Image.prototype.getResolution = function() { + return this.resolution_; +}; + + +/** + * @return {ol.ImageState} State. + */ +ol.Image.prototype.getState = function() { + return this.state; +}; + + +/** + * Tracks loading or read errors. + * + * @private + */ +ol.Image.prototype.handleImageError_ = function() { + this.state = ol.ImageState.ERROR; + this.unlistenImage_(); + this.dispatchChangeEvent(); +}; + + +/** + * Tracks successful image load. + * + * @private + */ +ol.Image.prototype.handleImageLoad_ = function() { + this.state = ol.ImageState.LOADED; + this.unlistenImage_(); + this.dispatchChangeEvent(); +}; + + +/** + * Load not yet loaded URI. + */ +ol.Image.prototype.load = function() { + if (this.state == ol.ImageState.IDLE) { + this.state = ol.ImageState.LOADING; + goog.asserts.assert(goog.isNull(this.imageListenerKeys_)); + this.imageListenerKeys_ = [ + goog.events.listenOnce(this.image_, goog.events.EventType.ERROR, + this.handleImageError_, false, this), + goog.events.listenOnce(this.image_, goog.events.EventType.LOAD, + this.handleImageLoad_, false, this) + ]; + this.image_.src = this.src_; + } +}; + + +/** + * Discards event handlers which listen for load completion or errors. + * + * @private + */ +ol.Image.prototype.unlistenImage_ = function() { + goog.asserts.assert(!goog.isNull(this.imageListenerKeys_)); + goog.array.forEach(this.imageListenerKeys_, goog.events.unlistenByKey); + this.imageListenerKeys_ = null; +}; diff --git a/master/ol/ol/imagetile.js b/master/ol/ol/imagetile.js new file mode 100644 index 0000000000..22b2ae6df2 --- /dev/null +++ b/master/ol/ol/imagetile.js @@ -0,0 +1,138 @@ +goog.provide('ol.ImageTile'); + +goog.require('goog.array'); +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileState'); + + + +/** + * @constructor + * @extends {ol.Tile} + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {ol.TileState} state State. + * @param {string} src Image source URI. + * @param {?string} crossOrigin Cross origin. + */ +ol.ImageTile = function(tileCoord, state, src, crossOrigin) { + + goog.base(this, tileCoord, state); + + /** + * Image URI + * + * @private + * @type {string} + */ + this.src_ = src; + + /** + * @private + * @type {Image} + */ + this.image_ = new Image(); + if (!goog.isNull(crossOrigin)) { + this.image_.crossOrigin = crossOrigin; + } + + /** + * @private + * @type {Object.} + */ + this.imageByContext_ = {}; + + /** + * @private + * @type {Array.} + */ + this.imageListenerKeys_ = null; + +}; +goog.inherits(ol.ImageTile, ol.Tile); + + +/** + * @inheritDoc + */ +ol.ImageTile.prototype.getImage = function(opt_context) { + if (goog.isDef(opt_context)) { + var image; + var key = goog.getUid(opt_context); + if (key in this.imageByContext_) { + return this.imageByContext_[key]; + } else if (goog.object.isEmpty(this.imageByContext_)) { + image = this.image_; + } else { + image = /** @type {Image} */ (this.image_.cloneNode(false)); + } + this.imageByContext_[key] = image; + return image; + } else { + return this.image_; + } +}; + + +/** + * @inheritDoc + */ +ol.ImageTile.prototype.getKey = function() { + return this.src_; +}; + + +/** + * Tracks loading or read errors. + * + * @private + */ +ol.ImageTile.prototype.handleImageError_ = function() { + this.state = ol.TileState.ERROR; + this.unlistenImage_(); + this.dispatchChangeEvent(); +}; + + +/** + * Tracks successful image load. + * + * @private + */ +ol.ImageTile.prototype.handleImageLoad_ = function() { + this.state = ol.TileState.LOADED; + this.unlistenImage_(); + this.dispatchChangeEvent(); +}; + + +/** + * Load not yet loaded URI. + */ +ol.ImageTile.prototype.load = function() { + if (this.state == ol.TileState.IDLE) { + this.state = ol.TileState.LOADING; + goog.asserts.assert(goog.isNull(this.imageListenerKeys_)); + this.imageListenerKeys_ = [ + goog.events.listenOnce(this.image_, goog.events.EventType.ERROR, + this.handleImageError_, false, this), + goog.events.listenOnce(this.image_, goog.events.EventType.LOAD, + this.handleImageLoad_, false, this) + ]; + this.image_.src = this.src_; + } +}; + + +/** + * Discards event handlers which listen for load completion or errors. + * + * @private + */ +ol.ImageTile.prototype.unlistenImage_ = function() { + goog.asserts.assert(!goog.isNull(this.imageListenerKeys_)); + goog.array.forEach(this.imageListenerKeys_, goog.events.unlistenByKey); + this.imageListenerKeys_ = null; +}; diff --git a/master/ol/ol/imageurlfunction.js b/master/ol/ol/imageurlfunction.js new file mode 100644 index 0000000000..5bd6ec96a7 --- /dev/null +++ b/master/ol/ol/imageurlfunction.js @@ -0,0 +1,37 @@ +goog.provide('ol.ImageUrlFunction'); +goog.provide('ol.ImageUrlFunctionType'); + +goog.require('ol.Extent'); +goog.require('ol.Size'); +goog.require('ol.source.wms'); + + +/** + * @typedef {function(ol.Extent, ol.Size, ol.Projection): (string|undefined)} + */ +ol.ImageUrlFunctionType; + + +/** + * @param {string} baseUrl Base URL (may have query data). + * @param {Object.} params WMS parameters. + * @return {ol.ImageUrlFunctionType} Image URL function. + */ +ol.ImageUrlFunction.createWMSParams = + function(baseUrl, params) { + return function(extent, size, projection) { + return ol.source.wms.getUrl( + baseUrl, params, extent, size, projection); + }; +}; + + +/** + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Size. + * @return {string|undefined} Image URL. + */ +ol.ImageUrlFunction.nullImageUrlFunction = + function(extent, size) { + return undefined; +}; diff --git a/master/ol/ol/interaction/condition.js b/master/ol/ol/interaction/condition.js new file mode 100644 index 0000000000..3644843ddc --- /dev/null +++ b/master/ol/ol/interaction/condition.js @@ -0,0 +1,68 @@ +goog.provide('ol.interaction.ConditionType'); +goog.provide('ol.interaction.condition'); + + +/** + * @typedef {function(goog.events.BrowserEvent): boolean} + */ +ol.interaction.ConditionType; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @return {boolean} True if only the alt key is pressed. + */ +ol.interaction.condition.altKeyOnly = function(browserEvent) { + return ( + browserEvent.altKey && + !browserEvent.platformModifierKey && + !browserEvent.shiftKey); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @return {boolean} True if only the alt and shift keys are pressed. + */ +ol.interaction.condition.altShiftKeysOnly = function(browserEvent) { + return ( + browserEvent.altKey && + !browserEvent.platformModifierKey && + browserEvent.shiftKey); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @return {boolean} True if only the no modifier keys are pressed. + */ +ol.interaction.condition.noModifierKeys = function(browserEvent) { + return ( + !browserEvent.altKey && + !browserEvent.platformModifierKey && + !browserEvent.shiftKey); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @return {boolean} True if only the platform modifier key is pressed. + */ +ol.interaction.condition.platformModifierKeyOnly = function(browserEvent) { + return ( + !browserEvent.altKey && + browserEvent.platformModifierKey && + !browserEvent.shiftKey); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @return {boolean} True if only the shift key is pressed. + */ +ol.interaction.condition.shiftKeyOnly = function(browserEvent) { + return ( + !browserEvent.altKey && + !browserEvent.platformModifierKey && + browserEvent.shiftKey); +}; diff --git a/master/ol/ol/interaction/dblclickzoominteraction.js b/master/ol/ol/interaction/dblclickzoominteraction.js new file mode 100644 index 0000000000..e758e67d44 --- /dev/null +++ b/master/ol/ol/interaction/dblclickzoominteraction.js @@ -0,0 +1,55 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.DblClickZoom'); + +goog.require('ol.MapBrowserEvent'); +goog.require('ol.MapBrowserEvent.EventType'); +goog.require('ol.View2D'); +goog.require('ol.interaction.Interaction'); + + +/** + * @define {number} Animation duration. + */ +ol.interaction.DBLCLICKZOOM_ANIMATION_DURATION = 250; + + + +/** + * @constructor + * @extends {ol.interaction.Interaction} + * @param {number} delta The zoom delta applied on each double click. + */ +ol.interaction.DblClickZoom = function(delta) { + /** + * @private + * @type {number} + */ + this.delta_ = delta; + + goog.base(this); +}; +goog.inherits(ol.interaction.DblClickZoom, ol.interaction.Interaction); + + +/** + * @inheritDoc + */ +ol.interaction.DblClickZoom.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK && + mapBrowserEvent.isMouseActionButton()) { + var map = mapBrowserEvent.map; + var anchor = mapBrowserEvent.getCoordinate(); + var delta = mapBrowserEvent.browserEvent.shiftKey ? + -this.delta_ : this.delta_; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + view.zoomByDelta(map, delta, anchor, + ol.interaction.DBLCLICKZOOM_ANIMATION_DURATION); + mapBrowserEvent.preventDefault(); + browserEvent.preventDefault(); + } +}; diff --git a/master/ol/ol/interaction/defaults.exports b/master/ol/ol/interaction/defaults.exports new file mode 100644 index 0000000000..2ab5e46392 --- /dev/null +++ b/master/ol/ol/interaction/defaults.exports @@ -0,0 +1 @@ +@exportSymbol ol.interaction.defaults ol.interaction.defaults diff --git a/master/ol/ol/interaction/defaults.js b/master/ol/ol/interaction/defaults.js new file mode 100644 index 0000000000..c016b690bf --- /dev/null +++ b/master/ol/ol/interaction/defaults.js @@ -0,0 +1,99 @@ +goog.provide('ol.interaction.defaults'); + +goog.require('ol.Collection'); +goog.require('ol.Kinetic'); +goog.require('ol.interaction.DblClickZoom'); +goog.require('ol.interaction.DragPan'); +goog.require('ol.interaction.DragRotate'); +goog.require('ol.interaction.DragZoom'); +goog.require('ol.interaction.Interaction'); +goog.require('ol.interaction.KeyboardPan'); +goog.require('ol.interaction.KeyboardZoom'); +goog.require('ol.interaction.MouseWheelZoom'); +goog.require('ol.interaction.TouchPan'); +goog.require('ol.interaction.TouchRotate'); +goog.require('ol.interaction.TouchZoom'); +goog.require('ol.interaction.condition'); + + +/** + * @param {ol.interaction.DefaultOptions=} opt_options Options. + * @param {Array.=} opt_interactions Additional + * interactions. + * @return {ol.Collection} Interactions. + */ +ol.interaction.defaults = function(opt_options, opt_interactions) { + + var options = goog.isDef(opt_options) ? opt_options : {}; + + var interactions = new ol.Collection(); + + var rotate = goog.isDef(options.rotate) ? + options.rotate : true; + if (rotate) { + interactions.push(new ol.interaction.DragRotate( + ol.interaction.condition.altShiftKeysOnly)); + } + + var doubleClickZoom = goog.isDef(options.doubleClickZoom) ? + options.doubleClickZoom : true; + if (doubleClickZoom) { + var zoomDelta = goog.isDef(options.zoomDelta) ? + options.zoomDelta : 1; + interactions.push(new ol.interaction.DblClickZoom(zoomDelta)); + } + + var touchPan = goog.isDef(options.touchPan) ? + options.touchPan : true; + if (touchPan) { + interactions.push(new ol.interaction.TouchPan( + new ol.Kinetic(-0.005, 0.05, 100))); + } + + var touchRotate = goog.isDef(options.touchRotate) ? + options.touchRotate : true; + if (touchRotate) { + interactions.push(new ol.interaction.TouchRotate()); + } + + var touchZoom = goog.isDef(options.touchZoom) ? + options.touchZoom : true; + if (touchZoom) { + interactions.push(new ol.interaction.TouchZoom()); + } + + var dragPan = goog.isDef(options.dragPan) ? + options.dragPan : true; + if (dragPan) { + interactions.push( + new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys, + new ol.Kinetic(-0.005, 0.05, 100))); + } + + var keyboard = goog.isDef(options.keyboard) ? + options.keyboard : true; + if (keyboard) { + interactions.push(new ol.interaction.KeyboardPan()); + interactions.push(new ol.interaction.KeyboardZoom()); + } + + var mouseWheelZoom = goog.isDef(options.mouseWheelZoom) ? + options.mouseWheelZoom : true; + if (mouseWheelZoom) { + interactions.push(new ol.interaction.MouseWheelZoom()); + } + + var shiftDragZoom = goog.isDef(options.shiftDragZoom) ? + options.shiftDragZoom : true; + if (shiftDragZoom) { + interactions.push( + new ol.interaction.DragZoom(ol.interaction.condition.shiftKeyOnly)); + } + + if (goog.isDef(opt_interactions)) { + interactions.extend(opt_interactions); + } + + return interactions; + +}; diff --git a/master/ol/ol/interaction/draginteraction.js b/master/ol/ol/interaction/draginteraction.js new file mode 100644 index 0000000000..ce39c4f9d3 --- /dev/null +++ b/master/ol/ol/interaction/draginteraction.js @@ -0,0 +1,132 @@ +goog.provide('ol.interaction.Drag'); + +goog.require('goog.asserts'); +goog.require('goog.functions'); +goog.require('ol.Coordinate'); +goog.require('ol.MapBrowserEvent'); +goog.require('ol.MapBrowserEvent.EventType'); +goog.require('ol.interaction.Interaction'); + + + +/** + * @constructor + * @extends {ol.interaction.Interaction} + */ +ol.interaction.Drag = function() { + + goog.base(this); + + /** + * @private + * @type {boolean} + */ + this.dragging_ = false; + + /** + * @type {number} + */ + this.startX = 0; + + /** + * @type {number} + */ + this.startY = 0; + + /** + * @type {number} + */ + this.offsetX = 0; + + /** + * @type {number} + */ + this.offsetY = 0; + + /** + * @type {ol.Coordinate} + */ + this.startCenter = null; + + /** + * @type {ol.Coordinate} + */ + this.startCoordinate = null; + +}; +goog.inherits(ol.interaction.Drag, ol.interaction.Interaction); + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + */ +ol.interaction.Drag.prototype.handleDrag = goog.nullFunction; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + */ +ol.interaction.Drag.prototype.handleDragEnd = goog.nullFunction; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + * @return {boolean} Capture dragging. + */ +ol.interaction.Drag.prototype.handleDragStart = goog.functions.FALSE; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + */ +ol.interaction.Drag.prototype.handleDown = goog.nullFunction; + + +/** + * @inheritDoc + */ +ol.interaction.Drag.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + var map = mapBrowserEvent.map; + if (!map.isDef()) { + return; + } + var view = map.getView(); + var browserEvent = mapBrowserEvent.browserEvent; + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DOWN) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + this.handleDown(mapBrowserEvent); + } + if (this.dragging_) { + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAG) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + this.deltaX = browserEvent.clientX - this.startX; + this.deltaY = browserEvent.clientY - this.startY; + this.handleDrag(mapBrowserEvent); + } else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAGEND) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + this.deltaX = browserEvent.clientX - this.startX; + this.deltaY = browserEvent.clientY - this.startY; + this.handleDragEnd(mapBrowserEvent); + this.dragging_ = false; + } + } else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAGSTART) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + this.startX = browserEvent.clientX; + this.startY = browserEvent.clientY; + this.deltaX = 0; + this.deltaY = 0; + this.startCenter = /** @type {!ol.Coordinate} */ (view.getCenter()); + this.startCoordinate = /** @type {ol.Coordinate} */ + (mapBrowserEvent.getCoordinate()); + var handled = this.handleDragStart(mapBrowserEvent); + if (handled) { + this.dragging_ = true; + mapBrowserEvent.preventDefault(); + } + } +}; diff --git a/master/ol/ol/interaction/dragpaninteraction.js b/master/ol/ol/interaction/dragpaninteraction.js new file mode 100644 index 0000000000..4827c92e2f --- /dev/null +++ b/master/ol/ol/interaction/dragpaninteraction.js @@ -0,0 +1,137 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.DragPan'); + +goog.require('goog.asserts'); +goog.require('ol.Coordinate'); +goog.require('ol.Kinetic'); +goog.require('ol.Pixel'); +goog.require('ol.PreRenderFunction'); +goog.require('ol.View2D'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.ConditionType'); +goog.require('ol.interaction.Drag'); + + + +/** + * @constructor + * @extends {ol.interaction.Drag} + * @param {ol.interaction.ConditionType} condition Condition. + * @param {ol.Kinetic=} opt_kinetic Kinetic object. + */ +ol.interaction.DragPan = function(condition, opt_kinetic) { + + goog.base(this); + + /** + * @private + * @type {ol.interaction.ConditionType} + */ + this.condition_ = condition; + + /** + * @private + * @type {ol.Kinetic|undefined} + */ + this.kinetic_ = opt_kinetic; + + /** + * @private + * @type {?ol.PreRenderFunction} + */ + this.kineticPreRenderFn_ = null; + +}; +goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); + + +/** + * @inheritDoc + */ +ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { + if (this.kinetic_) { + this.kinetic_.update( + mapBrowserEvent.browserEvent.clientX, + mapBrowserEvent.browserEvent.clientY); + } + var map = mapBrowserEvent.map; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var resolution = view.getResolution(); + var rotation = view.getRotation(); + var delta = + new ol.Coordinate(-resolution * this.deltaX, resolution * this.deltaY); + delta.rotate(rotation); + var newCenter = new ol.Coordinate( + this.startCenter.x + delta.x, this.startCenter.y + delta.y); + map.requestRenderFrame(); + view.setCenter(newCenter); +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { + + // FIXME works for View2D only + + var map = mapBrowserEvent.map; + var view = map.getView(); + view.setHint(ol.ViewHint.INTERACTING, -1); + + if (this.kinetic_ && this.kinetic_.end()) { + var distance = this.kinetic_.getDistance(); + var angle = this.kinetic_.getAngle(); + var center = view.getCenter(); + this.kineticPreRenderFn_ = this.kinetic_.pan(center); + map.addPreRenderFunction(this.kineticPreRenderFn_); + + var centerpx = map.getPixelFromCoordinate(center); + var destpx = new ol.Pixel( + centerpx.x - distance * Math.cos(angle), + centerpx.y - distance * Math.sin(angle)); + var dest = map.getCoordinateFromPixel(destpx); + view.setCenter(dest); + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + if (this.condition_(browserEvent)) { + if (this.kinetic_) { + this.kinetic_.begin(); + this.kinetic_.update(browserEvent.clientX, browserEvent.clientY); + } + var map = mapBrowserEvent.map; + map.requestRenderFrame(); + map.getView().setHint(ol.ViewHint.INTERACTING, 1); + return true; + } else { + return false; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragPan.prototype.handleDown = function(mapBrowserEvent) { + var map = mapBrowserEvent.map; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + goog.asserts.assert(!goog.isNull(mapBrowserEvent.frameState)); + if (!goog.isNull(this.kineticPreRenderFn_) && + map.removePreRenderFunction(this.kineticPreRenderFn_)) { + map.requestRenderFrame(); + view.setCenter(mapBrowserEvent.frameState.view2DState.center); + this.kineticPreRenderFn_ = null; + } +}; diff --git a/master/ol/ol/interaction/dragrotateandzoominteraction.js b/master/ol/ol/interaction/dragrotateandzoominteraction.js new file mode 100644 index 0000000000..cd8425b37a --- /dev/null +++ b/master/ol/ol/interaction/dragrotateandzoominteraction.js @@ -0,0 +1,88 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.DragRotateAndZoom'); + +goog.require('goog.math.Vec2'); +goog.require('ol.View2D'); +goog.require('ol.interaction.ConditionType'); +goog.require('ol.interaction.Drag'); + + + +/** + * @constructor + * @extends {ol.interaction.Drag} + * @param {ol.interaction.ConditionType} condition Condition. + */ +ol.interaction.DragRotateAndZoom = function(condition) { + + goog.base(this); + + /** + * @private + * @type {ol.interaction.ConditionType} + */ + this.condition_ = condition; + + /** + * @private + * @type {number|undefined} + */ + this.lastAngle_; + + /** + * @private + * @type {number|undefined} + */ + this.lastMagnitude_; + +}; +goog.inherits(ol.interaction.DragRotateAndZoom, ol.interaction.Drag); + + +/** + * @inheritDoc + */ +ol.interaction.DragRotateAndZoom.prototype.handleDrag = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + var map = mapBrowserEvent.map; + var size = map.getSize(); + var delta = new goog.math.Vec2( + browserEvent.offsetX - size.width / 2, + size.height / 2 - browserEvent.offsetY); + var theta = Math.atan2(delta.y, delta.x); + var magnitude = delta.magnitude(); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + map.requestRenderFrame(); + // FIXME the calls to map.rotate and map.zoomToResolution should use + // map.withFrozenRendering but an assertion fails :-( + if (goog.isDef(this.lastAngle_)) { + var angleDelta = theta - this.lastAngle_; + view.rotate(map, view.getRotation() - angleDelta); + } + this.lastAngle_ = theta; + if (goog.isDef(this.lastMagnitude_)) { + var resolution = this.lastMagnitude_ * (view.getResolution() / magnitude); + view.zoom(map, resolution); + } + this.lastMagnitude_ = magnitude; +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragRotateAndZoom.prototype.handleDragStart = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + if (this.condition_(browserEvent)) { + this.lastAngle_ = undefined; + this.lastMagnitude_ = undefined; + return true; + } else { + return false; + } +}; diff --git a/master/ol/ol/interaction/dragrotateinteraction.js b/master/ol/ol/interaction/dragrotateinteraction.js new file mode 100644 index 0000000000..2ad45dfa78 --- /dev/null +++ b/master/ol/ol/interaction/dragrotateinteraction.js @@ -0,0 +1,95 @@ +goog.provide('ol.interaction.DragRotate'); + +goog.require('ol.View2D'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.ConditionType'); +goog.require('ol.interaction.Drag'); + + +/** + * @define {number} Animation duration. + */ +ol.interaction.DRAGROTATE_ANIMATION_DURATION = 250; + + + +/** + * @constructor + * @extends {ol.interaction.Drag} + * @param {ol.interaction.ConditionType} condition Condition. + */ +ol.interaction.DragRotate = function(condition) { + + goog.base(this); + + /** + * @private + * @type {ol.interaction.ConditionType} + */ + this.condition_ = condition; + + /** + * @private + * @type {number|undefined} + */ + this.lastAngle_; + +}; +goog.inherits(ol.interaction.DragRotate, ol.interaction.Drag); + + +/** + * @inheritDoc + */ +ol.interaction.DragRotate.prototype.handleDrag = function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + var map = mapBrowserEvent.map; + var size = map.getSize(); + var offset = mapBrowserEvent.getPixel(); + var theta = Math.atan2(size.height / 2 - offset.y, offset.x - size.width / 2); + if (goog.isDef(this.lastAngle_)) { + var delta = theta - this.lastAngle_; + var view = map.getView(); + // FIXME supports View2D only + goog.asserts.assert(view instanceof ol.View2D); + map.requestRenderFrame(); + view.rotateWithoutConstraints(map, view.getRotation() - delta); + } + this.lastAngle_ = theta; +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragRotate.prototype.handleDragEnd = function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + var map = mapBrowserEvent.map; + // FIXME supports View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + view.rotate(map, view.getRotation(), undefined, + ol.interaction.DRAGROTATE_ANIMATION_DURATION); + view.setHint(ol.ViewHint.INTERACTING, -1); +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragRotate.prototype.handleDragStart = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + if (browserEvent.isMouseActionButton() && this.condition_(browserEvent)) { + var map = mapBrowserEvent.map; + // FIXME supports View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + map.requestRenderFrame(); + this.lastAngle_ = undefined; + view.setHint(ol.ViewHint.INTERACTING, 1); + return true; + } else { + return false; + } +}; diff --git a/master/ol/ol/interaction/dragzoominteraction.js b/master/ol/ol/interaction/dragzoominteraction.js new file mode 100644 index 0000000000..74541b4bab --- /dev/null +++ b/master/ol/ol/interaction/dragzoominteraction.js @@ -0,0 +1,96 @@ +// FIXME draw drag box +// FIXME works for View2D only + +goog.provide('ol.interaction.DragZoom'); + +goog.require('ol.Extent'); +goog.require('ol.Size'); +goog.require('ol.View2D'); +goog.require('ol.control.DragBox'); +goog.require('ol.interaction.ConditionType'); +goog.require('ol.interaction.Drag'); + + +/** + * @define {number} Hysterisis pixels. + */ +ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS = 8; + + +/** + * @const {number} + */ +ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED = + ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS * + ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS; + + + +/** + * @constructor + * @extends {ol.interaction.Drag} + * @param {ol.interaction.ConditionType} condition Condition. + */ +ol.interaction.DragZoom = function(condition) { + + goog.base(this); + + /** + * @private + * @type {ol.interaction.ConditionType} + */ + this.condition_ = condition; + + /** + * @type {ol.control.DragBox} + * @private + */ + this.dragBox_ = null; + + +}; +goog.inherits(ol.interaction.DragZoom, ol.interaction.Drag); + + +/** + * @inheritDoc + */ +ol.interaction.DragZoom.prototype.handleDragEnd = + function(mapBrowserEvent) { + this.dragBox_.setMap(null); + this.dragBox_ = null; + if (this.deltaX * this.deltaX + this.deltaY * this.deltaY >= + ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED) { + var map = mapBrowserEvent.map; + var extent = ol.Extent.boundingExtent( + this.startCoordinate, + mapBrowserEvent.getCoordinate()); + map.withFrozenRendering(function() { + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var mapSize = /** @type {ol.Size} */ (map.getSize()); + view.fitExtent(extent, mapSize); + // FIXME we should preserve rotation + view.setRotation(0); + }); + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragZoom.prototype.handleDragStart = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + if (browserEvent.isMouseActionButton() && this.condition_(browserEvent)) { + this.dragBox_ = new ol.control.DragBox({ + map: mapBrowserEvent.map, + startCoordinate: this.startCoordinate + }); + return true; + } else { + return false; + } +}; diff --git a/master/ol/ol/interaction/interaction.js b/master/ol/ol/interaction/interaction.js new file mode 100644 index 0000000000..f94d5e950f --- /dev/null +++ b/master/ol/ol/interaction/interaction.js @@ -0,0 +1,20 @@ +// FIXME factor out key precondition (shift et. al) + +goog.provide('ol.interaction.Interaction'); + +goog.require('ol.MapBrowserEvent'); + + + +/** + * @constructor + */ +ol.interaction.Interaction = function() { +}; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + */ +ol.interaction.Interaction.prototype.handleMapBrowserEvent = + goog.abstractMethod; diff --git a/master/ol/ol/interaction/keyboard.exports b/master/ol/ol/interaction/keyboard.exports new file mode 100644 index 0000000000..45ab209343 --- /dev/null +++ b/master/ol/ol/interaction/keyboard.exports @@ -0,0 +1,3 @@ +@exportSymbol ol.interaction.Keyboard +@exportProperty ol.interaction.Keyboard.prototype.addCallback + diff --git a/master/ol/ol/interaction/keyboardinteraction.js b/master/ol/ol/interaction/keyboardinteraction.js new file mode 100644 index 0000000000..8057b858ff --- /dev/null +++ b/master/ol/ol/interaction/keyboardinteraction.js @@ -0,0 +1,53 @@ +// FIXME this class is ugly and should be removed + +goog.provide('ol.interaction.Keyboard'); + +goog.require('ol.interaction.Interaction'); + + + +/** + * @constructor + * @extends {ol.interaction.Interaction} + */ +ol.interaction.Keyboard = function() { + + goog.base(this); + + /** + * @private + * @type {Object.} + */ + this.charCodeCallbacks_ = {}; + +}; +goog.inherits(ol.interaction.Keyboard, ol.interaction.Interaction); + + +/** + * @param {string} s String. + * @param {Function} callback Callback. + */ +ol.interaction.Keyboard.prototype.addCallback = function(s, callback) { + var i; + for (i = 0; i < s.length; ++i) { + this.charCodeCallbacks_[s.charCodeAt(i)] = callback; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.Keyboard.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { + var keyEvent = /** @type {goog.events.KeyEvent} */ + (mapBrowserEvent.browserEvent); + var callback = this.charCodeCallbacks_[keyEvent.charCode]; + if (callback) { + callback(); + mapBrowserEvent.preventDefault(); + } + } +}; diff --git a/master/ol/ol/interaction/keyboardpaninteraction.js b/master/ol/ol/interaction/keyboardpaninteraction.js new file mode 100644 index 0000000000..cb1ff8b11e --- /dev/null +++ b/master/ol/ol/interaction/keyboardpaninteraction.js @@ -0,0 +1,77 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.KeyboardPan'); + +goog.require('goog.events.KeyCodes'); +goog.require('goog.events.KeyHandler.EventType'); +goog.require('ol.Coordinate'); +goog.require('ol.View2D'); +goog.require('ol.interaction.Interaction'); + + +/** + * @define {number} Pan duration. + */ +ol.interaction.KEYBOARD_PAN_DURATION = 100; + + + +/** + * @constructor + * @extends {ol.interaction.Interaction} + * @param {ol.interaction.KeyboardPanOptions=} opt_options Options. + */ +ol.interaction.KeyboardPan = function(opt_options) { + + goog.base(this); + + var options = goog.isDef(opt_options) ? opt_options : {}; + + /** + * @private + * @type {number} + */ + this.delta_ = goog.isDef(options.delta) ? options.delta : 128; + +}; +goog.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction); + + +/** + * @inheritDoc + */ +ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { + var keyEvent = /** @type {goog.events.KeyEvent} */ + (mapBrowserEvent.browserEvent); + var keyCode = keyEvent.keyCode; + if (keyCode == goog.events.KeyCodes.DOWN || + keyCode == goog.events.KeyCodes.LEFT || + keyCode == goog.events.KeyCodes.RIGHT || + keyCode == goog.events.KeyCodes.UP) { + var map = mapBrowserEvent.map; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var resolution = view.getResolution(); + var rotation = view.getRotation(); + var mapUnitsDelta = resolution * this.delta_; + var deltaX = 0, deltaY = 0; + if (keyCode == goog.events.KeyCodes.DOWN) { + deltaY = -mapUnitsDelta; + } else if (keyCode == goog.events.KeyCodes.LEFT) { + deltaX = -mapUnitsDelta; + } else if (keyCode == goog.events.KeyCodes.RIGHT) { + deltaX = mapUnitsDelta; + } else { + deltaY = mapUnitsDelta; + } + var delta = new ol.Coordinate(deltaX, deltaY); + delta.rotate(rotation); + view.pan(map, delta, ol.interaction.KEYBOARD_PAN_DURATION); + keyEvent.preventDefault(); + mapBrowserEvent.preventDefault(); + } + } +}; diff --git a/master/ol/ol/interaction/keyboardzoominteraction.js b/master/ol/ol/interaction/keyboardzoominteraction.js new file mode 100644 index 0000000000..5cdaa334e1 --- /dev/null +++ b/master/ol/ol/interaction/keyboardzoominteraction.js @@ -0,0 +1,60 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.KeyboardZoom'); + +goog.require('goog.events.KeyHandler.EventType'); +goog.require('ol.View2D'); +goog.require('ol.interaction.Interaction'); + + +/** + * @define {number} Zoom duration. + */ +ol.interaction.KEYBOARD_ZOOM_DURATION = 100; + + + +/** + * @constructor + * @param {ol.interaction.KeyboardZoomOptions=} opt_options Options. + * @extends {ol.interaction.Interaction} + */ +ol.interaction.KeyboardZoom = function(opt_options) { + + goog.base(this); + + var options = goog.isDef(opt_options) ? opt_options : {}; + + /** + * @private + * @type {number} + */ + this.delta_ = goog.isDef(options.delta) ? options.delta : 1; + +}; +goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction); + + +/** + * @inheritDoc + */ +ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { + var keyEvent = /** @type {goog.events.KeyEvent} */ + (mapBrowserEvent.browserEvent); + var charCode = keyEvent.charCode; + if (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0)) { + var map = mapBrowserEvent.map; + var delta = (charCode == '+'.charCodeAt(0)) ? this.delta_ : -this.delta_; + map.requestRenderFrame(); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + view.zoomByDelta(map, delta, undefined, + ol.interaction.KEYBOARD_ZOOM_DURATION); + keyEvent.preventDefault(); + mapBrowserEvent.preventDefault(); + } + } +}; diff --git a/master/ol/ol/interaction/mousewheelzoominteraction.js b/master/ol/ol/interaction/mousewheelzoominteraction.js new file mode 100644 index 0000000000..125dba9713 --- /dev/null +++ b/master/ol/ol/interaction/mousewheelzoominteraction.js @@ -0,0 +1,121 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.MouseWheelZoom'); + +goog.require('goog.events.MouseWheelEvent'); +goog.require('goog.events.MouseWheelHandler.EventType'); +goog.require('goog.math'); +goog.require('ol.Coordinate'); +goog.require('ol.View2D'); +goog.require('ol.interaction.Interaction'); + + +/** + * @define {number} Animation duration. + */ +ol.interaction.MOUSEWHEELZOOM_ANIMATION_DURATION = 250; + + +/** + * @define {number} Maximum delta. + */ +ol.interaction.MOUSEWHEELZOOM_MAXDELTA = 1; + + +/** + * @define {number} Timeout duration. + */ +ol.interaction.MOUSEWHEELZOOM_TIMEOUT_DURATION = 80; + + + +/** + * @constructor + * @extends {ol.interaction.Interaction} + */ +ol.interaction.MouseWheelZoom = function() { + + goog.base(this); + + /** + * @private + * @type {number} + */ + this.delta_ = 0; + + /** + * @private + * @type {?ol.Coordinate} + */ + this.lastAnchor_ = null; + + /** + * @private + * @type {number|undefined} + */ + this.startTime_ = undefined; + + /** + * @private + * @type {number|undefined} + */ + this.timeoutId_ = undefined; + +}; +goog.inherits(ol.interaction.MouseWheelZoom, ol.interaction.Interaction); + + +/** + * @inheritDoc + */ +ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + + if (mapBrowserEvent.type == + goog.events.MouseWheelHandler.EventType.MOUSEWHEEL) { + var map = mapBrowserEvent.map; + var mouseWheelEvent = /** @type {goog.events.MouseWheelEvent} */ + (mapBrowserEvent.browserEvent); + goog.asserts.assert(mouseWheelEvent instanceof goog.events.MouseWheelEvent); + + this.lastAnchor_ = mapBrowserEvent.getCoordinate(); + this.delta_ += mouseWheelEvent.deltaY / 3; + + if (!goog.isDef(this.startTime_)) { + this.startTime_ = goog.now(); + } + + var duration = ol.interaction.MOUSEWHEELZOOM_TIMEOUT_DURATION; + var timeLeft = Math.max(duration - (goog.now() - this.startTime_), 0); + + goog.global.clearTimeout(this.timeoutId_); + this.timeoutId_ = goog.global.setTimeout( + goog.bind(this.doZoom_, this, map), timeLeft); + + mapBrowserEvent.preventDefault(); + mouseWheelEvent.preventDefault(); + } +}; + + +/** + * @private + * @param {ol.Map} map Map. + */ +ol.interaction.MouseWheelZoom.prototype.doZoom_ = function(map) { + var maxDelta = ol.interaction.MOUSEWHEELZOOM_MAXDELTA; + var delta = goog.math.clamp(this.delta_, -maxDelta, maxDelta); + + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + + map.requestRenderFrame(); + view.zoomByDelta(map, -delta, this.lastAnchor_, + ol.interaction.MOUSEWHEELZOOM_ANIMATION_DURATION); + + this.delta_ = 0; + this.lastAnchor_ = null; + this.startTime_ = undefined; + this.timeoutId_ = undefined; +}; diff --git a/master/ol/ol/interaction/touchinteraction.js b/master/ol/ol/interaction/touchinteraction.js new file mode 100644 index 0000000000..1e96fe7ecb --- /dev/null +++ b/master/ol/ol/interaction/touchinteraction.js @@ -0,0 +1,120 @@ + +goog.provide('ol.interaction.Touch'); + +goog.require('goog.functions'); +goog.require('ol.MapBrowserEvent'); +goog.require('ol.MapBrowserEvent.EventType'); +goog.require('ol.Pixel'); +goog.require('ol.interaction.Interaction'); + + + +/** + * @constructor + * @extends {ol.interaction.Interaction} + */ +ol.interaction.Touch = function() { + + goog.base(this); + + /** + * @type {boolean} + * @private + */ + this.handled_ = false; + + /** + * @type {Object} + * @private + */ + this.trackedTouches_ = {}; + + /** + * @type {Array.} + * @protected + */ + this.targetTouches = []; + +}; +goog.inherits(ol.interaction.Touch, ol.interaction.Interaction); + + +/** + * @param {Array.} touches TouchEvents. + * @return {ol.Pixel} Centroid pixel. + */ +ol.interaction.Touch.centroid = function(touches) { + var length = touches.length; + var clientX = 0; + var clientY = 0; + for (var i = 0; i < length; i++) { + clientX += touches[i].clientX; + clientY += touches[i].clientY; + } + return new ol.Pixel(clientX / length, clientY / length); +}; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @private + */ +ol.interaction.Touch.prototype.updateTrackedTouches_ = + function(mapBrowserEvent) { + var event = mapBrowserEvent.browserEvent.getBrowserEvent(); + if (goog.isDef(event.targetTouches)) { + // W3C touch events + this.targetTouches = event.targetTouches; + } else { + // IE pointer event + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHEND) { + delete this.trackedTouches_[event.pointerId]; + } else { + this.trackedTouches_[event.pointerId] = event; + } + this.targetTouches = goog.object.getValues(this.trackedTouches_); + } +}; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + */ +ol.interaction.Touch.prototype.handleTouchMove = goog.nullFunction; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + * @return {boolean} Capture dragging. + */ +ol.interaction.Touch.prototype.handleTouchEnd = goog.functions.FALSE; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + * @return {boolean} Capture dragging. + */ +ol.interaction.Touch.prototype.handleTouchStart = goog.functions.FALSE; + + +/** + * @inheritDoc + */ +ol.interaction.Touch.prototype.handleMapBrowserEvent = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent.getBrowserEvent(); + this.updateTrackedTouches_(mapBrowserEvent); + if (this.handled_) { + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHMOVE) { + this.handleTouchMove(mapBrowserEvent); + } else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHEND) { + this.handled_ = this.handleTouchEnd(mapBrowserEvent); + } + } + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHSTART) { + this.handled_ = this.handleTouchStart(mapBrowserEvent); + } +}; diff --git a/master/ol/ol/interaction/touchpaninteraction.js b/master/ol/ol/interaction/touchpaninteraction.js new file mode 100644 index 0000000000..452c43159a --- /dev/null +++ b/master/ol/ol/interaction/touchpaninteraction.js @@ -0,0 +1,121 @@ +// FIXME works for View2D only +goog.provide('ol.interaction.TouchPan'); + +goog.require('goog.asserts'); +goog.require('ol.Coordinate'); +goog.require('ol.Kinetic'); +goog.require('ol.Pixel'); +goog.require('ol.PreRenderFunction'); +goog.require('ol.View'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.Touch'); + + + +/** + * @constructor + * @extends {ol.interaction.Touch} + * @param {ol.Kinetic=} opt_kinetic Kinetic object. + */ +ol.interaction.TouchPan = function(opt_kinetic) { + + goog.base(this); + + /** + * @private + * @type {ol.Kinetic|undefined} + */ + this.kinetic_ = opt_kinetic; + + /** + * @private + * @type {?ol.PreRenderFunction} + */ + this.kineticPreRenderFn_ = null; + + /** + * @type {ol.Pixel} + */ + this.lastCentroid = null; + +}; +goog.inherits(ol.interaction.TouchPan, ol.interaction.Touch); + + +/** + * @inheritDoc + */ +ol.interaction.TouchPan.prototype.handleTouchMove = function(mapBrowserEvent) { + goog.asserts.assert(this.targetTouches.length >= 1); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); + if (!goog.isNull(this.lastCentroid)) { + if (this.kinetic_) { + this.kinetic_.update(centroid.x, centroid.y); + } + var deltaX = this.lastCentroid.x - centroid.x; + var deltaY = centroid.y - this.lastCentroid.y; + var view = mapBrowserEvent.map.getView(); + var center = new ol.Coordinate(deltaX, deltaY) + .scale(view.getResolution()) + .rotate(view.getRotation()) + .add(view.getCenter()); + view.setCenter(center); + } + this.lastCentroid = centroid; +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchPan.prototype.handleTouchEnd = + function(mapBrowserEvent) { + var map = mapBrowserEvent.map; + var view = map.getView(); + if (this.targetTouches.length == 0) { + view.setHint(ol.ViewHint.INTERACTING, -1); + if (this.kinetic_ && this.kinetic_.end()) { + var distance = this.kinetic_.getDistance(); + var angle = this.kinetic_.getAngle(); + var center = view.getCenter(); + this.kineticPreRenderFn_ = this.kinetic_.pan(center); + map.addPreRenderFunction(this.kineticPreRenderFn_); + var centerpx = map.getPixelFromCoordinate(center); + var destpx = new ol.Pixel( + centerpx.x - distance * Math.cos(angle), + centerpx.y - distance * Math.sin(angle)); + var dest = map.getCoordinateFromPixel(destpx); + view.setCenter(dest); + } + return false; + } else { + this.lastCentroid = null; + return true; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchPan.prototype.handleTouchStart = + function(mapBrowserEvent) { + if (this.targetTouches.length >= 1) { + var map = mapBrowserEvent.map; + var view = map.getView(); + this.lastCentroid = null; + if (!goog.isNull(this.kineticPreRenderFn_) && + map.removePreRenderFunction(this.kineticPreRenderFn_)) { + map.requestRenderFrame(); + view.setCenter(mapBrowserEvent.frameState.view2DState.center); + this.kineticPreRenderFn_ = null; + } + if (this.kinetic_) { + this.kinetic_.begin(); + } + view.setHint(ol.ViewHint.INTERACTING, 1); + return true; + } else { + return false; + } +}; diff --git a/master/ol/ol/interaction/touchrotateinteraction.js b/master/ol/ol/interaction/touchrotateinteraction.js new file mode 100644 index 0000000000..3f4abc3ce7 --- /dev/null +++ b/master/ol/ol/interaction/touchrotateinteraction.js @@ -0,0 +1,142 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.TouchRotate'); + +goog.require('goog.asserts'); +goog.require('ol.View'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.Touch'); + + +/** + * @define {number} Animation duration. + */ +ol.interaction.TOUCHROTATE_ANIMATION_DURATION = 250; + + + +/** + +/** + * @constructor + * @extends {ol.interaction.Touch} + * @param {number=} opt_threshold Minimal angle to start a rotation. + * Default to 0.3 (radian). + */ +ol.interaction.TouchRotate = function(opt_threshold) { + + goog.base(this); + + /** + * @private + * @type {number|undefined} + */ + this.lastAngle_; + + /** + * @private + * @type {boolean} + */ + this.rotating_ = false; + + /** + * @private + * @type {number} + */ + this.rotationDelta_ = 0.0; + + /** + * @private + * @type {number} + */ + this.threshold_ = goog.isDef(opt_threshold) ? opt_threshold : 0.3; + +}; +goog.inherits(ol.interaction.TouchRotate, ol.interaction.Touch); + + +/** + * @inheritDoc + */ +ol.interaction.TouchRotate.prototype.handleTouchMove = + function(mapBrowserEvent) { + goog.asserts.assert(this.targetTouches.length >= 2); + var rotationDelta = 0.0; + + var touch0 = this.targetTouches[0]; + var touch1 = this.targetTouches[1]; + var dx = touch0.clientX - touch1.clientX; + var dy = touch0.clientY - touch1.clientY; + + // angle between touches + var angle = Math.atan2( + touch1.clientY - touch0.clientY, + touch1.clientX - touch0.clientX); + + if (goog.isDef(this.lastAngle_)) { + var delta = angle - this.lastAngle_; + this.rotationDelta_ += delta; + if (!this.rotating_ && + Math.abs(this.rotationDelta_) > this.threshold_) { + this.rotating_ = true; + } + rotationDelta = delta; + } + this.lastAngle_ = angle; + + var map = mapBrowserEvent.map; + var view = map.getView(); + + // rotate anchor point. + // FIXME: should be the intersection point between the lines: + // touch0,touch1 and previousTouch0,previousTouch1 + var viewportPosition = goog.style.getClientPosition(map.getViewport()); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); + centroid.x -= viewportPosition.x; + centroid.y -= viewportPosition.y; + var anchor = map.getCoordinateFromPixel(centroid); + + // rotate + if (this.rotating_) { + view.rotateWithoutConstraints(map, view.getRotation() + rotationDelta, + anchor); + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchRotate.prototype.handleTouchEnd = + function(mapBrowserEvent) { + if (this.targetTouches.length < 2) { + var map = mapBrowserEvent.map; + var view = map.getView(); + if (this.rotating_) { + view.rotate(map, view.getRotation(), undefined, + ol.interaction.TOUCHROTATE_ANIMATION_DURATION); + } + view.setHint(ol.ViewHint.INTERACTING, -1); + return false; + } else { + return true; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchRotate.prototype.handleTouchStart = + function(mapBrowserEvent) { + if (this.targetTouches.length >= 2) { + var view = mapBrowserEvent.map.getView(); + this.lastAngle_ = undefined; + this.rotating_ = false; + this.rotationDelta_ = 0.0; + view.setHint(ol.ViewHint.INTERACTING, 1); + return true; + } else { + return false; + } +}; diff --git a/master/ol/ol/interaction/touchzoominteraction.js b/master/ol/ol/interaction/touchzoominteraction.js new file mode 100644 index 0000000000..bbb0bab518 --- /dev/null +++ b/master/ol/ol/interaction/touchzoominteraction.js @@ -0,0 +1,105 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.TouchZoom'); + +goog.require('goog.asserts'); +goog.require('ol.View'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.Touch'); + + +/** + * @define {number} Animation duration. + */ +ol.interaction.TOUCHZOOM_ANIMATION_DURATION = 250; + + + +/** + * @constructor + * @extends {ol.interaction.Touch} + */ +ol.interaction.TouchZoom = function() { + + goog.base(this); + + /** + * @private + * @type {number|undefined} + */ + this.lastDistance_; + +}; +goog.inherits(ol.interaction.TouchZoom, ol.interaction.Touch); + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchMove = + function(mapBrowserEvent) { + goog.asserts.assert(this.targetTouches.length >= 2); + var scaleDelta = 1.0; + + var touch0 = this.targetTouches[0]; + var touch1 = this.targetTouches[1]; + var dx = touch0.clientX - touch1.clientX; + var dy = touch0.clientY - touch1.clientY; + + // distance between touches + var distance = Math.sqrt(dx * dx + dy * dy); + + if (goog.isDef(this.lastDistance_)) { + scaleDelta = this.lastDistance_ / distance; + } + this.lastDistance_ = distance; + + var map = mapBrowserEvent.map; + var view = map.getView(); + + // scale anchor point. + var viewportPosition = goog.style.getClientPosition(map.getViewport()); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); + centroid.x -= viewportPosition.x; + centroid.y -= viewportPosition.y; + var anchor = map.getCoordinateFromPixel(centroid); + + // scale, bypass the resolution constraint + view.zoomWithoutConstraints(map, view.getResolution() * scaleDelta, anchor); + +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchEnd = + function(mapBrowserEvent) { + if (this.targetTouches.length < 2) { + var map = mapBrowserEvent.map; + var view = map.getView(); + // take the resolution constraint into account + view.zoom(map, view.getResolution(), undefined, + ol.interaction.TOUCHZOOM_ANIMATION_DURATION); + view.setHint(ol.ViewHint.INTERACTING, -1); + return false; + } else { + return true; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchStart = + function(mapBrowserEvent) { + if (this.targetTouches.length >= 2) { + var view = mapBrowserEvent.map.getView(); + this.lastDistance_ = undefined; + view.setHint(ol.ViewHint.INTERACTING, 1); + return true; + } else { + return false; + } +}; diff --git a/master/ol/ol/iview.js b/master/ol/ol/iview.js new file mode 100644 index 0000000000..5b7663bd1d --- /dev/null +++ b/master/ol/ol/iview.js @@ -0,0 +1,27 @@ +goog.provide('ol.IView'); + +goog.require('ol.IView2D'); +goog.require('ol.IView3D'); + + + +/** + * Interface for views. + * @interface + */ +ol.IView = function() { +}; + + +/** + * @return {ol.IView2D} View2D. + */ +ol.IView.prototype.getView2D = function() { +}; + + +/** + * @return {ol.IView3D} View3D. + */ +ol.IView.prototype.getView3D = function() { +}; diff --git a/master/ol/ol/iview2d.js b/master/ol/ol/iview2d.js new file mode 100644 index 0000000000..ad1d28f564 --- /dev/null +++ b/master/ol/ol/iview2d.js @@ -0,0 +1,58 @@ +goog.provide('ol.IView2D'); +goog.provide('ol.View2DState'); + +goog.require('ol.Coordinate'); +goog.require('ol.Projection'); + + +/** + * @typedef {{center: ol.Coordinate, + * projection: ol.Projection, + * resolution: number, + * rotation: number}} + */ +ol.View2DState; + + + +/** + * Interface for views. + * @interface + */ +ol.IView2D = function() { +}; + + +/** + * @return {ol.Coordinate|undefined} Map center. + */ +ol.IView2D.prototype.getCenter = function() { +}; + + +/** + * @return {ol.Projection|undefined} Map projection. + */ +ol.IView2D.prototype.getProjection = function() { +}; + + +/** + * @return {number|undefined} Map resolution. + */ +ol.IView2D.prototype.getResolution = function() { +}; + + +/** + * @return {number|undefined} Map rotation. + */ +ol.IView2D.prototype.getRotation = function() { +}; + + +/** + * @return {ol.View2DState} View2D state. + */ +ol.IView2D.prototype.getView2DState = function() { +}; diff --git a/master/ol/ol/iview3d.js b/master/ol/ol/iview3d.js new file mode 100644 index 0000000000..90153214b5 --- /dev/null +++ b/master/ol/ol/iview3d.js @@ -0,0 +1,12 @@ +goog.provide('ol.IView3D'); + + + +/** + * Interface for views. + * @interface + */ +ol.IView3D = function() { +}; + + diff --git a/master/ol/ol/kinetic.js b/master/ol/ol/kinetic.js new file mode 100644 index 0000000000..e6b78526d2 --- /dev/null +++ b/master/ol/ol/kinetic.js @@ -0,0 +1,154 @@ + +goog.provide('ol.Kinetic'); + +goog.require('ol.Coordinate'); +goog.require('ol.PreRenderFunction'); +goog.require('ol.animation'); + + +/** + * @typedef {{x: number, + * y: number, + * t: number}} + */ +ol.KineticPoint; + + + +/** + * @constructor + * @param {number} decay Rate of decay (must be negative). + * @param {number} minVelocity Minimum velocity (pixels/millisecond). + * @param {number} delay Delay to consider to calculate the kinetic + * initial values (milliseconds). + */ +ol.Kinetic = function(decay, minVelocity, delay) { + + /** + * @private + * @type {number} + */ + this.decay_ = decay; + + /** + * @private + * @type {number} + */ + this.minVelocity_ = minVelocity; + + /** + * @private + * @type {number} + */ + this.delay_ = delay; + + /** + * @private + * @type {Array.} + */ + this.points_ = []; + + /** + * @private + * @type {number} + */ + this.angle_ = 0; + + /** + * @private + * @type {number} + */ + this.initialVelocity_ = 0; +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.Kinetic.prototype.begin = function() { + this.points_.length = 0; + this.angle_ = 0; + this.initialVelocity_ = 0; +}; + + +/** + * @param {number} x X. + * @param {number} y Y. + */ +ol.Kinetic.prototype.update = function(x, y) { + this.points_.push({ + x: x, + y: y, + t: goog.now() + }); +}; + + +/** + * @return {boolean} Whether we should do kinetic animation. + */ +ol.Kinetic.prototype.end = function() { + var now = goog.now(); + var lastIndex = this.points_.length - 1; + var firstIndex = lastIndex - 1; + while (firstIndex >= 0 && this.points_[firstIndex].t > now - this.delay_) { + firstIndex--; + } + if (firstIndex >= 0) { + var first = this.points_[firstIndex]; + var last = this.points_[lastIndex]; + var dx = last.x - first.x; + var dy = last.y - first.y; + this.angle_ = Math.atan2(dy, dx); + this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / (last.t - first.t); + return this.initialVelocity_ > this.minVelocity_; + } + return false; +}; + + +/** + * @param {ol.Coordinate} source Source coordinate for the animation. + * @return {ol.PreRenderFunction} Pre-render function for kinetic animation. + */ +ol.Kinetic.prototype.pan = function(source) { + var decay = this.decay_; + var initialVelocity = this.initialVelocity_; + var minVelocity = this.minVelocity_; + var duration = this.getDuration_(); + var easingFunction = function(t) { + return initialVelocity * (Math.exp((decay * t) * duration) - 1) / + (minVelocity - initialVelocity); + }; + return ol.animation.pan({ + source: source, + duration: duration, + easing: easingFunction + }); +}; + + +/** + * @private + * @return {number} Duration of animation (milliseconds). + */ +ol.Kinetic.prototype.getDuration_ = function() { + return Math.log(this.minVelocity_ / this.initialVelocity_) / this.decay_; +}; + + +/** + * @return {number} Total distance travelled (pixels). + */ +ol.Kinetic.prototype.getDistance = function() { + return (this.minVelocity_ - this.initialVelocity_) / this.decay_; +}; + + +/** + * @return {number} Angle of the kinetic panning animation (radians). + */ +ol.Kinetic.prototype.getAngle = function() { + return this.angle_; +}; diff --git a/master/ol/ol/layer/imagelayer.exports b/master/ol/ol/layer/imagelayer.exports new file mode 100644 index 0000000000..f00c7ec5e5 --- /dev/null +++ b/master/ol/ol/layer/imagelayer.exports @@ -0,0 +1 @@ +@exportClass ol.layer.ImageLayer ol.layer.LayerOptions diff --git a/master/ol/ol/layer/imagelayer.js b/master/ol/ol/layer/imagelayer.js new file mode 100644 index 0000000000..8b61efce0e --- /dev/null +++ b/master/ol/ol/layer/imagelayer.js @@ -0,0 +1,24 @@ +goog.provide('ol.layer.ImageLayer'); + +goog.require('ol.layer.Layer'); +goog.require('ol.source.ImageSource'); + + + +/** + * @constructor + * @extends {ol.layer.Layer} + * @param {ol.layer.LayerOptions} layerOptions Layer options. + */ +ol.layer.ImageLayer = function(layerOptions) { + goog.base(this, layerOptions); +}; +goog.inherits(ol.layer.ImageLayer, ol.layer.Layer); + + +/** + * @return {ol.source.ImageSource} Single image source. + */ +ol.layer.ImageLayer.prototype.getImageSource = function() { + return /** @type {ol.source.ImageSource} */ (this.getSource()); +}; diff --git a/master/ol/ol/layer/layer.js b/master/ol/ol/layer/layer.js new file mode 100644 index 0000000000..cb06bed1ba --- /dev/null +++ b/master/ol/ol/layer/layer.js @@ -0,0 +1,316 @@ +goog.provide('ol.layer.Layer'); +goog.provide('ol.layer.LayerProperty'); +goog.provide('ol.layer.LayerState'); + +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('goog.math'); +goog.require('ol.Object'); +goog.require('ol.source.Source'); + + +/** + * @enum {string} + */ +ol.layer.LayerProperty = { + BRIGHTNESS: 'brightness', + CONTRAST: 'contrast', + HUE: 'hue', + OPACITY: 'opacity', + SATURATION: 'saturation', + VISIBLE: 'visible' +}; + + +/** + * @typedef {{brightness: number, + * contrast: number, + * hue: number, + * opacity: number, + * ready: boolean, + * saturation: number, + * visible: boolean}} + */ +ol.layer.LayerState; + + + +/** + * @constructor + * @extends {ol.Object} + * @param {ol.layer.LayerOptions} layerOptions LayerOptions. + */ +ol.layer.Layer = function(layerOptions) { + + goog.base(this); + + /** + * @private + * @type {ol.source.Source} + */ + this.source_ = layerOptions.source; + + this.setBrightness( + goog.isDef(layerOptions.brightness) ? layerOptions.brightness : 0); + this.setContrast( + goog.isDef(layerOptions.contrast) ? layerOptions.contrast : 1); + this.setHue( + goog.isDef(layerOptions.hue) ? layerOptions.hue : 0); + this.setOpacity( + goog.isDef(layerOptions.opacity) ? layerOptions.opacity : 1); + this.setSaturation( + goog.isDef(layerOptions.saturation) ? layerOptions.saturation : 1); + this.setVisible( + goog.isDef(layerOptions.visible) ? layerOptions.visible : true); + + if (!this.source_.isReady()) { + goog.events.listenOnce(this.source_, goog.events.EventType.LOAD, + this.handleSourceLoad_, false, this); + } + +}; +goog.inherits(ol.layer.Layer, ol.Object); + + +/** + * @private + */ +ol.layer.Layer.prototype.dispatchLoadEvent_ = function() { + this.dispatchEvent(goog.events.EventType.LOAD); +}; + + +/** + * @return {number} Brightness. + */ +ol.layer.Layer.prototype.getBrightness = function() { + return /** @type {number} */ (this.get(ol.layer.LayerProperty.BRIGHTNESS)); +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'getBrightness', + ol.layer.Layer.prototype.getBrightness); + + +/** + * @return {number} Contrast. + */ +ol.layer.Layer.prototype.getContrast = function() { + return /** @type {number} */ (this.get(ol.layer.LayerProperty.CONTRAST)); +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'getContrast', + ol.layer.Layer.prototype.getContrast); + + +/** + * @return {number} Hue. + */ +ol.layer.Layer.prototype.getHue = function() { + return /** @type {number} */ (this.get(ol.layer.LayerProperty.HUE)); +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'getHue', + ol.layer.Layer.prototype.getHue); + + +/** + * @return {ol.layer.LayerState} Layer state. + */ +ol.layer.Layer.prototype.getLayerState = function() { + var brightness = this.getBrightness(); + var contrast = this.getContrast(); + var hue = this.getHue(); + var opacity = this.getOpacity(); + var ready = this.isReady(); + var saturation = this.getSaturation(); + var visible = this.getVisible(); + return { + brightness: goog.isDef(brightness) ? brightness : 0, + contrast: goog.isDef(contrast) ? contrast : 1, + hue: goog.isDef(hue) ? hue : 0, + opacity: goog.isDef(opacity) ? opacity : 1, + ready: ready, + saturation: goog.isDef(saturation) ? saturation : 1, + visible: goog.isDef(visible) ? visible : true + }; +}; + + +/** + * @return {number} Opacity. + */ +ol.layer.Layer.prototype.getOpacity = function() { + return /** @type {number} */ (this.get(ol.layer.LayerProperty.OPACITY)); +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'getOpacity', + ol.layer.Layer.prototype.getOpacity); + + +/** + * @return {number} Saturation. + */ +ol.layer.Layer.prototype.getSaturation = function() { + return /** @type {number} */ (this.get(ol.layer.LayerProperty.SATURATION)); +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'getSaturation', + ol.layer.Layer.prototype.getSaturation); + + +/** + * @return {ol.source.Source} Source. + */ +ol.layer.Layer.prototype.getSource = function() { + return this.source_; +}; + + +/** + * @return {boolean} Visible. + */ +ol.layer.Layer.prototype.getVisible = function() { + return /** @type {boolean} */ (this.get(ol.layer.LayerProperty.VISIBLE)); +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'getVisible', + ol.layer.Layer.prototype.getVisible); + + +/** + * @private + */ +ol.layer.Layer.prototype.handleSourceLoad_ = function() { + this.dispatchLoadEvent_(); +}; + + +/** + * @return {boolean} Is ready. + */ +ol.layer.Layer.prototype.isReady = function() { + return this.getSource().isReady(); +}; + + +/** + * Adjust the layer brightness. A value of -1 will render the layer completely + * black. A value of 0 will leave the brightness unchanged. A value of 1 will + * render the layer completely white. Other values are linear multipliers on + * the effect (values are clamped between -1 and 1). + * + * The filter effects draft [1] says the brightness function is supposed to + * render 0 black, 1 unchanged, and all other values as a linear multiplier. + * + * The current WebKit implementation clamps values between -1 (black) and 1 + * (white) [2]. There is a bug open to change the filter effect spec [3]. + * + * TODO: revisit this if the spec is still unmodified before we release + * + * [1] https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html + * [2] https://github.com/WebKit/webkit/commit/8f4765e569 + * [3] https://www.w3.org/Bugs/Public/show_bug.cgi?id=15647 + * + * @param {number} brightness Brightness. + */ +ol.layer.Layer.prototype.setBrightness = function(brightness) { + brightness = goog.math.clamp(brightness, -1, 1); + if (brightness != this.getBrightness()) { + this.set(ol.layer.LayerProperty.BRIGHTNESS, brightness); + } +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'setBrightness', + ol.layer.Layer.prototype.setBrightness); + + +/** + * Adjust the layer contrast. A value of 0 will render the layer completely + * grey. A value of 1 will leave the contrast unchanged. Other values are + * linear multipliers on the effect (and values over 1 are permitted). + * + * @param {number} contrast Contrast. + */ +ol.layer.Layer.prototype.setContrast = function(contrast) { + contrast = Math.max(0, contrast); + if (contrast != this.getContrast()) { + this.set(ol.layer.LayerProperty.CONTRAST, contrast); + } +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'setContrast', + ol.layer.Layer.prototype.setContrast); + + +/** + * Apply a hue-rotation to the layer. A value of 0 will leave the hue + * unchanged. Other values are radians around the color circle. + * @param {number} hue Hue. + */ +ol.layer.Layer.prototype.setHue = function(hue) { + if (hue != this.getHue()) { + this.set(ol.layer.LayerProperty.HUE, hue); + } +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'setHue', + ol.layer.Layer.prototype.setHue); + + +/** + * @param {number} opacity Opacity. + */ +ol.layer.Layer.prototype.setOpacity = function(opacity) { + opacity = goog.math.clamp(opacity, 0, 1); + if (opacity != this.getOpacity()) { + this.set(ol.layer.LayerProperty.OPACITY, opacity); + } +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'setOpacity', + ol.layer.Layer.prototype.setOpacity); + + +/** + * Adjust layer saturation. A value of 0 will render the layer completely + * unsaturated. A value of 1 will leave the saturation unchanged. Other + * values are linear multipliers of the effect (and values over 1 are + * permitted). + * + * @param {number} saturation Saturation. + */ +ol.layer.Layer.prototype.setSaturation = function(saturation) { + saturation = Math.max(0, saturation); + if (saturation != this.getSaturation()) { + this.set(ol.layer.LayerProperty.SATURATION, saturation); + } +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'setSaturation', + ol.layer.Layer.prototype.setSaturation); + + +/** + * @param {boolean} visible Visible. + */ +ol.layer.Layer.prototype.setVisible = function(visible) { + visible = !!visible; + if (visible != this.getVisible()) { + this.set(ol.layer.LayerProperty.VISIBLE, visible); + } +}; +goog.exportProperty( + ol.layer.Layer.prototype, + 'setVisible', + ol.layer.Layer.prototype.setVisible); diff --git a/master/ol/ol/layer/tilelayer.exports b/master/ol/ol/layer/tilelayer.exports new file mode 100644 index 0000000000..a567e216ff --- /dev/null +++ b/master/ol/ol/layer/tilelayer.exports @@ -0,0 +1 @@ +@exportClass ol.layer.TileLayer ol.layer.LayerOptions diff --git a/master/ol/ol/layer/tilelayer.js b/master/ol/ol/layer/tilelayer.js new file mode 100644 index 0000000000..878185e77f --- /dev/null +++ b/master/ol/ol/layer/tilelayer.js @@ -0,0 +1,24 @@ +goog.provide('ol.layer.TileLayer'); + +goog.require('ol.layer.Layer'); +goog.require('ol.source.TileSource'); + + + +/** + * @constructor + * @extends {ol.layer.Layer} + * @param {ol.layer.LayerOptions} layerOptions Layer options. + */ +ol.layer.TileLayer = function(layerOptions) { + goog.base(this, layerOptions); +}; +goog.inherits(ol.layer.TileLayer, ol.layer.Layer); + + +/** + * @return {ol.source.TileSource} Source. + */ +ol.layer.TileLayer.prototype.getTileSource = function() { + return /** @type {ol.source.TileSource} */ (this.getSource()); +}; diff --git a/master/ol/ol/map.exports b/master/ol/ol/map.exports new file mode 100644 index 0000000000..6c0774b39f --- /dev/null +++ b/master/ol/ol/map.exports @@ -0,0 +1,15 @@ +@exportClass ol.Map ol.MapOptions +@exportProperty ol.Map.prototype.addLayer +@exportProperty ol.Map.prototype.addPreRenderFunction +@exportProperty ol.Map.prototype.addPreRenderFunctions +@exportProperty ol.Map.prototype.getInteractions +@exportProperty ol.Map.prototype.getRenderer +@exportProperty ol.Map.prototype.removeLayer + +@exportSymbol ol.RendererHint +@exportProperty ol.RendererHint.CANVAS +@exportProperty ol.RendererHint.DOM +@exportProperty ol.RendererHint.WEBGL + +@exportSymbol ol.RendererHints +@exportProperty ol.RendererHints.createFromQueryData diff --git a/master/ol/ol/map.js b/master/ol/ol/map.js new file mode 100644 index 0000000000..7e8e04dfcb --- /dev/null +++ b/master/ol/ol/map.js @@ -0,0 +1,961 @@ +// FIXME recheck layer/map projection compatability when projection changes +// FIXME layer renderers should skip when they can't reproject +// FIXME add tilt and height? + +goog.provide('ol.Map'); +goog.provide('ol.MapProperty'); +goog.provide('ol.RendererHint'); +goog.provide('ol.RendererHints'); + +goog.require('goog.Uri.QueryData'); +goog.require('goog.async.AnimationDelay'); +goog.require('goog.debug.Logger'); +goog.require('goog.dom'); +goog.require('goog.dom.ViewportSizeMonitor'); +goog.require('goog.events'); +goog.require('goog.events.BrowserEvent'); +goog.require('goog.events.Event'); +goog.require('goog.events.EventType'); +goog.require('goog.events.KeyHandler'); +goog.require('goog.events.KeyHandler.EventType'); +goog.require('goog.events.MouseWheelHandler'); +goog.require('goog.events.MouseWheelHandler.EventType'); +goog.require('goog.style'); +goog.require('ol.BrowserFeature'); +goog.require('ol.Collection'); +goog.require('ol.Color'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.FrameState'); +goog.require('ol.IView'); +goog.require('ol.MapBrowserEvent'); +goog.require('ol.MapBrowserEvent.EventType'); +goog.require('ol.MapBrowserEventHandler'); +goog.require('ol.MapEvent'); +goog.require('ol.MapEventType'); +goog.require('ol.Object'); +goog.require('ol.ObjectEventType'); +goog.require('ol.Pixel'); +goog.require('ol.PostRenderFunction'); +goog.require('ol.PreRenderFunction'); +goog.require('ol.Size'); +goog.require('ol.Tile'); +goog.require('ol.TileQueue'); +goog.require('ol.View'); +goog.require('ol.View2D'); +goog.require('ol.control.defaults'); +goog.require('ol.interaction.defaults'); +goog.require('ol.layer.Layer'); +goog.require('ol.projection'); +goog.require('ol.projection.addCommonProjections'); +goog.require('ol.renderer.Map'); +goog.require('ol.renderer.canvas.Map'); +goog.require('ol.renderer.canvas.SUPPORTED'); +goog.require('ol.renderer.dom.Map'); +goog.require('ol.renderer.dom.SUPPORTED'); +goog.require('ol.renderer.webgl.Map'); +goog.require('ol.renderer.webgl.SUPPORTED'); + + +/** + * @define {boolean} Whether to enable canvas. + */ +ol.ENABLE_CANVAS = true; + + +/** + * @define {boolean} Whether to enable DOM. + */ +ol.ENABLE_DOM = true; + + +/** + * @define {boolean} Whether to enable WebGL. + */ +ol.ENABLE_WEBGL = true; + + +/** + * @enum {string} + */ +ol.RendererHint = { + CANVAS: 'canvas', + DOM: 'dom', + WEBGL: 'webgl' +}; + + +/** + * @type {Array.} + */ +ol.DEFAULT_RENDERER_HINTS = [ + ol.RendererHint.WEBGL, + ol.RendererHint.CANVAS, + ol.RendererHint.DOM +]; + + +/** + * @enum {string} + */ +ol.MapProperty = { + BACKGROUND_COLOR: 'backgroundColor', + LAYERS: 'layers', + SIZE: 'size', + VIEW: 'view' +}; + + + +/** + * @constructor + * @extends {ol.Object} + * @param {ol.MapOptions} mapOptions Map options. + */ +ol.Map = function(mapOptions) { + + goog.base(this); + + if (goog.DEBUG) { + /** + * @protected + * @type {goog.debug.Logger} + */ + this.logger = goog.debug.Logger.getLogger('ol.map.' + goog.getUid(this)); + } + + var mapOptionsInternal = ol.Map.createOptionsInternal(mapOptions); + + /** + * @private + * @type {goog.async.AnimationDelay} + */ + this.animationDelay_ = + new goog.async.AnimationDelay(this.renderFrame_, undefined, this); + this.registerDisposable(this.animationDelay_); + + /** + * @private + * @type {goog.vec.Mat4.Number} + */ + this.coordinateToPixelMatrix_ = goog.vec.Mat4.createNumber(); + + /** + * @private + * @type {goog.vec.Mat4.Number} + */ + this.pixelToCoordinateMatrix_ = goog.vec.Mat4.createNumber(); + + /** + * @private + * @type {?ol.FrameState} + */ + this.frameState_ = null; + + /** + * @private + * @type {number} + */ + this.freezeRenderingCount_ = 0; + + /** + * @private + * @type {boolean} + */ + this.dirty_ = false; + + /** + * @private + * @type {Element} + */ + this.target_ = mapOptionsInternal.target; + + /** + * @private + * @type {?number} + */ + this.viewPropertyListenerKey_ = null; + + /** + * @private + * @type {Element} + */ + this.viewport_ = goog.dom.createDom(goog.dom.TagName.DIV, 'ol-viewport'); + this.viewport_.style.position = 'relative'; + this.viewport_.style.overflow = 'hidden'; + this.viewport_.style.width = '100%'; + this.viewport_.style.height = '100%'; + // prevent page zoom on IE >= 10 browsers + this.viewport_.style.msTouchAction = 'none'; + goog.dom.appendChild(this.target_, this.viewport_); + + /** + * @private + * @type {Element} + */ + this.overlayContainer_ = goog.dom.createDom(goog.dom.TagName.DIV, + 'ol-overlaycontainer'); + goog.events.listen(this.overlayContainer_, [ + goog.events.EventType.CLICK, + ol.BrowserFeature.HAS_TOUCH ? + goog.events.EventType.TOUCHSTART : goog.events.EventType.MOUSEDOWN + ], goog.events.Event.stopPropagation); + goog.dom.appendChild(this.viewport_, this.overlayContainer_); + + var mapBrowserEventHandler = new ol.MapBrowserEventHandler(this); + goog.events.listen(mapBrowserEventHandler, + goog.object.getValues(ol.MapBrowserEvent.EventType), + this.handleMapBrowserEvent, false, this); + this.registerDisposable(mapBrowserEventHandler); + + // FIXME we probably shouldn't listen on document... + var keyHandler = new goog.events.KeyHandler(document); + goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY, + this.handleBrowserEvent, false, this); + this.registerDisposable(keyHandler); + + var mouseWheelHandler = new goog.events.MouseWheelHandler(this.viewport_); + goog.events.listen(mouseWheelHandler, + goog.events.MouseWheelHandler.EventType.MOUSEWHEEL, + this.handleBrowserEvent, false, this); + this.registerDisposable(mouseWheelHandler); + + /** + * @type {ol.Collection} + * @private + */ + this.interactions_ = mapOptionsInternal.interactions; + + /** + * @type {ol.renderer.Map} + * @private + */ + this.renderer_ = + new mapOptionsInternal.rendererConstructor(this.viewport_, this); + this.registerDisposable(this.renderer_); + + /** + * @private + */ + this.viewportSizeMonitor_ = new goog.dom.ViewportSizeMonitor(); + + goog.events.listen(this.viewportSizeMonitor_, goog.events.EventType.RESIZE, + this.handleBrowserWindowResize, false, this); + + /** + * @private + * @type {ol.Coordinate} + */ + this.focus_ = null; + + /** + * @private + * @type {Array.} + */ + this.preRenderFunctions_ = []; + + /** + * @private + * @type {Array.} + */ + this.postRenderFunctions_ = []; + + /** + * @private + * @type {function(this: ol.Map)} + */ + this.handlePostRender_ = goog.bind(this.handlePostRender, this); + + /** + * @private + * @type {ol.TileQueue} + */ + this.tileQueue_ = new ol.TileQueue(goog.bind(this.getTilePriority, this)); + + goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.VIEW), + this.handleViewChanged_, false, this); + goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.SIZE), + this.handleSizeChanged_, false, this); + goog.events.listen( + this, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR), + this.handleBackgroundColorChanged_, false, this); + this.setValues(mapOptionsInternal.values); + + // this gives the map an initial size + this.handleBrowserWindowResize(); + + if (goog.isDef(mapOptionsInternal.controls)) { + goog.array.forEach(mapOptionsInternal.controls, + /** + * @param {ol.control.Control} control Control. + */ + function(control) { + control.setMap(this); + }, this); + } + +}; +goog.inherits(ol.Map, ol.Object); + + +/** + * @param {ol.layer.Layer} layer Layer. + */ +ol.Map.prototype.addLayer = function(layer) { + var layers = this.getLayers(); + goog.asserts.assert(goog.isDef(layers)); + layers.push(layer); +}; + + +/** + * @param {ol.PreRenderFunction} preRenderFunction Pre-render function. + */ +ol.Map.prototype.addPreRenderFunction = function(preRenderFunction) { + this.requestRenderFrame(); + this.preRenderFunctions_.push(preRenderFunction); +}; + + +/** + * @param {Array.} preRenderFunctions + * Pre-render functions. + */ +ol.Map.prototype.addPreRenderFunctions = function(preRenderFunctions) { + this.requestRenderFrame(); + Array.prototype.push.apply( + this.preRenderFunctions_, preRenderFunctions); +}; + + +/** + * @param {ol.PreRenderFunction} preRenderFunction Pre-render function. + * @return {boolean} Whether the preRenderFunction has been found and removed. + */ +ol.Map.prototype.removePreRenderFunction = function(preRenderFunction) { + return goog.array.remove(this.preRenderFunctions_, preRenderFunction); +}; + + +/** + * + * @inheritDoc + */ +ol.Map.prototype.disposeInternal = function() { + goog.dom.removeNode(this.viewport_); + goog.base(this, 'disposeInternal'); +}; + + +/** + * Freeze rendering. + */ +ol.Map.prototype.freezeRendering = function() { + ++this.freezeRenderingCount_; +}; + + +/** + * @return {ol.Color|undefined} Background color. + */ +ol.Map.prototype.getBackgroundColor = function() { + return /** @type {ol.Color|undefined} */ ( + this.get(ol.MapProperty.BACKGROUND_COLOR)); +}; +goog.exportProperty( + ol.Map.prototype, + 'getBackgroundColor', + ol.Map.prototype.getBackgroundColor); + + +/** + * @return {ol.renderer.Map} Renderer. + */ +ol.Map.prototype.getRenderer = function() { + return this.renderer_; +}; + + +/** + * @return {Element} Container. + */ +ol.Map.prototype.getTarget = function() { + return this.target_; +}; + + +/** + * @param {ol.Pixel} pixel Pixel. + * @return {ol.Coordinate} Coordinate. + */ +ol.Map.prototype.getCoordinateFromPixel = function(pixel) { + var frameState = this.frameState_; + if (goog.isNull(frameState)) { + return null; + } else { + var vec3 = [pixel.x, pixel.y, 0]; + goog.vec.Mat4.multVec3(frameState.pixelToCoordinateMatrix, vec3, vec3); + return new ol.Coordinate(vec3[0], vec3[1]); + } +}; + + +/** + * @return {ol.Collection} Interactions. + */ +ol.Map.prototype.getInteractions = function() { + return this.interactions_; +}; + + +/** + * @return {ol.Collection} Layers. + */ +ol.Map.prototype.getLayers = function() { + return /** @type {ol.Collection} */ (this.get(ol.MapProperty.LAYERS)); +}; +goog.exportProperty( + ol.Map.prototype, + 'getLayers', + ol.Map.prototype.getLayers); + + +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @return {ol.Pixel} Pixel. + */ +ol.Map.prototype.getPixelFromCoordinate = function(coordinate) { + var frameState = this.frameState_; + if (goog.isNull(frameState)) { + return null; + } else { + var vec3 = [coordinate.x, coordinate.y, 0]; + goog.vec.Mat4.multVec3(frameState.coordinateToPixelMatrix, vec3, vec3); + return new ol.Pixel(vec3[0], vec3[1]); + } +}; + + +/** + * @return {ol.Size|undefined} Size. + */ +ol.Map.prototype.getSize = function() { + return /** @type {ol.Size|undefined} */ (this.get(ol.MapProperty.SIZE)); +}; +goog.exportProperty( + ol.Map.prototype, + 'getSize', + ol.Map.prototype.getSize); + + +/** + * @return {ol.View} View. + */ +ol.Map.prototype.getView = function() { + return /** @type {ol.View} */ (this.get(ol.MapProperty.VIEW)); +}; +goog.exportProperty( + ol.Map.prototype, + 'getView', + ol.Map.prototype.getView); + + +/** + * @return {Element} Viewport. + */ +ol.Map.prototype.getViewport = function() { + return this.viewport_; +}; + + +/** + * @return {Element} 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. + */ +ol.Map.prototype.getOverlayContainer = function() { + return this.overlayContainer_; +}; + + +/** + * @param {ol.Tile} tile Tile. + * @param {string} tileSourceKey Tile source key. + * @param {ol.Coordinate} tileCenter Tile center. + * @return {number} Tile priority. + */ +ol.Map.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter) { + var frameState = this.frameState_; + if (goog.isNull(frameState) || !(tileSourceKey in frameState.wantedTiles)) { + return ol.TileQueue.DROP; + } + var coordKey = tile.tileCoord.toString(); + if (!frameState.wantedTiles[tileSourceKey][coordKey]) { + return ol.TileQueue.DROP; + } + var focus = goog.isNull(this.focus_) ? + frameState.view2DState.center : this.focus_; + var deltaX = tileCenter.x - focus.x; + var deltaY = tileCenter.y - focus.y; + return deltaX * deltaX + deltaY * deltaY; +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @param {string=} opt_type Type. + */ +ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) { + var type = opt_type || browserEvent.type; + var mapBrowserEvent = new ol.MapBrowserEvent(type, this, browserEvent); + this.handleMapBrowserEvent(mapBrowserEvent); + if (type == goog.events.EventType.MOUSEOUT) { + this.focus_ = null; + } else { + this.focus_ = mapBrowserEvent.getCoordinate(); + } +}; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle. + */ +ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { + mapBrowserEvent.frameState = this.frameState_; + var interactions = this.getInteractions(); + var interactionsArray = /** @type {Array.} */ + (interactions.getArray()); + if (this.dispatchEvent(mapBrowserEvent) !== false) { + for (var i = interactionsArray.length - 1; i >= 0; i--) { + var interaction = interactionsArray[i]; + interaction.handleMapBrowserEvent(mapBrowserEvent); + if (mapBrowserEvent.defaultPrevented) { + break; + } + } + } +}; + + +/** + * @protected + */ +ol.Map.prototype.handlePostRender = function() { + this.tileQueue_.reprioritize(); // FIXME only call if needed + var moreLoadingTiles = this.tileQueue_.loadMoreTiles(); + if (moreLoadingTiles) { + // The tile layer renderers need to know when tiles change + // to the LOADING state (to register the change listener + // on the tile). + this.requestRenderFrame(); + } + + var postRenderFunctions = this.postRenderFunctions_; + var i; + for (i = 0; i < postRenderFunctions.length; ++i) { + postRenderFunctions[i](this, this.frameState_); + } + postRenderFunctions.length = 0; +}; + + +/** + * @private + */ +ol.Map.prototype.handleBackgroundColorChanged_ = function() { + this.render(); +}; + + +/** + * @protected + */ +ol.Map.prototype.handleBrowserWindowResize = function() { + var size = goog.style.getSize(this.target_); + this.setSize(new ol.Size(size.width, size.height)); +}; + + +/** + * @private + */ +ol.Map.prototype.handleSizeChanged_ = function() { + this.render(); +}; + + +/** + * @private + */ +ol.Map.prototype.handleViewPropertyChanged_ = function() { + this.render(); +}; + + +/** + * @private + */ +ol.Map.prototype.handleViewChanged_ = function() { + if (!goog.isNull(this.viewPropertyListenerKey_)) { + goog.events.unlistenByKey(this.viewPropertyListenerKey_); + this.viewPropertyListenerKey_ = null; + } + var view = this.getView(); + if (goog.isDefAndNotNull(view)) { + this.viewPropertyListenerKey_ = goog.events.listen( + view, ol.ObjectEventType.CHANGED, + this.handleViewPropertyChanged_, false, this); + } + this.render(); +}; + + +/** + * @return {boolean} Is defined. + */ +ol.Map.prototype.isDef = function() { + var view = this.getView(); + return goog.isDef(view) && view.isDef() && + goog.isDefAndNotNull(this.getSize()); +}; + + +/** + * Render. + */ +ol.Map.prototype.render = function() { + if (this.animationDelay_.isActive()) { + // pass + } else if (this.freezeRenderingCount_ === 0) { + this.animationDelay_.fire(); + } else { + this.dirty_ = true; + } +}; + + +/** + * Request that renderFrame_ be called some time in the future. + */ +ol.Map.prototype.requestRenderFrame = function() { + if (this.freezeRenderingCount_ === 0) { + if (!this.animationDelay_.isActive()) { + this.animationDelay_.start(); + } + } else { + this.dirty_ = true; + } +}; + + +/** + * @param {ol.layer.Layer} layer Layer. + * @return {ol.layer.Layer|undefined} The removed layer or undefined if the + * layer was not found. + */ +ol.Map.prototype.removeLayer = function(layer) { + var layers = this.getLayers(); + goog.asserts.assert(goog.isDef(layers)); + return /** @type {ol.layer.Layer|undefined} */ (layers.remove(layer)); +}; + + +/** + * @param {number} time Time. + * @private + */ +ol.Map.prototype.renderFrame_ = function(time) { + + var i; + + if (this.freezeRenderingCount_ != 0) { + return; + } + + if (goog.DEBUG) { + this.logger.info('renderFrame_'); + } + + var size = this.getSize(); + var layers = this.getLayers(); + var layersArray = goog.isDef(layers) ? + /** @type {Array.} */ (layers.getArray()) : undefined; + var view = this.getView(); + var view2D = goog.isDef(view) ? this.getView().getView2D() : undefined; + /** @type {?ol.FrameState} */ + var frameState = null; + if (goog.isDef(layersArray) && goog.isDef(size) && goog.isDef(view2D) && + view2D.isDef()) { + var backgroundColor = this.getBackgroundColor(); + var viewHints = view.getHints(); + var layerStates = {}; + var layer; + for (i = 0; i < layersArray.length; ++i) { + layer = layersArray[i]; + layerStates[goog.getUid(layer)] = layer.getLayerState(); + } + var view2DState = view2D.getView2DState(); + frameState = { + animate: false, + attributions: {}, + backgroundColor: goog.isDef(backgroundColor) ? + backgroundColor : new ol.Color(255, 255, 255, 1), + coordinateToPixelMatrix: this.coordinateToPixelMatrix_, + extent: null, + layersArray: layersArray, + layerStates: layerStates, + pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_, + postRenderFunctions: [], + size: size, + tileQueue: this.tileQueue_, + time: time, + usedTiles: {}, + view2DState: view2DState, + viewHints: viewHints, + wantedTiles: {} + }; + } + + var preRenderFunctions = this.preRenderFunctions_; + var n = 0, preRenderFunction; + for (i = 0; i < preRenderFunctions.length; ++i) { + preRenderFunction = preRenderFunctions[i]; + if (preRenderFunction(this, frameState)) { + preRenderFunctions[n++] = preRenderFunction; + } + } + preRenderFunctions.length = n; + + if (!goog.isNull(frameState)) { + // FIXME works for View2D only + var center = view2DState.center; + var resolution = view2DState.resolution; + var rotation = view2DState.rotation; + var x = resolution * size.width / 2; + var y = resolution * size.height / 2; + var corners = [ + new ol.Coordinate(-x, -y), + new ol.Coordinate(-x, y), + new ol.Coordinate(x, -y), + new ol.Coordinate(x, y) + ]; + var corner; + for (i = 0; i < 4; ++i) { + corner = corners[i]; + corner.rotate(rotation); + corner.add(center); + } + frameState.extent = ol.Extent.boundingExtent.apply(null, corners); + } + + this.frameState_ = frameState; + this.renderer_.renderFrame(frameState); + this.dirty_ = false; + + if (!goog.isNull(frameState)) { + if (frameState.animate) { + this.requestRenderFrame(); + } + Array.prototype.push.apply( + this.postRenderFunctions_, frameState.postRenderFunctions); + } + + this.dispatchEvent( + new ol.MapEvent(ol.MapEventType.POSTRENDER, this, frameState)); + + goog.global.setTimeout(this.handlePostRender_, 0); + +}; + + +/** + * @param {ol.Color} backgroundColor Background color. + */ +ol.Map.prototype.setBackgroundColor = function(backgroundColor) { + this.set(ol.MapProperty.BACKGROUND_COLOR, backgroundColor); +}; +goog.exportProperty( + ol.Map.prototype, + 'setBackgroundColor', + ol.Map.prototype.setBackgroundColor); + + +/** + * @param {ol.Collection} layers Layers. + */ +ol.Map.prototype.setLayers = function(layers) { + this.set(ol.MapProperty.LAYERS, layers); +}; +goog.exportProperty( + ol.Map.prototype, + 'setLayers', + ol.Map.prototype.setLayers); + + +/** + * @param {ol.Size} size Size. + */ +ol.Map.prototype.setSize = function(size) { + this.set(ol.MapProperty.SIZE, size); +}; +goog.exportProperty( + ol.Map.prototype, + 'setSize', + ol.Map.prototype.setSize); + + +/** + * @param {ol.IView} view View. + */ +ol.Map.prototype.setView = function(view) { + this.set(ol.MapProperty.VIEW, view); +}; +goog.exportProperty( + ol.Map.prototype, + 'setView', + ol.Map.prototype.setView); + + +/** + * Unfreeze rendering. + */ +ol.Map.prototype.unfreezeRendering = function() { + goog.asserts.assert(this.freezeRenderingCount_ > 0); + if (--this.freezeRenderingCount_ === 0 && this.dirty_) { + this.animationDelay_.fire(); + } +}; + + +/** + * @param {function(this: T)} f Function. + * @param {T=} opt_obj Object. + * @template T + */ +ol.Map.prototype.withFrozenRendering = function(f, opt_obj) { + this.freezeRendering(); + try { + f.call(opt_obj); + } finally { + this.unfreezeRendering(); + } +}; + + +/** + * @typedef {{controls: Array., + * interactions: ol.Collection, + * rendererConstructor: + * function(new: ol.renderer.Map, Element, ol.Map), + * target: Element, + * values: Object.}} + */ +ol.MapOptionsInternal; + + +/** + * @param {ol.MapOptions} mapOptions Map options. + * @return {ol.MapOptionsInternal} Map options. + */ +ol.Map.createOptionsInternal = function(mapOptions) { + + /** + * @type {Object.} + */ + var values = {}; + + var layers; + if (goog.isDef(mapOptions.layers)) { + if (goog.isArray(mapOptions.layers)) { + layers = new ol.Collection(goog.array.clone(mapOptions.layers)); + } else { + goog.asserts.assert(mapOptions.layers instanceof ol.Collection); + layers = mapOptions.layers; + } + } else { + layers = new ol.Collection(); + } + values[ol.MapProperty.LAYERS] = layers; + + values[ol.MapProperty.VIEW] = goog.isDef(mapOptions.view) ? + mapOptions.view : new ol.View2D(); + + /** + * @type {function(new: ol.renderer.Map, Element, ol.Map)} + */ + var rendererConstructor = ol.renderer.Map; + + /** + * @type {Array.} + */ + var rendererHints; + if (goog.isDef(mapOptions.renderers)) { + rendererHints = mapOptions.renderers; + } else if (goog.isDef(mapOptions.renderer)) { + rendererHints = [mapOptions.renderer]; + } else { + rendererHints = ol.DEFAULT_RENDERER_HINTS; + } + + var i, rendererHint; + for (i = 0; i < rendererHints.length; ++i) { + rendererHint = rendererHints[i]; + if (rendererHint == ol.RendererHint.CANVAS) { + if (ol.ENABLE_CANVAS && ol.renderer.canvas.SUPPORTED) { + rendererConstructor = ol.renderer.canvas.Map; + break; + } + } else if (rendererHint == ol.RendererHint.DOM) { + if (ol.ENABLE_DOM && ol.renderer.dom.SUPPORTED) { + rendererConstructor = ol.renderer.dom.Map; + break; + } + } else if (rendererHint == ol.RendererHint.WEBGL) { + if (ol.ENABLE_WEBGL && ol.renderer.webgl.SUPPORTED) { + rendererConstructor = ol.renderer.webgl.Map; + break; + } + } + } + + var controls = goog.isDef(mapOptions.controls) ? + mapOptions.controls : ol.control.defaults(); + + var interactions = goog.isDef(mapOptions.interactions) ? + mapOptions.interactions : ol.interaction.defaults(); + + /** + * @type {Element} + */ + var target = goog.dom.getElement(mapOptions.target); + + return { + controls: controls, + interactions: interactions, + rendererConstructor: rendererConstructor, + target: target, + values: values + }; + +}; + + +/** + * @param {goog.Uri.QueryData=} opt_queryData Query data. + * @return {Array.} Renderer hints. + */ +ol.RendererHints.createFromQueryData = function(opt_queryData) { + var query = goog.global.location.search.substring(1), + queryData = goog.isDef(opt_queryData) ? + opt_queryData : new goog.Uri.QueryData(query); + if (queryData.containsKey('renderers')) { + return queryData.get('renderers').split(','); + } else if (queryData.containsKey('renderer')) { + return [queryData.get('renderer')]; + } else { + return ol.DEFAULT_RENDERER_HINTS; + } +}; + + +ol.projection.addCommonProjections(); diff --git a/master/ol/ol/mapbrowserevent.exports b/master/ol/ol/mapbrowserevent.exports new file mode 100644 index 0000000000..38eafbb2a1 --- /dev/null +++ b/master/ol/ol/mapbrowserevent.exports @@ -0,0 +1,2 @@ +@exportProperty ol.MapBrowserEvent.prototype.getCoordinate + diff --git a/master/ol/ol/mapbrowserevent.js b/master/ol/ol/mapbrowserevent.js new file mode 100644 index 0000000000..e86b83728d --- /dev/null +++ b/master/ol/ol/mapbrowserevent.js @@ -0,0 +1,361 @@ +goog.provide('ol.MapBrowserEvent'); +goog.provide('ol.MapBrowserEvent.EventType'); +goog.provide('ol.MapBrowserEventHandler'); + +goog.require('goog.array'); +goog.require('goog.events.BrowserEvent'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('goog.style'); +goog.require('ol.BrowserFeature'); +goog.require('ol.Coordinate'); +goog.require('ol.FrameState'); +goog.require('ol.MapEvent'); +goog.require('ol.Pixel'); + + + +/** + * @constructor + * @extends {ol.MapEvent} + * @param {string} type Event type. + * @param {ol.Map} map Map. + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @param {?ol.FrameState=} opt_frameState Frame state. + */ +ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) { + + goog.base(this, type, map, opt_frameState); + + /** + * @type {goog.events.BrowserEvent} + */ + this.browserEvent = browserEvent; + + /** + * @private + * @type {ol.Coordinate} + */ + this.coordinate_ = null; + + /** + * @private + * @type {ol.Pixel} + */ + this.pixel_ = null; + +}; +goog.inherits(ol.MapBrowserEvent, ol.MapEvent); + + +/** + * IE specific events. + * See http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx + * FIXME: replace with goog.events.EventType enum once we use + * goog/events/eventtype.js above r2211 + * @enum {string} + */ +ol.MapBrowserEvent.IEEventType = { + MSPOINTERDOWN: 'MSPointerDown', + MSPOINTERMOVE: 'MSPointerMove', + MSPOINTERUP: 'MSPointerUp' +}; + + +/** + * @return {ol.Coordinate} Coordinate. + */ +ol.MapBrowserEvent.prototype.getCoordinate = function() { + if (goog.isNull(this.coordinate_)) { + this.coordinate_ = this.map.getCoordinateFromPixel(this.getPixel()); + } + return this.coordinate_; +}; + + +/** + * Get pixel offset of the event from the top-left corner of the map viewport. + * @return {ol.Pixel} Pixel offset. + */ +ol.MapBrowserEvent.prototype.getPixel = function() { + if (goog.isNull(this.pixel_)) { + var eventPosition = goog.style.getRelativePosition( + this.browserEvent, this.map.getViewport()); + this.pixel_ = new ol.Pixel(eventPosition.x, eventPosition.y); + } + return this.pixel_; +}; + + +/** + * @return {boolean} Do we have a left click? + */ +ol.MapBrowserEvent.prototype.isMouseActionButton = function() { + // always assume a left-click on touch devices + return ol.BrowserFeature.HAS_TOUCH || + this.browserEvent.isMouseActionButton(); +}; + + + +/** + * @param {ol.Map} map The map with the viewport to listen to events on. + * @constructor + * @extends {goog.events.EventTarget} + */ +ol.MapBrowserEventHandler = function(map) { + + /** + * This is the element that we will listen to the real events on. + * @type {ol.Map} + * @private + */ + this.map_ = map; + + /** + * @type {Object} + * @private + */ + this.previous_ = null; + + /** + * @type {boolean} + * @private + */ + this.dragged_ = false; + + /** + * Timestamp for the first click of a double click. Will be set back to 0 + * as soon as a double click is detected. + * @type {?number} + * @private + */ + this.timestamp_ = null; + + /** + * @type {?number} + * @private + */ + this.clickListenerKey_ = null; + + /** + * @type {?number} + * @private + */ + this.downListenerKey_ = null; + + /** + * @type {Array.} + * @private + */ + this.dragListenerKeys_ = null; + + /** + * @type {Array.} + * @private + */ + this.touchListenerKeys_ = null; + + /** + * @type {goog.events.BrowserEvent} + * @private + */ + this.down_ = null; + + var element = this.map_.getViewport(); + this.clickListenerKey_ = goog.events.listen(element, + [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], + this.click_, false, this); + this.downListenerKey_ = goog.events.listen(element, + goog.events.EventType.MOUSEDOWN, + this.handleMouseDown_, false, this); + // touch events + this.touchListenerKeys_ = [ + goog.events.listen(element, [ + goog.events.EventType.TOUCHSTART, + ol.MapBrowserEvent.IEEventType.MSPOINTERDOWN + ], this.handleTouchStart_, false, this), + goog.events.listen(element, [ + goog.events.EventType.TOUCHMOVE, + ol.MapBrowserEvent.IEEventType.MSPOINTERMOVE + ], this.handleTouchMove_, false, this), + goog.events.listen(element, [ + goog.events.EventType.TOUCHEND, + ol.MapBrowserEvent.IEEventType.MSPOINTERUP + ], this.handleTouchEnd_, false, this) + ]; + +}; +goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget); + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) { + if (!this.dragged_) { + var newEvent; + var type = browserEvent.type; + if (this.timestamp_ == 0 || type == goog.events.EventType.DBLCLICK) { + newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent); + this.dispatchEvent(newEvent); + } else { + newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent); + this.dispatchEvent(newEvent); + } + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.handleMouseUp_ = function(browserEvent) { + if (this.previous_) { + this.down_ = null; + goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); + this.dragListenerKeys_ = null; + this.previous_ = null; + if (this.dragged_) { + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DRAGEND, this.map_, browserEvent); + this.dispatchEvent(newEvent); + } + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.handleMouseDown_ = function(browserEvent) { + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent); + this.dispatchEvent(newEvent); + if (!this.previous_) { + this.down_ = browserEvent; + this.previous_ = { + clientX: browserEvent.clientX, + clientY: browserEvent.clientY + }; + this.dragged_ = false; + this.dragListenerKeys_ = [ + goog.events.listen(document, goog.events.EventType.MOUSEMOVE, + this.handleMouseMove_, false, this), + goog.events.listen(document, goog.events.EventType.MOUSEUP, + this.handleMouseUp_, false, this) + ]; + // prevent browser image dragging with the dom renderer + browserEvent.preventDefault(); + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) { + var newEvent; + if (!this.dragged_) { + this.dragged_ = true; + newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DRAGSTART, this.map_, this.down_); + this.dispatchEvent(newEvent); + } + this.previous_ = { + clientX: browserEvent.clientX, + clientY: browserEvent.clientY + }; + newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DRAG, this.map_, browserEvent); + this.dispatchEvent(newEvent); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.handleTouchStart_ = function(browserEvent) { + // prevent context menu + browserEvent.preventDefault(); + this.down_ = browserEvent; + this.dragged_ = false; + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent); + this.dispatchEvent(newEvent); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.handleTouchMove_ = function(browserEvent) { + this.dragged_ = true; + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent); + this.dispatchEvent(newEvent); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) { + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent); + this.dispatchEvent(newEvent); + if (!this.dragged_) { + var now = goog.now(); + if (!this.timestamp_ || now - this.timestamp_ > 250) { + this.timestamp_ = now; + } else { + this.timestamp_ = 0; + } + this.click_(this.down_); + } + this.down_ = null; +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.MapBrowserEventHandler.prototype.disposeInternal = function() { + goog.events.unlistenByKey(this.clickListenerKey_); + goog.events.unlistenByKey(this.downListenerKey_); + if (!goog.isNull(this.dragListenerKeys_)) { + goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); + this.dragListenerKeys_ = null; + } + if (!goog.isNull(this.touchListenerKeys_)) { + goog.array.forEach(this.touchListenerKeys_, goog.events.unlistenByKey); + this.touchListenerKeys_ = null; + } + goog.base(this, 'disposeInternal'); +}; + + +/** + * Constants for event names. + * @enum {string} + */ +ol.MapBrowserEvent.EventType = { + CLICK: goog.events.EventType.CLICK, + DBLCLICK: goog.events.EventType.DBLCLICK, + DOWN: 'down', + DRAGSTART: 'dragstart', + DRAG: 'drag', + DRAGEND: 'dragend', + TOUCHSTART: goog.events.EventType.TOUCHSTART, + TOUCHMOVE: goog.events.EventType.TOUCHMOVE, + TOUCHEND: goog.events.EventType.TOUCHEND +}; diff --git a/master/ol/ol/mapevent.js b/master/ol/ol/mapevent.js new file mode 100644 index 0000000000..581a27f0e1 --- /dev/null +++ b/master/ol/ol/mapevent.js @@ -0,0 +1,53 @@ +goog.provide('ol.MapEvent'); +goog.provide('ol.MapEventType'); + +goog.require('goog.events.Event'); +goog.require('ol.FrameState'); + + +/** + * @enum {string} + */ +ol.MapEventType = { + POSTRENDER: 'postrender' +}; + + + +/** + * @constructor + * @extends {goog.events.Event} + * @param {string} type Event type. + * @param {ol.Map} map Map. + * @param {?ol.FrameState=} opt_frameState Frame state. + */ +ol.MapEvent = function(type, map, opt_frameState) { + + goog.base(this, type); + + /** + * @type {ol.Map} + */ + this.map = map; + + /** + * @type {boolean} + */ + this.defaultPrevented = false; + + /** + * @type {?ol.FrameState} + */ + this.frameState = goog.isDef(opt_frameState) ? opt_frameState : null; + +}; +goog.inherits(ol.MapEvent, goog.events.Event); + + +/** + * Prevents the default action. + */ +ol.MapEvent.prototype.preventDefault = function() { + goog.base(this, 'preventDefault'); + this.defaultPrevented = true; +}; diff --git a/master/ol/ol/math.js b/master/ol/ol/math.js new file mode 100644 index 0000000000..b1fa7f9024 --- /dev/null +++ b/master/ol/ol/math.js @@ -0,0 +1,57 @@ +goog.provide('ol.math'); + + +/** + * @param {number} x X. + * @return {number} Hyperbolic cosine of x. + */ +ol.math.cosh = function(x) { + return (Math.exp(x) + Math.exp(-x)) / 2; +}; + + +/** + * @param {number} x X. + * @return {number} Hyperbolic cotangent of x. + */ +ol.math.coth = function(x) { + var expMinusTwoX = Math.exp(-2 * x); + return (1 + expMinusTwoX) / (1 - expMinusTwoX); +}; + + +/** + * @param {number} x X. + * @return {number} Hyperbolic cosecant of x. + */ +ol.math.csch = function(x) { + return 2 / (Math.exp(x) - Math.exp(-x)); +}; + + +/** + * @param {number} x X. + * @return {number} Hyperbolic secant of x. + */ +ol.math.sech = function(x) { + return 2 / (Math.exp(x) + Math.exp(-x)); +}; + + +/** + * @param {number} x X. + * @return {number} Hyperbolic sine of x. + */ +ol.math.sinh = function(x) { + return (Math.exp(x) - Math.exp(-x)) / 2; +}; + + +/** + * @param {number} x X. + * @return {number} Hyperbolic tangent of x. + */ +ol.math.tanh = function(x) { + var expMinusTwoX = Math.exp(-2 * x); + return (1 - expMinusTwoX) / (1 + expMinusTwoX); +}; diff --git a/master/ol/ol/object.exports b/master/ol/ol/object.exports new file mode 100644 index 0000000000..98c8370bdb --- /dev/null +++ b/master/ol/ol/object.exports @@ -0,0 +1,10 @@ +@exportSymbol ol.Object +@exportProperty ol.Object.prototype.bindTo +@exportProperty ol.Object.prototype.changed +@exportProperty ol.Object.prototype.get +@exportProperty ol.Object.prototype.notify +@exportProperty ol.Object.prototype.set +@exportProperty ol.Object.prototype.setOptions +@exportProperty ol.Object.prototype.setValues +@exportProperty ol.Object.prototype.unbind +@exportProperty ol.Object.prototype.unbindAll diff --git a/master/ol/ol/object.js b/master/ol/ol/object.js new file mode 100644 index 0000000000..861eb651ad --- /dev/null +++ b/master/ol/ol/object.js @@ -0,0 +1,302 @@ + +/** + * An implementation of Google Maps' MVCObject. + * @see https://developers.google.com/maps/articles/mvcfun + * @see https://developers.google.com/maps/documentation/javascript/reference + */ + +goog.provide('ol.Object'); +goog.provide('ol.ObjectEventType'); + +goog.require('goog.array'); +goog.require('goog.events'); +goog.require('goog.events.EventTarget'); +goog.require('goog.object'); + + +/** + * @enum {string} + */ +ol.ObjectEventType = { + CHANGED: 'changed' +}; + + +/** + * @enum {string} + */ +ol.ObjectProperty = { + ACCESSORS: 'ol_accessors_', + BINDINGS: 'ol_bindings_' +}; + + + +/** + * @constructor + * @extends {goog.events.EventTarget} + * @param {Object.=} opt_values Values. + */ +ol.Object = function(opt_values) { + goog.base(this); + + /** + * @private + * @type {Object.} + */ + this.values_ = {}; + + if (goog.isDef(opt_values)) { + this.setValues(opt_values); + } +}; +goog.inherits(ol.Object, goog.events.EventTarget); + + +/** + * @private + * @type {Object.} + */ +ol.Object.changedEventTypeCache_ = {}; + + +/** + * @private + * @type {Object.} + */ +ol.Object.getterNameCache_ = {}; + + +/** + * @private + * @type {Object.} + */ +ol.Object.setterNameCache_ = {}; + + +/** + * @param {string} str String. + * @return {string} Capitalized string. + */ +ol.Object.capitalize = function(str) { + return str.substr(0, 1).toUpperCase() + str.substr(1); +}; + + +/** + * @param {ol.Object} obj Object. + * @return {Object.} Accessors. + */ +ol.Object.getAccessors = function(obj) { + return obj[ol.ObjectProperty.ACCESSORS] || + (obj[ol.ObjectProperty.ACCESSORS] = {}); +}; + + +/** + * @param {string} key Key. + * @return {string} Changed name. + */ +ol.Object.getChangedEventType = function(key) { + return ol.Object.changedEventTypeCache_.hasOwnProperty(key) ? + ol.Object.changedEventTypeCache_[key] : + (ol.Object.changedEventTypeCache_[key] = key.toLowerCase() + '_changed'); +}; + + +/** + * @param {string} key String. + * @return {string} Getter name. + */ +ol.Object.getGetterName = function(key) { + return ol.Object.getterNameCache_.hasOwnProperty(key) ? + ol.Object.getterNameCache_[key] : + (ol.Object.getterNameCache_[key] = 'get' + ol.Object.capitalize(key)); +}; + + +/** + * @param {ol.Object} obj Object. + * @return {Object.} Listeners. + */ +ol.Object.getListeners = function(obj) { + return obj[ol.ObjectProperty.BINDINGS] || + (obj[ol.ObjectProperty.BINDINGS] = {}); +}; + + +/** + * @param {string} key String. + * @return {string} Setter name. + */ +ol.Object.getSetterName = function(key) { + return ol.Object.setterNameCache_.hasOwnProperty(key) ? + ol.Object.setterNameCache_[key] : + (ol.Object.setterNameCache_[key] = 'set' + ol.Object.capitalize(key)); +}; + + +/** + * @param {string} key Key. + * @param {ol.Object} target Target. + * @param {string=} opt_targetKey Target key. + * @param {boolean=} opt_noNotify No notify. + */ +ol.Object.prototype.bindTo = + function(key, target, opt_targetKey, opt_noNotify) { + var targetKey = opt_targetKey || key; + this.unbind(key); + var eventType = ol.Object.getChangedEventType(targetKey); + var listeners = ol.Object.getListeners(this); + listeners[key] = goog.events.listen(target, eventType, function() { + this.notifyInternal_(key); + }, undefined, this); + var accessors = ol.Object.getAccessors(this); + accessors[key] = {target: target, key: targetKey}; + var noNotify = opt_noNotify || false; + if (!noNotify) { + this.notifyInternal_(key); + } +}; + + +/** + * @param {string} key Key. + */ +ol.Object.prototype.changed = goog.nullFunction; + + +/** + * @param {string} key Key. + * @return {*} Value. + */ +ol.Object.prototype.get = function(key) { + var value; + var accessors = ol.Object.getAccessors(this); + if (accessors.hasOwnProperty(key)) { + var accessor = accessors[key]; + var target = accessor.target; + var targetKey = accessor.key; + var getterName = ol.Object.getGetterName(targetKey); + if (target[getterName]) { + value = target[getterName](); + } else { + value = target.get(targetKey); + } + } else if (this.values_.hasOwnProperty(key)) { + value = this.values_[key]; + } + return value; +}; + + +/** + * Get a list of object property names. + * @return {Array.} List of property names. + */ +ol.Object.prototype.getKeys = function() { + var keys = goog.object.getKeys(ol.Object.getAccessors(this)).concat( + goog.object.getKeys(this.values_)); + goog.array.removeDuplicates(keys); + return keys; +}; + + +/** + * @param {string} key Key. + */ +ol.Object.prototype.notify = function(key) { + var accessors = ol.Object.getAccessors(this); + if (accessors.hasOwnProperty(key)) { + var accessor = accessors[key]; + var target = accessor.target; + var targetKey = accessor.key; + target.notify(targetKey); + } else { + this.notifyInternal_(key); + } +}; + + +/** + * @param {string} key Key. + * @private + */ +ol.Object.prototype.notifyInternal_ = function(key) { + var eventType = ol.Object.getChangedEventType(key); + this.dispatchEvent(eventType); + this.dispatchEvent(ol.ObjectEventType.CHANGED); +}; + + +/** + * @param {string} key Key. + * @param {*} value Value. + */ +ol.Object.prototype.set = function(key, value) { + var accessors = ol.Object.getAccessors(this); + if (accessors.hasOwnProperty(key)) { + var accessor = accessors[key]; + var target = accessor.target; + var targetKey = accessor.key; + var setterName = ol.Object.getSetterName(targetKey); + if (target[setterName]) { + target[setterName](value); + } else { + target.set(targetKey, value); + } + } else { + this.values_[key] = value; + this.notifyInternal_(key); + } +}; + + +/** + * @param {Object.} options Options. + */ +ol.Object.prototype.setOptions = function(options) { + var key, value, setterName; + for (key in options) { + value = options[key]; + setterName = ol.Object.getSetterName(key); + if (this[setterName]) { + this[setterName](value); + } else { + this.set(key, value); + } + } +}; + + +/** + * @param {Object.} values Values. + */ +ol.Object.prototype.setValues = ol.Object.prototype.setOptions; + + +/** + * @param {string} key Key. + */ +ol.Object.prototype.unbind = function(key) { + var listeners = ol.Object.getListeners(this); + var listener = listeners[key]; + if (listener) { + delete listeners[key]; + goog.events.unlistenByKey(listener); + var value = this.get(key); + var accessors = ol.Object.getAccessors(this); + delete accessors[key]; + this.values_[key] = value; + } +}; + + +/** + * Removes all bindings. + */ +ol.Object.prototype.unbindAll = function() { + for (var key in ol.Object.getListeners(this)) { + this.unbind(key); + } +}; diff --git a/master/ol/ol/ol.js b/master/ol/ol/ol.js new file mode 100644 index 0000000000..14a0e3d7b2 --- /dev/null +++ b/master/ol/ol/ol.js @@ -0,0 +1,9 @@ +goog.provide('ol'); + +goog.require('goog.debug.Logger'); + + +if (goog.DEBUG) { + var logger = goog.debug.Logger.getLogger('ol'); + logger.setLevel(goog.debug.Logger.Level.FINEST); +} diff --git a/master/ol/ol/parser/ogc/exceptionreport.js b/master/ol/ol/parser/ogc/exceptionreport.js new file mode 100644 index 0000000000..ce2e4990c1 --- /dev/null +++ b/master/ol/ol/parser/ogc/exceptionreport.js @@ -0,0 +1,96 @@ +goog.provide('ol.parser.ogc.ExceptionReport'); +goog.require('goog.dom.xml'); +goog.require('ol.parser.XML'); + + + +/** + * @constructor + * @extends {ol.parser.XML} + */ +ol.parser.ogc.ExceptionReport = function() { + var exceptionReader = function(node, exceptionReport) { + var exception = { + code: node.getAttribute('exceptionCode'), + locator: node.getAttribute('locator'), + texts: [] + }; + exceptionReport.exceptions.push(exception); + this.readChildNodes(node, exception); + }; + var exceptionTextReader = function(node, exception) { + var text = this.getChildValue(node); + exception.texts.push(text); + }; + this.readers = { + 'http://www.opengis.net/ogc': { + 'ServiceExceptionReport': function(node, obj) { + obj['exceptionReport'] = {}; + obj['exceptionReport']['exceptions'] = []; + this.readChildNodes(node, obj['exceptionReport']); + }, + 'ServiceException': function(node, exceptionReport) { + var exception = {}; + exception['code'] = node.getAttribute('code'); + exception['locator'] = node.getAttribute('locator'); + exception['text'] = this.getChildValue(node); + exceptionReport['exceptions'].push(exception); + } + }, + 'http://www.opengis.net/ows': { + 'ExceptionReport': function(node, obj) { + obj.success = false; + obj.exceptionReport = { + version: node.getAttribute('version'), + language: node.getAttribute('language'), + exceptions: [] + }; + this.readChildNodes(node, obj.exceptionReport); + }, + 'Exception': function(node, exceptionReport) { + exceptionReader.apply(this, arguments); + }, + 'ExceptionText': function(node, exception) { + exceptionTextReader.apply(this, arguments); + } + }, + 'http://www.opengis.net/ows/1.1': { + 'ExceptionReport': function(node, obj) { + obj.exceptionReport = { + version: node.getAttribute('version'), + language: node.getAttribute('xml:lang'), + exceptions: [] + }; + this.readChildNodes(node, obj.exceptionReport); + }, + 'Exception': function(node, exceptionReport) { + exceptionReader.apply(this, arguments); + }, + 'ExceptionText': function(node, exception) { + exceptionTextReader.apply(this, arguments); + } + } + }; + goog.base(this); +}; +goog.inherits(ol.parser.ogc.ExceptionReport, ol.parser.XML); + + +/** + * Read OGC exception report data from a string, and return an object with + * information about the exceptions. + * + * @param {string|Document} data to read/parse. + * @return {Object} Information about the exceptions that occurred. + */ +ol.parser.ogc.ExceptionReport.prototype.read = function(data) { + if (typeof data == 'string') { + data = goog.dom.xml.loadXml(data); + } + var exceptionInfo = {}; + exceptionInfo['exceptionReport'] = null; + if (data) { + this.readChildNodes(data, exceptionInfo); + } + return exceptionInfo; +}; diff --git a/master/ol/ol/parser/ogc/owscommon_v1.js b/master/ol/ol/parser/ogc/owscommon_v1.js new file mode 100644 index 0000000000..ae01b4ec93 --- /dev/null +++ b/master/ol/ol/parser/ogc/owscommon_v1.js @@ -0,0 +1,214 @@ +goog.provide('ol.parser.ogc.OWSCommon_v1'); +goog.require('ol.Extent'); +goog.require('ol.parser.XML'); + + + +/** + * @constructor + * @extends {ol.parser.XML} + */ +ol.parser.ogc.OWSCommon_v1 = function() { + this.readers = { + 'http://www.opengis.net/ows': { + 'ServiceIdentification': function(node, obj) { + obj['serviceIdentification'] = {}; + this.readChildNodes(node, obj['serviceIdentification']); + }, + 'Title': function(node, obj) { + obj['title'] = this.getChildValue(node); + }, + 'Abstract': function(node, serviceIdentification) { + serviceIdentification['abstract'] = this.getChildValue(node); + }, + 'Keywords': function(node, serviceIdentification) { + serviceIdentification['keywords'] = {}; + this.readChildNodes(node, serviceIdentification['keywords']); + }, + 'Keyword': function(node, keywords) { + keywords[this.getChildValue(node)] = true; + }, + 'ServiceType': function(node, serviceIdentification) { + serviceIdentification['serviceType'] = { + 'codeSpace': node.getAttribute('codeSpace'), + 'value': this.getChildValue(node)}; + }, + 'ServiceTypeVersion': function(node, serviceIdentification) { + serviceIdentification['serviceTypeVersion'] = this.getChildValue(node); + }, + 'Fees': function(node, serviceIdentification) { + serviceIdentification['fees'] = this.getChildValue(node); + }, + 'AccessConstraints': function(node, serviceIdentification) { + serviceIdentification['accessConstraints'] = + this.getChildValue(node); + }, + 'ServiceProvider': function(node, obj) { + obj['serviceProvider'] = {}; + this.readChildNodes(node, obj['serviceProvider']); + }, + 'ProviderName': function(node, serviceProvider) { + serviceProvider['providerName'] = this.getChildValue(node); + }, + 'ProviderSite': function(node, serviceProvider) { + serviceProvider['providerSite'] = this.getAttributeNS(node, + 'http://www.w3.org/1999/xlink', 'href'); + }, + 'ServiceContact': function(node, serviceProvider) { + serviceProvider['serviceContact'] = {}; + this.readChildNodes(node, serviceProvider['serviceContact']); + }, + 'IndividualName': function(node, serviceContact) { + serviceContact['individualName'] = this.getChildValue(node); + }, + 'PositionName': function(node, serviceContact) { + serviceContact['positionName'] = this.getChildValue(node); + }, + 'ContactInfo': function(node, serviceContact) { + serviceContact['contactInfo'] = {}; + this.readChildNodes(node, serviceContact['contactInfo']); + }, + 'Phone': function(node, contactInfo) { + contactInfo['phone'] = {}; + this.readChildNodes(node, contactInfo['phone']); + }, + 'Voice': function(node, phone) { + phone['voice'] = this.getChildValue(node); + }, + 'Address': function(node, contactInfo) { + contactInfo['address'] = {}; + this.readChildNodes(node, contactInfo['address']); + }, + 'DeliveryPoint': function(node, address) { + address['deliveryPoint'] = this.getChildValue(node); + }, + 'City': function(node, address) { + address['city'] = this.getChildValue(node); + }, + 'AdministrativeArea': function(node, address) { + address['administrativeArea'] = this.getChildValue(node); + }, + 'PostalCode': function(node, address) { + address['postalCode'] = this.getChildValue(node); + }, + 'Country': function(node, address) { + address['country'] = this.getChildValue(node); + }, + 'ElectronicMailAddress': function(node, address) { + address['electronicMailAddress'] = this.getChildValue(node); + }, + 'Role': function(node, serviceContact) { + serviceContact['role'] = this.getChildValue(node); + }, + 'OperationsMetadata': function(node, obj) { + obj['operationsMetadata'] = {}; + this.readChildNodes(node, obj['operationsMetadata']); + }, + 'Operation': function(node, operationsMetadata) { + var name = node.getAttribute('name'); + operationsMetadata[name] = {}; + this.readChildNodes(node, operationsMetadata[name]); + }, + 'DCP': function(node, operation) { + operation['dcp'] = {}; + this.readChildNodes(node, operation['dcp']); + }, + 'HTTP': function(node, dcp) { + dcp['http'] = {}; + this.readChildNodes(node, dcp['http']); + }, + 'Get': function(node, http) { + if (!http['get']) { + http['get'] = []; + } + var obj = { + 'url': this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', + 'href') + }; + this.readChildNodes(node, obj); + http['get'].push(obj); + }, + 'Post': function(node, http) { + if (!http['post']) { + http['post'] = []; + } + var obj = { + 'url': this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', + 'href') + }; + this.readChildNodes(node, obj); + http['post'].push(obj); + }, + 'Parameter': function(node, operation) { + if (!operation['parameters']) { + operation['parameters'] = {}; + } + var name = node.getAttribute('name'); + operation['parameters'][name] = {}; + this.readChildNodes(node, operation['parameters'][name]); + }, + 'Constraint': function(node, obj) { + if (!obj['constraints']) { + obj['constraints'] = {}; + } + var name = node.getAttribute('name'); + obj['constraints'][name] = {}; + this.readChildNodes(node, obj['constraints'][name]); + }, + 'Value': function(node, allowedValues) { + allowedValues[this.getChildValue(node)] = true; + }, + 'OutputFormat': function(node, obj) { + obj['formats'].push({'value': this.getChildValue(node)}); + this.readChildNodes(node, obj); + }, + 'WGS84BoundingBox': function(node, obj) { + var boundingBox = {}; + boundingBox['crs'] = node.getAttribute('crs'); + if (obj['BoundingBox']) { + obj['BoundingBox'].push(boundingBox); + } else { + obj['projection'] = boundingBox['crs']; + boundingBox = obj; + } + this.readChildNodes(node, boundingBox); + }, + 'BoundingBox': function(node, obj) { + // FIXME: We consider that BoundingBox is the same as WGS84BoundingBox + // LowerCorner = "min_x min_y" + // UpperCorner = "max_x max_y" + // It should normally depend on the projection + var readers = this.readers['http://www.opengis.net/ows']; + readers['WGS84BoundingBox'].apply(this, [node, obj]); + }, + 'LowerCorner': function(node, obj) { + var str = this.getChildValue(node).replace( + this.regExes.trimSpace, ''); + str = str.replace(this.regExes.trimComma, ','); + var pointList = str.split(this.regExes.splitSpace); + obj['left'] = pointList[0]; + obj['bottom'] = pointList[1]; + }, + 'UpperCorner': function(node, obj) { + var str = this.getChildValue(node).replace( + this.regExes.trimSpace, ''); + str = str.replace(this.regExes.trimComma, ','); + var pointList = str.split(this.regExes.splitSpace); + obj['right'] = pointList[0]; + obj['top'] = pointList[1]; + obj['bounds'] = new ol.Extent(parseFloat(obj['left']), + parseFloat(obj['bottom']), parseFloat(obj['right']), + parseFloat(obj['top'])); + delete obj['left']; + delete obj['bottom']; + delete obj['right']; + delete obj['top']; + }, + 'Language': function(node, obj) { + obj['language'] = this.getChildValue(node); + } + } + }; + goog.base(this); +}; +goog.inherits(ol.parser.ogc.OWSCommon_v1, ol.parser.XML); diff --git a/master/ol/ol/parser/ogc/owscommon_v1_1_0.js b/master/ol/ol/parser/ogc/owscommon_v1_1_0.js new file mode 100644 index 0000000000..98c7bfc016 --- /dev/null +++ b/master/ol/ol/parser/ogc/owscommon_v1_1_0.js @@ -0,0 +1,45 @@ +goog.provide('ol.parser.ogc.OWSCommon_v1_1_0'); +goog.require('goog.object'); +goog.require('ol.parser.ogc.OWSCommon_v1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.OWSCommon_v1} + */ +ol.parser.ogc.OWSCommon_v1_1_0 = function() { + goog.base(this); + this.readers['http://www.opengis.net/ows/1.1'] = + this.readers['http://www.opengis.net/ows']; + goog.object.extend(this.readers['http://www.opengis.net/ows/1.1'], { + 'AllowedValues': function(node, parameter) { + parameter['allowedValues'] = {}; + this.readChildNodes(node, parameter['allowedValues']); + }, + 'AnyValue': function(node, parameter) { + parameter['anyValue'] = true; + }, + 'DataType': function(node, parameter) { + parameter['dataType'] = this.getChildValue(node); + }, + 'Range': function(node, allowedValues) { + allowedValues['range'] = {}; + this.readChildNodes(node, allowedValues['range']); + }, + 'MinimumValue': function(node, range) { + range['minValue'] = this.getChildValue(node); + }, + 'MaximumValue': function(node, range) { + range['maxValue'] = this.getChildValue(node); + }, + 'Identifier': function(node, obj) { + obj['identifier'] = this.getChildValue(node); + }, + 'SupportedCRS': function(node, obj) { + obj['supportedCRS'] = this.getChildValue(node); + } + }); +}; +goog.inherits(ol.parser.ogc.OWSCommon_v1_1_0, + ol.parser.ogc.OWSCommon_v1); diff --git a/master/ol/ol/parser/ogc/versioned.js b/master/ol/ol/parser/ogc/versioned.js new file mode 100644 index 0000000000..0f22bfe273 --- /dev/null +++ b/master/ol/ol/parser/ogc/versioned.js @@ -0,0 +1,121 @@ +goog.provide('ol.parser.ogc.Versioned'); +goog.require('goog.dom.xml'); +goog.require('ol.parser.ogc.ExceptionReport'); + + + +/** + * @constructor + * @param {Object} formatOptions Options which will be set on this object. + */ +ol.parser.ogc.Versioned = function(formatOptions) { + formatOptions = formatOptions || {}; + this.options = formatOptions; + this.defaultVersion = formatOptions.defaultVersion || null; + this.version = formatOptions.version; + this.profile = formatOptions.profile; + if (formatOptions.allowFallback !== undefined) { + this.allowFallback = formatOptions.allowFallback; + } else { + this.allowFallback = false; + } + if (formatOptions.stringifyOutput !== undefined) { + this.stringifyOutput = formatOptions.stringifyOutput; + } else { + this.stringifyOutput = false; + } +}; + + +/** + * @param {Element} root root element. + * @param {Object=} opt_options optional configuration object. + * @return {string} the version to use. + */ +ol.parser.ogc.Versioned.prototype.getVersion = function(root, opt_options) { + var version; + // read + if (root) { + version = this.version; + if (!version) { + version = root.getAttribute('version'); + if (!version) { + version = this.defaultVersion; + } + } + } else { + // write + version = (opt_options && opt_options.version) || + this.version || this.defaultVersion; + } + return version; +}; + + +/** + * @param {string} version the version to use. + * @return {Object} the parser to use. + */ +ol.parser.ogc.Versioned.prototype.getParser = function(version) { + version = version || this.defaultVersion; + var profile = this.profile ? '_' + this.profile : ''; + if (!this.parser || this.parser.VERSION != version) { + var format = this.parsers['v' + version.replace(/\./g, '_') + profile]; + if (!format) { + if (profile !== '' && this.allowFallback) { + // fallback to the non-profiled version of the parser + profile = ''; + format = this.parsers['v' + version.replace(/\./g, '_') + profile]; + } + if (!format) { + throw 'Can\'t find a parser for version ' + + version + profile; + } + } + this.parser = new format(this.options); + } + return this.parser; +}; + + +/** + * Write a document. + * + * @param {Object} obj An object representing the document. + * @param {Object=} opt_options Optional configuration object. + * @return {Element|string} the XML created. + */ +ol.parser.ogc.Versioned.prototype.write = function(obj, opt_options) { + var version = this.getVersion(null, opt_options); + this.parser = this.getParser(version); + var root = this.parser.write(obj, opt_options); + if (this.stringifyOutput === false) { + return root; + } else { + return goog.dom.xml.serialize(root); + } +}; + + +/** + * @param {string|Document} data Data to read. + * @param {Object=} opt_options Options for the reader. + * @return {Object} An object representing the document. + */ +ol.parser.ogc.Versioned.prototype.read = function(data, opt_options) { + if (typeof data == 'string') { + data = goog.dom.xml.loadXml(data); + } + var root = data.documentElement; + var version = this.getVersion(root); + this.parser = this.getParser(version); + var obj = this.parser.read(data, opt_options); + var errorProperty = this.parser.errorProperty || null; + if (errorProperty !== null && obj[errorProperty] === undefined) { + // an error must have happened, so parse it and report back + var format = new ol.parser.ogc.ExceptionReport(); + obj.error = format.read(data); + } + obj.version = version; + return obj; +}; diff --git a/master/ol/ol/parser/ogc/wmscapabilities.exports b/master/ol/ol/parser/ogc/wmscapabilities.exports new file mode 100644 index 0000000000..2552ec6664 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.parser.ogc.WMSCapabilities +@exportProperty ol.parser.ogc.WMSCapabilities.prototype.read diff --git a/master/ol/ol/parser/ogc/wmscapabilities.js b/master/ol/ol/parser/ogc/wmscapabilities.js new file mode 100644 index 0000000000..82efbd4beb --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities.js @@ -0,0 +1,68 @@ +goog.provide('ol.parser.ogc.WMSCapabilities'); +goog.require('ol.parser.ogc.Versioned'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_0_0'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1_0'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1_1'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_3_0'); + + +/** + * @define {boolean} Whether to enable WMS Capabilities version 1.0.0. + */ +ol.ENABLE_WMSCAPS_1_0_0 = false; + + +/** + * @define {boolean} Whether to enable WMS Capabilities version 1.1.0. + */ +ol.ENABLE_WMSCAPS_1_1_0 = true; + + +/** + * @define {boolean} Whether to enable WMS Capabilities version 1.1.1. + */ +ol.ENABLE_WMSCAPS_1_1_1 = true; + + +/** + * @define {boolean} Whether to enable WMS Capabilities version 1.3.0. + */ +ol.ENABLE_WMSCAPS_1_3_0 = true; + + +/** + * @define {boolean} Whether to enable WMS Capabilities version 1.1.1. + * WMSC profile. + */ +ol.ENABLE_WMSCAPS_1_1_1_WMSC = true; + + + +/** + * @constructor + * @param {Object=} opt_options Options which will be set on this object. + * @extends {ol.parser.ogc.Versioned} + */ +ol.parser.ogc.WMSCapabilities = function(opt_options) { + opt_options = opt_options || {}; + opt_options['defaultVersion'] = '1.1.1'; + this.parsers = {}; + if (ol.ENABLE_WMSCAPS_1_0_0) { + this.parsers['v1_0_0'] = ol.parser.ogc.WMSCapabilities_v1_0_0; + } + if (ol.ENABLE_WMSCAPS_1_1_0) { + this.parsers['v1_1_0'] = ol.parser.ogc.WMSCapabilities_v1_1_0; + } + if (ol.ENABLE_WMSCAPS_1_1_1) { + this.parsers['v1_1_1'] = ol.parser.ogc.WMSCapabilities_v1_1_1; + } + if (ol.ENABLE_WMSCAPS_1_1_1_WMSC) { + this.parsers['v1_1_1_WMSC'] = ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC; + } + if (ol.ENABLE_WMSCAPS_1_3_0) { + this.parsers['v1_3_0'] = ol.parser.ogc.WMSCapabilities_v1_3_0; + } + goog.base(this, opt_options); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities, ol.parser.ogc.Versioned); diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1.js b/master/ol/ol/parser/ogc/wmscapabilities_v1.js new file mode 100644 index 0000000000..860392da99 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1.js @@ -0,0 +1,315 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1'); +goog.require('goog.dom.xml'); +goog.require('goog.object'); +goog.require('ol.parser.XML'); + + + +/** + * @constructor + * @extends {ol.parser.XML} + */ +ol.parser.ogc.WMSCapabilities_v1 = function() { + this.defaultNamespaceURI = 'http://www.opengis.net/wms'; + this.errorProperty = 'service'; + this.readers = { + 'http://www.opengis.net/wms': { + 'Service': function(node, obj) { + obj['service'] = {}; + this.readChildNodes(node, obj['service']); + }, + 'Name': function(node, obj) { + obj['name'] = this.getChildValue(node); + }, + 'Title': function(node, obj) { + obj['title'] = this.getChildValue(node); + }, + 'Abstract': function(node, obj) { + obj['abstract'] = this.getChildValue(node); + }, + 'BoundingBox': function(node, obj) { + var bbox = {}; + bbox['bbox'] = [ + parseFloat(node.getAttribute('minx')), + parseFloat(node.getAttribute('miny')), + parseFloat(node.getAttribute('maxx')), + parseFloat(node.getAttribute('maxy')) + ]; + var res = { + x: parseFloat(node.getAttribute('resx')), + y: parseFloat(node.getAttribute('resy')) + }; + if (! (isNaN(res.x) && isNaN(res.y))) { + bbox['res'] = res; + } + // return the bbox so that descendant classes can set the + // CRS and SRS and add it to the obj + return bbox; + }, + 'OnlineResource': function(node, obj) { + obj['href'] = this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', + 'href'); + }, + 'ContactInformation': function(node, obj) { + obj['contactInformation'] = {}; + this.readChildNodes(node, obj['contactInformation']); + }, + 'ContactPersonPrimary': function(node, obj) { + obj['personPrimary'] = {}; + this.readChildNodes(node, obj['personPrimary']); + }, + 'ContactPerson': function(node, obj) { + obj['person'] = this.getChildValue(node); + }, + 'ContactOrganization': function(node, obj) { + obj['organization'] = this.getChildValue(node); + }, + 'ContactPosition': function(node, obj) { + obj['position'] = this.getChildValue(node); + }, + 'ContactAddress': function(node, obj) { + obj['contactAddress'] = {}; + this.readChildNodes(node, obj['contactAddress']); + }, + 'AddressType': function(node, obj) { + obj['type'] = this.getChildValue(node); + }, + 'Address': function(node, obj) { + obj['address'] = this.getChildValue(node); + }, + 'City': function(node, obj) { + obj['city'] = this.getChildValue(node); + }, + 'StateOrProvince': function(node, obj) { + obj['stateOrProvince'] = this.getChildValue(node); + }, + 'PostCode': function(node, obj) { + obj['postcode'] = this.getChildValue(node); + }, + 'Country': function(node, obj) { + obj['country'] = this.getChildValue(node); + }, + 'ContactVoiceTelephone': function(node, obj) { + obj['phone'] = this.getChildValue(node); + }, + 'ContactFacsimileTelephone': function(node, obj) { + obj['fax'] = this.getChildValue(node); + }, + 'ContactElectronicMailAddress': function(node, obj) { + obj['email'] = this.getChildValue(node); + }, + 'Fees': function(node, obj) { + var fees = this.getChildValue(node); + if (fees && fees.toLowerCase() != 'none') { + obj['fees'] = fees; + } + }, + 'AccessConstraints': function(node, obj) { + var constraints = this.getChildValue(node); + if (constraints && constraints.toLowerCase() != 'none') { + obj['accessConstraints'] = constraints; + } + }, + 'Capability': function(node, obj) { + obj['capability'] = {}; + obj['capability']['nestedLayers'] = []; + obj['capability']['layers'] = []; + this.readChildNodes(node, obj['capability']); + }, + 'Request': function(node, obj) { + obj['request'] = {}; + this.readChildNodes(node, obj['request']); + }, + 'GetCapabilities': function(node, obj) { + obj['getcapabilities'] = {}; + obj['getcapabilities']['formats'] = []; + this.readChildNodes(node, obj['getcapabilities']); + }, + 'Format': function(node, obj) { + if (goog.isArray(obj['formats'])) { + obj['formats'].push(this.getChildValue(node)); + } else { + obj['format'] = this.getChildValue(node); + } + }, + 'DCPType': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'HTTP': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'Get': function(node, obj) { + obj['get'] = {}; + this.readChildNodes(node, obj['get']); + }, + 'Post': function(node, obj) { + obj['post'] = {}; + this.readChildNodes(node, obj['post']); + }, + 'GetMap': function(node, obj) { + obj['getmap'] = {}; + obj['getmap']['formats'] = []; + this.readChildNodes(node, obj['getmap']); + }, + 'GetFeatureInfo': function(node, obj) { + obj['getfeatureinfo'] = {}; + obj['getfeatureinfo']['formats'] = []; + this.readChildNodes(node, obj['getfeatureinfo']); + }, + 'Exception': function(node, obj) { + obj['exception'] = {}; + obj['exception']['formats'] = []; + this.readChildNodes(node, obj['exception']); + }, + 'Layer': function(node, obj) { + var parentLayer, capability; + if (obj['capability']) { + capability = obj['capability']; + parentLayer = obj; + } else { + capability = obj; + } + var attrNode = node.getAttributeNode('queryable'); + var queryable = (attrNode && attrNode.specified) ? + node.getAttribute('queryable') : null; + attrNode = node.getAttributeNode('cascaded'); + var cascaded = (attrNode && attrNode.specified) ? + node.getAttribute('cascaded') : null; + attrNode = node.getAttributeNode('opaque'); + var opaque = (attrNode && attrNode.specified) ? + node.getAttribute('opaque') : null; + var noSubsets = node.getAttribute('noSubsets'); + var fixedWidth = node.getAttribute('fixedWidth'); + var fixedHeight = node.getAttribute('fixedHeight'); + var parent = parentLayer || {}; + var layer = { + 'nestedLayers': [], + 'styles': parentLayer ? [].concat(parentLayer['styles']) : [], + 'srs': {}, + 'metadataURLs': [], + 'bbox': {}, + 'llbbox': parent['llbbox'], + 'dimensions': {}, + 'authorityURLs': {}, + 'identifiers': {}, + 'keywords': [], + 'queryable': (queryable && queryable !== '') ? + (queryable === '1' || queryable === 'true') : + (parent['queryable'] || false), + 'cascaded': (cascaded !== null) ? parseInt(cascaded, 10) : + (parent['cascaded'] || 0), + 'opaque': opaque ? + (opaque === '1' || opaque === 'true') : + (parent['opaque'] || false), + 'noSubsets': (noSubsets !== null) ? + (noSubsets === '1' || noSubsets === 'true') : + (parent['noSubsets'] || false), + 'fixedWidth': (fixedWidth !== null) ? + parseInt(fixedWidth, 10) : (parent['fixedWidth'] || 0), + 'fixedHeight': (fixedHeight !== null) ? + parseInt(fixedHeight, 10) : (parent['fixedHeight'] || 0), + 'minScale': parent['minScale'], + 'maxScale': parent['maxScale'], + 'attribution': parent['attribution'] + }; + if (parentLayer) { + goog.object.extend(layer['srs'], parent['srs']); + goog.object.extend(layer['bbox'], parent['bbox']); + goog.object.extend(layer['dimensions'], parent['dimensions']); + goog.object.extend(layer['authorityURLs'], parent['authorityURLs']); + } + obj['nestedLayers'].push(layer); + layer['capability'] = capability; + this.readChildNodes(node, layer); + delete layer['capability']; + if (layer['name']) { + var parts = layer['name'].split(':'), + request = capability['request'], + gfi = request['getfeatureinfo']; + if (parts.length > 0) { + layer['prefix'] = parts[0]; + } + capability['layers'].push(layer); + if (layer['formats'] === undefined) { + layer['formats'] = request['getmap']['formats']; + } + if (layer['infoFormats'] === undefined && gfi) { + layer['infoFormats'] = gfi['formats']; + } + } + }, + 'Attribution': function(node, obj) { + obj['attribution'] = {}; + this.readChildNodes(node, obj['attribution']); + }, + 'LogoURL': function(node, obj) { + obj['logo'] = { + 'width': node.getAttribute('width'), + 'height': node.getAttribute('height') + }; + this.readChildNodes(node, obj['logo']); + }, + 'Style': function(node, obj) { + var style = {}; + obj['styles'].push(style); + this.readChildNodes(node, style); + }, + 'LegendURL': function(node, obj) { + var legend = { + 'width': node.getAttribute('width'), + 'height': node.getAttribute('height') + }; + obj['legend'] = legend; + this.readChildNodes(node, legend); + }, + 'MetadataURL': function(node, obj) { + var metadataURL = {'type': node.getAttribute('type')}; + obj['metadataURLs'].push(metadataURL); + this.readChildNodes(node, metadataURL); + }, + 'DataURL': function(node, obj) { + obj['dataURL'] = {}; + this.readChildNodes(node, obj['dataURL']); + }, + 'FeatureListURL': function(node, obj) { + obj['featureListURL'] = {}; + this.readChildNodes(node, obj['featureListURL']); + }, + 'AuthorityURL': function(node, obj) { + var name = node.getAttribute('name'); + var authority = {}; + this.readChildNodes(node, authority); + obj['authorityURLs'][name] = authority['href']; + }, + 'Identifier': function(node, obj) { + var authority = node.getAttribute('authority'); + obj['identifiers'][authority] = this.getChildValue(node); + }, + 'KeywordList': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'SRS': function(node, obj) { + obj['srs'][this.getChildValue(node)] = true; + } + } + }; + goog.base(this); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1, ol.parser.XML); + + +/** + * @param {string|Document|Element} data Data to read. + * @return {Object} An object representing the document. + */ +ol.parser.ogc.WMSCapabilities_v1.prototype.read = function(data) { + if (typeof data == 'string') { + data = goog.dom.xml.loadXml(data); + } + if (data && data.nodeType == 9) { + data = data.documentElement; + } + var obj = {}; + this.readNode(data, obj); + return obj; +}; diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1_0_0.js b/master/ol/ol/parser/ogc/wmscapabilities_v1_0_0.js new file mode 100644 index 0000000000..4e78ea7c5e --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1_0_0.js @@ -0,0 +1,62 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1_0_0'); +goog.require('goog.string'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1_0'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WMSCapabilities_v1_1_0} + */ +ol.parser.ogc.WMSCapabilities_v1_0_0 = function() { + goog.base(this); + this.version = '1.0.0'; + goog.object.extend(this.readers['http://www.opengis.net/wms'], { + 'Format': function(node, obj) { + for (var i = 0, ii = node.childNodes.length; i < ii; i++) { + var child = node.childNodes[i]; + var local = child.localName || child.nodeName.split(':').pop(); + if (goog.isArray(obj['formats'])) { + obj['formats'].push(local); + } else { + obj['format'] = local; + } + } + }, + 'Keywords': function(node, obj) { + if (!goog.isDef(obj['keywords'])) { + obj['keywords'] = []; + } + var keywords = this.getChildValue(node).split(/ +/); + for (var i = 0, ii = keywords.length; i < ii; ++i) { + if (!goog.string.isEmpty(keywords[i])) { + obj['keywords'].push({'value': keywords[i]}); + } + } + }, + 'OnlineResource': function(node, obj) { + obj['href'] = this.getChildValue(node); + }, + 'Get': function(node, obj) { + obj['get'] = {'href': node.getAttribute('onlineResource')}; + }, + 'Post': function(node, obj) { + obj['post'] = {'href': node.getAttribute('onlineResource')}; + }, + 'Map': function(node, obj) { + var reader = this.readers[this.defaultNamespaceURI]['GetMap']; + reader.apply(this, arguments); + }, + 'Capabilities': function(node, obj) { + var reader = this.readers[this.defaultNamespaceURI]['GetCapabilities']; + reader.apply(this, arguments); + }, + 'FeatureInfo': function(node, obj) { + var reader = this.readers[this.defaultNamespaceURI]['GetFeatureInfo']; + reader.apply(this, arguments); + } + }); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_0_0, + ol.parser.ogc.WMSCapabilities_v1_1_0); + diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1_1.js b/master/ol/ol/parser/ogc/wmscapabilities_v1_1.js new file mode 100644 index 0000000000..927e76b9d0 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1_1.js @@ -0,0 +1,99 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1_1'); +goog.require('ol.parser.ogc.WMSCapabilities_v1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WMSCapabilities_v1} + */ +ol.parser.ogc.WMSCapabilities_v1_1 = function() { + goog.base(this); + var bboxreader = this.readers['http://www.opengis.net/wms']['BoundingBox']; + goog.object.extend(this.readers['http://www.opengis.net/wms'], { + 'WMT_MS_Capabilities': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'Keyword': function(node, obj) { + if (obj['keywords']) { + obj['keywords'].push({'value': this.getChildValue(node)}); + } + }, + 'DescribeLayer': function(node, obj) { + obj['describelayer'] = {'formats': []}; + this.readChildNodes(node, obj['describelayer']); + }, + 'GetLegendGraphic': function(node, obj) { + obj['getlegendgraphic'] = {'formats': []}; + this.readChildNodes(node, obj['getlegendgraphic']); + }, + 'GetStyles': function(node, obj) { + obj['getstyles'] = {'formats': []}; + this.readChildNodes(node, obj['getstyles']); + }, + 'PutStyles': function(node, obj) { + obj['putstyles'] = {'formats': []}; + this.readChildNodes(node, obj['putstyles']); + }, + 'UserDefinedSymbolization': function(node, obj) { + var userSymbols = { + 'supportSLD': parseInt(node.getAttribute('SupportSLD'), 10) == 1, + 'userLayer': parseInt(node.getAttribute('UserLayer'), 10) == 1, + 'userStyle': parseInt(node.getAttribute('UserStyle'), 10) == 1, + 'remoteWFS': parseInt(node.getAttribute('RemoteWFS'), 10) == 1 + }; + obj['userSymbols'] = userSymbols; + }, + 'LatLonBoundingBox': function(node, obj) { + obj['llbbox'] = [ + parseFloat(node.getAttribute('minx')), + parseFloat(node.getAttribute('miny')), + parseFloat(node.getAttribute('maxx')), + parseFloat(node.getAttribute('maxy')) + ]; + }, + 'BoundingBox': function(node, obj) { + var bbox = bboxreader.apply(this, arguments); + bbox['srs'] = node.getAttribute('SRS'); + obj['bbox'][bbox['srs']] = bbox; + }, + 'ScaleHint': function(node, obj) { + var min = parseFloat(node.getAttribute('min')); + var max = parseFloat(node.getAttribute('max')); + var rad2 = Math.pow(2, 0.5); + var dpi = (25.4 / 0.28); + var ipm = 39.37; + if (min !== 0) { + obj['maxScale'] = parseFloat((min / rad2) * ipm * dpi); + } + if (max != Number.POSITIVE_INFINITY) { + obj['minScale'] = parseFloat((max / rad2) * ipm * dpi); + } + }, + 'Dimension': function(node, obj) { + var name = node.getAttribute('name').toLowerCase(); + var dim = { + 'name': name, + 'units': node.getAttribute('units'), + 'unitsymbol': node.getAttribute('unitSymbol') + }; + obj['dimensions'][dim.name] = dim; + }, + 'Extent': function(node, obj) { + var name = node.getAttribute('name').toLowerCase(); + if (name in obj['dimensions']) { + var extent = obj['dimensions'][name]; + extent['nearestVal'] = + node.getAttribute('nearestValue') === '1'; + extent['multipleVal'] = + node.getAttribute('multipleValues') === '1'; + extent['current'] = node.getAttribute('current') === '1'; + extent['default'] = node.getAttribute('default') || ''; + var values = this.getChildValue(node); + extent['values'] = values.split(','); + } + } + }); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_1, + ol.parser.ogc.WMSCapabilities_v1); diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1_1_0.js b/master/ol/ol/parser/ogc/wmscapabilities_v1_1_0.js new file mode 100644 index 0000000000..e00a3da270 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1_1_0.js @@ -0,0 +1,25 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1_1_0'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WMSCapabilities_v1_1} + */ +ol.parser.ogc.WMSCapabilities_v1_1_0 = function() { + goog.base(this); + this.version = '1.1.0'; + goog.object.extend(this.readers['http://www.opengis.net/wms'], { + 'SRS': function(node, obj) { + var srs = this.getChildValue(node); + var values = srs.split(/ +/); + for (var i = 0, len = values.length; i < len; i++) { + obj['srs'][values[i]] = true; + } + } + }); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_1_0, + ol.parser.ogc.WMSCapabilities_v1_1); + diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1_1_1.js b/master/ol/ol/parser/ogc/wmscapabilities_v1_1_1.js new file mode 100644 index 0000000000..87e7ab50de --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1_1_1.js @@ -0,0 +1,21 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1_1_1'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WMSCapabilities_v1_1} + */ +ol.parser.ogc.WMSCapabilities_v1_1_1 = function() { + goog.base(this); + this.version = '1.1.1'; + goog.object.extend(this.readers['http://www.opengis.net/wms'], { + 'SRS': function(node, obj) { + obj['srs'][this.getChildValue(node)] = true; + } + }); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_1_1, + ol.parser.ogc.WMSCapabilities_v1_1); + diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js b/master/ol/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js new file mode 100644 index 0000000000..dac01bc925 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js @@ -0,0 +1,46 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC'); +goog.require('ol.parser.ogc.WMSCapabilities_v1_1_1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WMSCapabilities_v1_1_1} + */ +ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC = function() { + goog.base(this); + this.profile = 'WMSC'; + goog.object.extend(this.readers['http://www.opengis.net/wms'], { + 'VendorSpecificCapabilities': function(node, obj) { + obj['vendorSpecific'] = {'tileSets': []}; + this.readChildNodes(node, obj['vendorSpecific']); + }, + 'TileSet': function(node, vendorSpecific) { + var tileset = {'srs': {}, 'bbox': {}, 'resolutions': []}; + this.readChildNodes(node, tileset); + vendorSpecific.tileSets.push(tileset); + }, + 'Resolutions': function(node, tileset) { + var res = this.getChildValue(node).split(' '); + for (var i = 0, len = res.length; i < len; i++) { + if (res[i] !== '') { + tileset['resolutions'].push(parseFloat(res[i])); + } + } + }, + 'Width': function(node, tileset) { + tileset['width'] = parseInt(this.getChildValue(node), 10); + }, + 'Height': function(node, tileset) { + tileset['height'] = parseInt(this.getChildValue(node), 10); + }, + 'Layers': function(node, tileset) { + tileset['layers'] = this.getChildValue(node); + }, + 'Styles': function(node, tileset) { + tileset['styles'] = this.getChildValue(node); + } + }); +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC, + ol.parser.ogc.WMSCapabilities_v1_1_1); diff --git a/master/ol/ol/parser/ogc/wmscapabilities_v1_3_0.js b/master/ol/ol/parser/ogc/wmscapabilities_v1_3_0.js new file mode 100644 index 0000000000..e1144bf9b0 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmscapabilities_v1_3_0.js @@ -0,0 +1,109 @@ +goog.provide('ol.parser.ogc.WMSCapabilities_v1_3_0'); +goog.require('ol.parser.ogc.WMSCapabilities_v1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WMSCapabilities_v1} + */ +ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { + goog.base(this); + var bboxreader = this.readers['http://www.opengis.net/wms']['BoundingBox']; + goog.object.extend(this.readers['http://www.opengis.net/wms'], { + 'WMS_Capabilities': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'LayerLimit': function(node, obj) { + obj['layerLimit'] = parseInt(this.getChildValue(node), 10); + }, + 'MaxWidth': function(node, obj) { + obj['maxWidth'] = parseInt(this.getChildValue(node), 10); + }, + 'MaxHeight': function(node, obj) { + obj['maxHeight'] = parseInt(this.getChildValue(node), 10); + }, + 'BoundingBox': function(node, obj) { + var bbox = bboxreader.apply(this, arguments); + bbox['srs'] = node.getAttribute('CRS'); + obj['bbox'][bbox['srs']] = bbox; + }, + 'CRS': function(node, obj) { + // CRS is the synonym of SRS + this.readers['http://www.opengis.net/wms']['SRS'].apply(this, arguments); + }, + 'EX_GeographicBoundingBox': function(node, obj) { + // replacement of LatLonBoundingBox + obj['llbbox'] = []; + this.readChildNodes(node, obj['llbbox']); + }, + 'westBoundLongitude': function(node, obj) { + obj[0] = this.getChildValue(node); + }, + 'eastBoundLongitude': function(node, obj) { + obj[2] = this.getChildValue(node); + }, + 'southBoundLatitude': function(node, obj) { + obj[1] = this.getChildValue(node); + }, + 'northBoundLatitude': function(node, obj) { + obj[3] = this.getChildValue(node); + }, + 'MinScaleDenominator': function(node, obj) { + obj['maxScale'] = parseFloat(this.getChildValue(node)).toPrecision(16); + }, + 'MaxScaleDenominator': function(node, obj) { + obj['minScale'] = parseFloat(this.getChildValue(node)).toPrecision(16); + }, + 'Dimension': function(node, obj) { + // dimension has extra attributes: default, multipleValues, + // nearestValue, current which used to be part of Extent. It now + // also contains the values. + var name = node.getAttribute('name').toLowerCase(); + var dim = { + 'name': name, + 'units': node.getAttribute('units'), + 'unitsymbol': node.getAttribute('unitSymbol'), + 'nearestVal': node.getAttribute('nearestValue') === '1', + 'multipleVal': node.getAttribute('multipleValues') === '1', + 'default': node.getAttribute('default') || '', + 'current': node.getAttribute('current') === '1', + 'values': this.getChildValue(node).split(',') + }; + // Theoretically there can be more dimensions with the same + // name, but with a different unit. Until we meet such a case, + // let's just keep the same structure as the WMS 1.1 + // GetCapabilities parser uses. We will store the last + // one encountered. + obj['dimensions'][dim['name']] = dim; + }, + 'Keyword': function(node, obj) { + var keyword = {'value': this.getChildValue(node), + 'vocabulary': node.getAttribute('vocabulary')}; + if (obj['keywords']) { + obj['keywords'].push(keyword); + } + } + }); + this.readers['sld'] = { + 'UserDefinedSymbolization': function(node, obj) { + var readers = this.readers['http://www.opengis.net/wms']; + readers.UserDefinedSymbolization.apply(this, arguments); + // add the two extra attributes + var value = node.getAttribute('InlineFeature'); + obj['userSymbols']['inlineFeature'] = parseInt(value, 10) == 1; + value = node.getAttribute('RemoteWCS'); + obj['userSymbols']['remoteWCS'] = parseInt(value, 10) == 1; + }, + 'DescribeLayer': function(node, obj) { + var readers = this.readers['http://www.opengis.net/wms']; + readers.DescribeLayer.apply(this, arguments); + }, + 'GetLegendGraphic': function(node, obj) { + var readers = this.readers['http://www.opengis.net/wms']; + readers.GetLegendGraphic.apply(this, arguments); + } + }; +}; +goog.inherits(ol.parser.ogc.WMSCapabilities_v1_3_0, + ol.parser.ogc.WMSCapabilities_v1); diff --git a/master/ol/ol/parser/ogc/wmtscapabilities.exports b/master/ol/ol/parser/ogc/wmtscapabilities.exports new file mode 100644 index 0000000000..dec7a65f4e --- /dev/null +++ b/master/ol/ol/parser/ogc/wmtscapabilities.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.parser.ogc.WMTSCapabilities +@exportProperty ol.parser.ogc.WMTSCapabilities.prototype.read diff --git a/master/ol/ol/parser/ogc/wmtscapabilities.js b/master/ol/ol/parser/ogc/wmtscapabilities.js new file mode 100644 index 0000000000..fee0293153 --- /dev/null +++ b/master/ol/ol/parser/ogc/wmtscapabilities.js @@ -0,0 +1,19 @@ +goog.provide('ol.parser.ogc.WMTSCapabilities'); +goog.require('ol.parser.ogc.Versioned'); +goog.require('ol.parser.ogc.WMTSCapabilities_v1_0_0'); + + + +/** + * @constructor + * @param {Object=} opt_options Options which will be set on this object. + * @extends {ol.parser.ogc.Versioned} + */ +ol.parser.ogc.WMTSCapabilities = function(opt_options) { + opt_options = opt_options || {}; + opt_options['defaultVersion'] = '1.0.0'; + this.parsers = {}; + this.parsers['v1_0_0'] = ol.parser.ogc.WMTSCapabilities_v1_0_0; + goog.base(this, opt_options); +}; +goog.inherits(ol.parser.ogc.WMTSCapabilities, ol.parser.ogc.Versioned); diff --git a/master/ol/ol/parser/ogc/wmtscapabilities_v1_0_0.js b/master/ol/ol/parser/ogc/wmtscapabilities_v1_0_0.js new file mode 100644 index 0000000000..4c88cdd59f --- /dev/null +++ b/master/ol/ol/parser/ogc/wmtscapabilities_v1_0_0.js @@ -0,0 +1,166 @@ +goog.provide('ol.parser.ogc.WMTSCapabilities_v1_0_0'); +goog.require('goog.dom.xml'); +goog.require('ol.Coordinate'); +goog.require('ol.parser.XML'); +goog.require('ol.parser.ogc.OWSCommon_v1_1_0'); +goog.require('ol.projection'); + + + +/** + * @constructor + * @extends {ol.parser.XML} + */ +ol.parser.ogc.WMTSCapabilities_v1_0_0 = function() { + this.defaultNamespaceURI = 'http://www.opengis.net/wtms/1.0'; + this.errorProperty = 'serviceIdentification'; + this.readers = { + 'http://www.opengis.net/wmts/1.0': { + 'Capabilities': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'Contents': function(node, obj) { + obj['contents'] = {}; + obj['contents']['layers'] = []; + obj['contents']['tileMatrixSets'] = {}; + this.readChildNodes(node, obj['contents']); + }, + 'Layer': function(node, obj) { + var layer = { + 'styles': [], + 'formats': [], + 'dimensions': [], + 'tileMatrixSetLinks': [] + }; + layer['layers'] = []; + this.readChildNodes(node, layer); + obj['layers'].push(layer); + }, + 'Style': function(node, obj) { + var style = {}; + style['isDefault'] = (node.getAttribute('isDefault') === 'true'); + this.readChildNodes(node, style); + obj['styles'].push(style); + }, + 'Format': function(node, obj) { + obj['formats'].push(this.getChildValue(node)); + }, + 'TileMatrixSetLink': function(node, obj) { + var tileMatrixSetLink = {}; + this.readChildNodes(node, tileMatrixSetLink); + obj['tileMatrixSetLinks'].push(tileMatrixSetLink); + }, + 'TileMatrixSet': function(node, obj) { + // node could be child of wmts:Contents or wmts:TileMatrixSetLink + // duck type wmts:Contents by looking for layers + if (obj['layers']) { + // TileMatrixSet as object type in schema + var tileMatrixSet = { + 'matrixIds': [] + }; + this.readChildNodes(node, tileMatrixSet); + obj['tileMatrixSets'][tileMatrixSet['identifier']] = tileMatrixSet; + } else { + // TileMatrixSet as string type in schema + obj['tileMatrixSet'] = this.getChildValue(node); + } + }, + 'TileMatrix': function(node, obj) { + var tileMatrix = { + 'supportedCRS': obj.supportedCRS + }; + this.readChildNodes(node, tileMatrix); + obj['matrixIds'].push(tileMatrix); + }, + 'ScaleDenominator': function(node, obj) { + obj['scaleDenominator'] = parseFloat(this.getChildValue(node)); + }, + 'TopLeftCorner': function(node, obj) { + var topLeftCorner = this.getChildValue(node); + var coords = topLeftCorner.split(' '); + var axisOrientation = + ol.projection.get(obj['supportedCRS']).getAxisOrientation(); + obj['topLeftCorner'] = ol.Coordinate.fromProjectedArray( + [parseFloat(coords[0]), parseFloat(coords[1])], axisOrientation); + }, + 'TileWidth': function(node, obj) { + obj['tileWidth'] = parseInt(this.getChildValue(node), 10); + }, + 'TileHeight': function(node, obj) { + obj['tileHeight'] = parseInt(this.getChildValue(node), 10); + }, + 'MatrixWidth': function(node, obj) { + obj['matrixWidth'] = parseInt(this.getChildValue(node), 10); + }, + 'MatrixHeight': function(node, obj) { + obj['matrixHeight'] = parseInt(this.getChildValue(node), 10); + }, + 'ResourceURL': function(node, obj) { + var resourceType = node.getAttribute('resourceType'); + var format = node.getAttribute('format'); + var template = node.getAttribute('template'); + if (!obj['resourceUrls']) { + obj['resourceUrls'] = {}; + } + if (!obj['resourceUrls'][resourceType]) { + obj['resourceUrls'][resourceType] = {}; + } + if (!obj['resourceUrls'][resourceType][format]) { + obj['resourceUrls'][resourceType][format] = []; + } + obj['resourceUrls'][resourceType][format].push(template); + }, + 'WSDL': function(node, obj) { + obj['wsdl'] = {}; + obj['wsdl']['href'] = this.getAttributeNS(node, + 'http://www.w3.org/1999/xlink', 'href'); + // TODO: other attributes of element + }, + 'ServiceMetadataURL': function(node, obj) { + obj['serviceMetadataUrl'] = {}; + obj['serviceMetadataUrl']['href'] = + this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', 'href'); + // TODO: other attributes of element + }, + 'LegendURL': function(node, obj) { + obj['legend'] = {}; + obj['legend']['href'] = this.getAttributeNS(node, + 'http://www.w3.org/1999/xlink', 'href'); + obj['legend']['format'] = node.getAttribute('format'); + }, + 'Dimension': function(node, obj) { + var dimension = {'values': []}; + this.readChildNodes(node, dimension); + obj['dimensions'].push(dimension); + }, + 'Default': function(node, obj) { + obj['default'] = this.getChildValue(node); + }, + 'Value': function(node, obj) { + obj['values'].push(this.getChildValue(node)); + } + } + }; + var ows = new ol.parser.ogc.OWSCommon_v1_1_0(); + this.readers['http://www.opengis.net/ows/1.1'] = + ows.readers['http://www.opengis.net/ows/1.1']; + goog.base(this); +}; +goog.inherits(ol.parser.ogc.WMTSCapabilities_v1_0_0, ol.parser.XML); + + +/** + * @param {string|Document|Element} data Data to read. + * @return {Object} An object representing the document. + */ +ol.parser.ogc.WMTSCapabilities_v1_0_0.prototype.read = function(data) { + if (typeof data == 'string') { + data = goog.dom.xml.loadXml(data); + } + if (data && data.nodeType == 9) { + data = data.documentElement; + } + var obj = {}; + this.readNode(data, obj); + return obj; +}; diff --git a/master/ol/ol/parser/xml.js b/master/ol/ol/parser/xml.js new file mode 100644 index 0000000000..6e07cf645c --- /dev/null +++ b/master/ol/ol/parser/xml.js @@ -0,0 +1,147 @@ +goog.provide('ol.parser.XML'); + + + +/** + * @constructor + */ +ol.parser.XML = function() { + this.regExes = { + trimSpace: (/^\s*|\s*$/g), + removeSpace: (/\s*/g), + splitSpace: (/\s+/), + trimComma: (/\s*,\s*/g) + }; +}; + + +/** + * Shorthand for applying one of the named readers given the node + * namespace and local name. Readers take two args (node, obj) and + * generally extend or modify the second. + * + * @param {Element|Document} node The node to be read (required). + * @param {Object} obj The object to be modified (optional). + * @return {Object} The input object, modified (or a new one if none was + * provided). + */ +ol.parser.XML.prototype.readNode = function(node, obj) { + if (!obj) { + obj = {}; + } + var group = this.readers[node.namespaceURI] || + this.readers[this.defaultNamespaceURI]; + if (group) { + var local = node.localName || node.nodeName.split(':').pop(); + var reader = group[local] || group['*']; + if (reader) { + reader.apply(this, [node, obj]); + } + } + return obj; +}; + + +/** + * Shorthand for applying the named readers to all children of a node. + * For each child of type 1 (element), is called. + * + * @param {Element|Document} node The node to be read (required). + * @param {Object} obj The object to be modified (optional). + * @return {Object} The input object, modified. + */ +ol.parser.XML.prototype.readChildNodes = function(node, obj) { + if (!obj) { + obj = {}; + } + var children = node.childNodes; + var child; + for (var i = 0, len = children.length; i < len; ++i) { + child = children[i]; + if (child.nodeType == 1) { + this.readNode(child, obj); + } + } + return obj; +}; + + +/** + * Get the textual value of the node if it exists, or return an + * optional default string. Returns an empty string if no first child + * exists and no default value is supplied. + * + * @param {Element} node The element used to look for a first child value. + * @param {string} def Optional string to return in the event that no + * first child value exists. + * @return {string} The value of the first child of the given node. + */ +ol.parser.XML.prototype.getChildValue = function(node, def) { + var value = def || ''; + if (node) { + for (var child = node.firstChild; child; child = child.nextSibling) { + switch (child.nodeType) { + case 3: // text node + case 4: // cdata section + value += child.nodeValue; + break; + default: + break; + } + } + } + return value; +}; + + +/** + * Get an attribute node given the namespace URI and local name. + * + * @param {Element} node Node on which to search for attribute nodes. + * @param {string} uri Namespace URI. + * @param {string} name Local name of the attribute (without the prefix). + * @return {?Element} An attribute node or null if none found. + */ +ol.parser.XML.prototype.getAttributeNodeNS = function(node, uri, name) { + var attributeNode = null; + if (node.getAttributeNodeNS) { + attributeNode = node.getAttributeNodeNS(uri, name); + } else { + var attributes = node.attributes; + var potentialNode, fullName; + for (var i = 0, len = attributes.length; i < len; ++i) { + potentialNode = attributes[i]; + if (potentialNode.namespaceURI == uri) { + fullName = (potentialNode.prefix) ? + (potentialNode.prefix + ':' + name) : name; + if (fullName == potentialNode.nodeName) { + attributeNode = potentialNode; + break; + } + } + } + } + return attributeNode; +}; + + +/** + * Get an attribute value given the namespace URI and local name. + * + * @param {Element} node Node on which to search for an attribute. + * @param {string} uri Namespace URI. + * @param {string} name Local name of the attribute (without the prefix). + * @return {string} An attribute value or and empty string if none found. + */ +ol.parser.XML.prototype.getAttributeNS = function(node, uri, name) { + var attributeValue = ''; + if (node.getAttributeNS) { + attributeValue = node.getAttributeNS(uri, name) || ''; + } else { + var attributeNode = this.getAttributeNodeNS(node, uri, name); + if (attributeNode) { + attributeValue = attributeNode.nodeValue; + } + } + return attributeValue; +}; diff --git a/master/ol/ol/pixel.js b/master/ol/ol/pixel.js new file mode 100644 index 0000000000..39eb9070bf --- /dev/null +++ b/master/ol/ol/pixel.js @@ -0,0 +1,16 @@ +goog.provide('ol.Pixel'); + +goog.require('goog.math.Coordinate'); + + + +/** + * @constructor + * @extends {goog.math.Coordinate} + * @param {number} x X. + * @param {number} y Y. + */ +ol.Pixel = function(x, y) { + goog.base(this, x, y); +}; +goog.inherits(ol.Pixel, goog.math.Coordinate); diff --git a/master/ol/ol/pixelbounds.js b/master/ol/ol/pixelbounds.js new file mode 100644 index 0000000000..42a63f3b91 --- /dev/null +++ b/master/ol/ol/pixelbounds.js @@ -0,0 +1,18 @@ +goog.provide('ol.PixelBounds'); + +goog.require('ol.Rectangle'); + + + +/** + * @constructor + * @extends {ol.Rectangle} + * @param {number} minX Minimum X. + * @param {number} minY Minimum Y. + * @param {number} maxX Maximum X. + * @param {number} maxY Maximum Y. + */ +ol.PixelBounds = function(minX, minY, maxX, maxY) { + goog.base(this, minX, minY, maxX, maxY); +}; +goog.inherits(ol.PixelBounds, ol.Rectangle); diff --git a/master/ol/ol/projection.exports b/master/ol/ol/projection.exports new file mode 100644 index 0000000000..7d2e1680bd --- /dev/null +++ b/master/ol/ol/projection.exports @@ -0,0 +1,21 @@ +@exportClass ol.Projection ol.ProjectionOptions +@exportProperty ol.Projection.prototype.getAxisOrientation +@exportProperty ol.Projection.prototype.getCode +@exportProperty ol.Projection.prototype.getExtent +@exportProperty ol.Projection.prototype.getPointResolution +@exportProperty ol.Projection.prototype.getUnits +@exportProperty ol.Projection.prototype.getMetersPerUnit +@exportProperty ol.Projection.prototype.isGlobal + +@exportSymbol ol.ProjectionUnits +@exportProperty ol.ProjectionUnits.DEGREES +@exportProperty ol.ProjectionUnits.FEET +@exportProperty ol.ProjectionUnits.METERS + +@exportSymbol ol.projection.addProjection +@exportSymbol ol.projection.get +@exportSymbol ol.projection.getTransform +@exportSymbol ol.projection.getTransformFromProjections +@exportSymbol ol.projection.transform +@exportSymbol ol.projection.transformWithProjections +@exportSymbol ol.projection.configureProj4jsProjection diff --git a/master/ol/ol/projection.js b/master/ol/ol/projection.js new file mode 100644 index 0000000000..2a33d8cd4c --- /dev/null +++ b/master/ol/ol/projection.js @@ -0,0 +1,688 @@ +goog.provide('ol.Projection'); +goog.provide('ol.ProjectionLike'); +goog.provide('ol.ProjectionUnits'); +goog.provide('ol.projection'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.object'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.TransformFunction'); +goog.require('ol.sphere.NORMAL'); + + +/** + * @define {boolean} Enable Proj4js. + */ +ol.ENABLE_PROJ4JS = true; + + +/** + * @const {boolean} Have Proj4js. + */ +ol.HAVE_PROJ4JS = ol.ENABLE_PROJ4JS && typeof Proj4js == 'object'; + + +/** + * @typedef {ol.Projection|string|undefined} + */ +ol.ProjectionLike; + + +/** + * @enum {string} + */ +ol.ProjectionUnits = { + DEGREES: 'degrees', + FEET: 'ft', + METERS: 'm' +}; + + +/** + * @const {Object.} Meters per unit lookup table. + */ +ol.METERS_PER_UNIT = {}; +ol.METERS_PER_UNIT[ol.ProjectionUnits.DEGREES] = + 2 * Math.PI * ol.sphere.NORMAL.radius / 360; +ol.METERS_PER_UNIT[ol.ProjectionUnits.FEET] = 0.3048; +ol.METERS_PER_UNIT[ol.ProjectionUnits.METERS] = 1; + + + +/** + * @constructor + * @param {ol.ProjectionOptions} options Options object. + */ +ol.Projection = function(options) { + + /** + * @private + * @type {string} + */ + this.code_ = options.code; + + /** + * @private + * @type {ol.ProjectionUnits} + */ + this.units_ = options.units; + + /** + * @private + * @type {ol.Extent} + */ + this.extent_ = options.extent; + + /** + * @private + * @type {string} + */ + this.axisOrientation_ = goog.isDef(options.axisOrientation) ? + options.axisOrientation : 'enu'; + + /** + * @private + * @type {boolean} + */ + this.global_ = goog.isDef(options.global) ? + options.global : false; + + /** + * @private + * @type {ol.tilegrid.TileGrid} + */ + this.defaultTileGrid_ = null; + +}; + + +/** + * @return {string} Code. + */ +ol.Projection.prototype.getCode = function() { + return this.code_; +}; + + +/** + * @return {ol.Extent} Extent. + */ +ol.Projection.prototype.getExtent = function() { + return this.extent_; +}; + + +/** + * @param {number} resolution Resolution. + * @param {ol.Coordinate} point Point. + * @return {number} Point resolution. + */ +ol.Projection.prototype.getPointResolution = goog.abstractMethod; + + +/** + * @return {ol.ProjectionUnits} Units. + */ +ol.Projection.prototype.getUnits = function() { + return this.units_; +}; + + +/** + * @return {number} Meters. + */ +ol.Projection.prototype.getMetersPerUnit = function() { + return ol.METERS_PER_UNIT[this.units_]; +}; + + +/** + * @return {string} Axis orientation. + */ +ol.Projection.prototype.getAxisOrientation = function() { + return this.axisOrientation_; +}; + + +/** + * @return {boolean} Wether the projection is global. + */ +ol.Projection.prototype.isGlobal = function() { + return this.global_; +}; + + +/** + * @return {ol.tilegrid.TileGrid} The default tile grid. + */ +ol.Projection.prototype.getDefaultTileGrid = function() { + return this.defaultTileGrid_; +}; + + +/** + * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid. + */ +ol.Projection.prototype.setDefaultTileGrid = function(tileGrid) { + this.defaultTileGrid_ = tileGrid; +}; + + + +/** + * @constructor + * @extends {ol.Projection} + * @param {Proj4js.Proj} proj4jsProj Proj4js projection. + * @param {ol.Proj4jsProjectionOptions} options Projection config options. + * @private + */ +ol.Proj4jsProjection_ = function(proj4jsProj, options) { + + var units = /** @type {ol.ProjectionUnits} */ (proj4jsProj.units); + + var config = /** @type {ol.ProjectionOptions} */ ({ + units: units, + axisOrientation: proj4jsProj.axis + }); + goog.object.extend(config, options); + + goog.base(this, config); + + /** + * @private + * @type {Proj4js.Proj} + */ + this.proj4jsProj_ = proj4jsProj; + + /** + * @private + * @type {?ol.TransformFunction} + */ + this.toEPSG4326_ = null; + +}; +goog.inherits(ol.Proj4jsProjection_, ol.Projection); + + +/** + * @inheritDoc + */ +ol.Proj4jsProjection_.prototype.getPointResolution = + function(resolution, point) { + if (this.getUnits() == ol.ProjectionUnits.DEGREES) { + return resolution; + } else { + // Estimate point resolution 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. + if (goog.isNull(this.toEPSG4326_)) { + this.toEPSG4326_ = ol.projection.getTransformFromProjections( + this, ol.projection.getProj4jsProjectionFromCode_({ + code: 'EPSG:4326', + extent: null + })); + } + var vertices = [ + point.x - resolution / 2, point.y, + point.x + resolution / 2, point.y, + point.x, point.y - resolution / 2, + point.x, point.y + resolution / 2 + ]; + vertices = this.toEPSG4326_(vertices, vertices, 2); + var width = ol.sphere.NORMAL.haversineDistance( + new ol.Coordinate(vertices[0], vertices[1]), + new ol.Coordinate(vertices[2], vertices[3])); + var height = ol.sphere.NORMAL.haversineDistance( + new ol.Coordinate(vertices[4], vertices[5]), + new ol.Coordinate(vertices[6], vertices[7])); + var pointResolution = (width + height) / 2; + if (this.getUnits() == ol.ProjectionUnits.FEET) { + // The radius of the normal sphere is defined in meters, so we must + // convert back to feet. + pointResolution /= 0.3048; + } + return pointResolution; + } +}; + + +/** + * @return {Proj4js.Proj} Proj4js projection. + */ +ol.Proj4jsProjection_.prototype.getProj4jsProj = function() { + return this.proj4jsProj_; +}; + + +/** + * @private + * @type {Object.} + */ +ol.projection.proj4jsProjections_ = {}; + + +/** + * @private + * @type {Object.} + */ +ol.projection.projections_ = {}; + + +/** + * @private + * @type {Object.>} + */ +ol.projection.transforms_ = {}; + + +/** + * Registers transformation functions that don't alter coordinates. Those allow + * to transform between projections with equal meaning. + * + * @param {Array.} projections Projections. + */ +ol.projection.addEquivalentProjections = function(projections) { + ol.projection.addProjections(projections); + goog.array.forEach(projections, function(source) { + goog.array.forEach(projections, function(destination) { + if (source !== destination) { + ol.projection.addTransform( + source, destination, ol.projection.cloneTransform); + } + }); + }); +}; + + +/** + * Registers transformation functions to convert coordinates in any projection + * in projection1 to any projection in projection2. + * + * @param {Array.} projections1 Projections with equal meaning. + * @param {Array.} projections2 Projections with equal meaning. + * @param {ol.TransformFunction} forwardTransform Transformation from any + * projection in projection1 to any projection in projection2. + * @param {ol.TransformFunction} inverseTransform Transform from any projection + * in projection2 to any projection in projection1.. + */ +ol.projection.addEquivalentTransforms = + function(projections1, projections2, forwardTransform, inverseTransform) { + goog.array.forEach(projections1, function(projection1) { + goog.array.forEach(projections2, function(projection2) { + ol.projection.addTransform(projection1, projection2, forwardTransform); + ol.projection.addTransform(projection2, projection1, inverseTransform); + }); + }); +}; + + +/** + * @param {ol.Proj4jsProjection_} proj4jsProjection Proj4js projection. + * @private + */ +ol.projection.addProj4jsProjection_ = function(proj4jsProjection) { + var proj4jsProjections = ol.projection.proj4jsProjections_; + var code = proj4jsProjection.getCode(); + goog.asserts.assert(!goog.object.containsKey(proj4jsProjections, code)); + proj4jsProjections[code] = proj4jsProjection; +}; + + +/** + * @param {ol.Projection} projection Projection. + */ +ol.projection.addProjection = function(projection) { + var projections = ol.projection.projections_; + var code = projection.getCode(); + goog.asserts.assert(!goog.object.containsKey(projections, code)); + projections[code] = projection; + ol.projection.addTransform( + projection, projection, ol.projection.cloneTransform); +}; + + +/** + * @param {Array.} projections Projections. + */ +ol.projection.addProjections = function(projections) { + goog.array.forEach(projections, function(projection) { + ol.projection.addProjection(projection); + }); +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.projection.clearAllProjections = function() { + if (ol.ENABLE_PROJ4JS) { + ol.projection.proj4jsProjections_ = {}; + } + ol.projection.projections_ = {}; + ol.projection.transforms_ = {}; +}; + + +/** + * @param {ol.Projection|string|undefined} projection Projection. + * @param {string} defaultCode Default code. + * @return {ol.Projection} Projection. + */ +ol.projection.createProjection = function(projection, defaultCode) { + if (!goog.isDefAndNotNull(projection)) { + return ol.projection.get(defaultCode); + } else if (goog.isString(projection)) { + return ol.projection.get(projection); + } else { + goog.asserts.assert(projection instanceof ol.Projection); + return projection; + } +}; + + +/** + * Registers a conversion function to convert coordinates from the source + * projection to the destination projection. + * + * @param {ol.Projection} source Source. + * @param {ol.Projection} destination Destination. + * @param {ol.TransformFunction} transformFn Transform. + */ +ol.projection.addTransform = function(source, destination, transformFn) { + var sourceCode = source.getCode(); + var destinationCode = destination.getCode(); + var transforms = ol.projection.transforms_; + if (!goog.object.containsKey(transforms, sourceCode)) { + transforms[sourceCode] = {}; + } + goog.asserts.assert( + !goog.object.containsKey(transforms[sourceCode], destinationCode)); + transforms[sourceCode][destinationCode] = transformFn; +}; + + +/** + * Unregisters the conversion function to convert coordinates from the source + * projection to the destination projection. This method is used to clean up + * cached transforms during testing. + * + * @param {ol.Projection} source Source projection. + * @param {ol.Projection} destination Destination projection. + * @return {ol.TransformFunction} transformFn The unregistered transform. + */ +ol.projection.removeTransform = function(source, destination) { + var sourceCode = source.getCode(); + var destinationCode = destination.getCode(); + var transforms = ol.projection.transforms_; + goog.asserts.assert(sourceCode in transforms); + goog.asserts.assert(destinationCode in transforms[sourceCode]); + var transform = transforms[sourceCode][destinationCode]; + delete transforms[sourceCode][destinationCode]; + var keys = goog.object.getKeys(transforms[sourceCode]); + if (keys.length == 0) { + delete transforms[sourceCode]; + } + return transform; +}; + + +/** + * @param {ol.ProjectionLike} projectionLike Either a code string which is a + * combination of authority and identifier such as "EPSG:4326", or an + * existing projection object, or undefined. + * @return {ol.Projection} Projection. + */ +ol.projection.get = function(projectionLike) { + var projection; + if (projectionLike instanceof ol.Projection) { + projection = projectionLike; + } else if (goog.isString(projectionLike)) { + var code = projectionLike; + projection = ol.projection.projections_[code]; + if (ol.HAVE_PROJ4JS && !goog.isDef(projection)) { + projection = ol.projection.getProj4jsProjectionFromCode_({ + code: code, + extent: null + }); + } + if (!goog.isDef(projection)) { + goog.asserts.assert(goog.isDef(projection)); + projection = null; + } + } else { + projection = null; + } + return projection; +}; + + +/** + * @param {ol.Proj4jsProjectionOptions} options Projection config options. + * @private + * @return {ol.Proj4jsProjection_} Proj4js projection. + */ +ol.projection.getProj4jsProjectionFromCode_ = function(options) { + var code = options.code; + var proj4jsProjections = ol.projection.proj4jsProjections_; + var proj4jsProjection = proj4jsProjections[code]; + if (!goog.isDef(proj4jsProjection)) { + var proj4jsProj = new Proj4js.Proj(code); + var srsCode = proj4jsProj.srsCode; + proj4jsProjection = proj4jsProjections[srsCode]; + if (!goog.isDef(proj4jsProjection)) { + var config = /** @type {ol.Proj4jsProjectionOptions} */ + (goog.object.clone(options)); + config.code = srsCode; + proj4jsProjection = new ol.Proj4jsProjection_(proj4jsProj, config); + proj4jsProjections[srsCode] = proj4jsProjection; + } + proj4jsProjections[code] = proj4jsProjection; + } + return proj4jsProjection; +}; + + +/** + * Checks if two projections are the same, that is every coordinate in one + * projection does represent the same geographic point as the same coordinate in + * the other projection. + * + * @param {ol.Projection} projection1 Projection 1. + * @param {ol.Projection} projection2 Projection 2. + * @return {boolean} Equivalent. + */ +ol.projection.equivalent = function(projection1, projection2) { + if (projection1 === projection2) { + return true; + } else if (projection1.getUnits() != projection2.getUnits()) { + return false; + } else { + var transformFn = ol.projection.getTransformFromProjections( + projection1, projection2); + return transformFn === ol.projection.cloneTransform; + } +}; + + +/** + * 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. + * + * @param {ol.ProjectionLike} source Source. + * @param {ol.ProjectionLike} destination Destination. + * @return {ol.TransformFunction} Transform. + */ +ol.projection.getTransform = function(source, destination) { + var sourceProjection = ol.projection.get(source); + var destinationProjection = ol.projection.get(destination); + return ol.projection.getTransformFromProjections( + sourceProjection, destinationProjection); +}; + + +/** + * Searches a function that can be used to convert coordinates from the source + * projection to the destination projection. + * + * @param {ol.Projection} sourceProjection Source projection. + * @param {ol.Projection} destinationProjection Destination projection. + * @return {ol.TransformFunction} Transform. + */ +ol.projection.getTransformFromProjections = + function(sourceProjection, destinationProjection) { + var transforms = ol.projection.transforms_; + var sourceCode = sourceProjection.getCode(); + var destinationCode = destinationProjection.getCode(); + var transform; + if (goog.object.containsKey(transforms, sourceCode) && + goog.object.containsKey(transforms[sourceCode], destinationCode)) { + transform = transforms[sourceCode][destinationCode]; + } + if (ol.HAVE_PROJ4JS && !goog.isDef(transform)) { + var proj4jsSource; + if (sourceProjection instanceof ol.Proj4jsProjection_) { + proj4jsSource = sourceProjection; + } else { + proj4jsSource = + ol.projection.getProj4jsProjectionFromCode_({ + code: sourceCode, + extent: null + }); + } + var sourceProj4jsProj = proj4jsSource.getProj4jsProj(); + var proj4jsDestination; + if (destinationProjection instanceof ol.Proj4jsProjection_) { + proj4jsDestination = destinationProjection; + } else { + proj4jsDestination = + ol.projection.getProj4jsProjectionFromCode_({ + code: destinationCode, + extent: null + }); + } + var destinationProj4jsProj = proj4jsDestination.getProj4jsProj(); + transform = + /** + * @param {Array.} input Input coordinate values. + * @param {Array.=} opt_output Output array of coordinates. + * @param {number=} opt_dimension Dimension. + * @return {Array.} Output coordinate values. + */ + function(input, opt_output, opt_dimension) { + var length = input.length, + dimension = opt_dimension > 1 ? opt_dimension : 2, + output = opt_output; + if (!goog.isDef(output)) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + } + goog.asserts.assert(output.length % dimension === 0); + var proj4jsPoint; + for (var i = 0; i < length; i += dimension) { + proj4jsPoint = new Proj4js.Point(input[i], input[i + 1]); + proj4jsPoint = Proj4js.transform( + sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint); + output[i] = proj4jsPoint.x; + output[i + 1] = proj4jsPoint.y; + } + return output; + }; + ol.projection.addTransform( + sourceProjection, destinationProjection, transform); + } + if (!goog.isDef(transform)) { + goog.asserts.assert(goog.isDef(transform)); + transform = ol.projection.identityTransform; + } + return transform; +}; + + +/** + * @param {Array.} input Input coordinate array. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension. + * @return {Array.} Input coordinate array (same array as input). + */ +ol.projection.identityTransform = function(input, opt_output, opt_dimension) { + if (goog.isDef(opt_output) && input !== opt_output) { + // TODO: consider making this a warning instead + goog.asserts.assert(false, 'This should not be used internally.'); + for (var i = 0, ii = input.length; i < ii; ++i) { + opt_output[i] = input[i]; + } + input = opt_output; + } + return input; +}; + + +/** + * @param {Array.} input Input coordinate array. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension. + * @return {Array.} Output coordinate array (new array, same coordinate + * values). + */ +ol.projection.cloneTransform = function(input, opt_output, opt_dimension) { + var output; + if (goog.isDef(opt_output)) { + for (var i = 0, ii = input.length; i < ii; ++i) { + opt_output[i] = input[i]; + } + output = opt_output; + } else { + output = input.slice(); + } + return output; +}; + + +/** + * @param {ol.Coordinate} point Point. + * @param {ol.ProjectionLike} source Source. + * @param {ol.ProjectionLike} destination Destination. + * @return {ol.Coordinate} Point. + */ +ol.projection.transform = function(point, source, destination) { + var transformFn = ol.projection.getTransform(source, destination); + var vertex = [point.x, point.y]; + vertex = transformFn(vertex, vertex, 2); + return new ol.Coordinate(vertex[0], vertex[1]); +}; + + +/** + * Transforms the given point to the destination projection. + * + * @param {ol.Coordinate} point Point. + * @param {ol.Projection} sourceProjection Source projection. + * @param {ol.Projection} destinationProjection Destination projection. + * @return {ol.Coordinate} Point. + */ +ol.projection.transformWithProjections = + function(point, sourceProjection, destinationProjection) { + var transformFn = ol.projection.getTransformFromProjections( + sourceProjection, destinationProjection); + var vertex = [point.x, point.y]; + vertex = transformFn(vertex, vertex, 2); + return new ol.Coordinate(vertex[0], vertex[1]); +}; + + +/** + * @param {ol.Proj4jsProjectionOptions} options Projection config options. + * @return {ol.Proj4jsProjection_} Proj4js projection. + */ +ol.projection.configureProj4jsProjection = function(options) { + goog.asserts.assert(!goog.object.containsKey( + ol.projection.proj4jsProjections_, options.code)); + return ol.projection.getProj4jsProjectionFromCode_(options); +}; diff --git a/master/ol/ol/projection/common.js b/master/ol/ol/projection/common.js new file mode 100644 index 0000000000..e750b4c011 --- /dev/null +++ b/master/ol/ol/projection/common.js @@ -0,0 +1,23 @@ +goog.provide('ol.projection.addCommonProjections'); + +goog.require('ol.projection'); +goog.require('ol.projection.EPSG3857'); +goog.require('ol.projection.EPSG4326'); + + +/** + * FIXME empty description for jsdoc + */ +ol.projection.addCommonProjections = function() { + // Add transformations that don't alter coordinates to convert within set of + // projections with equal meaning. + ol.projection.addEquivalentProjections(ol.projection.EPSG3857.PROJECTIONS); + ol.projection.addEquivalentProjections(ol.projection.EPSG4326.PROJECTIONS); + // Add transformations to convert EPSG:4326 like coordinates to EPSG:3857 like + // coordinates and back. + ol.projection.addEquivalentTransforms( + ol.projection.EPSG4326.PROJECTIONS, + ol.projection.EPSG3857.PROJECTIONS, + ol.projection.EPSG3857.fromEPSG4326, + ol.projection.EPSG3857.toEPSG4326); +}; diff --git a/master/ol/ol/projection/epsg3857.js b/master/ol/ol/projection/epsg3857.js new file mode 100644 index 0000000000..1e3c709f39 --- /dev/null +++ b/master/ol/ol/projection/epsg3857.js @@ -0,0 +1,144 @@ +goog.provide('ol.projection.EPSG3857'); + +goog.require('goog.array'); +goog.require('ol.Extent'); +goog.require('ol.Projection'); +goog.require('ol.ProjectionUnits'); +goog.require('ol.math'); +goog.require('ol.projection'); + + + +/** + * @constructor + * @extends {ol.Projection} + * @param {string} code Code. + */ +ol.projection.EPSG3857 = function(code) { + goog.base(this, { + code: code, + units: ol.ProjectionUnits.METERS, + extent: ol.projection.EPSG3857.EXTENT, + global: true + }); +}; +goog.inherits(ol.projection.EPSG3857, ol.Projection); + + +/** + * @const + * @type {number} + */ +ol.projection.EPSG3857.RADIUS = 6378137; + + +/** + * @const + * @type {number} + */ +ol.projection.EPSG3857.HALF_SIZE = Math.PI * ol.projection.EPSG3857.RADIUS; + + +/** + * @const + * @type {ol.Extent} + */ +ol.projection.EPSG3857.EXTENT = new ol.Extent( + -ol.projection.EPSG3857.HALF_SIZE, -ol.projection.EPSG3857.HALF_SIZE, + ol.projection.EPSG3857.HALF_SIZE, ol.projection.EPSG3857.HALF_SIZE); + + +/** + * Lists several projection codes with the same meaning as EPSG:3857. + * + * @type {Array.} + */ +ol.projection.EPSG3857.CODES = [ + 'EPSG:3857', + 'EPSG:102100', + 'EPSG:102113', + 'EPSG:900913' +]; + + +/** + * Projections equal to EPSG:3857. + * + * @const + * @type {Array.} + */ +ol.projection.EPSG3857.PROJECTIONS = goog.array.map( + ol.projection.EPSG3857.CODES, + function(code) { + return new ol.projection.EPSG3857(code); + }); + + +/** + * Transformation from EPSG:4326 to EPSG:3857. + * + * @param {Array.} input Input array of coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output array of coordinate values. + */ +ol.projection.EPSG3857.fromEPSG4326 = function( + input, opt_output, opt_dimension) { + var length = input.length, + dimension = opt_dimension > 1 ? opt_dimension : 2, + output = opt_output; + if (!goog.isDef(output)) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + } + goog.asserts.assert(output.length % dimension === 0); + for (var i = 0; i < length; i += dimension) { + output[i] = ol.projection.EPSG3857.RADIUS * Math.PI * input[i] / 180; + output[i + 1] = ol.projection.EPSG3857.RADIUS * + Math.log(Math.tan(Math.PI * (input[i + 1] + 90) / 360)); + } + return output; +}; + + +/** + * Transformation from EPSG:3857 to EPSG:4326. + * + * @param {Array.} input Input array of coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output array of coordinate values. + */ +ol.projection.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) { + var length = input.length, + dimension = opt_dimension > 1 ? opt_dimension : 2, + output = opt_output; + if (!goog.isDef(output)) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + } + goog.asserts.assert(output.length % dimension === 0); + for (var i = 0; i < length; i += dimension) { + output[i] = 180 * input[i] / (ol.projection.EPSG3857.RADIUS * Math.PI); + output[i + 1] = 360 * Math.atan( + Math.exp(input[i + 1] / ol.projection.EPSG3857.RADIUS)) / Math.PI - 90; + } + return output; +}; + + +/** + * @inheritDoc + */ +ol.projection.EPSG3857.prototype.getPointResolution = + function(resolution, point) { + return resolution / ol.math.cosh(point.y / ol.projection.EPSG3857.RADIUS); +}; diff --git a/master/ol/ol/projection/epsg4326.js b/master/ol/ol/projection/epsg4326.js new file mode 100644 index 0000000000..bfc3dd37ec --- /dev/null +++ b/master/ol/ol/projection/epsg4326.js @@ -0,0 +1,57 @@ +goog.provide('ol.projection.EPSG4326'); + +goog.require('ol.Extent'); +goog.require('ol.Projection'); +goog.require('ol.ProjectionUnits'); +goog.require('ol.projection'); + + + +/** + * @constructor + * @extends {ol.Projection} + * @param {string} code Code. + * @param {string=} opt_axisOrientation Axis orientation. + */ +ol.projection.EPSG4326 = function(code, opt_axisOrientation) { + goog.base(this, { + code: code, + units: ol.ProjectionUnits.DEGREES, + extent: ol.projection.EPSG4326.EXTENT, + axisOrientation: opt_axisOrientation, + global: true + }); +}; +goog.inherits(ol.projection.EPSG4326, ol.Projection); + + +/** + * Extent of the EPSG:4326 projection which is the whole world. + * + * @const + * @type {ol.Extent} + */ +ol.projection.EPSG4326.EXTENT = new ol.Extent(-180, -90, 180, 90); + + +/** + * Projections equal to EPSG:4326. + * + * @const + * @type {Array.} + */ +ol.projection.EPSG4326.PROJECTIONS = [ + new ol.projection.EPSG4326('CRS:84'), + new ol.projection.EPSG4326('EPSG:4326', 'neu'), + new ol.projection.EPSG4326('urn:ogc:def:crs:EPSG:6.6:4326', 'neu'), + new ol.projection.EPSG4326('urn:ogc:def:crs:OGC:1.3:CRS84') +]; + + +/** + * @inheritDoc + */ +ol.projection.EPSG4326.prototype.getPointResolution = + function(resolution, point) { + return resolution; +}; diff --git a/master/ol/ol/rectangle.js b/master/ol/ol/rectangle.js new file mode 100644 index 0000000000..9d7a27af5e --- /dev/null +++ b/master/ol/ol/rectangle.js @@ -0,0 +1,139 @@ +goog.provide('ol.Rectangle'); + +goog.require('goog.asserts'); +goog.require('ol.Coordinate'); +goog.require('ol.Size'); + + + +/** + * @constructor + * @param {number} minX Minimum X. + * @param {number} minY Minimum Y. + * @param {number} maxX Maximum X. + * @param {number} maxY Maximum Y. + */ +ol.Rectangle = function(minX, minY, maxX, maxY) { + + goog.asserts.assert(minX <= maxX); + goog.asserts.assert(minY <= maxY); + + /** + * @type {number} + */ + this.minX = minX; + + /** + * @type {number} + */ + this.minY = minY; + + /** + * @type {number} + */ + this.maxX = maxX; + + /** + * @type {number} + */ + this.maxY = maxY; + +}; + + +/** + * @param {ol.Rectangle} rectangle Rectangle. + * @return {boolean} Equals. + */ +ol.Rectangle.prototype.equals = function(rectangle) { + return this.minX == rectangle.minX && this.minY == rectangle.minY && + this.maxX == rectangle.maxX && this.maxY == rectangle.maxY; +}; + + +/** + * @param {ol.Rectangle} rectangle Rectangle. + */ +ol.Rectangle.prototype.extend = function(rectangle) { + this.minX = Math.min(this.minX, rectangle.minX); + this.minY = Math.min(this.minY, rectangle.minY); + this.maxX = Math.max(this.maxX, rectangle.maxX); + this.maxY = Math.max(this.maxY, rectangle.maxY); +}; + + +/** + * @return {ol.Coordinate} Center. + */ +ol.Rectangle.prototype.getCenter = function() { + return new ol.Coordinate( + (this.minX + this.maxX) / 2, (this.minY + this.maxY) / 2); +}; + + +/** + * @return {number} Height. + */ +ol.Rectangle.prototype.getHeight = function() { + return this.maxY - this.minY; +}; + + +/** + * @return {ol.Size} Size. + */ +ol.Rectangle.prototype.getSize = function() { + return new ol.Size(this.getWidth(), this.getHeight()); +}; + + +/** + * @return {number} Width. + */ +ol.Rectangle.prototype.getWidth = function() { + return this.maxX - this.minX; +}; + + +/** + * @param {ol.Rectangle} rectangle Rectangle. + * @return {boolean} Intersects. + */ +ol.Rectangle.prototype.intersects = function(rectangle) { + return this.minX <= rectangle.maxX && + this.maxX >= rectangle.minX && + this.minY <= rectangle.maxY && + this.maxY >= rectangle.minY; +}; + + +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @return {ol.Coordinate} Coordinate. + */ +ol.Rectangle.prototype.normalize = function(coordinate) { + return new ol.Coordinate( + (coordinate.x - this.minX) / this.getWidth(), + (coordinate.y - this.minY) / this.getHeight()); +}; + + +/** + * @return {string} String. + */ +ol.Rectangle.prototype.toString = function() { + return '(' + [this.minX, this.minY, this.maxX, this.maxY].join(', ') + ')'; +}; + + +/** + * @param {number} value Value. + */ +ol.Rectangle.prototype.scaleFromCenter = function(value) { + var deltaX = (this.getWidth() / 2.0) * (value - 1); + var deltaY = (this.getHeight() / 2.0) * (value - 1); + this.minX -= deltaX; + this.minY -= deltaY; + this.maxX += deltaX; + this.maxY += deltaY; +}; diff --git a/master/ol/ol/renderer/canvas/canvasimagelayerrenderer.js b/master/ol/ol/renderer/canvas/canvasimagelayerrenderer.js new file mode 100644 index 0000000000..1465f7f544 --- /dev/null +++ b/master/ol/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -0,0 +1,119 @@ +goog.provide('ol.renderer.canvas.ImageLayer'); + +goog.require('goog.vec.Mat4'); +goog.require('ol.Image'); +goog.require('ol.ImageState'); +goog.require('ol.ViewHint'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.renderer.Map'); +goog.require('ol.renderer.canvas.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.canvas.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.ImageLayer} imageLayer Single image layer. + */ +ol.renderer.canvas.ImageLayer = function(mapRenderer, imageLayer) { + + goog.base(this, mapRenderer, imageLayer); + + /** + * @private + * @type {?ol.Image} + */ + this.image_ = null; + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.transform_ = goog.vec.Mat4.createNumber(); + +}; +goog.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.Layer); + + +/** + * @inheritDoc + */ +ol.renderer.canvas.ImageLayer.prototype.getImage = function() { + return goog.isNull(this.image_) ? + null : this.image_.getImageElement(this); +}; + + +/** + * @return {ol.layer.ImageLayer} Single image layer. + */ +ol.renderer.canvas.ImageLayer.prototype.getImageLayer = function() { + return /** @type {ol.layer.ImageLayer} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.ImageLayer.prototype.getTransform = function() { + return this.transform_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.ImageLayer.prototype.renderFrame = + function(frameState, layerState) { + + var view2DState = frameState.view2DState; + var viewCenter = view2DState.center; + var viewResolution = view2DState.resolution; + var viewRotation = view2DState.rotation; + + var image; + var imageLayer = this.getImageLayer(); + var imageSource = imageLayer.getImageSource(); + + var hints = frameState.viewHints; + + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { + image = imageSource.getImage( + frameState.extent, viewResolution, view2DState.projection); + if (!goog.isNull(image)) { + var imageState = image.getState(); + if (imageState == ol.ImageState.IDLE) { + goog.events.listenOnce(image, goog.events.EventType.CHANGE, + this.handleImageChange, false, this); + image.load(); + } else if (imageState == ol.ImageState.LOADED) { + this.image_ = image; + } + } + } + + if (!goog.isNull(this.image_)) { + image = this.image_; + + var imageExtent = image.getExtent(); + var imageResolution = image.getResolution(); + var transform = this.transform_; + goog.vec.Mat4.makeIdentity(transform); + goog.vec.Mat4.translate(transform, + frameState.size.width / 2, frameState.size.height / 2, 0); + goog.vec.Mat4.rotateZ(transform, viewRotation); + goog.vec.Mat4.scale( + transform, + imageResolution / viewResolution, + imageResolution / viewResolution, + 1); + goog.vec.Mat4.translate( + transform, + (imageExtent.minX - viewCenter.x) / imageResolution, + (viewCenter.y - imageExtent.maxY) / imageResolution, + 0); + + this.updateAttributions(frameState.attributions, image.getAttributions()); + } +}; diff --git a/master/ol/ol/renderer/canvas/canvaslayerrenderer.js b/master/ol/ol/renderer/canvas/canvaslayerrenderer.js new file mode 100644 index 0000000000..074e1b87a1 --- /dev/null +++ b/master/ol/ol/renderer/canvas/canvaslayerrenderer.js @@ -0,0 +1,29 @@ +goog.provide('ol.renderer.canvas.Layer'); + +goog.require('ol.layer.Layer'); +goog.require('ol.renderer.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.Layer} layer Layer. + */ +ol.renderer.canvas.Layer = function(mapRenderer, layer) { + goog.base(this, mapRenderer, layer); +}; +goog.inherits(ol.renderer.canvas.Layer, ol.renderer.Layer); + + +/** + * @return {HTMLCanvasElement|HTMLVideoElement|Image} Canvas. + */ +ol.renderer.canvas.Layer.prototype.getImage = goog.abstractMethod; + + +/** + * @return {!goog.vec.Mat4.Number} Transform. + */ +ol.renderer.canvas.Layer.prototype.getTransform = goog.abstractMethod; diff --git a/master/ol/ol/renderer/canvas/canvasmaprenderer.js b/master/ol/ol/renderer/canvas/canvasmaprenderer.js new file mode 100644 index 0000000000..24ee38307f --- /dev/null +++ b/master/ol/ol/renderer/canvas/canvasmaprenderer.js @@ -0,0 +1,149 @@ +// FIXME offset panning + +goog.provide('ol.renderer.canvas.Map'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.style'); +goog.require('goog.vec.Mat4'); +goog.require('ol.Size'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.renderer.Map'); +goog.require('ol.renderer.canvas.ImageLayer'); +goog.require('ol.renderer.canvas.TileLayer'); + + + +/** + * @constructor + * @extends {ol.renderer.Map} + * @param {Element} container Container. + * @param {ol.Map} map Map. + */ +ol.renderer.canvas.Map = function(container, map) { + + goog.base(this, container, map); + + /** + * @private + * @type {ol.Size} + */ + this.canvasSize_ = new ol.Size(container.clientHeight, container.clientWidth); + + /** + * @private + * @type {Element} + */ + this.canvas_ = goog.dom.createElement(goog.dom.TagName.CANVAS); + this.canvas_.height = this.canvasSize_.height; + this.canvas_.width = this.canvasSize_.width; + this.canvas_.className = 'ol-unselectable'; + goog.dom.insertChildAt(container, this.canvas_, 0); + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + + /** + * @private + * @type {CanvasRenderingContext2D} + */ + this.context_ = this.canvas_.getContext('2d'); + +}; +goog.inherits(ol.renderer.canvas.Map, ol.renderer.Map); + + +/** + * @inheritDoc + */ +ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) { + if (layer instanceof ol.layer.ImageLayer) { + return new ol.renderer.canvas.ImageLayer(this, layer); + } else if (layer instanceof ol.layer.TileLayer) { + return new ol.renderer.canvas.TileLayer(this, layer); + } else { + goog.asserts.assert(false); + return null; + } +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.Map.prototype.getCanvas = function() { + return this.canvas_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) { + + if (goog.isNull(frameState)) { + if (this.renderedVisible_) { + goog.style.showElement(this.canvas_, false); + this.renderedVisible_ = false; + } + return; + } + + var size = frameState.size; + if (!this.canvasSize_.equals(size)) { + this.canvas_.width = size.width; + this.canvas_.height = size.height; + this.canvasSize_ = size; + } + + var context = this.context_; + context.setTransform(1, 0, 0, 1, 0, 0); + var backgroundColor = frameState.backgroundColor; + context.fillStyle = 'rgb(' + + backgroundColor.r.toFixed(0) + ',' + + backgroundColor.g.toFixed(0) + ',' + + backgroundColor.b.toFixed(0) + ')'; + context.globalAlpha = 1; + context.fillRect(0, 0, size.width, size.height); + + goog.array.forEach(frameState.layersArray, function(layer) { + + var layerState = frameState.layerStates[goog.getUid(layer)]; + if (!layerState.visible) { + return; + } else if (!layerState.ready) { + frameState.animate = true; + return; + } + var layerRenderer = this.getLayerRenderer(layer); + layerRenderer.renderFrame(frameState, layerState); + + var image = layerRenderer.getImage(); + if (!goog.isNull(image)) { + var transform = layerRenderer.getTransform(); + context.setTransform( + goog.vec.Mat4.getElement(transform, 0, 0), + goog.vec.Mat4.getElement(transform, 1, 0), + goog.vec.Mat4.getElement(transform, 0, 1), + goog.vec.Mat4.getElement(transform, 1, 1), + goog.vec.Mat4.getElement(transform, 0, 3), + goog.vec.Mat4.getElement(transform, 1, 3)); + + context.globalAlpha = layerState.opacity; + context.drawImage(image, 0, 0); + } + + }, this); + + if (!this.renderedVisible_) { + goog.style.showElement(this.canvas_, true); + this.renderedVisible_ = true; + } + + this.calculateMatrices2D(frameState); + +}; diff --git a/master/ol/ol/renderer/canvas/canvasrenderer.js b/master/ol/ol/renderer/canvas/canvasrenderer.js new file mode 100644 index 0000000000..2eda861ddc --- /dev/null +++ b/master/ol/ol/renderer/canvas/canvasrenderer.js @@ -0,0 +1,10 @@ +goog.provide('ol.renderer.canvas.SUPPORTED'); + +goog.require('ol.canvas'); + + +/** + * @const + * @type {boolean} Is supported. + */ +ol.renderer.canvas.SUPPORTED = ol.canvas.SUPPORTED; diff --git a/master/ol/ol/renderer/canvas/canvastilelayerrenderer.js b/master/ol/ol/renderer/canvas/canvastilelayerrenderer.js new file mode 100644 index 0000000000..6c083c9c50 --- /dev/null +++ b/master/ol/ol/renderer/canvas/canvastilelayerrenderer.js @@ -0,0 +1,260 @@ +// FIXME find correct globalCompositeOperation +// FIXME optimize :-) + +goog.provide('ol.renderer.canvas.TileLayer'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.vec.Mat4'); +goog.require('ol.Size'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileState'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.renderer.Map'); +goog.require('ol.renderer.canvas.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.canvas.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.TileLayer} tileLayer Tile layer. + */ +ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) { + + goog.base(this, mapRenderer, tileLayer); + + /** + * @private + * @type {HTMLCanvasElement} + */ + this.canvas_ = null; + + /** + * @private + * @type {ol.Size} + */ + this.canvasSize_ = null; + + /** + * @private + * @type {CanvasRenderingContext2D} + */ + this.context_ = null; + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.transform_ = goog.vec.Mat4.createNumber(); + + /** + * @private + * @type {Array.} + */ + this.renderedTiles_ = null; + +}; +goog.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer); + + +/** + * @inheritDoc + */ +ol.renderer.canvas.TileLayer.prototype.getImage = function() { + return this.canvas_; +}; + + +/** + * @return {ol.layer.TileLayer} Tile layer. + */ +ol.renderer.canvas.TileLayer.prototype.getTileLayer = function() { + return /** @type {ol.layer.TileLayer} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.TileLayer.prototype.getTransform = function() { + return this.transform_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.TileLayer.prototype.renderFrame = + function(frameState, layerState) { + + var view2DState = frameState.view2DState; + var projection = view2DState.projection; + + var tileLayer = this.getTileLayer(); + var tileSource = tileLayer.getTileSource(); + var tileSourceKey = goog.getUid(tileSource).toString(); + var tileGrid = tileSource.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } + var z = tileGrid.getZForResolution(view2DState.resolution); + var tileSize = tileGrid.getTileSize(z); + var tileResolution = tileGrid.getResolution(z); + var tileRange = tileGrid.getTileRangeForExtentAndResolution( + frameState.extent, tileResolution); + var tileRangeWidth = tileRange.getWidth(); + var tileRangeHeight = tileRange.getHeight(); + + var canvasSize = new ol.Size( + tileSize.width * tileRangeWidth, tileSize.height * tileRangeHeight); + + var canvas, context; + if (goog.isNull(this.canvas_)) { + canvas = /** @type {HTMLCanvasElement} */ + (goog.dom.createElement(goog.dom.TagName.CANVAS)); + canvas.width = canvasSize.width; + canvas.height = canvasSize.height; + context = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); + this.canvas_ = canvas; + this.canvasSize_ = canvasSize; + this.context_ = context; + this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight); + } else { + canvas = this.canvas_; + context = this.context_; + if (!this.canvasSize_.equals(canvasSize)) { + canvas.width = canvasSize.width; + canvas.height = canvasSize.height; + this.canvasSize_ = canvasSize; + this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight); + } + } + + /** + * @type {Object.>} + */ + var tilesToDrawByZ = {}; + tilesToDrawByZ[z] = {}; + + var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { + return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; + }, tileSource, tileGrid, projection); + var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, + tilesToDrawByZ, getTileIfLoaded); + + var allTilesLoaded = true; + var tile, tileCenter, tileCoord, tileState, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + + tileCoord = new ol.TileCoord(z, x, y); + tile = tileSource.getTile(tileCoord, tileGrid, projection); + tileState = tile.getState(); + if (tileState == ol.TileState.IDLE) { + this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); + } else if (tileState == ol.TileState.LOADING) { + this.listenToTileChange(tile); + } else if (tileState == ol.TileState.LOADED || + tileState == ol.TileState.EMPTY) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; + continue; + } else if (tileState == ol.TileState.ERROR) { + continue; + } + + allTilesLoaded = false; + tileGrid.forEachTileCoordParentTileRange(tileCoord, findLoadedTiles); + + } + } + + /** @type {Array.} */ + var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); + goog.array.sort(zs); + var opaque = tileSource.getOpaque(); + var origin = tileGrid.getTileCoordExtent( + new ol.TileCoord(z, tileRange.minX, tileRange.maxY)).getTopLeft(); + var currentZ, i, index, scale, tileCoordKey, tileExtent, tilesToDraw; + var ix, iy, interimTileExtent, interimTileRange, maxX, maxY, minX, minY; + var height, width; + for (i = 0; i < zs.length; ++i) { + currentZ = zs[i]; + tileSize = tileGrid.getTileSize(currentZ); + tilesToDraw = tilesToDrawByZ[currentZ]; + if (currentZ == z) { + for (tileCoordKey in tilesToDraw) { + tile = tilesToDraw[tileCoordKey]; + tileCoord = tile.tileCoord; + index = (tileCoord.y - tileRange.minY) * tileRangeWidth + + (tileCoord.x - tileRange.minX); + if (this.renderedTiles_[index] != tile) { + x = tileSize.width * (tile.tileCoord.x - tileRange.minX); + y = tileSize.height * (tileRange.maxY - tile.tileCoord.y); + tileState = tile.getState(); + if (tileState == ol.TileState.EMPTY || !opaque) { + context.clearRect(x, y, tileSize.width, tileSize.height); + } + if (tileState == ol.TileState.LOADED) { + context.drawImage(tile.getImage(), x, y); + } + this.renderedTiles_[index] = tile; + } + } + } else { + scale = tileGrid.getResolution(currentZ) / tileResolution; + for (tileCoordKey in tilesToDraw) { + tile = tilesToDraw[tileCoordKey]; + tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord); + x = (tileExtent.minX - origin.x) / tileResolution; + y = (origin.y - tileExtent.maxY) / tileResolution; + width = scale * tileSize.width; + height = scale * tileSize.height; + tileState = tile.getState(); + if (tileState == ol.TileState.EMPTY || !opaque) { + context.clearRect(x, y, width, height); + } + if (tileState == ol.TileState.LOADED) { + context.drawImage(tile.getImage(), x, y, width, height); + } + interimTileRange = + tileGrid.getTileRangeForExtentAndZ(tileExtent, z); + minX = Math.max(interimTileRange.minX, tileRange.minX); + maxX = Math.min(interimTileRange.maxX, tileRange.maxX); + minY = Math.max(interimTileRange.minY, tileRange.minY); + maxY = Math.min(interimTileRange.maxY, tileRange.maxY); + for (ix = minX; ix <= maxX; ++ix) { + for (iy = minY; iy <= maxY; ++iy) { + this.renderedTiles_[(iy - tileRange.minY) * tileRangeWidth + + (ix - tileRange.minX)] = undefined; + } + } + } + } + } + + this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); + tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid); + this.scheduleExpireCache(frameState, tileSource); + + var transform = this.transform_; + goog.vec.Mat4.makeIdentity(transform); + goog.vec.Mat4.translate(transform, + frameState.size.width / 2, frameState.size.height / 2, 0); + goog.vec.Mat4.rotateZ(transform, view2DState.rotation); + goog.vec.Mat4.scale( + transform, + tileResolution / view2DState.resolution, + tileResolution / view2DState.resolution, + 1); + goog.vec.Mat4.translate( + transform, + (origin.x - view2DState.center.x) / tileResolution, + (view2DState.center.y - origin.y) / tileResolution, + 0); + +}; diff --git a/master/ol/ol/renderer/canvas/map.exports b/master/ol/ol/renderer/canvas/map.exports new file mode 100644 index 0000000000..784a80737e --- /dev/null +++ b/master/ol/ol/renderer/canvas/map.exports @@ -0,0 +1 @@ +@exportProperty ol.renderer.canvas.Map.prototype.getCanvas diff --git a/master/ol/ol/renderer/dom/domimagelayerrenderer.js b/master/ol/ol/renderer/dom/domimagelayerrenderer.js new file mode 100644 index 0000000000..4b9ae54332 --- /dev/null +++ b/master/ol/ol/renderer/dom/domimagelayerrenderer.js @@ -0,0 +1,125 @@ +goog.provide('ol.renderer.dom.ImageLayer'); + +goog.require('goog.dom'); +goog.require('goog.vec.Mat4'); +goog.require('ol.Image'); +goog.require('ol.ImageState'); +goog.require('ol.ViewHint'); +goog.require('ol.dom'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.renderer.dom.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.dom.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.ImageLayer} imageLayer Image layer. + */ +ol.renderer.dom.ImageLayer = function(mapRenderer, imageLayer) { + var target = goog.dom.createElement(goog.dom.TagName.DIV); + target.className = 'ol-layer-image'; + target.style.position = 'absolute'; + + goog.base(this, mapRenderer, imageLayer, target); + + /** + * The last rendered image. + * @private + * @type {?ol.Image} + */ + this.image_ = null; + + /** + * @private + * @type {goog.vec.Mat4.AnyType} + */ + this.transform_ = goog.vec.Mat4.createNumberIdentity(); + +}; +goog.inherits(ol.renderer.dom.ImageLayer, ol.renderer.dom.Layer); + + +/** + * @return {ol.layer.ImageLayer} Image layer. + */ +ol.renderer.dom.ImageLayer.prototype.getImageLayer = function() { + return /** @type {ol.layer.ImageLayer} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.dom.ImageLayer.prototype.renderFrame = + function(frameState, layerState) { + + var view2DState = frameState.view2DState; + var viewCenter = view2DState.center; + var viewResolution = view2DState.resolution; + var viewRotation = view2DState.rotation; + + var image = this.image_; + var imageLayer = this.getImageLayer(); + var imageSource = imageLayer.getImageSource(); + + var hints = frameState.viewHints; + + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { + var image_ = imageSource.getImage( + frameState.extent, viewResolution, view2DState.projection); + if (!goog.isNull(image_)) { + var imageState = image_.getState(); + if (imageState == ol.ImageState.IDLE) { + goog.events.listenOnce(image_, goog.events.EventType.CHANGE, + this.handleImageChange, false, this); + image_.load(); + } else if (imageState == ol.ImageState.LOADED) { + image = image_; + } + } + } + + if (!goog.isNull(image)) { + var imageExtent = image.getExtent(); + var imageResolution = image.getResolution(); + var transform = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.makeIdentity(transform); + goog.vec.Mat4.translate(transform, + frameState.size.width / 2, frameState.size.height / 2, 0); + goog.vec.Mat4.rotateZ(transform, viewRotation); + goog.vec.Mat4.scale( + transform, + imageResolution / viewResolution, + imageResolution / viewResolution, + 1); + goog.vec.Mat4.translate( + transform, + (imageExtent.minX - viewCenter.x) / imageResolution, + (viewCenter.y - imageExtent.maxY) / imageResolution, + 0); + if (image != this.image_) { + var imageElement = image.getImageElement(this); + imageElement.style.position = 'absolute'; + goog.dom.removeChildren(this.target); + goog.dom.appendChild(this.target, imageElement); + this.image_ = image; + } + this.setTransform(transform); + + this.updateAttributions(frameState.attributions, image.getAttributions()); + } + +}; + + +/** + * @param {goog.vec.Mat4.AnyType} transform Transform. + */ +ol.renderer.dom.ImageLayer.prototype.setTransform = function(transform) { + if (!goog.vec.Mat4.equals(transform, this.transform_)) { + ol.dom.transformElement2D(this.target, transform, 6); + goog.vec.Mat4.setFromArray(this.transform_, transform); + } +}; diff --git a/master/ol/ol/renderer/dom/domlayerrenderer.js b/master/ol/ol/renderer/dom/domlayerrenderer.js new file mode 100644 index 0000000000..7b59b1e7be --- /dev/null +++ b/master/ol/ol/renderer/dom/domlayerrenderer.js @@ -0,0 +1,43 @@ +goog.provide('ol.renderer.dom.Layer'); + +goog.require('ol.layer.Layer'); +goog.require('ol.renderer.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.Layer} layer Layer. + * @param {!Element} target Target. + */ +ol.renderer.dom.Layer = function(mapRenderer, layer, target) { + + goog.base(this, mapRenderer, layer); + + /** + * @type {!Element} + * @protected + */ + this.target = target; + +}; +goog.inherits(ol.renderer.dom.Layer, ol.renderer.Layer); + + +/** + * @inheritDoc + */ +ol.renderer.dom.Layer.prototype.disposeInternal = function() { + goog.dom.removeNode(this.target); + goog.base(this, 'disposeInternal'); +}; + + +/** + * @return {!Element} Target. + */ +ol.renderer.dom.Layer.prototype.getTarget = function() { + return this.target; +}; diff --git a/master/ol/ol/renderer/dom/dommaprenderer.js b/master/ol/ol/renderer/dom/dommaprenderer.js new file mode 100644 index 0000000000..a833d5fd91 --- /dev/null +++ b/master/ol/ol/renderer/dom/dommaprenderer.js @@ -0,0 +1,103 @@ +goog.provide('ol.renderer.dom.Map'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.style'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.renderer.Map'); +goog.require('ol.renderer.dom.ImageLayer'); +goog.require('ol.renderer.dom.TileLayer'); + + + +/** + * @constructor + * @extends {ol.renderer.Map} + * @param {Element} container Container. + * @param {ol.Map} map Map. + */ +ol.renderer.dom.Map = function(container, map) { + + goog.base(this, container, map); + + /** + * @type {!Element} + * @private + */ + this.layersPane_ = goog.dom.createElement(goog.dom.TagName.DIV); + this.layersPane_.className = 'ol-layers ol-unselectable'; + var style = this.layersPane_.style; + style.position = 'absolute'; + style.width = '100%'; + style.height = '100%'; + + goog.dom.insertChildAt(container, this.layersPane_, 0); + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + +}; +goog.inherits(ol.renderer.dom.Map, ol.renderer.Map); + + +/** + * @inheritDoc + */ +ol.renderer.dom.Map.prototype.addLayer = function(layer) { + goog.base(this, 'addLayer', layer); + this.getMap().render(); +}; + + +/** + * @inheritDoc + */ +ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) { + var layerRenderer; + if (layer instanceof ol.layer.TileLayer) { + layerRenderer = new ol.renderer.dom.TileLayer(this, layer); + } else if (layer instanceof ol.layer.ImageLayer) { + layerRenderer = new ol.renderer.dom.ImageLayer(this, layer); + } + goog.asserts.assert(goog.isDef(layerRenderer)); + goog.dom.appendChild(this.layersPane_, layerRenderer.getTarget()); + return layerRenderer; +}; + + +/** + * @inheritDoc + */ +ol.renderer.dom.Map.prototype.renderFrame = function(frameState) { + + if (goog.isNull(frameState)) { + if (this.renderedVisible_) { + goog.style.showElement(this.layersPane_, false); + this.renderedVisible_ = false; + } + return; + } + + goog.array.forEach(frameState.layersArray, function(layer) { + var layerState = frameState.layerStates[goog.getUid(layer)]; + if (!layerState.ready) { + return; + } + var layerRenderer = this.getLayerRenderer(layer); + layerRenderer.renderFrame(frameState, layerState); + }, this); + + if (!this.renderedVisible_) { + goog.style.showElement(this.layersPane_, true); + this.renderedVisible_ = true; + } + + this.calculateMatrices2D(frameState); + +}; diff --git a/master/ol/ol/renderer/dom/domrenderer.js b/master/ol/ol/renderer/dom/domrenderer.js new file mode 100644 index 0000000000..d57cfbf6d0 --- /dev/null +++ b/master/ol/ol/renderer/dom/domrenderer.js @@ -0,0 +1,8 @@ +goog.provide('ol.renderer.dom.SUPPORTED'); + + +/** + * @const + * @type {boolean} Is supported. + */ +ol.renderer.dom.SUPPORTED = true; diff --git a/master/ol/ol/renderer/dom/domtilelayerrenderer.js b/master/ol/ol/renderer/dom/domtilelayerrenderer.js new file mode 100644 index 0000000000..fd1e221106 --- /dev/null +++ b/master/ol/ol/renderer/dom/domtilelayerrenderer.js @@ -0,0 +1,372 @@ +// FIXME probably need to reset TileLayerZ if offsets get too large +// FIXME when zooming out, preserve higher Z divs to avoid white flash + +goog.provide('ol.renderer.dom.TileLayer'); + +goog.require('goog.asserts'); +goog.require('goog.dom'); +goog.require('goog.style'); +goog.require('goog.vec.Mat4'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileState'); +goog.require('ol.ViewHint'); +goog.require('ol.dom'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.renderer.dom.Layer'); +goog.require('ol.tilegrid.TileGrid'); + + + +/** + * @constructor + * @extends {ol.renderer.dom.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.TileLayer} tileLayer Tile layer. + */ +ol.renderer.dom.TileLayer = function(mapRenderer, tileLayer) { + + var target = goog.dom.createElement(goog.dom.TagName.DIV); + target.className = 'ol-layer-tile'; + target.style.position = 'absolute'; + + goog.base(this, mapRenderer, tileLayer, target); + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + + /** + * @private + * @type {number} + */ + this.renderedOpacity_ = 1; + + /** + * @private + * @type {Object.} + */ + this.tileLayerZs_ = {}; + +}; +goog.inherits(ol.renderer.dom.TileLayer, ol.renderer.dom.Layer); + + +/** + * @return {ol.layer.TileLayer} Tile layer. + */ +ol.renderer.dom.TileLayer.prototype.getTileLayer = function() { + return /** @type {ol.layer.TileLayer} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.dom.TileLayer.prototype.renderFrame = + function(frameState, layerState) { + + if (!layerState.visible) { + if (this.renderedVisible_) { + goog.style.showElement(this.target, false); + this.renderedVisible_ = false; + } + return; + } + + var view2DState = frameState.view2DState; + var projection = view2DState.projection; + + var tileLayer = this.getTileLayer(); + var tileSource = tileLayer.getTileSource(); + var tileSourceKey = goog.getUid(tileSource).toString(); + var tileGrid = tileSource.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } + var z = tileGrid.getZForResolution(view2DState.resolution); + var tileResolution = tileGrid.getResolution(z); + var tileRange = tileGrid.getTileRangeForExtentAndResolution( + frameState.extent, tileResolution); + + /** @type {Object.>} */ + var tilesToDrawByZ = {}; + tilesToDrawByZ[z] = {}; + + var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { + return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; + }, tileSource, tileGrid, projection); + var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, + tilesToDrawByZ, getTileIfLoaded); + + var allTilesLoaded = true; + var tile, tileCenter, tileCoord, tileState, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + + tileCoord = new ol.TileCoord(z, x, y); + tile = tileSource.getTile(tileCoord, tileGrid, projection); + tileState = tile.getState(); + if (tileState == ol.TileState.IDLE) { + this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); + } else if (tileState == ol.TileState.LOADING) { + this.listenToTileChange(tile); + } else if (tileState == ol.TileState.LOADED) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; + continue; + } else if (tileState == ol.TileState.ERROR || + tileState == ol.TileState.EMPTY) { + continue; + } + + allTilesLoaded = false; + tileGrid.forEachTileCoordParentTileRange(tileCoord, findLoadedTiles); + + } + + } + + /** @type {Array.} */ + var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); + goog.array.sort(zs); + + /** @type {Object.} */ + var newTileLayerZKeys = {}; + + var iz, tileCoordKey, tileCoordOrigin, tileLayerZ, tileLayerZKey, tilesToDraw; + for (iz = 0; iz < zs.length; ++iz) { + tileLayerZKey = zs[iz]; + if (tileLayerZKey in this.tileLayerZs_) { + tileLayerZ = this.tileLayerZs_[tileLayerZKey]; + } else { + tileCoordOrigin = + tileGrid.getTileCoordForCoordAndZ(view2DState.center, tileLayerZKey); + tileLayerZ = new ol.renderer.dom.TileLayerZ_(tileGrid, tileCoordOrigin); + newTileLayerZKeys[tileLayerZKey] = true; + this.tileLayerZs_[tileLayerZKey] = tileLayerZ; + } + tilesToDraw = tilesToDrawByZ[tileLayerZKey]; + for (tileCoordKey in tilesToDraw) { + tileLayerZ.addTile(tilesToDraw[tileCoordKey]); + } + tileLayerZ.finalizeAddTiles(); + } + + /** @type {Array.} */ + var tileLayerZKeys = + goog.array.map(goog.object.getKeys(this.tileLayerZs_), Number); + goog.array.sort(tileLayerZKeys); + + var i, j, origin, resolution; + var transform = goog.vec.Mat4.createNumber(); + for (i = 0; i < tileLayerZKeys.length; ++i) { + tileLayerZKey = tileLayerZKeys[i]; + tileLayerZ = this.tileLayerZs_[tileLayerZKey]; + if (!(tileLayerZKey in tilesToDrawByZ)) { + goog.dom.removeNode(tileLayerZ.target); + delete this.tileLayerZs_[tileLayerZKey]; + continue; + } + resolution = tileLayerZ.getResolution(); + origin = tileLayerZ.getOrigin(); + goog.vec.Mat4.makeIdentity(transform); + goog.vec.Mat4.translate( + transform, frameState.size.width / 2, frameState.size.height / 2, 0); + goog.vec.Mat4.rotateZ(transform, view2DState.rotation); + goog.vec.Mat4.scale(transform, resolution / view2DState.resolution, + resolution / view2DState.resolution, 1); + goog.vec.Mat4.translate( + transform, + (origin.x - view2DState.center.x) / resolution, + (view2DState.center.y - origin.y) / resolution, + 0); + tileLayerZ.setTransform(transform); + if (tileLayerZKey in newTileLayerZKeys) { + for (j = tileLayerZKey - 1; j >= 0; --j) { + if (j in this.tileLayerZs_) { + goog.dom.insertSiblingAfter( + tileLayerZ.target, this.tileLayerZs_[j].target); + break; + } + } + if (j < 0) { + goog.dom.insertChildAt(this.target, tileLayerZ.target, 0); + } + } else { + if (!frameState.viewHints[ol.ViewHint.ANIMATING] && + !frameState.viewHints[ol.ViewHint.INTERACTING]) { + tileLayerZ.removeTilesOutsideExtent(frameState.extent); + } + } + } + + if (layerState.opacity != this.renderedOpacity_) { + goog.style.setOpacity(this.target, layerState.opacity); + this.renderedOpacity_ = layerState.opacity; + } + + if (layerState.visible && !this.renderedVisible_) { + goog.style.showElement(this.target, true); + this.renderedVisible_ = true; + } + + this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); + tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid); + this.scheduleExpireCache(frameState, tileSource); + +}; + + + +/** + * @constructor + * @private + * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. + * @param {ol.TileCoord} tileCoordOrigin Tile coord origin. + */ +ol.renderer.dom.TileLayerZ_ = function(tileGrid, tileCoordOrigin) { + + /** + * @type {!Element} + */ + this.target = goog.dom.createElement(goog.dom.TagName.DIV); + this.target.style.position = 'absolute'; + + /** + * @private + * @type {ol.tilegrid.TileGrid} + */ + this.tileGrid_ = tileGrid; + + /** + * @private + * @type {ol.TileCoord} + */ + this.tileCoordOrigin_ = tileCoordOrigin; + + /** + * @private + * @type {ol.Coordinate} + */ + this.origin_ = tileGrid.getTileCoordExtent(tileCoordOrigin).getTopLeft(); + + /** + * @private + * @type {number} + */ + this.resolution_ = tileGrid.getResolution(tileCoordOrigin.z); + + /** + * @private + * @type {Object.} + */ + this.tiles_ = {}; + + /** + * @private + * @type {DocumentFragment} + */ + this.documentFragment_ = null; + + /** + * @private + * @type {goog.vec.Mat4.AnyType} + */ + this.transform_ = goog.vec.Mat4.createNumberIdentity(); + +}; + + +/** + * @param {ol.Tile} tile Tile. + */ +ol.renderer.dom.TileLayerZ_.prototype.addTile = function(tile) { + var tileCoord = tile.tileCoord; + goog.asserts.assert(tileCoord.z == this.tileCoordOrigin_.z); + var tileCoordKey = tileCoord.toString(); + if (tileCoordKey in this.tiles_) { + return; + } + var tileSize = this.tileGrid_.getTileSize(tileCoord.z); + var image = tile.getImage(this); + var style = image.style; + style.position = 'absolute'; + style.left = + ((tileCoord.x - this.tileCoordOrigin_.x) * tileSize.width) + 'px'; + style.top = + ((this.tileCoordOrigin_.y - tileCoord.y) * tileSize.height) + 'px'; + if (goog.isNull(this.documentFragment_)) { + this.documentFragment_ = document.createDocumentFragment(); + } + goog.dom.appendChild(this.documentFragment_, image); + this.tiles_[tileCoordKey] = tile; +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.renderer.dom.TileLayerZ_.prototype.finalizeAddTiles = function() { + if (!goog.isNull(this.documentFragment_)) { + goog.dom.appendChild(this.target, this.documentFragment_); + this.documentFragment_ = null; + } +}; + + +/** + * @return {ol.Coordinate} Origin. + */ +ol.renderer.dom.TileLayerZ_.prototype.getOrigin = function() { + return this.origin_; +}; + + +/** + * @return {number} Resolution. + */ +ol.renderer.dom.TileLayerZ_.prototype.getResolution = function() { + return this.resolution_; +}; + + +/** + * @param {ol.Extent} extent Extent. + */ +ol.renderer.dom.TileLayerZ_.prototype.removeTilesOutsideExtent = + function(extent) { + var tileRange = + this.tileGrid_.getTileRangeForExtentAndZ(extent, this.tileCoordOrigin_.z); + var tilesToRemove = []; + var tile, tileCoordKey; + for (tileCoordKey in this.tiles_) { + tile = this.tiles_[tileCoordKey]; + if (!tileRange.contains(tile.tileCoord)) { + tilesToRemove.push(tile); + } + } + var i; + for (i = 0; i < tilesToRemove.length; ++i) { + tile = tilesToRemove[i]; + tileCoordKey = tile.tileCoord.toString(); + goog.dom.removeNode(tile.getImage(this)); + delete this.tiles_[tileCoordKey]; + } +}; + + +/** + * @param {goog.vec.Mat4.AnyType} transform Transform. + */ +ol.renderer.dom.TileLayerZ_.prototype.setTransform = function(transform) { + if (!goog.vec.Mat4.equals(transform, this.transform_)) { + ol.dom.transformElement2D(this.target, transform, 6); + goog.vec.Mat4.setFromArray(this.transform_, transform); + } +}; diff --git a/master/ol/ol/renderer/layerrenderer.js b/master/ol/ol/renderer/layerrenderer.js new file mode 100644 index 0000000000..f48ec2e312 --- /dev/null +++ b/master/ol/ol/renderer/layerrenderer.js @@ -0,0 +1,301 @@ +goog.provide('ol.renderer.Layer'); + +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('ol.Attribution'); +goog.require('ol.FrameState'); +goog.require('ol.Image'); +goog.require('ol.ImageState'); +goog.require('ol.Object'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); +goog.require('ol.TileState'); +goog.require('ol.layer.Layer'); +goog.require('ol.layer.LayerProperty'); +goog.require('ol.layer.LayerState'); +goog.require('ol.source.TileSource'); + + + +/** + * @constructor + * @extends {ol.Object} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.Layer} layer Layer. + */ +ol.renderer.Layer = function(mapRenderer, layer) { + + goog.base(this); + + /** + * @private + * @type {ol.renderer.Map} + */ + this.mapRenderer_ = mapRenderer; + + /** + * @private + * @type {ol.layer.Layer} + */ + this.layer_ = layer; + + /** + * @protected + * @type {Object.} + */ + this.observedTileKeys = {}; + + goog.events.listen(this.layer_, + ol.Object.getChangedEventType(ol.layer.LayerProperty.BRIGHTNESS), + this.handleLayerBrightnessChange, false, this); + + goog.events.listen(this.layer_, + ol.Object.getChangedEventType(ol.layer.LayerProperty.CONTRAST), + this.handleLayerContrastChange, false, this); + + goog.events.listen(this.layer_, + ol.Object.getChangedEventType(ol.layer.LayerProperty.HUE), + this.handleLayerHueChange, false, this); + + goog.events.listen(this.layer_, goog.events.EventType.LOAD, + this.handleLayerLoad, false, this); + + goog.events.listen(this.layer_, + ol.Object.getChangedEventType(ol.layer.LayerProperty.OPACITY), + this.handleLayerOpacityChange, false, this); + + goog.events.listen(this.layer_, + ol.Object.getChangedEventType(ol.layer.LayerProperty.SATURATION), + this.handleLayerSaturationChange, false, this); + + goog.events.listen(this.layer_, + ol.Object.getChangedEventType(ol.layer.LayerProperty.VISIBLE), + this.handleLayerVisibleChange, false, this); + +}; +goog.inherits(ol.renderer.Layer, ol.Object); + + +/** + * @protected + */ +ol.renderer.Layer.prototype.dispatchChangeEvent = function() { + this.dispatchEvent(goog.events.EventType.CHANGE); +}; + + +/** + * @return {ol.layer.Layer} Layer. + */ +ol.renderer.Layer.prototype.getLayer = function() { + return this.layer_; +}; + + +/** + * @return {ol.Map} Map. + */ +ol.renderer.Layer.prototype.getMap = function() { + return this.mapRenderer_.getMap(); +}; + + +/** + * @return {ol.renderer.Map} Map renderer. + */ +ol.renderer.Layer.prototype.getMapRenderer = function() { + return this.mapRenderer_; +}; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerBrightnessChange = goog.nullFunction; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerContrastChange = goog.nullFunction; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerHueChange = goog.nullFunction; + + +/** + * Handle changes in image state. + * @param {goog.events.Event} event Image change event. + * @protected + */ +ol.renderer.Layer.prototype.handleImageChange = function(event) { + var image = /** @type {ol.Image} */ (event.target); + if (image.getState() === ol.ImageState.LOADED) { + this.getMap().requestRenderFrame(); + } +}; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerLoad = function() { + this.dispatchChangeEvent(); +}; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerOpacityChange = function() { + this.dispatchChangeEvent(); +}; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerSaturationChange = goog.nullFunction; + + +/** + * @protected + */ +ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { + this.dispatchChangeEvent(); +}; + + +/** + * Handle changes in tile state. + * @param {goog.events.Event} event Tile change event. + * @private + */ +ol.renderer.Layer.prototype.handleTileChange_ = function(event) { + var tile = /** @type {ol.Tile} */ (event.target); + if (tile.getState() === ol.TileState.LOADED) { + this.getMap().requestRenderFrame(); + } + delete this.observedTileKeys[tile.getKey()]; +}; + + +/** + * Listen once to tileKey, le change event. + * @param {ol.Tile} tile Tile. + * @protected + */ +ol.renderer.Layer.prototype.listenToTileChange = function(tile) { + var tileKey = tile.getKey(); + if (!(tileKey in this.observedTileKeys)) { + this.observedTileKeys[tileKey] = true; + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, + this.handleTileChange_, false, this); + } +}; + + +/** + * @param {ol.FrameState} frameState Frame state. + * @param {ol.layer.LayerState} layerState Layer state. + */ +ol.renderer.Layer.prototype.renderFrame = goog.abstractMethod; + + +/** + * @protected + * @param {ol.FrameState} frameState Frame state. + * @param {ol.source.TileSource} tileSource Tile source. + */ +ol.renderer.Layer.prototype.scheduleExpireCache = + function(frameState, tileSource) { + if (tileSource.canExpireCache()) { + frameState.postRenderFunctions.push( + goog.partial(function(tileSource, map, frameState) { + var tileSourceKey = goog.getUid(tileSource).toString(); + tileSource.expireCache(frameState.usedTiles[tileSourceKey]); + }, tileSource)); + } +}; + + +/** + * @protected + * @param {Object.} attributionsSet Attributions + * set (target). + * @param {Array.} attributions Attributions (source). + */ +ol.renderer.Layer.prototype.updateAttributions = + function(attributionsSet, attributions) { + if (goog.isDefAndNotNull(attributions)) { + var i; + var attribution; + for (i = 0; i < attributions.length; ++i) { + attribution = attributions[i]; + attributionsSet[goog.getUid(attribution).toString()] = attribution; + } + } +}; + + +/** + * @protected + * @param {Object.>} usedTiles Used tiles. + * @param {ol.source.TileSource} tileSource Tile source. + * @param {number} z Z. + * @param {ol.TileRange} tileRange Tile range. + */ +ol.renderer.Layer.prototype.updateUsedTiles = + function(usedTiles, tileSource, z, tileRange) { + // FIXME should we use tilesToDrawByZ instead? + var tileSourceKey = goog.getUid(tileSource).toString(); + var zKey = z.toString(); + if (tileSourceKey in usedTiles) { + if (zKey in usedTiles[tileSourceKey]) { + usedTiles[tileSourceKey][zKey].extend(tileRange); + } else { + usedTiles[tileSourceKey][zKey] = tileRange; + } + } else { + usedTiles[tileSourceKey] = {}; + usedTiles[tileSourceKey][zKey] = tileRange; + } +}; + + +/** + * @protected + * @param {Object.>} wantedTiles Wanted tiles. + * @param {ol.source.TileSource} tileSource Tile source. + * @param {ol.TileCoord} tileCoord Tile coordinate. + */ +ol.renderer.Layer.prototype.updateWantedTiles = + function(wantedTiles, tileSource, tileCoord) { + var tileSourceKey = goog.getUid(tileSource).toString(); + var coordKey = tileCoord.toString(); + if (!(tileSourceKey in wantedTiles)) { + wantedTiles[tileSourceKey] = {}; + } + wantedTiles[tileSourceKey][coordKey] = true; +}; + + +/** + * @param {function(ol.Tile): boolean} isLoadedFunction Function to + * determine if the tile is loaded. + * @param {ol.source.TileSource} tileSource Tile source. + * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. + * @param {ol.Projection} projection Projection. + * @return {function(ol.TileCoord): ol.Tile} Returns a tile if it is loaded. + */ +ol.renderer.Layer.prototype.createGetTileIfLoadedFunction = + function(isLoadedFunction, tileSource, tileGrid, projection) { + return function(tileCoord) { + var tile = tileSource.getTile(tileCoord, tileGrid, projection); + return isLoadedFunction(tile) ? tile : null; + }; +}; diff --git a/master/ol/ol/renderer/maprenderer.js b/master/ol/ol/renderer/maprenderer.js new file mode 100644 index 0000000000..dfd69e5464 --- /dev/null +++ b/master/ol/ol/renderer/maprenderer.js @@ -0,0 +1,269 @@ +goog.provide('ol.renderer.Map'); + +goog.require('goog.Disposable'); +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.events'); +goog.require('goog.functions'); +goog.require('goog.vec.Mat4'); +goog.require('ol.CollectionEvent'); +goog.require('ol.CollectionEventType'); +goog.require('ol.FrameState'); +goog.require('ol.Object'); +goog.require('ol.layer.Layer'); +goog.require('ol.renderer.Layer'); + + + +/** + * @constructor + * @extends {goog.Disposable} + * @param {Element} container Container. + * @param {ol.Map} map Map. + */ +ol.renderer.Map = function(container, map) { + + goog.base(this); + + /** + * @private + * @type {Element} + */ + this.container_ = container; + + /** + * @protected + * @type {ol.Map} + */ + this.map = map; + + /** + * @protected + * @type {Object.} + */ + this.layerRenderers = {}; + + // + // We listen to layer add/remove to add/remove layer renderers. + // + + /** + * @private + * @type {?number} + */ + this.mapLayersChangedListenerKey_ = + goog.events.listen( + map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS), + this.handleLayersChanged, false, this); + + /** + * @private + * @type {Array.} + */ + this.layersListenerKeys_ = null; + + /** + * @private + * @type {Object.} + */ + this.layerRendererChangeListenKeys_ = {}; + +}; +goog.inherits(ol.renderer.Map, goog.Disposable); + + +/** + * @param {ol.layer.Layer} layer Layer. + * @protected + */ +ol.renderer.Map.prototype.addLayer = function(layer) { + var layerRenderer = this.createLayerRenderer(layer); + this.setLayerRenderer(layer, layerRenderer); +}; + + +/** + * @param {ol.FrameState} frameState FrameState. + * @protected + */ +ol.renderer.Map.prototype.calculateMatrices2D = function(frameState) { + + var view2DState = frameState.view2DState; + var coordinateToPixelMatrix = frameState.coordinateToPixelMatrix; + + goog.vec.Mat4.makeIdentity(coordinateToPixelMatrix); + goog.vec.Mat4.translate(coordinateToPixelMatrix, + frameState.size.width / 2, + frameState.size.height / 2, + 0); + goog.vec.Mat4.scale(coordinateToPixelMatrix, + 1 / view2DState.resolution, + -1 / view2DState.resolution, + 1); + goog.vec.Mat4.rotateZ(coordinateToPixelMatrix, + -view2DState.rotation); + goog.vec.Mat4.translate(coordinateToPixelMatrix, + -view2DState.center.x, + -view2DState.center.y, + 0); + + var inverted = goog.vec.Mat4.invert( + coordinateToPixelMatrix, frameState.pixelToCoordinateMatrix); + goog.asserts.assert(inverted); + +}; + + +/** + * @param {ol.layer.Layer} layer Layer. + * @protected + * @return {ol.renderer.Layer} layerRenderer Layer renderer. + */ +ol.renderer.Map.prototype.createLayerRenderer = function(layer) { + return new ol.renderer.Layer(this, layer); +}; + + +/** + * @inheritDoc + */ +ol.renderer.Map.prototype.disposeInternal = function() { + goog.object.forEach(this.layerRenderers, function(layerRenderer) { + goog.dispose(layerRenderer); + }); + goog.events.unlistenByKey(this.mapLayersChangedListenerKey_); + if (!goog.isNull(this.layersListenerKeys_)) { + goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); + } + goog.base(this, 'disposeInternal'); +}; + + +/** + * @return {Element} Canvas. + */ +ol.renderer.Map.prototype.getCanvas = goog.functions.NULL; + + +/** + * @param {ol.layer.Layer} layer Layer. + * @protected + * @return {ol.renderer.Layer} Layer renderer. + */ +ol.renderer.Map.prototype.getLayerRenderer = function(layer) { + var layerKey = goog.getUid(layer); + var layerRenderer = this.layerRenderers[layerKey]; + goog.asserts.assert(goog.isDef(layerRenderer)); + return layerRenderer; +}; + + +/** + * @return {ol.Map} Map. + */ +ol.renderer.Map.prototype.getMap = function() { + return this.map; +}; + + +/** + * @param {goog.events.Event} event Event. + * @protected + */ +ol.renderer.Map.prototype.handleLayerRendererChange = function(event) { + this.getMap().render(); +}; + + +/** + * @param {ol.CollectionEvent} collectionEvent Collection event. + * @protected + */ +ol.renderer.Map.prototype.handleLayersAdd = function(collectionEvent) { + var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem); + this.addLayer(layer); +}; + + +/** + * @protected + */ +ol.renderer.Map.prototype.handleLayersChanged = function() { + goog.disposeAll(goog.object.getValues(this.layerRenderers)); + this.layerRenderers = {}; + if (!goog.isNull(this.layersListenerKeys_)) { + goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); + this.layersListenerKeys_ = null; + } + var layers = this.map.getLayers(); + if (goog.isDefAndNotNull(layers)) { + layers.forEach(this.addLayer, this); + this.layersListenerKeys_ = [ + goog.events.listen(layers, ol.CollectionEventType.ADD, + this.handleLayersAdd, false, this), + goog.events.listen(layers, ol.CollectionEventType.REMOVE, + this.handleLayersRemove, false, this) + ]; + } +}; + + +/** + * @param {ol.CollectionEvent} collectionEvent Collection event. + * @protected + */ +ol.renderer.Map.prototype.handleLayersRemove = function(collectionEvent) { + var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem); + this.removeLayer(layer); +}; + + +/** + * @param {ol.layer.Layer} layer Layer. + * @protected + */ +ol.renderer.Map.prototype.removeLayer = function(layer) { + goog.dispose(this.removeLayerRenderer(layer)); +}; + + +/** + * @param {ol.layer.Layer} layer Layer. + * @return {ol.renderer.Layer} Layer renderer. + * @protected + */ +ol.renderer.Map.prototype.removeLayerRenderer = function(layer) { + var layerKey = goog.getUid(layer); + if (layerKey in this.layerRenderers) { + var layerRenderer = this.layerRenderers[layerKey]; + delete this.layerRenderers[layerKey]; + goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); + delete this.layerRendererChangeListenKeys_[layerKey]; + return layerRenderer; + } else { + return null; + } +}; + + +/** + * Render. + * @param {?ol.FrameState} frameState Frame state. + */ +ol.renderer.Map.prototype.renderFrame = goog.nullFunction; + + +/** + * @param {ol.layer.Layer} layer Layer. + * @param {ol.renderer.Layer} layerRenderer Layer renderer. + * @protected + */ +ol.renderer.Map.prototype.setLayerRenderer = function(layer, layerRenderer) { + var layerKey = goog.getUid(layer); + goog.asserts.assert(!(layerKey in this.layerRenderers)); + this.layerRenderers[layerKey] = layerRenderer; + goog.asserts.assert(!(layerKey in this.layerRendererChangeListenKeys_)); + this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( + layerRenderer, goog.events.EventType.CHANGE, + this.handleLayerRendererChange, false, this); +}; diff --git a/master/ol/ol/renderer/webgl/shader.js b/master/ol/ol/renderer/webgl/shader.js new file mode 100644 index 0000000000..e425155641 --- /dev/null +++ b/master/ol/ol/renderer/webgl/shader.js @@ -0,0 +1,81 @@ +goog.provide('ol.renderer.webgl.FragmentShader'); +goog.provide('ol.renderer.webgl.VertexShader'); + +goog.require('goog.functions'); +goog.require('goog.webgl'); + + + +/** + * @constructor + * @param {string} source Source. + */ +ol.renderer.webgl.Shader = function(source) { + + /** + * @private + * @type {string} + */ + this.source_ = source; + +}; + + +/** + * @return {number} Type. + */ +ol.renderer.webgl.Shader.prototype.getType = goog.abstractMethod; + + +/** + * @return {string} Source. + */ +ol.renderer.webgl.Shader.prototype.getSource = function() { + return this.source_; +}; + + +/** + * @return {boolean} Is animated? + */ +ol.renderer.webgl.Shader.prototype.isAnimated = goog.functions.FALSE; + + + +/** + * @constructor + * @extends {ol.renderer.webgl.Shader} + * @param {string} source Source. + */ +ol.renderer.webgl.FragmentShader = function(source) { + goog.base(this, source); +}; +goog.inherits(ol.renderer.webgl.FragmentShader, ol.renderer.webgl.Shader); + + +/** + * @inheritDoc + */ +ol.renderer.webgl.FragmentShader.prototype.getType = function() { + return goog.webgl.FRAGMENT_SHADER; +}; + + + +/** + * @constructor + * @extends {ol.renderer.webgl.Shader} + * @param {string} source Source. + */ +ol.renderer.webgl.VertexShader = function(source) { + goog.base(this, source); +}; +goog.inherits(ol.renderer.webgl.VertexShader, ol.renderer.webgl.Shader); + + +/** + * @inheritDoc + */ +ol.renderer.webgl.VertexShader.prototype.getType = function() { + return goog.webgl.VERTEX_SHADER; +}; diff --git a/master/ol/ol/renderer/webgl/webglimagelayerrenderer.js b/master/ol/ol/renderer/webgl/webglimagelayerrenderer.js new file mode 100644 index 0000000000..46d2246c85 --- /dev/null +++ b/master/ol/ol/renderer/webgl/webglimagelayerrenderer.js @@ -0,0 +1,237 @@ +goog.provide('ol.renderer.webgl.ImageLayer'); + +goog.require('goog.vec.Mat4'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.Image'); +goog.require('ol.ImageState'); +goog.require('ol.ViewHint'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.renderer.webgl.Layer'); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.ImageLayer} imageLayer Tile layer. + */ +ol.renderer.webgl.ImageLayer = function(mapRenderer, imageLayer) { + + goog.base(this, mapRenderer, imageLayer); + + /** + * The last rendered image. + * @private + * @type {?ol.Image} + */ + this.image_ = null; + + /** + * The last rendered texture. + * @private + * @type {WebGLTexture} + */ + this.texture_ = null; + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.texCoordMatrix_ = goog.vec.Mat4.createNumberIdentity(); + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.projectionMatrix_ = goog.vec.Mat4.createNumber(); + +}; +goog.inherits(ol.renderer.webgl.ImageLayer, ol.renderer.webgl.Layer); + + +/** + * @private + * @param {ol.Image} image Image. + * @return {WebGLTexture} Texture. + */ +ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) { + + // We meet the conditions to work with non-power of two textures. + // http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences#Non-Power_of_Two_Texture_Support + // http://learningwebgl.com/blog/?p=2101 + + var imageElement = image.getImageElement(this); + var gl = this.getMapRenderer().getGL(); + + var texture = gl.createTexture(); + + gl.bindTexture(goog.webgl.TEXTURE_2D, texture); + gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA, + goog.webgl.RGBA, goog.webgl.UNSIGNED_BYTE, imageElement); + + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_S, + goog.webgl.CLAMP_TO_EDGE); + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_T, + goog.webgl.CLAMP_TO_EDGE); + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MIN_FILTER, goog.webgl.LINEAR); + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, goog.webgl.LINEAR); + + return texture; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.disposeInternal = function() { + var mapRenderer = this.getMapRenderer(); + var gl = mapRenderer.getGL(); + if (!gl.isContextLost()) { + gl.deleteTexture(this.texture_); + } + goog.base(this, 'disposeInternal'); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.getTexCoordMatrix = function() { + return this.texCoordMatrix_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.getTexture = function() { + return this.texture_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.getProjectionMatrix = function() { + return this.projectionMatrix_; +}; + + +/** + * @return {ol.layer.ImageLayer} Tile layer. + */ +ol.renderer.webgl.ImageLayer.prototype.getImageLayer = function() { + return /** @type {ol.layer.ImageLayer} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.handleWebGLContextLost = function() { + this.texture_ = null; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.renderFrame = + function(frameState, layerState) { + + var gl = this.getMapRenderer().getGL(); + + var view2DState = frameState.view2DState; + var viewCenter = view2DState.center; + var viewResolution = view2DState.resolution; + var viewRotation = view2DState.rotation; + + var image = this.image_; + var texture = this.texture_; + var imageLayer = this.getImageLayer(); + var imageSource = imageLayer.getImageSource(); + + var hints = frameState.viewHints; + + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { + var image_ = imageSource.getImage( + frameState.extent, viewResolution, view2DState.projection); + if (!goog.isNull(image_)) { + var imageState = image_.getState(); + if (imageState == ol.ImageState.IDLE) { + goog.events.listenOnce(image_, goog.events.EventType.CHANGE, + this.handleImageChange, false, this); + image_.load(); + } else if (imageState == ol.ImageState.LOADED) { + image = image_; + texture = this.createTexture_(image_); + if (!goog.isNull(this.texture_)) { + frameState.postRenderFunctions.push( + goog.partial(function(gl, texture) { + if (!gl.isContextLost()) { + gl.deleteTexture(texture); + } + }, gl, this.texture_)); + } + } + } + } + + if (!goog.isNull(image)) { + goog.asserts.assert(!goog.isNull(texture)); + + var canvas = this.getMapRenderer().getCanvas(); + + this.updateProjectionMatrix_(canvas.width, canvas.height, + viewCenter, viewResolution, viewRotation, image.getExtent()); + + // Translate and scale to flip the Y coord. + var texCoordMatrix = this.texCoordMatrix_; + goog.vec.Mat4.makeIdentity(texCoordMatrix); + goog.vec.Mat4.scale(texCoordMatrix, 1, -1, 1); + goog.vec.Mat4.translate(texCoordMatrix, 0, -1, 0); + + this.image_ = image; + this.texture_ = texture; + + this.updateAttributions(frameState.attributions, image.getAttributions()); + } +}; + + +/** + * @private + * @param {number} canvasWidth Canvas width. + * @param {number} canvasHeight Canvas height. + * @param {ol.Coordinate} viewCenter View center. + * @param {number} viewResolution View resolution. + * @param {number} viewRotation View rotation. + * @param {ol.Extent} imageExtent Image extent. + */ +ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = + function(canvasWidth, canvasHeight, viewCenter, + viewResolution, viewRotation, imageExtent) { + + var canvasExtentWidth = canvasWidth * viewResolution; + var canvasExtentHeight = canvasHeight * viewResolution; + + var projectionMatrix = this.projectionMatrix_; + goog.vec.Mat4.makeIdentity(projectionMatrix); + goog.vec.Mat4.scale(projectionMatrix, + 2 / canvasExtentWidth, 2 / canvasExtentHeight, 1); + goog.vec.Mat4.rotateZ(projectionMatrix, -viewRotation); + goog.vec.Mat4.translate(projectionMatrix, + imageExtent.minX - viewCenter.x, + imageExtent.minY - viewCenter.y, + 0); + goog.vec.Mat4.scale(projectionMatrix, + imageExtent.getWidth() / 2, imageExtent.getHeight() / 2, 1); + goog.vec.Mat4.translate(projectionMatrix, 1, 1, 0); + +}; diff --git a/master/ol/ol/renderer/webgl/webgllayerrenderer.js b/master/ol/ol/renderer/webgl/webgllayerrenderer.js new file mode 100644 index 0000000000..7199246d4b --- /dev/null +++ b/master/ol/ol/renderer/webgl/webgllayerrenderer.js @@ -0,0 +1,167 @@ +// FIXME move colorMatrix_ elsewhere? + +goog.provide('ol.renderer.webgl.Layer'); + +goog.require('goog.vec.Mat4'); +goog.require('ol.layer.Layer'); +goog.require('ol.renderer.Layer'); +goog.require('ol.vec.Mat4'); + + + +/** + * @constructor + * @extends {ol.renderer.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.Layer} layer Layer. + */ +ol.renderer.webgl.Layer = function(mapRenderer, layer) { + + goog.base(this, mapRenderer, layer); + + /** + * @private + * @type {!goog.vec.Mat4.Float32} + */ + this.brightnessMatrix_ = goog.vec.Mat4.createFloat32(); + + /** + * @private + * @type {!goog.vec.Mat4.Float32} + */ + this.contrastMatrix_ = goog.vec.Mat4.createFloat32(); + + /** + * @private + * @type {!goog.vec.Mat4.Float32} + */ + this.hueMatrix_ = goog.vec.Mat4.createFloat32(); + + /** + * @private + * @type {!goog.vec.Mat4.Float32} + */ + this.saturationMatrix_ = goog.vec.Mat4.createFloat32(); + + /** + * @private + * @type {!goog.vec.Mat4.Float32} + */ + this.colorMatrix_ = goog.vec.Mat4.createFloat32(); + + /** + * @private + * @type {boolean} + */ + this.colorMatrixDirty_ = true; + + this.handleLayerBrightnessChange(); + this.handleLayerContrastChange(); + this.handleLayerHueChange(); + this.handleLayerSaturationChange(); + +}; +goog.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer); + + +/** + * @return {!goog.vec.Mat4.Float32} Color matrix. + */ +ol.renderer.webgl.Layer.prototype.getColorMatrix = function() { + if (this.colorMatrixDirty_) { + this.updateColorMatrix_(); + } + return this.colorMatrix_; +}; + + +/** + * @inheritDoc + * @return {ol.renderer.Map} MapRenderer. + */ +ol.renderer.webgl.Layer.prototype.getMapRenderer = function() { + return /** @type {ol.renderer.webgl.Map} */ (goog.base( + this, 'getMapRenderer')); +}; + + +/** + * @return {!goog.vec.Mat4.Number} Matrix. + */ +ol.renderer.webgl.Layer.prototype.getTexCoordMatrix = goog.abstractMethod; + + +/** + * @return {WebGLTexture} Texture. + */ +ol.renderer.webgl.Layer.prototype.getTexture = goog.abstractMethod; + + +/** + * @return {!goog.vec.Mat4.Number} Matrix. + */ +ol.renderer.webgl.Layer.prototype.getProjectionMatrix = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Layer.prototype.handleLayerBrightnessChange = function() { + var value = this.getLayer().getBrightness(); + ol.vec.Mat4.makeBrightness(this.brightnessMatrix_, value); + this.colorMatrixDirty_ = true; + this.dispatchChangeEvent(); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Layer.prototype.handleLayerContrastChange = function() { + var value = this.getLayer().getContrast(); + ol.vec.Mat4.makeContrast(this.contrastMatrix_, value); + this.colorMatrixDirty_ = true; + this.dispatchChangeEvent(); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Layer.prototype.handleLayerHueChange = function() { + var value = this.getLayer().getHue(); + ol.vec.Mat4.makeHue(this.hueMatrix_, value); + this.colorMatrixDirty_ = true; + this.dispatchChangeEvent(); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Layer.prototype.handleLayerSaturationChange = function() { + var saturation = this.getLayer().getSaturation(); + ol.vec.Mat4.makeSaturation(this.saturationMatrix_, saturation); + this.colorMatrixDirty_ = true; + this.dispatchChangeEvent(); +}; + + +/** + * Handle webglcontextlost. + */ +ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = goog.nullFunction; + + +/** + * @private + */ +ol.renderer.webgl.Layer.prototype.updateColorMatrix_ = function() { + var colorMatrix = this.colorMatrix_; + goog.vec.Mat4.makeIdentity(colorMatrix); + goog.vec.Mat4.multMat(colorMatrix, this.contrastMatrix_, colorMatrix); + goog.vec.Mat4.multMat(colorMatrix, this.brightnessMatrix_, colorMatrix); + goog.vec.Mat4.multMat(colorMatrix, this.saturationMatrix_, colorMatrix); + goog.vec.Mat4.multMat(colorMatrix, this.hueMatrix_, colorMatrix); + this.colorMatrixDirty_ = false; +}; diff --git a/master/ol/ol/renderer/webgl/webglmaprenderer.js b/master/ol/ol/renderer/webgl/webglmaprenderer.js new file mode 100644 index 0000000000..867c2c3d2a --- /dev/null +++ b/master/ol/ol/renderer/webgl/webglmaprenderer.js @@ -0,0 +1,588 @@ +// FIXME check against gl.getParameter(webgl.MAX_TEXTURE_SIZE) + +goog.provide('ol.renderer.webgl.Map'); +goog.provide('ol.renderer.webgl.map.shader'); + +goog.require('goog.array'); +goog.require('goog.debug.Logger'); +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.events.Event'); +goog.require('goog.style'); +goog.require('goog.webgl'); +goog.require('ol.FrameState'); +goog.require('ol.Size'); +goog.require('ol.Tile'); +goog.require('ol.layer.ImageLayer'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.renderer.Map'); +goog.require('ol.renderer.webgl.FragmentShader'); +goog.require('ol.renderer.webgl.ImageLayer'); +goog.require('ol.renderer.webgl.TileLayer'); +goog.require('ol.renderer.webgl.VertexShader'); +goog.require('ol.structs.LRUCache'); +goog.require('ol.webgl'); +goog.require('ol.webgl.WebGLContextEventType'); + + +/** + * @define {number} Texture cache high water mark. + */ +ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK = 1024; + + +/** + * @typedef {{magFilter: number, minFilter: number, texture: WebGLTexture}} + */ +ol.renderer.webgl.TextureCacheEntry; + + + +/** + * @constructor + * @extends {ol.renderer.webgl.FragmentShader} + * @see https://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.cpp + */ +ol.renderer.webgl.map.shader.Fragment = function() { + goog.base(this, [ + 'precision mediump float;', + '', + 'uniform mat4 u_colorMatrix;', + 'uniform float u_opacity;', + 'uniform sampler2D u_texture;', + '', + 'varying vec2 v_texCoord;', + '', + 'void main(void) {', + '', + ' vec4 texColor = texture2D(u_texture, v_texCoord);', + ' vec4 color = u_colorMatrix * vec4(texColor.rgb, 1.);', + ' color.a = texColor.a * u_opacity;', + '', + ' gl_FragColor = color;', + '', + '}' + ].join('\n')); +}; +goog.inherits( + ol.renderer.webgl.map.shader.Fragment, ol.renderer.webgl.FragmentShader); +goog.addSingletonGetter(ol.renderer.webgl.map.shader.Fragment); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.VertexShader} + */ +ol.renderer.webgl.map.shader.Vertex = function() { + goog.base(this, [ + 'attribute vec2 a_position;', + 'attribute vec2 a_texCoord;', + '', + 'uniform mat4 u_texCoordMatrix;', + 'uniform mat4 u_projectionMatrix;', + '', + 'varying vec2 v_texCoord;', + '', + 'void main(void) {', + ' gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.);', + ' v_texCoord = (u_texCoordMatrix * vec4(a_texCoord, 0., 1.)).st;', + '}' + ].join('\n')); +}; +goog.inherits( + ol.renderer.webgl.map.shader.Vertex, ol.renderer.webgl.VertexShader); +goog.addSingletonGetter(ol.renderer.webgl.map.shader.Vertex); + + + +/** + * @constructor + * @extends {ol.renderer.Map} + * @param {Element} container Container. + * @param {ol.Map} map Map. + */ +ol.renderer.webgl.Map = function(container, map) { + + goog.base(this, container, map); + + if (goog.DEBUG) { + /** + * @inheritDoc + */ + this.logger = goog.debug.Logger.getLogger( + 'ol.renderer.webgl.maprenderer.' + goog.getUid(this)); + } + + /** + * @private + * @type {Element} + */ + this.canvas_ = goog.dom.createElement(goog.dom.TagName.CANVAS); + this.canvas_.height = container.clientHeight; + this.canvas_.width = container.clientWidth; + this.canvas_.className = 'ol-unselectable'; + goog.dom.insertChildAt(container, this.canvas_, 0); + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + + /** + * @private + * @type {ol.Size} + */ + this.canvasSize_ = new ol.Size(container.clientHeight, container.clientWidth); + + /** + * @private + * @type {WebGLRenderingContext} + */ + this.gl_ = ol.webgl.getContext(this.canvas_, { + alpha: false, + antialias: true, + depth: false, + preserveDrawingBuffer: false, + stencil: false + }); + goog.asserts.assert(!goog.isNull(this.gl_)); + + goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST, + this.handleWebGLContextLost, false, this); + goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED, + this.handleWebGLContextRestored, false, this); + + /** + * @private + * @type {{a_position: number, + * a_texCoord: number, + * u_colorMatrix: WebGLUniformLocation, + * u_opacity: WebGLUniformLocation, + * u_texture: WebGLUniformLocation, + * u_texCoordMatrix: WebGLUniformLocation, + * u_projectionMatrix: WebGLUniformLocation}|null} + */ + this.locations_ = null; + + /** + * @private + * @type {WebGLBuffer} + */ + this.arrayBuffer_ = null; + + /** + * @private + * @type {Object.} + */ + this.shaderCache_ = {}; + + /** + * @private + * @type {Object.} + */ + this.programCache_ = {}; + + /** + * @private + * @type {ol.structs.LRUCache} + */ + this.textureCache_ = new ol.structs.LRUCache(); + + /** + * @private + * @type {number} + */ + this.textureCacheFrameMarkerCount_ = 0; + + /** + * @private + * @type {ol.renderer.webgl.FragmentShader} + */ + this.fragmentShader_ = ol.renderer.webgl.map.shader.Fragment.getInstance(); + + /** + * @private + * @type {ol.renderer.webgl.VertexShader} + */ + this.vertexShader_ = ol.renderer.webgl.map.shader.Vertex.getInstance(); + + this.initializeGL_(); + +}; +goog.inherits(ol.renderer.webgl.Map, ol.renderer.Map); + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.addLayer = function(layer) { + goog.base(this, 'addLayer', layer); + if (layer.getVisible()) { + this.getMap().render(); + } +}; + + +/** + * @param {ol.Tile} tile Tile. + * @param {number} magFilter Mag filter. + * @param {number} minFilter Min filter. + */ +ol.renderer.webgl.Map.prototype.bindTileTexture = + function(tile, magFilter, minFilter) { + var gl = this.getGL(); + var tileKey = tile.getKey(); + if (this.textureCache_.containsKey(tileKey)) { + var textureCacheEntry = this.textureCache_.get(tileKey); + gl.bindTexture(goog.webgl.TEXTURE_2D, textureCacheEntry.texture); + if (textureCacheEntry.magFilter != magFilter) { + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, magFilter); + textureCacheEntry.magFilter = magFilter; + } + if (textureCacheEntry.minFilter != minFilter) { + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, minFilter); + textureCacheEntry.minFilter = minFilter; + } + } else { + var texture = gl.createTexture(); + gl.bindTexture(goog.webgl.TEXTURE_2D, texture); + gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA, goog.webgl.RGBA, + goog.webgl.UNSIGNED_BYTE, tile.getImage()); + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, magFilter); + gl.texParameteri( + goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_S, + goog.webgl.CLAMP_TO_EDGE); + gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_T, + goog.webgl.CLAMP_TO_EDGE); + this.textureCache_.set(tileKey, { + texture: texture, + magFilter: magFilter, + minFilter: minFilter + }); + } +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) { + var layerRenderer = null; + if (layer instanceof ol.layer.TileLayer) { + layerRenderer = new ol.renderer.webgl.TileLayer(this, layer); + } else if (layer instanceof ol.layer.ImageLayer) { + layerRenderer = new ol.renderer.webgl.ImageLayer(this, layer); + } else { + goog.asserts.assert(false); + } + return layerRenderer; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.disposeInternal = function() { + var gl = this.getGL(); + if (!gl.isContextLost()) { + goog.object.forEach(this.programCache_, function(program) { + gl.deleteProgram(program); + }); + goog.object.forEach(this.shaderCache_, function(shader) { + gl.deleteShader(shader); + }); + this.textureCache_.forEach(function(textureCacheEntry) { + if (!goog.isNull(textureCacheEntry)) { + gl.deleteTexture(textureCacheEntry.texture); + } + }); + } + goog.base(this, 'disposeInternal'); +}; + + +/** + * @param {ol.Map} map Map. + * @param {ol.FrameState} frameState Frame state. + * @private + */ +ol.renderer.webgl.Map.prototype.expireCache_ = function(map, frameState) { + var gl = this.getGL(); + var key, textureCacheEntry; + while (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ > + ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) { + textureCacheEntry = /** @type {?ol.renderer.webgl.TextureCacheEntry} */ + (this.textureCache_.peekLast()); + if (goog.isNull(textureCacheEntry)) { + if (+this.textureCache_.peekLastKey() == frameState.time) { + break; + } else { + --this.textureCacheFrameMarkerCount_; + } + } else { + gl.deleteTexture(textureCacheEntry.texture); + } + this.textureCache_.pop(); + } +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.getCanvas = function() { + return this.canvas_; +}; + + +/** + * @return {WebGLRenderingContext} GL. + */ +ol.renderer.webgl.Map.prototype.getGL = function() { + return this.gl_; +}; + + +/** + * @param {ol.renderer.webgl.FragmentShader} fragmentShaderObject + * Fragment shader. + * @param {ol.renderer.webgl.VertexShader} vertexShaderObject Vertex shader. + * @return {WebGLProgram} Program. + */ +ol.renderer.webgl.Map.prototype.getProgram = function( + fragmentShaderObject, vertexShaderObject) { + var programKey = + goog.getUid(fragmentShaderObject) + '/' + goog.getUid(vertexShaderObject); + if (programKey in this.programCache_) { + return this.programCache_[programKey]; + } else { + var gl = this.getGL(); + var program = gl.createProgram(); + gl.attachShader(program, this.getShader(fragmentShaderObject)); + gl.attachShader(program, this.getShader(vertexShaderObject)); + gl.linkProgram(program); + if (goog.DEBUG) { + if (!gl.getProgramParameter(program, goog.webgl.LINK_STATUS) && + !gl.isContextLost()) { + this.logger.severe(gl.getProgramInfoLog(program)); + goog.asserts.assert( + gl.getProgramParameter(program, goog.webgl.LINK_STATUS)); + } + } + this.programCache_[programKey] = program; + return program; + } +}; + + +/** + * @param {ol.renderer.webgl.Shader} shaderObject Shader object. + * @return {WebGLShader} Shader. + */ +ol.renderer.webgl.Map.prototype.getShader = function(shaderObject) { + var shaderKey = goog.getUid(shaderObject); + if (shaderKey in this.shaderCache_) { + return this.shaderCache_[shaderKey]; + } else { + var gl = this.getGL(); + var shader = gl.createShader(shaderObject.getType()); + gl.shaderSource(shader, shaderObject.getSource()); + gl.compileShader(shader); + if (goog.DEBUG) { + if (!gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS) && + !gl.isContextLost()) { + this.logger.severe(gl.getShaderInfoLog(shader)); + goog.asserts.assert( + gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS)); + } + } + this.shaderCache_[shaderKey] = shader; + return shader; + } +}; + + +/** + * @param {goog.events.Event} event Event. + * @protected + */ +ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) { + if (goog.DEBUG) { + this.logger.info('WebGLContextLost'); + } + event.preventDefault(); + this.locations_ = null; + this.arrayBuffer_ = null; + this.shaderCache_ = {}; + this.programCache_ = {}; + this.textureCache_.clear(); + this.textureCacheFrameMarkerCount_ = 0; + goog.object.forEach(this.layerRenderers, function(layerRenderer) { + layerRenderer.handleWebGLContextLost(); + }); +}; + + +/** + * @protected + */ +ol.renderer.webgl.Map.prototype.handleWebGLContextRestored = function() { + if (goog.DEBUG) { + this.logger.info('WebGLContextRestored'); + } + this.initializeGL_(); + this.getMap().render(); +}; + + +/** + * @private + */ +ol.renderer.webgl.Map.prototype.initializeGL_ = function() { + var gl = this.gl_; + gl.activeTexture(goog.webgl.TEXTURE0); + gl.blendFunc(goog.webgl.SRC_ALPHA, goog.webgl.ONE_MINUS_SRC_ALPHA); + gl.disable(goog.webgl.CULL_FACE); + gl.disable(goog.webgl.DEPTH_TEST); + gl.disable(goog.webgl.SCISSOR_TEST); +}; + + +/** + * @param {ol.Tile} tile Tile. + * @return {boolean} Is tile texture loaded. + */ +ol.renderer.webgl.Map.prototype.isTileTextureLoaded = function(tile) { + return this.textureCache_.containsKey(tile.getKey()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.removeLayer = function(layer) { + goog.base(this, 'removeLayer', layer); + if (layer.getVisible()) { + this.getMap().render(); + } +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) { + + var gl = this.getGL(); + + if (goog.isNull(frameState)) { + if (this.renderedVisible_) { + goog.style.showElement(this.canvas_, false); + this.renderedVisible_ = false; + } + return false; + } + + this.textureCache_.set(frameState.time.toString(), null); + ++this.textureCacheFrameMarkerCount_; + + goog.array.forEach(frameState.layersArray, function(layer) { + var layerState = frameState.layerStates[goog.getUid(layer)]; + if (!layerState.visible || !layerState.ready) { + return; + } + var layerRenderer = this.getLayerRenderer(layer); + layerRenderer.renderFrame(frameState, layerState); + }, this); + + var size = frameState.size; + if (!this.canvasSize_.equals(size)) { + this.canvas_.width = size.width; + this.canvas_.height = size.height; + this.canvasSize_ = size; + } + + gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, null); + + var clearColor = frameState.backgroundColor; + gl.clearColor(clearColor.r / 255, clearColor.g / 255, + clearColor.b / 255, clearColor.a); + gl.clear(goog.webgl.COLOR_BUFFER_BIT); + gl.enable(goog.webgl.BLEND); + gl.viewport(0, 0, size.width, size.height); + + var program = this.getProgram(this.fragmentShader_, this.vertexShader_); + gl.useProgram(program); + if (goog.isNull(this.locations_)) { + this.locations_ = { + a_position: gl.getAttribLocation(program, 'a_position'), + a_texCoord: gl.getAttribLocation(program, 'a_texCoord'), + u_colorMatrix: gl.getUniformLocation(program, 'u_colorMatrix'), + u_texCoordMatrix: gl.getUniformLocation(program, 'u_texCoordMatrix'), + u_projectionMatrix: gl.getUniformLocation(program, 'u_projectionMatrix'), + u_opacity: gl.getUniformLocation(program, 'u_opacity'), + u_texture: gl.getUniformLocation(program, 'u_texture') + }; + } + + if (goog.isNull(this.arrayBuffer_)) { + var arrayBuffer = gl.createBuffer(); + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, arrayBuffer); + gl.bufferData(goog.webgl.ARRAY_BUFFER, new Float32Array([ + -1, -1, 0, 0, + 1, -1, 1, 0, + -1, 1, 0, 1, + 1, 1, 1, 1 + ]), goog.webgl.STATIC_DRAW); + this.arrayBuffer_ = arrayBuffer; + } else { + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_); + } + + gl.enableVertexAttribArray(this.locations_.a_position); + gl.vertexAttribPointer( + this.locations_.a_position, 2, goog.webgl.FLOAT, false, 16, 0); + gl.enableVertexAttribArray(this.locations_.a_texCoord); + gl.vertexAttribPointer( + this.locations_.a_texCoord, 2, goog.webgl.FLOAT, false, 16, 8); + gl.uniform1i(this.locations_.u_texture, 0); + + goog.array.forEach(frameState.layersArray, function(layer) { + var layerState = frameState.layerStates[goog.getUid(layer)]; + if (!layerState.visible || !layerState.ready) { + return; + } + var layerRenderer = this.getLayerRenderer(layer); + gl.uniformMatrix4fv( + this.locations_.u_texCoordMatrix, false, + layerRenderer.getTexCoordMatrix()); + gl.uniformMatrix4fv( + this.locations_.u_projectionMatrix, false, + layerRenderer.getProjectionMatrix()); + gl.uniformMatrix4fv( + this.locations_.u_colorMatrix, false, layerRenderer.getColorMatrix()); + gl.uniform1f(this.locations_.u_opacity, layer.getOpacity()); + gl.bindTexture(goog.webgl.TEXTURE_2D, layerRenderer.getTexture()); + gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4); + }, this); + + if (!this.renderedVisible_) { + goog.style.showElement(this.canvas_, true); + this.renderedVisible_ = true; + } + + this.calculateMatrices2D(frameState); + + if (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ > + ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) { + frameState.postRenderFunctions.push(goog.bind(this.expireCache_, this)); + } + +}; diff --git a/master/ol/ol/renderer/webgl/webglrenderer.js b/master/ol/ol/renderer/webgl/webglrenderer.js new file mode 100644 index 0000000000..7dc4f06f25 --- /dev/null +++ b/master/ol/ol/renderer/webgl/webglrenderer.js @@ -0,0 +1,10 @@ +goog.provide('ol.renderer.webgl.SUPPORTED'); + +goog.require('ol.webgl'); + + +/** + * @const + * @type {boolean} Is supported. + */ +ol.renderer.webgl.SUPPORTED = ol.webgl.SUPPORTED; diff --git a/master/ol/ol/renderer/webgl/webgltilelayerrenderer.js b/master/ol/ol/renderer/webgl/webgltilelayerrenderer.js new file mode 100644 index 0000000000..2c6fcae043 --- /dev/null +++ b/master/ol/ol/renderer/webgl/webgltilelayerrenderer.js @@ -0,0 +1,485 @@ +// FIXME large resolutions lead to too large framebuffers :-( +// FIXME animated shaders! check in redraw + +goog.provide('ol.renderer.webgl.TileLayer'); +goog.provide('ol.renderer.webgl.tilelayerrenderer'); +goog.provide('ol.renderer.webgl.tilelayerrenderer.shader.Fragment'); +goog.provide('ol.renderer.webgl.tilelayerrenderer.shader.Vertex'); + +goog.require('goog.array'); +goog.require('goog.object'); +goog.require('goog.structs.PriorityQueue'); +goog.require('goog.vec.Mat4'); +goog.require('goog.vec.Vec4'); +goog.require('goog.webgl'); +goog.require('ol.Extent'); +goog.require('ol.FrameState'); +goog.require('ol.Size'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); +goog.require('ol.TileState'); +goog.require('ol.layer.TileLayer'); +goog.require('ol.renderer.webgl.FragmentShader'); +goog.require('ol.renderer.webgl.Layer'); +goog.require('ol.renderer.webgl.VertexShader'); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.FragmentShader} + */ +ol.renderer.webgl.tilelayerrenderer.shader.Fragment = function() { + goog.base(this, [ + 'precision mediump float;', + '', + 'uniform sampler2D uTexture;', + '', + 'varying vec2 vTexCoord;', + '', + 'void main(void) {', + ' gl_FragColor = texture2D(uTexture, vTexCoord);', + '}' + ].join('\n')); +}; +goog.inherits( + ol.renderer.webgl.tilelayerrenderer.shader.Fragment, + ol.renderer.webgl.FragmentShader); +goog.addSingletonGetter(ol.renderer.webgl.tilelayerrenderer.shader.Fragment); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.VertexShader} + */ +ol.renderer.webgl.tilelayerrenderer.shader.Vertex = function() { + goog.base(this, [ + 'attribute vec2 aPosition;', + 'attribute vec2 aTexCoord;', + '', + 'varying vec2 vTexCoord;', + '', + 'uniform vec4 uTileOffset;', + '', + 'void main(void) {', + ' gl_Position.xy = aPosition * uTileOffset.xy + uTileOffset.zw;', + ' gl_Position.z = 0.;', + ' gl_Position.w = 1.;', + ' vTexCoord = aTexCoord;', + '}' + ].join('\n')); +}; +goog.inherits( + ol.renderer.webgl.tilelayerrenderer.shader.Vertex, + ol.renderer.webgl.VertexShader); +goog.addSingletonGetter(ol.renderer.webgl.tilelayerrenderer.shader.Vertex); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.TileLayer} tileLayer Tile layer. + */ +ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) { + + goog.base(this, mapRenderer, tileLayer); + + /** + * @private + * @type {ol.renderer.webgl.FragmentShader} + */ + this.fragmentShader_ = + ol.renderer.webgl.tilelayerrenderer.shader.Fragment.getInstance(); + + /** + * @private + * @type {ol.renderer.webgl.VertexShader} + */ + this.vertexShader_ = + ol.renderer.webgl.tilelayerrenderer.shader.Vertex.getInstance(); + + /** + * @private + * @type {{aPosition: number, + * aTexCoord: number, + * uTileOffset: WebGLUniformLocation, + * uTexture: WebGLUniformLocation}|null} + */ + this.locations_ = null; + + /** + * @private + * @type {WebGLBuffer} + */ + this.arrayBuffer_ = null; + + /** + * @private + * @type {WebGLTexture} + */ + this.texture_ = null; + + /** + * @private + * @type {WebGLFramebuffer} + */ + this.framebuffer_ = null; + + /** + * @private + * @type {number|undefined} + */ + this.framebufferDimension_ = undefined; + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.texCoordMatrix_ = goog.vec.Mat4.createNumber(); + + /** + * @private + * @type {!goog.vec.Mat4.Number} + */ + this.projectionMatrix_ = goog.vec.Mat4.createNumberIdentity(); + + /** + * @private + * @type {ol.TileRange} + */ + this.renderedTileRange_ = null; + + /** + * @private + * @type {ol.Extent} + */ + this.renderedFramebufferExtent_ = null; + +}; +goog.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer); + + +/** + * @param {ol.FrameState} frameState Frame state. + * @param {number} framebufferDimension Framebuffer dimension. + * @private + */ +ol.renderer.webgl.TileLayer.prototype.bindFramebuffer_ = + function(frameState, framebufferDimension) { + + var mapRenderer = this.getMapRenderer(); + var gl = mapRenderer.getGL(); + + if (!goog.isDef(this.framebufferDimension_) || + this.framebufferDimension_ != framebufferDimension) { + + var map = this.getMap(); + frameState.postRenderFunctions.push( + goog.partial(function(gl, framebuffer, texture) { + if (!gl.isContextLost()) { + gl.deleteFramebuffer(framebuffer); + gl.deleteTexture(texture); + } + }, gl, this.framebuffer_, this.texture_)); + + var texture = gl.createTexture(); + gl.bindTexture(goog.webgl.TEXTURE_2D, texture); + gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA, + framebufferDimension, framebufferDimension, 0, goog.webgl.RGBA, + goog.webgl.UNSIGNED_BYTE, null); + gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, + goog.webgl.LINEAR); + gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MIN_FILTER, + goog.webgl.LINEAR); + + var framebuffer = gl.createFramebuffer(); + gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, framebuffer); + gl.framebufferTexture2D(goog.webgl.FRAMEBUFFER, + goog.webgl.COLOR_ATTACHMENT0, goog.webgl.TEXTURE_2D, texture, 0); + + this.texture_ = texture; + this.framebuffer_ = framebuffer; + this.framebufferDimension_ = framebufferDimension; + + } else { + gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, this.framebuffer_); + } + +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() { + var mapRenderer = this.getMapRenderer(); + var gl = mapRenderer.getGL(); + if (!gl.isContextLost()) { + gl.deleteBuffer(this.arrayBuffer_); + gl.deleteFramebuffer(this.framebuffer_); + gl.deleteTexture(this.texture_); + } + goog.base(this, 'disposeInternal'); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.getTexCoordMatrix = function() { + return this.texCoordMatrix_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.getTexture = function() { + return this.texture_; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.getProjectionMatrix = function() { + return this.projectionMatrix_; +}; + + +/** + * @return {ol.layer.TileLayer} Tile layer. + */ +ol.renderer.webgl.TileLayer.prototype.getTileLayer = function() { + return /** @type {ol.layer.TileLayer} */ (this.getLayer()); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() { + this.locations_ = null; + this.arrayBuffer_ = null; + this.texture_ = null; + this.framebuffer_ = null; + this.framebufferDimension_ = undefined; +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.renderFrame = + function(frameState, layerState) { + + var mapRenderer = this.getMapRenderer(); + var gl = mapRenderer.getGL(); + + var view2DState = frameState.view2DState; + var projection = view2DState.projection; + var center = view2DState.center; + + var tileLayer = this.getTileLayer(); + var tileSource = tileLayer.getTileSource(); + var tileSourceKey = goog.getUid(tileSource).toString(); + var tileGrid = tileSource.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } + var z = tileGrid.getZForResolution(view2DState.resolution); + var tileResolution = tileGrid.getResolution(z); + var tileRange = tileGrid.getTileRangeForExtentAndResolution( + frameState.extent, tileResolution); + + var framebufferExtent; + if (!goog.isNull(this.renderedTileRange_) && + this.renderedTileRange_.equals(tileRange)) { + framebufferExtent = this.renderedFramebufferExtent_; + } else { + + var tileRangeSize = tileRange.getSize(); + var tileSize = tileGrid.getTileSize(z); + + var maxDimension = Math.max( + tileRangeSize.width * tileSize.width, + tileRangeSize.height * tileSize.height); + var framebufferDimension = + Math.pow(2, Math.ceil(Math.log(maxDimension) / Math.log(2))); + var framebufferExtentSize = new ol.Size( + tileResolution * framebufferDimension, + tileResolution * framebufferDimension); + var origin = tileGrid.getOrigin(z); + var minX = origin.x + tileRange.minX * tileSize.width * tileResolution; + var minY = origin.y + tileRange.minY * tileSize.height * tileResolution; + framebufferExtent = new ol.Extent( + minX, + minY, + minX + framebufferExtentSize.width, + minY + framebufferExtentSize.height); + + this.bindFramebuffer_(frameState, framebufferDimension); + gl.viewport(0, 0, framebufferDimension, framebufferDimension); + + gl.clearColor(0, 0, 0, 0); + gl.clear(goog.webgl.COLOR_BUFFER_BIT); + gl.disable(goog.webgl.BLEND); + + var program = mapRenderer.getProgram( + this.fragmentShader_, this.vertexShader_); + gl.useProgram(program); + if (goog.isNull(this.locations_)) { + this.locations_ = { + aPosition: gl.getAttribLocation(program, 'aPosition'), + aTexCoord: gl.getAttribLocation(program, 'aTexCoord'), + uTileOffset: gl.getUniformLocation(program, 'uTileOffset'), + uTexture: gl.getUniformLocation(program, 'uTexture') + }; + } + + if (goog.isNull(this.arrayBuffer_)) { + var arrayBuffer = gl.createBuffer(); + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, arrayBuffer); + gl.bufferData(goog.webgl.ARRAY_BUFFER, new Float32Array([ + 0, 0, 0, 1, + 1, 0, 1, 1, + 0, 1, 0, 0, + 1, 1, 1, 0 + ]), goog.webgl.STATIC_DRAW); + this.arrayBuffer_ = arrayBuffer; + } else { + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_); + } + + gl.enableVertexAttribArray(this.locations_.aPosition); + gl.vertexAttribPointer( + this.locations_.aPosition, 2, goog.webgl.FLOAT, false, 16, 0); + gl.enableVertexAttribArray(this.locations_.aTexCoord); + gl.vertexAttribPointer( + this.locations_.aTexCoord, 2, goog.webgl.FLOAT, false, 16, 8); + gl.uniform1i(this.locations_.uTexture, 0); + + /** + * @type {Object.>} + */ + var tilesToDrawByZ = {}; + tilesToDrawByZ[z] = {}; + + var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { + return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED && + mapRenderer.isTileTextureLoaded(tile); + }, tileSource, tileGrid, projection); + var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, + tilesToDrawByZ, getTileIfLoaded); + + var tilesToLoad = new goog.structs.PriorityQueue(); + + var allTilesLoaded = true; + var deltaX, deltaY, priority, tile, tileCenter, tileCoord, tileState, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + + tileCoord = new ol.TileCoord(z, x, y); + tile = tileSource.getTile(tileCoord, tileGrid, projection); + tileState = tile.getState(); + if (tileState == ol.TileState.IDLE) { + this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); + } else if (tileState == ol.TileState.LOADING) { + this.listenToTileChange(tile); + } else if (tileState == ol.TileState.LOADED) { + if (mapRenderer.isTileTextureLoaded(tile)) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; + continue; + } else { + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + deltaX = tileCenter.x - center.x; + deltaY = tileCenter.y - center.y; + priority = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + tilesToLoad.enqueue(priority, tile); + } + } else if (tileState == ol.TileState.ERROR || + tileState == ol.TileState.EMPTY) { + continue; + } + + allTilesLoaded = false; + tileGrid.forEachTileCoordParentTileRange(tileCoord, findLoadedTiles); + + } + + } + + /** @type {Array.} */ + var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); + goog.array.sort(zs); + var uTileOffset = goog.vec.Vec4.createFloat32(); + goog.array.forEach(zs, function(z) { + goog.object.forEach(tilesToDrawByZ[z], function(tile) { + var tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord); + var sx = 2 * tileExtent.getWidth() / framebufferExtentSize.width; + var sy = 2 * tileExtent.getHeight() / framebufferExtentSize.height; + var tx = 2 * (tileExtent.minX - framebufferExtent.minX) / + framebufferExtentSize.width - 1; + var ty = 2 * (tileExtent.minY - framebufferExtent.minY) / + framebufferExtentSize.height - 1; + goog.vec.Vec4.setFromValues(uTileOffset, sx, sy, tx, ty); + gl.uniform4fv(this.locations_.uTileOffset, uTileOffset); + mapRenderer.bindTileTexture(tile, goog.webgl.LINEAR, goog.webgl.LINEAR); + gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4); + }, this); + }, this); + + if (!tilesToLoad.isEmpty()) { + frameState.postRenderFunctions.push( + goog.partial(function(mapRenderer, tilesToLoad) { + var i, tile; + // FIXME determine a suitable number of textures to upload per frame + for (i = 0; !tilesToLoad.isEmpty() && i < 4; ++i) { + tile = /** @type {ol.Tile} */ (tilesToLoad.remove()); + mapRenderer.bindTileTexture( + tile, goog.webgl.LINEAR, goog.webgl.LINEAR); + } + }, mapRenderer, tilesToLoad)); + } + + if (allTilesLoaded) { + this.renderedTileRange_ = tileRange; + this.renderedFramebufferExtent_ = framebufferExtent; + } else { + this.renderedTileRange_ = null; + this.renderedFramebufferExtent_ = null; + frameState.animate = true; + } + + } + + this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); + tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid); + this.scheduleExpireCache(frameState, tileSource); + + goog.vec.Mat4.makeIdentity(this.texCoordMatrix_); + goog.vec.Mat4.translate(this.texCoordMatrix_, + (view2DState.center.x - framebufferExtent.minX) / + (framebufferExtent.maxX - framebufferExtent.minX), + (view2DState.center.y - framebufferExtent.minY) / + (framebufferExtent.maxY - framebufferExtent.minY), + 0); + goog.vec.Mat4.rotateZ(this.texCoordMatrix_, view2DState.rotation); + goog.vec.Mat4.scale(this.texCoordMatrix_, + frameState.size.width * view2DState.resolution / + (framebufferExtent.maxX - framebufferExtent.minX), + frameState.size.height * view2DState.resolution / + (framebufferExtent.maxY - framebufferExtent.minY), + 1); + goog.vec.Mat4.translate(this.texCoordMatrix_, + -0.5, + -0.5, + 0); + +}; diff --git a/master/ol/ol/resolutionconstraint.js b/master/ol/ol/resolutionconstraint.js new file mode 100644 index 0000000000..5aa47625be --- /dev/null +++ b/master/ol/ol/resolutionconstraint.js @@ -0,0 +1,73 @@ +goog.provide('ol.ResolutionConstraint'); +goog.provide('ol.ResolutionConstraintType'); + +goog.require('goog.math'); +goog.require('ol.array'); + + +/** + * @typedef {function((number|undefined), number): (number|undefined)} + */ +ol.ResolutionConstraintType; + + +/** + * @param {number} power Power. + * @param {number} maxResolution Maximum resolution. + * @param {number=} opt_minResolution Minimum resolution. + * @return {ol.ResolutionConstraintType} Zoom function. + */ +ol.ResolutionConstraint.createContinuous = + function(power, maxResolution, opt_minResolution) { + var minResolution = opt_minResolution || 0; + return function(resolution, delta) { + if (goog.isDef(resolution)) { + resolution /= Math.pow(power, delta); + return goog.math.clamp(resolution, minResolution, maxResolution); + } else { + return undefined; + } + }; +}; + + +/** + * @param {Array.} resolutions Resolutions. + * @return {ol.ResolutionConstraintType} Zoom function. + */ +ol.ResolutionConstraint.createSnapToResolutions = + function(resolutions) { + return function(resolution, delta) { + if (goog.isDef(resolution)) { + var z = ol.array.linearFindNearest(resolutions, resolution); + z = goog.math.clamp(z + delta, 0, resolutions.length - 1); + return resolutions[z]; + } else { + return undefined; + } + }; +}; + + +/** + * @param {number} power Power. + * @param {number} maxResolution Maximum resolution. + * @param {number=} opt_maxLevel Maximum level. + * @return {ol.ResolutionConstraintType} Zoom function. + */ +ol.ResolutionConstraint.createSnapToPower = + function(power, maxResolution, opt_maxLevel) { + return function(resolution, delta) { + if (goog.isDef(resolution)) { + var oldLevel = Math.floor( + Math.log(maxResolution / resolution) / Math.log(power) + 0.5); + var newLevel = Math.max(oldLevel + delta, 0); + if (goog.isDef(opt_maxLevel)) { + newLevel = Math.min(newLevel, opt_maxLevel); + } + return maxResolution / Math.pow(power, newLevel); + } else { + return undefined; + } + }; +}; diff --git a/master/ol/ol/rotationconstraint.js b/master/ol/ol/rotationconstraint.js new file mode 100644 index 0000000000..c297e13608 --- /dev/null +++ b/master/ol/ol/rotationconstraint.js @@ -0,0 +1,59 @@ +goog.provide('ol.RotationConstraint'); +goog.provide('ol.RotationConstraintType'); + + +/** + * @typedef {function((number|undefined), number): (number|undefined)} + */ +ol.RotationConstraintType; + + +/** + * @param {number|undefined} rotation Rotation. + * @param {number} delta Delta. + * @return {number|undefined} Rotation. + */ +ol.RotationConstraint.none = function(rotation, delta) { + if (goog.isDef(rotation)) { + return rotation + delta; + } else { + return undefined; + } +}; + + +/** + * @param {number} n N. + * @return {ol.RotationConstraintType} Rotation constraint. + */ +ol.RotationConstraint.createSnapToN = function(n) { + var theta = 2 * Math.PI / n; + return function(rotation, delta) { + if (goog.isDef(rotation)) { + rotation = Math.floor((rotation + delta) / theta + 0.5) * theta; + return rotation; + } else { + return undefined; + } + }; +}; + + +/** + * @param {number=} opt_tolerance Tolerance. + * @return {ol.RotationConstraintType} Rotation constraint. + */ +ol.RotationConstraint.createSnapToZero = function(opt_tolerance) { + var tolerance = opt_tolerance || 0.1; + return function(rotation, delta) { + if (goog.isDef(rotation)) { + if (Math.abs(rotation + delta) <= tolerance) { + return 0; + } else { + return rotation + delta; + } + } else { + return undefined; + } + }; +}; diff --git a/master/ol/ol/size.js b/master/ol/ol/size.js new file mode 100644 index 0000000000..c751b14fae --- /dev/null +++ b/master/ol/ol/size.js @@ -0,0 +1,25 @@ +goog.provide('ol.Size'); + +goog.require('goog.math.Size'); + + + +/** + * @constructor + * @extends {goog.math.Size} + * @param {number} width Width. + * @param {number} height Height. + */ +ol.Size = function(width, height) { + goog.base(this, width, height); +}; +goog.inherits(ol.Size, goog.math.Size); + + +/** + * @param {ol.Size} size Size. + * @return {boolean} Equals. + */ +ol.Size.prototype.equals = function(size) { + return this.width == size.width && this.height == size.height; +}; diff --git a/master/ol/ol/source/bingmaps.exports b/master/ol/ol/source/bingmaps.exports new file mode 100644 index 0000000000..9f1a06157a --- /dev/null +++ b/master/ol/ol/source/bingmaps.exports @@ -0,0 +1 @@ +@exportClass ol.source.BingMaps ol.source.BingMapsOptions diff --git a/master/ol/ol/source/bingmapssource.js b/master/ol/ol/source/bingmapssource.js new file mode 100644 index 0000000000..82d668979a --- /dev/null +++ b/master/ol/ol/source/bingmapssource.js @@ -0,0 +1,158 @@ +goog.provide('ol.source.BingMaps'); + +goog.require('goog.Uri'); +goog.require('goog.array'); +goog.require('goog.net.Jsonp'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.Size'); +goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); +goog.require('ol.TileUrlFunction'); +goog.require('ol.projection'); +goog.require('ol.source.ImageTileSource'); +goog.require('ol.tilegrid.XYZ'); + + + +/** + * @constructor + * @extends {ol.source.ImageTileSource} + * @param {ol.source.BingMapsOptions} bingMapsOptions Bing Maps options. + */ +ol.source.BingMaps = function(bingMapsOptions) { + + goog.base(this, { + opaque: true, + projection: ol.projection.get('EPSG:3857') + }); + + /** + * @private + * @type {string} + */ + this.culture_ = goog.isDef(bingMapsOptions.culture) ? + bingMapsOptions.culture : 'en-us'; + + /** + * @private + * @type {boolean} + */ + this.ready_ = false; + + var uri = new goog.Uri( + '//dev.virtualearth.net/REST/v1/Imagery/Metadata/' + + bingMapsOptions.style); + var jsonp = new goog.net.Jsonp(uri, 'jsonp'); + jsonp.send({ + 'include': 'ImageryProviders', + 'key': bingMapsOptions.key + }, goog.bind(this.handleImageryMetadataResponse, this)); + +}; +goog.inherits(ol.source.BingMaps, ol.source.ImageTileSource); + + +/** + * @param {BingMapsImageryMetadataResponse} response Response. + */ +ol.source.BingMaps.prototype.handleImageryMetadataResponse = + function(response) { + + goog.asserts.assert( + response.authenticationResultCode == 'ValidCredentials'); + goog.asserts.assert(response.statusCode == 200); + goog.asserts.assert(response.statusDescription == 'OK'); + + var brandLogoUri = response.brandLogoUri; + var copyright = response.copyright; + goog.asserts.assert(response.resourceSets.length == 1); + var resourceSet = response.resourceSets[0]; + goog.asserts.assert(resourceSet.resources.length == 1); + var resource = resourceSet.resources[0]; + + var zoomMin = resource.zoomMin; + var zoomMax = resource.zoomMax; + var tileSize = new ol.Size(resource.imageWidth, resource.imageHeight); + var tileGrid = new ol.tilegrid.XYZ({ + maxZoom: zoomMax, + tileSize: tileSize + }); + this.tileGrid = tileGrid; + + this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( + function(tileCoord) { + if (tileCoord.z < zoomMin || zoomMax < tileCoord.z) { + return null; + } + var n = 1 << tileCoord.z; + var y = -tileCoord.y - 1; + if (y < 0 || n <= y) { + return null; + } else { + var x = goog.math.modulo(tileCoord.x, n); + return new ol.TileCoord(tileCoord.z, x, y); + } + }, + ol.TileUrlFunction.createFromTileUrlFunctions( + goog.array.map( + resource.imageUrlSubdomains, + function(subdomain) { + var imageUrl = resource.imageUrl + .replace('{subdomain}', subdomain) + .replace('{culture}', this.culture_); + return function(tileCoord) { + if (goog.isNull(tileCoord)) { + return undefined; + } else { + return imageUrl.replace( + '{quadkey}', tileCoord.quadKey()); + } + }; + }))); + + var transform = ol.projection.getTransformFromProjections( + ol.projection.get('EPSG:4326'), this.getProjection()); + var attributions = goog.array.map( + resource.imageryProviders, + function(imageryProvider) { + var html = imageryProvider.attribution; + /** @type {Object.>} */ + var tileRanges = {}; + goog.array.forEach( + imageryProvider.coverageAreas, + function(coverageArea) { + var minZ = coverageArea.zoomMin; + var maxZ = coverageArea.zoomMax; + var bbox = coverageArea.bbox; + var epsg4326Extent = + new ol.Extent(bbox[1], bbox[0], bbox[3], bbox[2]); + var extent = epsg4326Extent.transform(transform); + var tileRange, z, zKey; + for (z = minZ; z <= maxZ; ++z) { + zKey = z.toString(); + tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z); + if (zKey in tileRanges) { + tileRanges[zKey].push(tileRange); + } else { + tileRanges[zKey] = [tileRange]; + } + } + }); + return new ol.Attribution(html, tileRanges); + }); + this.setAttributions(attributions); + + this.ready_ = true; + + this.dispatchLoadEvent(); + +}; + + +/** + * @inheritDoc + */ +ol.source.BingMaps.prototype.isReady = function() { + return this.ready_; +}; diff --git a/master/ol/ol/source/debugtilesource.exports b/master/ol/ol/source/debugtilesource.exports new file mode 100644 index 0000000000..2c74b974f3 --- /dev/null +++ b/master/ol/ol/source/debugtilesource.exports @@ -0,0 +1 @@ +@exportClass ol.source.DebugTileSource ol.source.DebugTileSourceOptions diff --git a/master/ol/ol/source/debugtilesource.js b/master/ol/ol/source/debugtilesource.js new file mode 100644 index 0000000000..5b93fac9e5 --- /dev/null +++ b/master/ol/ol/source/debugtilesource.js @@ -0,0 +1,134 @@ +goog.provide('ol.source.DebugTileSource'); + +goog.require('ol.Size'); +goog.require('ol.Tile'); +goog.require('ol.TileCache'); +goog.require('ol.TileCoord'); +goog.require('ol.TileState'); +goog.require('ol.source.TileSource'); +goog.require('ol.tilegrid.TileGrid'); + + + +/** + * @constructor + * @extends {ol.Tile} + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. + * @private + */ +ol.DebugTile_ = function(tileCoord, tileGrid) { + + goog.base(this, tileCoord, ol.TileState.LOADED); + + /** + * @private + * @type {ol.TileCoord} + */ + this.tileCoord_ = tileCoord; + + /** + * @private + * @type {ol.Size} + */ + this.tileSize_ = tileGrid.getTileSize(tileCoord.z); + + /** + * @private + * @type {Object.} + */ + this.canvasByContext_ = {}; + +}; +goog.inherits(ol.DebugTile_, ol.Tile); + + +/** + * @inheritDoc + */ +ol.DebugTile_.prototype.getImage = function(opt_context) { + var key = goog.isDef(opt_context) ? goog.getUid(opt_context) : -1; + if (key in this.canvasByContext_) { + return this.canvasByContext_[key]; + } else { + + var tileSize = this.tileSize_; + + var canvas = /** @type {HTMLCanvasElement} */ + (goog.dom.createElement(goog.dom.TagName.CANVAS)); + canvas.width = tileSize.width; + canvas.height = tileSize.height; + + var context = canvas.getContext('2d'); + + context.strokeStyle = 'black'; + context.strokeRect(0.5, 0.5, tileSize.width + 0.5, tileSize.height + 0.5); + + context.fillStyle = 'black'; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.font = '24px sans-serif'; + context.fillText( + this.tileCoord_.toString(), tileSize.width / 2, tileSize.height / 2); + + this.canvasByContext_[key] = canvas; + return canvas; + + } +}; + + + +/** + * @constructor + * @extends {ol.source.TileSource} + * @param {ol.source.DebugTileSourceOptions} options Options. + */ +ol.source.DebugTileSource = function(options) { + + goog.base(this, { + extent: options.extent, + opaque: false, + projection: options.projection, + tileGrid: options.tileGrid + }); + + /** + * @private + * @type {ol.TileCache} + */ + this.tileCache_ = new ol.TileCache(); + +}; +goog.inherits(ol.source.DebugTileSource, ol.source.TileSource); + + +/** + * @inheritDoc + */ +ol.source.DebugTileSource.prototype.canExpireCache = function() { + return this.tileCache_.canExpireCache(); +}; + + +/** + * @inheritDoc + */ +ol.source.DebugTileSource.prototype.expireCache = function(usedTiles) { + this.tileCache_.expireCache(usedTiles); +}; + + +/** + * @inheritDoc + */ +ol.source.DebugTileSource.prototype.getTile = function(tileCoord) { + var key = tileCoord.toString(); + if (this.tileCache_.containsKey(key)) { + return /** @type {!ol.DebugTile_} */ (this.tileCache_.get(key)); + } else { + var tile = new ol.DebugTile_(tileCoord, this.tileGrid); + this.tileCache_.set(key, tile); + return tile; + } +}; diff --git a/master/ol/ol/source/imagesource.js b/master/ol/ol/source/imagesource.js new file mode 100644 index 0000000000..b96973af8b --- /dev/null +++ b/master/ol/ol/source/imagesource.js @@ -0,0 +1,116 @@ +goog.provide('ol.source.ImageSource'); + +goog.require('goog.array'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.Image'); +goog.require('ol.ImageUrlFunction'); +goog.require('ol.ImageUrlFunctionType'); +goog.require('ol.Projection'); +goog.require('ol.Size'); +goog.require('ol.array'); +goog.require('ol.source.Source'); + + +/** + * @typedef {{attributions: (Array.|undefined), + * crossOrigin: (null|string|undefined), + * extent: (null|ol.Extent|undefined), + * projection: ol.ProjectionLike, + * resolutions: (Array.|undefined), + * imageUrlFunction: (ol.ImageUrlFunctionType| + * undefined)}} + */ +ol.source.ImageSourceOptions; + + + +/** + * @constructor + * @extends {ol.source.Source} + * @param {ol.source.ImageSourceOptions} options Single + * image source options. + */ +ol.source.ImageSource = function(options) { + + goog.base(this, { + attributions: options.attributions, + extent: options.extent, + projection: options.projection + }); + + /** + * @protected + * @type {ol.ImageUrlFunctionType} + */ + this.imageUrlFunction = + goog.isDef(options.imageUrlFunction) ? + options.imageUrlFunction : + ol.ImageUrlFunction.nullImageUrlFunction; + + /** + * @private + * @type {?string} + */ + this.crossOrigin_ = + goog.isDef(options.crossOrigin) ? options.crossOrigin : 'anonymous'; + + /** + * @private + * @type {Array.} + */ + this.resolutions_ = goog.isDef(options.resolutions) ? + options.resolutions : null; + goog.asserts.assert(goog.isNull(this.resolutions_) || + goog.array.isSorted(this.resolutions_, + function(a, b) { + return b - a; + }, true)); + +}; +goog.inherits(ol.source.ImageSource, ol.source.Source); + + +/** + * @protected + * @param {ol.Extent} extent Extent. + * @param {number} resolution Resolution. + * @param {ol.Size} size Size. + * @param {ol.Projection} projection Projection. + * @return {ol.Image} Single image. + */ +ol.source.ImageSource.prototype.createImage = + function(extent, resolution, size, projection) { + var image = null; + var imageUrl = this.imageUrlFunction(extent, size, projection); + if (goog.isDef(imageUrl)) { + image = new ol.Image( + extent, resolution, imageUrl, this.crossOrigin_, + this.getAttributions()); + } + return image; +}; + + +/** + * @protected + * @param {number} resolution Resolution. + * @return {number} Resolution. + */ +ol.source.ImageSource.prototype.findNearestResolution = + function(resolution) { + if (!goog.isNull(this.resolutions_)) { + var idx = ol.array.linearFindNearest(this.resolutions_, resolution); + resolution = this.resolutions_[idx]; + } + return resolution; +}; + + +/** + * @param {ol.Extent} extent Extent. + * @param {number} resolution Resolution. + * @param {ol.Projection} projection Projection. + * @return {ol.Image} Single image. + */ +ol.source.ImageSource.prototype.getImage = goog.abstractMethod; diff --git a/master/ol/ol/source/imagetilesource.js b/master/ol/ol/source/imagetilesource.js new file mode 100644 index 0000000000..97c6999095 --- /dev/null +++ b/master/ol/ol/source/imagetilesource.js @@ -0,0 +1,117 @@ +goog.provide('ol.source.ImageTileSource'); +goog.provide('ol.source.ImageTileSourceOptions'); + +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.ImageTile'); +goog.require('ol.Projection'); +goog.require('ol.Tile'); +goog.require('ol.TileCache'); +goog.require('ol.TileState'); +goog.require('ol.TileUrlFunction'); +goog.require('ol.TileUrlFunctionType'); +goog.require('ol.source.TileSource'); +goog.require('ol.tilegrid.TileGrid'); + + +/** + * @typedef {{attributions: (Array.|undefined), + * crossOrigin: (null|string|undefined), + * extent: (ol.Extent|undefined), + * opaque: (boolean|undefined), + * projection: ol.ProjectionLike, + * tileGrid: (ol.tilegrid.TileGrid|undefined), + * tileUrlFunction: (ol.TileUrlFunctionType|undefined)}} + */ +ol.source.ImageTileSourceOptions; + + + +/** + * @constructor + * @extends {ol.source.TileSource} + * @param {ol.source.ImageTileSourceOptions} options Options. + */ +ol.source.ImageTileSource = function(options) { + + goog.base(this, { + attributions: options.attributions, + extent: options.extent, + opaque: options.opaque, + projection: options.projection, + tileGrid: options.tileGrid + }); + + /** + * @protected + * @type {ol.TileUrlFunctionType} + */ + this.tileUrlFunction = goog.isDef(options.tileUrlFunction) ? + options.tileUrlFunction : + ol.TileUrlFunction.nullTileUrlFunction; + + /** + * @private + * @type {?string} + */ + this.crossOrigin_ = + goog.isDef(options.crossOrigin) ? options.crossOrigin : 'anonymous'; + + /** + * @private + * @type {ol.TileCache} + */ + this.tileCache_ = new ol.TileCache(); + +}; +goog.inherits(ol.source.ImageTileSource, ol.source.TileSource); + + +/** + * @inheritDoc + */ +ol.source.ImageTileSource.prototype.canExpireCache = function() { + return this.tileCache_.canExpireCache(); +}; + + +/** + * @inheritDoc + */ +ol.source.ImageTileSource.prototype.expireCache = function(usedTiles) { + this.tileCache_.expireCache(usedTiles); +}; + + +/** + * @inheritDoc + */ +ol.source.ImageTileSource.prototype.getTile = + function(tileCoord, tileGrid, projection) { + var key = tileCoord.toString(); + if (this.tileCache_.containsKey(key)) { + return /** @type {!ol.Tile} */ (this.tileCache_.get(key)); + } else { + goog.asserts.assert(tileGrid); + goog.asserts.assert(projection); + var tileUrl = this.tileUrlFunction(tileCoord, tileGrid, projection); + var tile = new ol.ImageTile( + tileCoord, + goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY, + goog.isDef(tileUrl) ? tileUrl : '', + this.crossOrigin_); + this.tileCache_.set(key, tile); + return tile; + } +}; + + +/** + * @inheritDoc + */ +ol.source.ImageTileSource.prototype.useTile = function(tileCoord) { + var key = tileCoord.toString(); + if (this.tileCache_.containsKey(key)) { + this.tileCache_.get(key); + } +}; diff --git a/master/ol/ol/source/mapquest.exports b/master/ol/ol/source/mapquest.exports new file mode 100644 index 0000000000..d26cb03f25 --- /dev/null +++ b/master/ol/ol/source/mapquest.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.source.MapQuestOSM +@exportSymbol ol.source.MapQuestOpenAerial diff --git a/master/ol/ol/source/mapquestsource.js b/master/ol/ol/source/mapquestsource.js new file mode 100644 index 0000000000..ae12b33a25 --- /dev/null +++ b/master/ol/ol/source/mapquestsource.js @@ -0,0 +1,63 @@ +goog.provide('ol.source.MapQuestOSM'); +goog.provide('ol.source.MapQuestOpenAerial'); + +goog.require('ol.Attribution'); +goog.require('ol.source.XYZ'); + + + +/** + * @constructor + * @extends {ol.source.XYZ} + */ +ol.source.MapQuestOSM = function() { + + var attributions = [ + new ol.Attribution( + 'Tiles Courtesy of ' + + 'MapQuest ' + + ''), + new ol.Attribution( + 'Data © ' + + 'OpenStreetMap ' + + 'contributors, ' + + 'CC BY-SA') + ]; + + goog.base(this, { + attributions: attributions, + opaque: true, + maxZoom: 28, + url: 'http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg' + }); + +}; +goog.inherits(ol.source.MapQuestOSM, ol.source.XYZ); + + + +/** + * @constructor + * @extends {ol.source.XYZ} + */ +ol.source.MapQuestOpenAerial = function() { + + var attributions = [ + new ol.Attribution( + 'Tiles Courtesy of ' + + 'MapQuest ' + + ''), + new ol.Attribution( + 'Portions Courtesy NASA/JPL-Caltech and ' + + 'U.S. Depart. of Agriculture, Farm Service Agency') + ]; + + goog.base(this, { + attributions: attributions, + maxZoom: 18, + opaque: true, + url: 'http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg' + }); + +}; +goog.inherits(ol.source.MapQuestOpenAerial, ol.source.XYZ); diff --git a/master/ol/ol/source/openstreetmap.exports b/master/ol/ol/source/openstreetmap.exports new file mode 100644 index 0000000000..a2b205a252 --- /dev/null +++ b/master/ol/ol/source/openstreetmap.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.source.OpenStreetMap + diff --git a/master/ol/ol/source/openstreetmapsource.js b/master/ol/ol/source/openstreetmapsource.js new file mode 100644 index 0000000000..258fe22637 --- /dev/null +++ b/master/ol/ol/source/openstreetmapsource.js @@ -0,0 +1,27 @@ +goog.provide('ol.source.OpenStreetMap'); + +goog.require('ol.Attribution'); +goog.require('ol.source.XYZ'); + + + +/** + * @constructor + * @extends {ol.source.XYZ} + */ +ol.source.OpenStreetMap = function() { + + var attribution = new ol.Attribution( + '© OpenStreetMap ' + + 'contributors, ' + + 'CC BY-SA'); + + goog.base(this, { + attributions: [attribution], + opaque: true, + maxZoom: 18, + url: 'http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png' + }); + +}; +goog.inherits(ol.source.OpenStreetMap, ol.source.XYZ); diff --git a/master/ol/ol/source/singleimagewms.exports b/master/ol/ol/source/singleimagewms.exports new file mode 100644 index 0000000000..17486b875c --- /dev/null +++ b/master/ol/ol/source/singleimagewms.exports @@ -0,0 +1 @@ +@exportClass ol.source.SingleImageWMS ol.source.SingleImageWMSOptions diff --git a/master/ol/ol/source/singleimagewmssource.js b/master/ol/ol/source/singleimagewmssource.js new file mode 100644 index 0000000000..211abdbd36 --- /dev/null +++ b/master/ol/ol/source/singleimagewmssource.js @@ -0,0 +1,70 @@ +goog.provide('ol.source.SingleImageWMS'); + +goog.require('ol.Extent'); +goog.require('ol.Image'); +goog.require('ol.ImageUrlFunction'); +goog.require('ol.Size'); +goog.require('ol.source.ImageSource'); + + + +/** + * @constructor + * @extends {ol.source.ImageSource} + * @param {ol.source.SingleImageWMSOptions} options Options. + */ +ol.source.SingleImageWMS = function(options) { + var imageUrlFunction = goog.isDef(options.url) ? + ol.ImageUrlFunction.createWMSParams(options.url, options.params) : + ol.ImageUrlFunction.nullImageUrlFunction; + + goog.base(this, { + attributions: options.attributions, + crossOrigin: options.crossOrigin, + extent: options.extent, + projection: options.projection, + resolutions: options.resolutions, + imageUrlFunction: imageUrlFunction + }); + + /** + * @private + * @type {ol.Image} + */ + this.image_ = null; + + /** + * FIXME configurable? + * @private + * @type {number} + */ + this.ratio_ = 1.5; + +}; +goog.inherits(ol.source.SingleImageWMS, ol.source.ImageSource); + + +/** + * @inheritDoc + */ +ol.source.SingleImageWMS.prototype.getImage = + function(extent, resolution, projection) { + resolution = this.findNearestResolution(resolution); + + var image = this.image_; + if (!goog.isNull(image) && + image.getResolution() == resolution && + image.getExtent().containsExtent(extent)) { + return image; + } + + extent = new ol.Extent(extent.minX, extent.minY, + extent.maxX, extent.maxY); + extent.scaleFromCenter(this.ratio_); + var width = extent.getWidth() / resolution; + var height = extent.getHeight() / resolution; + var size = new ol.Size(width, height); + + this.image_ = this.createImage(extent, resolution, size, projection); + return this.image_; +}; diff --git a/master/ol/ol/source/source.js b/master/ol/ol/source/source.js new file mode 100644 index 0000000000..89954b54db --- /dev/null +++ b/master/ol/ol/source/source.js @@ -0,0 +1,119 @@ +goog.provide('ol.source.Source'); + +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('goog.functions'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.projection'); + + +/** + * @typedef {{attributions: (Array.|undefined), + * extent: (ol.Extent|undefined), + * projection: ol.ProjectionLike}} + */ +ol.source.SourceOptions; + + + +/** + * @constructor + * @extends {goog.events.EventTarget} + * @param {ol.source.SourceOptions} sourceOptions Source options. + */ +ol.source.Source = function(sourceOptions) { + + goog.base(this); + + /** + * @private + * @type {ol.Projection} + */ + this.projection_ = ol.projection.get(sourceOptions.projection); + + /** + * @private + * @type {ol.Extent} + */ + this.extent_ = goog.isDef(sourceOptions.extent) ? + sourceOptions.extent : goog.isDef(sourceOptions.projection) ? + this.projection_.getExtent() : null; + + /** + * @private + * @type {Array.} + */ + this.attributions_ = goog.isDef(sourceOptions.attributions) ? + sourceOptions.attributions : null; + +}; +goog.inherits(ol.source.Source, goog.events.EventTarget); + + +/** + * @protected + */ +ol.source.Source.prototype.dispatchLoadEvent = function() { + this.dispatchEvent(goog.events.EventType.LOAD); +}; + + +/** + * @return {Array.} Attributions. + */ +ol.source.Source.prototype.getAttributions = function() { + return this.attributions_; +}; + + +/** + * @return {ol.Extent} Extent. + */ +ol.source.Source.prototype.getExtent = function() { + return this.extent_; +}; + + +/** + * @return {ol.Projection} Projection. + */ +ol.source.Source.prototype.getProjection = function() { + return this.projection_; +}; + + +/** + * @return {Array.|undefined} Resolutions. + */ +ol.source.Source.prototype.getResolutions = goog.abstractMethod; + + +/** + * @return {boolean} Is ready. + */ +ol.source.Source.prototype.isReady = goog.functions.TRUE; + + +/** + * @param {Array.} attributions Attributions. + */ +ol.source.Source.prototype.setAttributions = function(attributions) { + this.attributions_ = attributions; +}; + + +/** + * @param {ol.Extent} extent Extent. + */ +ol.source.Source.prototype.setExtent = function(extent) { + this.extent_ = extent; +}; + + +/** + * @param {ol.Projection} projection Projetion. + */ +ol.source.Source.prototype.setProjection = function(projection) { + this.projection_ = projection; +}; diff --git a/master/ol/ol/source/stamen.exports b/master/ol/ol/source/stamen.exports new file mode 100644 index 0000000000..61702ead25 --- /dev/null +++ b/master/ol/ol/source/stamen.exports @@ -0,0 +1 @@ +@exportClass ol.source.Stamen ol.source.StamenOptions diff --git a/master/ol/ol/source/stamensource.js b/master/ol/ol/source/stamensource.js new file mode 100644 index 0000000000..a29ec962da --- /dev/null +++ b/master/ol/ol/source/stamensource.js @@ -0,0 +1,117 @@ +goog.provide('ol.source.Stamen'); + +goog.require('ol.Attribution'); +goog.require('ol.source.XYZ'); + + +/** + * @type {Object.} + */ +ol.source.StamenLayerConfig = { + 'terrain': { + extension: 'jpg', + opaque: true + }, + 'terrain-background': { + extension: 'jpg', + opaque: true + }, + 'terrain-labels': { + extension: 'png', + opaque: false + }, + 'terrain-lines': { + extension: 'png', + opaque: false + }, + 'toner-background': { + extension: 'png', + opaque: true + }, + 'toner': { + extension: 'png', + opaque: true + }, + 'toner-hybrid': { + extension: 'png', + opaque: false + }, + 'toner-labels': { + extension: 'png', + opaque: false + }, + 'toner-lines': { + extension: 'png', + opaque: false + }, + 'toner-lite': { + extension: 'png', + opaque: true + }, + 'watercolor': { + extension: 'jpg', + opaque: true + } +}; + + +/** + * @type {Object.} + */ +ol.source.StamenProviderConfig = { + 'terrain': { + minZoom: 4, + maxZoom: 18 + }, + 'toner': { + minZoom: 0, + maxZoom: 20 + }, + 'watercolor': { + minZoom: 3, + maxZoom: 16 + } +}; + + +/** + * @const {Array.} + */ +ol.source.STAMEN_ATTRIBUTIONS = [new ol.Attribution( + 'Map tiles by Stamen Design, under ' + + 'CC BY 3.0. ' + + 'Data by OpenStreetMap, under ' + + 'CC BY SA.')]; + + + +/** + * @constructor + * @extends {ol.source.XYZ} + * @param {ol.source.StamenOptions} options Options. + */ +ol.source.Stamen = function(options) { + + var i = options.layer.indexOf('-'); + var provider = i == -1 ? options.layer : options.layer.slice(0, i); + goog.asserts.assert(provider in ol.source.StamenProviderConfig); + var providerConfig = ol.source.StamenProviderConfig[provider]; + + goog.asserts.assert(options.layer in ol.source.StamenLayerConfig); + var layerConfig = ol.source.StamenLayerConfig[options.layer]; + + var url = goog.isDef(options.url) ? options.url : + 'http://{a-d}.tile.stamen.com/' + options.layer + '/{z}/{x}/{y}.' + + layerConfig.extension; + + goog.base(this, { + attributions: ol.source.STAMEN_ATTRIBUTIONS, + maxZoom: providerConfig.maxZoom, + // FIXME uncomment the following when tilegrid supports minZoom + //minZoom: providerConfig.minZoom, + opaque: layerConfig.opaque, + url: url + }); + +}; +goog.inherits(ol.source.Stamen, ol.source.XYZ); diff --git a/master/ol/ol/source/staticimage.exports b/master/ol/ol/source/staticimage.exports new file mode 100644 index 0000000000..5df3d4893f --- /dev/null +++ b/master/ol/ol/source/staticimage.exports @@ -0,0 +1 @@ +@exportClass ol.source.StaticImage ol.source.StaticImageOptions diff --git a/master/ol/ol/source/staticimagesource.js b/master/ol/ol/source/staticimagesource.js new file mode 100644 index 0000000000..d788e20fa5 --- /dev/null +++ b/master/ol/ol/source/staticimagesource.js @@ -0,0 +1,65 @@ +goog.provide('ol.source.StaticImage'); + +goog.require('ol.Image'); +goog.require('ol.ImageUrlFunctionType'); +goog.require('ol.projection'); +goog.require('ol.source.ImageSource'); + + + +/** + * @constructor + * @extends {ol.source.ImageSource} + * @param {ol.source.StaticImageOptions} options Options. + */ +ol.source.StaticImage = function(options) { + + var imageFunction = ol.source.StaticImage.createImageFunction( + options.url); + + var imageExtent = options.imageExtent; + var imageSize = options.imageSize; + var imageResolution = imageExtent.getHeight() / imageSize.height; + var projection = ol.projection.get(options.projection); + + goog.base(this, { + attributions: options.attributions, + crossOrigin: options.crossOrigin, + extent: options.extent, + projection: options.projection, + imageUrlFunction: imageFunction, + resolutions: [imageResolution] + }); + + /** + * @private + * @type {ol.Image} + */ + this.image_ = this.createImage( + imageExtent, imageResolution, imageSize, projection); + +}; +goog.inherits(ol.source.StaticImage, ol.source.ImageSource); + + +/** + * @inheritDoc + */ +ol.source.StaticImage.prototype.getImage = + function(extent, resolution, projection) { + if (extent.intersects(this.image_.getExtent())) { + return this.image_; + } + return null; +}; + + +/** + * @param {string|undefined} url URL. + * @return {ol.ImageUrlFunctionType} Function. + */ +ol.source.StaticImage.createImageFunction = function(url) { + return function(extent, size, projection) { + return url; + }; +}; diff --git a/master/ol/ol/source/tiledwms.exports b/master/ol/ol/source/tiledwms.exports new file mode 100644 index 0000000000..ad50ff46a9 --- /dev/null +++ b/master/ol/ol/source/tiledwms.exports @@ -0,0 +1 @@ +@exportClass ol.source.TiledWMS ol.source.TiledWMSOptions diff --git a/master/ol/ol/source/tiledwmssource.js b/master/ol/ol/source/tiledwmssource.js new file mode 100644 index 0000000000..9de3627372 --- /dev/null +++ b/master/ol/ol/source/tiledwmssource.js @@ -0,0 +1,81 @@ +// FIXME add minZoom support + +goog.provide('ol.source.TiledWMS'); + + +goog.require('goog.array'); +goog.require('ol.Extent'); +goog.require('ol.TileCoord'); +goog.require('ol.TileUrlFunction'); +goog.require('ol.source.ImageTileSource'); + + + +/** + * @constructor + * @extends {ol.source.ImageTileSource} + * @param {ol.source.TiledWMSOptions} tiledWMSOptions options. + */ +ol.source.TiledWMS = function(tiledWMSOptions) { + var tileGrid; + if (goog.isDef(tiledWMSOptions.tileGrid)) { + tileGrid = tiledWMSOptions.tileGrid; + } + + var tileUrlFunction; + if (tiledWMSOptions.urls) { + var tileUrlFunctions = goog.array.map( + tiledWMSOptions.urls, function(url) { + return ol.TileUrlFunction.createWMSParams( + url, tiledWMSOptions.params); + }); + tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions( + tileUrlFunctions); + } else if (tiledWMSOptions.url) { + tileUrlFunction = ol.TileUrlFunction.createWMSParams( + tiledWMSOptions.url, tiledWMSOptions.params); + } else { + tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction; + } + var transparent = goog.isDef(tiledWMSOptions.params['TRANSPARENT']) ? + tiledWMSOptions.params['TRANSPARENT'] : true; + var extent = tiledWMSOptions.extent; + + var tileCoordTransform = function(tileCoord, tileGrid, projection) { + if (tileGrid.getResolutions().length <= tileCoord.z) { + return null; + } + var x = tileCoord.x; + var tileExtent = tileGrid.getTileCoordExtent(tileCoord); + var projectionExtent = projection.getExtent(); + extent = goog.isDef(extent) ? extent : projectionExtent; + + if (!goog.isNull(extent) && projection.isGlobal() && + extent.minX === projectionExtent.minX && + extent.maxX === projectionExtent.maxX) { + var numCols = Math.ceil( + (extent.maxX - extent.minX) / (tileExtent.maxX - tileExtent.minX)); + x = goog.math.modulo(x, numCols); + tileExtent = tileGrid.getTileCoordExtent( + new ol.TileCoord(tileCoord.z, x, tileCoord.y)); + } + // FIXME We shouldn't need a typecast here. + if (!tileExtent.intersects(/** @type {ol.Extent} */ (extent))) { + return null; + } + return new ol.TileCoord(tileCoord.z, x, tileCoord.y); + }; + + goog.base(this, { + attributions: tiledWMSOptions.attributions, + crossOrigin: tiledWMSOptions.crossOrigin, + extent: extent, + tileGrid: tiledWMSOptions.tileGrid, + opaque: !transparent, + projection: tiledWMSOptions.projection, + tileUrlFunction: ol.TileUrlFunction.withTileCoordTransform( + tileCoordTransform, tileUrlFunction) + }); + +}; +goog.inherits(ol.source.TiledWMS, ol.source.ImageTileSource); diff --git a/master/ol/ol/source/tilejson.exports b/master/ol/ol/source/tilejson.exports new file mode 100644 index 0000000000..e05dca5e1d --- /dev/null +++ b/master/ol/ol/source/tilejson.exports @@ -0,0 +1 @@ +@exportClass ol.source.TileJSON ol.source.TileJSONOptions diff --git a/master/ol/ol/source/tilejsonsource.js b/master/ol/ol/source/tilejsonsource.js new file mode 100644 index 0000000000..27c5ec7cac --- /dev/null +++ b/master/ol/ol/source/tilejsonsource.js @@ -0,0 +1,154 @@ +// FIXME add some error checking +// FIXME check order of async callbacks +// FIXME use minzoom when supported + +/** + * @see http://mapbox.com/developers/api/ + */ + +goog.provide('ol.source.TileJSON'); +goog.provide('ol.tilejson'); + +goog.require('goog.asserts'); +goog.require('goog.net.jsloader'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); +goog.require('ol.TileUrlFunction'); +goog.require('ol.projection'); +goog.require('ol.source.ImageTileSource'); +goog.require('ol.tilegrid.XYZ'); + + +/** + * @private + * @type {Array.} + */ +ol.tilejson.grids_ = []; + + +/** + * @param {TileJSON} tileJSON Tile JSON. + */ +var grid = function(tileJSON) { + ol.tilejson.grids_.push(tileJSON); +}; +goog.exportSymbol('grid', grid); + + + +/** + * @constructor + * @extends {ol.source.ImageTileSource} + * @param {ol.source.TileJSONOptions} tileJsonOptions TileJSON optios. + */ +ol.source.TileJSON = function(tileJsonOptions) { + + goog.base(this, { + projection: ol.projection.get('EPSG:3857') + }); + + /** + * @private + * @type {boolean} + */ + this.ready_ = false; + + /** + * @private + * @type {!goog.async.Deferred} + */ + this.deferred_ = + goog.net.jsloader.load(tileJsonOptions.uri, {cleanupWhenDone: true}); + this.deferred_.addCallback(this.handleTileJSONResponse, this); + +}; +goog.inherits(ol.source.TileJSON, ol.source.ImageTileSource); + + +/** + * @protected + */ +ol.source.TileJSON.prototype.handleTileJSONResponse = function() { + + var tileJSON = ol.tilejson.grids_.pop(); + + var epsg4326Projection = ol.projection.get('EPSG:4326'); + + var epsg4326Extent, extent; + if (goog.isDef(tileJSON.bounds)) { + var bounds = tileJSON.bounds; + epsg4326Extent = new ol.Extent( + bounds[0], bounds[1], bounds[2], bounds[3]); + extent = epsg4326Extent.transform(ol.projection.getTransformFromProjections( + epsg4326Projection, this.getProjection())); + this.setExtent(extent); + } else { + epsg4326Extent = null; + extent = null; + } + + var scheme = goog.isDef(tileJSON.scheme) || 'xyz'; + if (goog.isDef(tileJSON.scheme)) { + goog.asserts.assert(tileJSON.scheme == 'xyz'); + } + var minZoom = tileJSON.minzoom || 0; + goog.asserts.assert(minZoom === 0); // FIXME + var maxZoom = tileJSON.maxzoom || 22; + var tileGrid = new ol.tilegrid.XYZ({ + maxZoom: maxZoom + }); + this.tileGrid = tileGrid; + + this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( + function(tileCoord) { + if (tileCoord.z < minZoom || maxZoom < tileCoord.z) { + return null; + } + var n = 1 << tileCoord.z; + var y = -tileCoord.y - 1; + if (y < 0 || n <= y) { + return null; + } + var x = goog.math.modulo(tileCoord.x, n); + if (!goog.isNull(extent)) { + var tileExtent = tileGrid.getTileCoordExtent( + new ol.TileCoord(tileCoord.z, x, tileCoord.y)); + if (!tileExtent.intersects(extent)) { + return null; + } + } + return new ol.TileCoord(tileCoord.z, x, y); + }, + ol.TileUrlFunction.createFromTemplates(tileJSON.tiles)); + + if (goog.isDef(tileJSON.attribution)) { + var attributionExtent = goog.isNull(extent) ? + epsg4326Projection.getExtent() : extent; + /** @type {Object.>} */ + var tileRanges = {}; + var z, zKey; + for (z = minZoom; z <= maxZoom; ++z) { + zKey = z.toString(); + tileRanges[zKey] = + [tileGrid.getTileRangeForExtentAndZ(attributionExtent, z)]; + } + this.setAttributions([ + new ol.Attribution(tileJSON.attribution, tileRanges) + ]); + } + + this.ready_ = true; + + this.dispatchLoadEvent(); + +}; + + +/** + * @inheritDoc + */ +ol.source.TileJSON.prototype.isReady = function() { + return this.ready_; +}; diff --git a/master/ol/ol/source/tilesource.js b/master/ol/ol/source/tilesource.js new file mode 100644 index 0000000000..01d8fe7d3c --- /dev/null +++ b/master/ol/ol/source/tilesource.js @@ -0,0 +1,165 @@ +goog.provide('ol.source.TileSource'); +goog.provide('ol.source.TileSourceOptions'); + +goog.require('goog.functions'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); +goog.require('ol.source.Source'); +goog.require('ol.tilegrid.TileGrid'); + + +/** + * @typedef {{attributions: (Array.|undefined), + * extent: (ol.Extent|undefined), + * opaque: (boolean|undefined), + * projection: ol.ProjectionLike, + * tileGrid: (ol.tilegrid.TileGrid|undefined)}} + */ +ol.source.TileSourceOptions; + + + +/** + * @constructor + * @extends {ol.source.Source} + * @param {ol.source.TileSourceOptions} tileSourceOptions Tile source options. + */ +ol.source.TileSource = function(tileSourceOptions) { + + goog.base(this, { + attributions: tileSourceOptions.attributions, + extent: tileSourceOptions.extent, + projection: tileSourceOptions.projection + }); + + /** + * @private + * @type {boolean} + */ + this.opaque_ = goog.isDef(tileSourceOptions.opaque) ? + tileSourceOptions.opaque : false; + + /** + * @protected + * @type {ol.tilegrid.TileGrid} + */ + this.tileGrid = goog.isDef(tileSourceOptions.tileGrid) ? + tileSourceOptions.tileGrid : null; + +}; +goog.inherits(ol.source.TileSource, ol.source.Source); + + +/** + * @return {boolean} Can expire cache. + */ +ol.source.TileSource.prototype.canExpireCache = goog.functions.FALSE; + + +/** + * @param {Object.} usedTiles Used tiles. + */ +ol.source.TileSource.prototype.expireCache = goog.abstractMethod; + + +/** + * Look for loaded tiles over a given tile range and zoom level. Adds + * properties to the provided lookup representing key/tile pairs for already + * loaded tiles. + * + * @param {Object.>} loadedTilesByZ A lookup of + * loaded tiles by zoom level. + * @param {function(ol.TileCoord): ol.Tile} getTileIfLoaded A function that + * returns the tile only if it is fully loaded. + * @param {number} z Zoom level. + * @param {ol.TileRange} tileRange Tile range. + * @return {boolean} The tile range is fully covered with loaded tiles. + */ +ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, + getTileIfLoaded, z, tileRange) { + // FIXME this could be more efficient about filling partial holes + var fullyCovered = true; + var tile, tileCoord, tileCoordKey, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + tileCoord = new ol.TileCoord(z, x, y); + tileCoordKey = tileCoord.toString(); + if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) { + continue; + } + tile = getTileIfLoaded(tileCoord); + if (!goog.isNull(tile)) { + if (!loadedTilesByZ[z]) { + loadedTilesByZ[z] = {}; + } + loadedTilesByZ[z][tileCoordKey] = tile; + } else { + fullyCovered = false; + } + } + } + return fullyCovered; +}; + + +/** + * @return {boolean} Opaque. + */ +ol.source.TileSource.prototype.getOpaque = function() { + return this.opaque_; +}; + + +/** + * @inheritDoc + */ +ol.source.TileSource.prototype.getResolutions = function() { + return this.tileGrid.getResolutions(); +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {ol.tilegrid.TileGrid=} opt_tileGrid Tile grid. + * @param {ol.Projection=} opt_projection Projection. + * @return {!ol.Tile} Tile. + */ +ol.source.TileSource.prototype.getTile = goog.abstractMethod; + + +/** + * @return {ol.tilegrid.TileGrid} Tile grid. + */ +ol.source.TileSource.prototype.getTileGrid = function() { + return this.tileGrid; +}; + + +/** + * @param {number} z Z. + * @param {ol.Extent} extent Extent. + * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. + */ +ol.source.TileSource.prototype.useLowResolutionTiles = + function(z, extent, tileGrid) { + var tileRange, x, y, zKey; + // FIXME this should loop up to tileGrid's minZ when implemented + for (; z >= 0; --z) { + tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z); + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + this.useTile(z + '/' + x + '/' + y); + } + } + } +}; + + +/** + * Marks a tile coord as being used, without triggering a load. + * @param {string} tileCoordKey Tile coordinate key. + */ +ol.source.TileSource.prototype.useTile = goog.nullFunction; diff --git a/master/ol/ol/source/wms.js b/master/ol/ol/source/wms.js new file mode 100644 index 0000000000..d81e822549 --- /dev/null +++ b/master/ol/ol/source/wms.js @@ -0,0 +1,39 @@ +goog.provide('ol.source.wms'); + + +/** + * @param {string} baseUrl WMS base url. + * @param {Object.} params Request parameters. + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Size. + * @param {ol.Projection} projection Projection. + * @return {string} WMS GetMap request URL. + */ +ol.source.wms.getUrl = + function(baseUrl, params, extent, size, projection) { + var baseParams = { + 'SERVICE': 'WMS', + 'VERSION': '1.3.0', + 'REQUEST': 'GetMap', + 'FORMAT': 'image/png', + 'TRANSPARENT': true, + 'WIDTH': Math.round(size.width), + 'HEIGHT': Math.round(size.height) + }; + goog.object.extend(baseParams, params); + + //TODO: Provide our own appendParams function to avoid this empty string hack + var stylesParam = 'STYLES'; + baseParams[stylesParam] = params[stylesParam] || new String(''); + + var wms13 = baseParams['VERSION'] > '1.3'; + baseParams[wms13 ? 'CRS' : 'SRS'] = projection.getCode(); + + var axisOrientation = projection.getAxisOrientation(); + var bboxValues = (wms13 && axisOrientation.substr(0, 2) == 'ne') ? + [extent.minY, extent.minX, extent.maxY, extent.maxX] : + [extent.minX, extent.minY, extent.maxX, extent.maxY]; + baseParams['BBOX'] = bboxValues.join(','); + + return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams); +}; diff --git a/master/ol/ol/source/xyzsource.js b/master/ol/ol/source/xyzsource.js new file mode 100644 index 0000000000..66e17eed56 --- /dev/null +++ b/master/ol/ol/source/xyzsource.js @@ -0,0 +1,113 @@ +// FIXME add minZoom support + +goog.provide('ol.source.XYZ'); +goog.provide('ol.source.XYZOptions'); + +goog.require('goog.math'); +goog.require('ol.Attribution'); +goog.require('ol.Extent'); +goog.require('ol.Projection'); +goog.require('ol.TileCoord'); +goog.require('ol.TileUrlFunction'); +goog.require('ol.TileUrlFunctionType'); +goog.require('ol.projection'); +goog.require('ol.source.ImageTileSource'); +goog.require('ol.tilegrid.XYZ'); + + +/** + * @typedef {{attributions: (Array.|undefined), + * crossOrigin: (string|undefined), + * extent: (ol.Extent|undefined), + * maxZoom: number, + * projection: (ol.Projection|undefined), + * tileUrlFunction: (ol.TileUrlFunctionType|undefined), + * url: (string|undefined), + * urls: (Array.|undefined)}} + */ +ol.source.XYZOptions; + + + +/** + * @constructor + * @extends {ol.source.ImageTileSource} + * @param {ol.source.XYZOptions} xyzOptions XYZ options. + */ +ol.source.XYZ = function(xyzOptions) { + + var projection = xyzOptions.projection || + ol.projection.get('EPSG:3857'); + + /** + * @type {ol.TileUrlFunctionType} + */ + var tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction; + // FIXME use goog.nullFunction ? + if (goog.isDef(xyzOptions.tileUrlFunction)) { + tileUrlFunction = xyzOptions.tileUrlFunction; + } else if (goog.isDef(xyzOptions.urls)) { + tileUrlFunction = ol.TileUrlFunction.createFromTemplates(xyzOptions.urls); + } else if (goog.isDef(xyzOptions.url)) { + tileUrlFunction = ol.TileUrlFunction.createFromTemplate(xyzOptions.url); + } + + var tileGrid = new ol.tilegrid.XYZ({ + maxZoom: xyzOptions.maxZoom + }); + + // FIXME factor out common code + var extent = xyzOptions.extent; + if (goog.isDefAndNotNull(extent)) { + + tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( + function(tileCoord) { + if (xyzOptions.maxZoom < tileCoord.z) { + return null; + } + var n = 1 << tileCoord.z; + var y = -tileCoord.y - 1; + if (y < 0 || n <= y) { + return null; + } + var x = goog.math.modulo(tileCoord.x, n); + var tileExtent = tileGrid.getTileCoordExtent( + new ol.TileCoord(tileCoord.z, x, tileCoord.y)); + // FIXME we shouldn't need a typecast here + if (!tileExtent.intersects(/** @type {ol.Extent} */ (extent))) { + return null; + } + return new ol.TileCoord(tileCoord.z, x, y); + }, + tileUrlFunction); + + } else { + + tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( + function(tileCoord) { + if (xyzOptions.maxZoom < tileCoord.z) { + return null; + } + var n = 1 << tileCoord.z; + var y = -tileCoord.y - 1; + if (y < 0 || n <= y) { + return null; + } else { + var x = goog.math.modulo(tileCoord.x, n); + return new ol.TileCoord(tileCoord.z, x, y); + } + }, + tileUrlFunction); + } + + goog.base(this, { + attributions: xyzOptions.attributions, + crossOrigin: xyzOptions.crossOrigin, + extent: xyzOptions.extent, + projection: projection, + tileGrid: tileGrid, + tileUrlFunction: tileUrlFunction + }); + +}; +goog.inherits(ol.source.XYZ, ol.source.ImageTileSource); diff --git a/master/ol/ol/sphere.js b/master/ol/ol/sphere.js new file mode 100644 index 0000000000..70c154ca64 --- /dev/null +++ b/master/ol/ol/sphere.js @@ -0,0 +1,189 @@ +/** + * @license + * Latitude/longitude spherical geodesy formulae taken from + * http://www.movable-type.co.uk/scripts/latlong.html + * Licenced under CC-BY-3.0. + */ + +// FIXME add intersection of two paths given start points and bearings +// FIXME add rhumb lines + +goog.provide('ol.Sphere'); + +goog.require('goog.math'); +goog.require('ol.Coordinate'); + + + +/** + * @constructor + * @param {number} radius Radius. + */ +ol.Sphere = function(radius) { + + /** + * @type {number} + */ + this.radius = radius; + +}; + + +/** + * Returns the distance from c1 to c2 using the spherical law of cosines. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @return {number} Spherical law of cosines distance. + */ +ol.Sphere.prototype.cosineDistance = function(c1, c2) { + var lat1 = goog.math.toRadians(c1.y); + var lat2 = goog.math.toRadians(c2.y); + var deltaLon = goog.math.toRadians(c2.x - c1.x); + return this.radius * Math.acos( + Math.sin(lat1) * Math.sin(lat2) + + Math.cos(lat1) * Math.cos(lat2) * Math.cos(deltaLon)); +}; + + +/** + * Returns the distance of c3 from the great circle path defined by c1 and c2. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @param {ol.Coordinate} c3 Coordinate 3. + * @return {number} Cross-track distance. + */ +ol.Sphere.prototype.crossTrackDistance = function(c1, c2, c3) { + var d12 = this.cosineDistance(c1, c2); + var d13 = this.cosineDistance(c1, c2); + var theta12 = goog.math.toRadians(this.initialBearing(c1, c2)); + var theta13 = goog.math.toRadians(this.initialBearing(c1, c3)); + return this.radius * + Math.asin(Math.sin(d13 / this.radius) * Math.sin(theta13 - theta12)); +}; + + +/** + * Returns the distance from c1 to c2 using Pythagoras's theorem on an + * equirectangular projection. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @return {number} Equirectangular distance. + */ +ol.Sphere.prototype.equirectangularDistance = function(c1, c2) { + var lat1 = goog.math.toRadians(c1.y); + var lat2 = goog.math.toRadians(c2.y); + var deltaLon = goog.math.toRadians(c2.x - c1.x); + var x = deltaLon * Math.cos((lat1 + lat2) / 2); + var y = lat2 - lat1; + return this.radius * Math.sqrt(x * x + y * y); +}; + + +/** + * Returns the final bearing from c1 to c2. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @return {number} Initial bearing. + */ +ol.Sphere.prototype.finalBearing = function(c1, c2) { + return (this.initialBearing(c2, c1) + 180) % 360; +}; + + +/** + * Returns the distance from c1 to c2 using the haversine formula. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @return {number} Haversine distance. + */ +ol.Sphere.prototype.haversineDistance = function(c1, c2) { + var lat1 = goog.math.toRadians(c1.y); + var lat2 = goog.math.toRadians(c2.y); + var deltaLatBy2 = (lat2 - lat1) / 2; + var deltaLonBy2 = goog.math.toRadians(c2.x - c1.x) / 2; + var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) + + Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) * + Math.cos(lat1) * Math.cos(lat2); + return 2 * this.radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); +}; + + +/** + * Returns the initial bearing from c1 to c2. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @return {number} Initial bearing. + */ +ol.Sphere.prototype.initialBearing = function(c1, c2) { + var lat1 = goog.math.toRadians(c1.y); + var lat2 = goog.math.toRadians(c2.y); + var deltaLon = goog.math.toRadians(c2.x - c1.x); + var y = Math.sin(deltaLon) * Math.cos(lat2); + var x = Math.cos(lat1) * Math.sin(lat2) - + Math.sin(lat1) * Math.cos(lat2) * Math.cos(deltaLon); + return goog.math.toDegrees(Math.atan2(y, x)); +}; + + +/** + * Returns the maximum latitude of the great circle defined by bearing and + * latitude. + * + * @param {number} bearing Bearing. + * @param {number} latitude Latitude. + * @return {number} Maximum latitude. + */ +ol.Sphere.prototype.maximumLatitude = function(bearing, latitude) { + return Math.cos(Math.abs(Math.sin(goog.math.toRadians(bearing)) * + Math.cos(goog.math.toRadians(latitude)))); +}; + + +/** + * Returns the midpoint between c1 and c2. + * + * @param {ol.Coordinate} c1 Coordinate 1. + * @param {ol.Coordinate} c2 Coordinate 2. + * @return {ol.Coordinate} Midpoint. + */ +ol.Sphere.prototype.midpoint = function(c1, c2) { + var lat1 = goog.math.toRadians(c1.y); + var lat2 = goog.math.toRadians(c2.y); + var lon1 = goog.math.toRadians(c1.x); + var deltaLon = goog.math.toRadians(c2.x - c1.x); + var Bx = Math.cos(lat2) * Math.cos(deltaLon); + var By = Math.cos(lat2) * Math.sin(deltaLon); + var cosLat1PlusBx = Math.cos(lat1) + Bx; + var lat = Math.atan2(Math.sin(lat1) + Math.sin(lat2), + Math.sqrt(cosLat1PlusBx * cosLat1PlusBx + By * By)); + var lon = lon1 + Math.atan2(By, cosLat1PlusBx); + return new ol.Coordinate(goog.math.toDegrees(lon), goog.math.toDegrees(lat)); +}; + + +/** + * Returns the coordinate at the given distance and bearing from c. + * + * @param {ol.Coordinate} c1 Coordinate. + * @param {number} distance Distance. + * @param {number} bearing Bearing. + * @return {ol.Coordinate} Coordinate. + */ +ol.Sphere.prototype.offset = function(c1, distance, bearing) { + var lat1 = goog.math.toRadians(c1.y); + var lon1 = goog.math.toRadians(c1.x); + var dByR = distance / this.radius; + var lat = Math.asin( + Math.sin(lat1) * Math.cos(dByR) + + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing)); + var lon = lon1 + Math.atan2( + Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), + Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat)); + return new ol.Coordinate(goog.math.toDegrees(lon), goog.math.toDegrees(lat)); +}; diff --git a/master/ol/ol/sphere/normal.js b/master/ol/ol/sphere/normal.js new file mode 100644 index 0000000000..e07bf000b4 --- /dev/null +++ b/master/ol/ol/sphere/normal.js @@ -0,0 +1,10 @@ +goog.provide('ol.sphere.NORMAL'); + +goog.require('ol.Sphere'); + + +/** + * The normal sphere. + * @const {ol.Sphere} + */ +ol.sphere.NORMAL = new ol.Sphere(6370997); diff --git a/master/ol/ol/sphere/wgs84.js b/master/ol/ol/sphere/wgs84.js new file mode 100644 index 0000000000..e30aafeb4b --- /dev/null +++ b/master/ol/ol/sphere/wgs84.js @@ -0,0 +1,10 @@ +goog.provide('ol.sphere.WGS84'); + +goog.require('ol.Sphere'); + + +/** + * A sphere with radius equal to the semi-major axis of the WGS84 ellipsoid. + * @const {ol.Sphere} + */ +ol.sphere.WGS84 = new ol.Sphere(6378137); diff --git a/master/ol/ol/structs/lrucache.js b/master/ol/ol/structs/lrucache.js new file mode 100644 index 0000000000..7792dc2f61 --- /dev/null +++ b/master/ol/ol/structs/lrucache.js @@ -0,0 +1,242 @@ +goog.provide('ol.structs.LRUCache'); + +goog.require('goog.asserts'); +goog.require('goog.object'); + + + +/** + * @constructor + * Implements a Least-Recently-Used cache where the keys do not conflict with + * Object's properties (e.g. 'hasOwnProperty' is not allowed as a key). Expiring + * items from the cache is the responsibility of the user. + */ +ol.structs.LRUCache = function() { + + /** + * @private + * @type {number} + */ + this.count_ = 0; + + /** + * @private + * @type {Object.} + */ + this.entries_ = {}; + + /** + * @private + * @type {?ol.structs.LRUCacheEntry} + */ + this.oldest_ = null; + + /** + * @private + * @type {?ol.structs.LRUCacheEntry} + */ + this.newest_ = null; + +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.structs.LRUCache.prototype.assertValid = function() { + if (this.count_ === 0) { + goog.asserts.assert(goog.object.isEmpty(this.entries_)); + goog.asserts.assert(goog.isNull(this.oldest_)); + goog.asserts.assert(goog.isNull(this.newest_)); + } else { + goog.asserts.assert(goog.object.getCount(this.entries_) == this.count_); + goog.asserts.assert(!goog.isNull(this.oldest_)); + goog.asserts.assert(goog.isNull(this.oldest_.older)); + goog.asserts.assert(!goog.isNull(this.newest_)); + goog.asserts.assert(goog.isNull(this.newest_.newer)); + var i, entry; + var older = null; + i = 0; + for (entry = this.oldest_; !goog.isNull(entry); entry = entry.newer) { + goog.asserts.assert(entry.older === older); + older = entry; + ++i; + } + goog.asserts.assert(i == this.count_); + var newer = null; + i = 0; + for (entry = this.newest_; !goog.isNull(entry); entry = entry.older) { + goog.asserts.assert(entry.newer === newer); + newer = entry; + ++i; + } + goog.asserts.assert(i == this.count_); + } +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.structs.LRUCache.prototype.clear = function() { + this.count_ = 0; + this.entries_ = {}; + this.oldest_ = null; + this.newest_ = null; +}; + + +/** + * @param {string} key Key. + * @return {boolean} Contains key. + */ +ol.structs.LRUCache.prototype.containsKey = function(key) { + return this.entries_.hasOwnProperty(key); +}; + + +/** + * @param {Function} f Function. + * @param {Object=} opt_obj Object. + */ +ol.structs.LRUCache.prototype.forEach = function(f, opt_obj) { + var entry = this.oldest_; + while (!goog.isNull(entry)) { + f.call(opt_obj, entry.value_, entry.key_, this); + entry = entry.newer; + } +}; + + +/** + * @param {string} key Key. + * @return {*} Value. + */ +ol.structs.LRUCache.prototype.get = function(key) { + var entry = this.entries_[key]; + goog.asserts.assert(goog.isDef(entry)); + if (entry === this.newest_) { + return entry.value_; + } else if (entry === this.oldest_) { + this.oldest_ = this.oldest_.newer; + this.oldest_.older = null; + } else { + entry.newer.older = entry.older; + entry.older.newer = entry.newer; + } + entry.newer = null; + entry.older = this.newest_; + this.newest_.newer = entry; + this.newest_ = entry; + return entry.value_; +}; + + +/** + * @return {number} Count. + */ +ol.structs.LRUCache.prototype.getCount = function() { + return this.count_; +}; + + +/** + * @return {Array.} Keys. + */ +ol.structs.LRUCache.prototype.getKeys = function() { + var keys = new Array(this.count_); + var i = 0; + var entry; + for (entry = this.newest_; !goog.isNull(entry); entry = entry.older) { + keys[i++] = entry.key_; + } + goog.asserts.assert(i == this.count_); + return keys; +}; + + +/** + * @return {Array} Values. + */ +ol.structs.LRUCache.prototype.getValues = function() { + var values = new Array(this.count_); + var i = 0; + var entry; + for (entry = this.newest_; !goog.isNull(entry); entry = entry.older) { + values[i++] = entry.value_; + } + goog.asserts.assert(i == this.count_); + return values; +}; + + +/** + * @return {*} Last value. + */ +ol.structs.LRUCache.prototype.peekLast = function() { + goog.asserts.assert(!goog.isNull(this.oldest_)); + return this.oldest_.value_; +}; + + +/** + * @return {string} Last key. + */ +ol.structs.LRUCache.prototype.peekLastKey = function() { + goog.asserts.assert(!goog.isNull(this.oldest_)); + return this.oldest_.key_; +}; + + +/** + * @return {*} value Value. + */ +ol.structs.LRUCache.prototype.pop = function() { + goog.asserts.assert(!goog.isNull(this.oldest_)); + goog.asserts.assert(!goog.isNull(this.newest_)); + var entry = this.oldest_; + goog.asserts.assert(entry.key_ in this.entries_); + delete this.entries_[entry.key_]; + if (!goog.isNull(entry.newer)) { + entry.newer.older = null; + } + this.oldest_ = entry.newer; + if (goog.isNull(this.oldest_)) { + this.newest_ = null; + } + --this.count_; + return entry.value_; +}; + + +/** + * @param {string} key Key. + * @param {*} value Value. + */ +ol.structs.LRUCache.prototype.set = function(key, value) { + goog.asserts.assert(!(key in {})); + goog.asserts.assert(!(key in this.entries_)); + var entry = { + key_: key, + newer: null, + older: this.newest_, + value_: value + }; + if (goog.isNull(this.newest_)) { + this.oldest_ = entry; + } else { + this.newest_.newer = entry; + } + this.newest_ = entry; + this.entries_[key] = entry; + ++this.count_; +}; + + +/** + * @typedef {{key_: string, + * newer: ol.structs.LRUCacheEntry, + * older: ol.structs.LRUCacheEntry, + * value_: *}} + */ +ol.structs.LRUCacheEntry; diff --git a/master/ol/ol/tile.js b/master/ol/ol/tile.js new file mode 100644 index 0000000000..c343c5b908 --- /dev/null +++ b/master/ol/ol/tile.js @@ -0,0 +1,84 @@ +// FIXME should inQueue be private? + +goog.provide('ol.Tile'); +goog.provide('ol.TileState'); + +goog.require('goog.events'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('ol.TileCoord'); + + +/** + * @enum {number} + */ +ol.TileState = { + IDLE: 0, + LOADING: 1, + LOADED: 2, + ERROR: 3, + EMPTY: 4 +}; + + + +/** + * @constructor + * @extends {goog.events.EventTarget} + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {ol.TileState} state State. + */ +ol.Tile = function(tileCoord, state) { + + goog.base(this); + + /** + * @type {ol.TileCoord} + */ + this.tileCoord = tileCoord; + + /** + * @protected + * @type {ol.TileState} + */ + this.state = state; + +}; +goog.inherits(ol.Tile, goog.events.EventTarget); + + +/** + * @protected + */ +ol.Tile.prototype.dispatchChangeEvent = function() { + this.dispatchEvent(goog.events.EventType.CHANGE); +}; + + +/** + * @param {Object=} opt_context Object. + * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image. + */ +ol.Tile.prototype.getImage = goog.abstractMethod; + + +/** + * @return {string} Key. + */ +ol.Tile.prototype.getKey = function() { + return goog.getUid(this).toString(); +}; + + +/** + * @return {ol.TileState} State. + */ +ol.Tile.prototype.getState = function() { + return this.state; +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.Tile.prototype.load = goog.abstractMethod; diff --git a/master/ol/ol/tilecache.js b/master/ol/ol/tilecache.js new file mode 100644 index 0000000000..0fd289c2b9 --- /dev/null +++ b/master/ol/ol/tilecache.js @@ -0,0 +1,57 @@ +goog.provide('ol.TileCache'); + +goog.require('ol.Tile'); +goog.require('ol.TileRange'); +goog.require('ol.structs.LRUCache'); + + +/** + * @define {number} Default high water mark. + */ +ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK = 512; + + + +/** + * @constructor + * @extends {ol.structs.LRUCache} + * @param {number=} opt_highWaterMark High water mark. + */ +ol.TileCache = function(opt_highWaterMark) { + + goog.base(this); + + /** + * @private + * @type {number} + */ + this.highWaterMark_ = goog.isDef(opt_highWaterMark) ? + opt_highWaterMark : ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK; + +}; +goog.inherits(ol.TileCache, ol.structs.LRUCache); + + +/** + * @return {boolean} Can expire cache. + */ +ol.TileCache.prototype.canExpireCache = function() { + return this.getCount() > this.highWaterMark_; +}; + + +/** + * @param {Object.} usedTiles Used tiles. + */ +ol.TileCache.prototype.expireCache = function(usedTiles) { + var tile, zKey; + while (this.canExpireCache()) { + tile = /** @type {ol.Tile} */ (this.peekLast()); + zKey = tile.tileCoord.z.toString(); + if (zKey in usedTiles && usedTiles[zKey].contains(tile.tileCoord)) { + break; + } else { + this.pop(); + } + } +}; diff --git a/master/ol/ol/tilecoord.js b/master/ol/ol/tilecoord.js new file mode 100644 index 0000000000..2924614d89 --- /dev/null +++ b/master/ol/ol/tilecoord.js @@ -0,0 +1,115 @@ +goog.provide('ol.TileCoord'); + +goog.require('goog.array'); +goog.require('ol.Coordinate'); + + +/** + * @enum {number} + */ +ol.QuadKeyCharCode = { + ZERO: '0'.charCodeAt(0), + ONE: '1'.charCodeAt(0), + TWO: '2'.charCodeAt(0), + THREE: '3'.charCodeAt(0) +}; + + + +/** + * @constructor + * @extends {ol.Coordinate} + * @param {number} z Zoom level. + * @param {number} x X. + * @param {number} y Y. + */ +ol.TileCoord = function(z, x, y) { + + goog.base(this, x, y); + + /** + * @type {number} Zoom level + */ + this.z = z; + +}; +goog.inherits(ol.TileCoord, ol.Coordinate); + + +/** + * @param {string} quadKey Quad key. + * @return {ol.TileCoord} Tile coordinate. + */ +ol.TileCoord.createFromQuadKey = function(quadKey) { + var z = quadKey.length, x = 0, y = 0; + var mask = 1 << (z - 1); + var i; + for (i = 0; i < z; ++i) { + switch (quadKey.charCodeAt(i)) { + case ol.QuadKeyCharCode.ONE: + x += mask; + break; + case ol.QuadKeyCharCode.TWO: + y += mask; + break; + case ol.QuadKeyCharCode.THREE: + x += mask; + y += mask; + break; + } + mask >>= 1; + } + return new ol.TileCoord(z, x, y); +}; + + +/** + * @param {string} str String that follows pattern “z/x/y” where x, y and z are + * numbers. + * @return {ol.TileCoord} Tile coord. + */ +ol.TileCoord.createFromString = function(str) { + var v = str.split('/'); + v = goog.array.map(v, function(e, i, a) { + return parseInt(e, 10); + }); + return new ol.TileCoord(v[0], v[1], v[2]); +}; + + +/** + * @return {number} Hash. + */ +ol.TileCoord.prototype.hash = function() { + return (this.x << this.z) + this.y; +}; + + +/** + * @return {string} Quad key. + */ +ol.TileCoord.prototype.quadKey = function() { + var digits = new Array(this.z); + var mask = 1 << (this.z - 1); + var i, charCode; + for (i = 0; i < this.z; ++i) { + charCode = ol.QuadKeyCharCode.ZERO; + if (this.x & mask) { + charCode += 1; + } + if (this.y & mask) { + charCode += 2; + } + digits[i] = String.fromCharCode(charCode); + mask >>= 1; + } + return digits.join(''); +}; + + +/** + * @return {string} String. + */ +ol.TileCoord.prototype.toString = function() { + return [this.z, this.x, this.y].join('/'); +}; diff --git a/master/ol/ol/tilegrid/tilegrid.exports b/master/ol/ol/tilegrid/tilegrid.exports new file mode 100644 index 0000000000..f276cab084 --- /dev/null +++ b/master/ol/ol/tilegrid/tilegrid.exports @@ -0,0 +1 @@ +@exportClass ol.tilegrid.TileGrid ol.tilegrid.TileGridOptions diff --git a/master/ol/ol/tilegrid/tilegrid.js b/master/ol/ol/tilegrid/tilegrid.js new file mode 100644 index 0000000000..bcbbe26bd6 --- /dev/null +++ b/master/ol/ol/tilegrid/tilegrid.js @@ -0,0 +1,375 @@ +// FIXME cope with tile grids whose minium zoom is not zero + +goog.provide('ol.tilegrid.TileGrid'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.PixelBounds'); +goog.require('ol.Projection'); +goog.require('ol.Size'); +goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); +goog.require('ol.array'); + + +/** + * @define {number} Default tile size. + */ +ol.DEFAULT_TILE_SIZE = 256; + + +/** + * @define {number} Default maximum zoom for default tile grids. + */ +ol.DEFAULT_MAX_ZOOM = 42; + + + +/** + * @constructor + * @param {ol.tilegrid.TileGridOptions} tileGridOptions Tile grid options. + */ +ol.tilegrid.TileGrid = function(tileGridOptions) { + + /** + * @private + * @type {!Array.} + */ + this.resolutions_ = tileGridOptions.resolutions; + goog.asserts.assert(goog.array.isSorted(this.resolutions_, function(a, b) { + return b - a; + }, true)); + + /** + * @private + * @type {number} + */ + this.numResolutions_ = this.resolutions_.length; + + /** + * @private + * @type {ol.Coordinate} + */ + this.origin_ = goog.isDef(tileGridOptions.origin) ? + tileGridOptions.origin : null; + + /** + * @private + * @type {Array.} + */ + this.origins_ = null; + if (goog.isDef(tileGridOptions.origins)) { + this.origins_ = tileGridOptions.origins; + goog.asserts.assert(this.origins_.length == this.resolutions_.length); + } + goog.asserts.assert( + (goog.isNull(this.origin_) && !goog.isNull(this.origins_)) || + (!goog.isNull(this.origin_) && goog.isNull(this.origins_))); + + /** + * @private + * @type {Array.} + */ + this.tileSizes_ = null; + if (goog.isDef(tileGridOptions.tileSizes)) { + this.tileSizes_ = tileGridOptions.tileSizes; + goog.asserts.assert(this.tileSizes_.length == this.resolutions_.length); + } + + /** + * @private + * @type {ol.Size} + */ + this.tileSize_ = goog.isDef(tileGridOptions.tileSize) ? + tileGridOptions.tileSize : + goog.isNull(this.tileSizes_) ? + new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE) : null; + goog.asserts.assert( + (goog.isNull(this.tileSize_) && !goog.isNull(this.tileSizes_)) || + (!goog.isNull(this.tileSize_) && goog.isNull(this.tileSizes_))); + +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {function(this: T, number, ol.TileRange): boolean} callback Callback. + * @param {T=} opt_obj Object. + * @template T + */ +ol.tilegrid.TileGrid.prototype.forEachTileCoordParentTileRange = + function(tileCoord, callback, opt_obj) { + var tileCoordExtent = this.getTileCoordExtent(tileCoord); + var z = tileCoord.z - 1; + while (z >= 0) { + if (callback.call( + opt_obj, z, this.getTileRangeForExtentAndZ(tileCoordExtent, z))) { + return; + } + --z; + } +}; + + +/** + * @param {number} z Z. + * @return {ol.Coordinate} Origin. + */ +ol.tilegrid.TileGrid.prototype.getOrigin = function(z) { + if (!goog.isNull(this.origin_)) { + return this.origin_; + } else { + goog.asserts.assert(!goog.isNull(this.origins_)); + goog.asserts.assert(0 <= z && z < this.origins_.length); + return this.origins_[z]; + } +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {number} resolution Resolution. + * @return {ol.PixelBounds} Pixel bounds. + */ +ol.tilegrid.TileGrid.prototype.getPixelBoundsForTileCoordAndResolution = + function(tileCoord, resolution) { + var scale = resolution / this.getResolution(tileCoord.z); + var tileSize = this.getTileSize(tileCoord.z); + tileSize = new ol.Size(tileSize.width / scale, + tileSize.height / scale); + var minX, maxX, minY, maxY; + minX = Math.round(tileCoord.x * tileSize.width); + maxX = Math.round((tileCoord.x + 1) * tileSize.width); + minY = Math.round(tileCoord.y * tileSize.height); + maxY = Math.round((tileCoord.y + 1) * tileSize.height); + return new ol.PixelBounds(minX, minY, maxX, maxY); +}; + + +/** + * @param {number} z Z. + * @return {number} Resolution. + */ +ol.tilegrid.TileGrid.prototype.getResolution = function(z) { + goog.asserts.assert(0 <= z && z < this.numResolutions_); + return this.resolutions_[z]; +}; + + +/** + * @return {Array.} Resolutions. + */ +ol.tilegrid.TileGrid.prototype.getResolutions = function() { + return this.resolutions_; +}; + + +/** + * @param {number} z Z. + * @param {ol.TileRange} tileRange Tile range. + * @return {ol.Extent} Extent. + */ +ol.tilegrid.TileGrid.prototype.getTileRangeExtent = function(z, tileRange) { + var origin = this.getOrigin(z); + var resolution = this.getResolution(z); + var tileSize = this.getTileSize(z); + var minX = origin.x + tileRange.minX * tileSize.width * resolution; + var minY = origin.y + tileRange.minY * tileSize.height * resolution; + var maxX = origin.x + (tileRange.maxX + 1) * tileSize.width * resolution; + var maxY = origin.y + (tileRange.maxY + 1) * tileSize.height * resolution; + return new ol.Extent(minX, minY, maxX, maxY); +}; + + +/** + * @param {ol.Extent} extent Extent. + * @param {number} resolution Resolution. + * @return {ol.TileRange} Tile range. + */ +ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndResolution = function( + extent, resolution) { + var min = this.getTileCoordForCoordAndResolution_( + new ol.Coordinate(extent.minX, extent.minY), resolution); + var max = this.getTileCoordForCoordAndResolution_( + new ol.Coordinate(extent.maxX, extent.maxY), resolution, true); + return new ol.TileRange(min.x, min.y, max.x, max.y); +}; + + +/** + * @param {ol.Extent} extent Extent. + * @param {number} z Z. + * @return {ol.TileRange} Tile range. + */ +ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndZ = function(extent, z) { + var resolution = this.getResolution(z); + return this.getTileRangeForExtentAndResolution(extent, resolution); +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @return {ol.Coordinate} Tile center. + */ +ol.tilegrid.TileGrid.prototype.getTileCoordCenter = function(tileCoord) { + var origin = this.getOrigin(tileCoord.z); + var resolution = this.getResolution(tileCoord.z); + var tileSize = this.getTileSize(tileCoord.z); + var x = origin.x + (tileCoord.x + 0.5) * tileSize.width * resolution; + var y = origin.y + (tileCoord.y + 0.5) * tileSize.height * resolution; + return new ol.Coordinate(x, y); +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @return {ol.Extent} Extent. + */ +ol.tilegrid.TileGrid.prototype.getTileCoordExtent = function(tileCoord) { + var origin = this.getOrigin(tileCoord.z); + var resolution = this.getResolution(tileCoord.z); + var tileSize = this.getTileSize(tileCoord.z); + var minX = origin.x + tileCoord.x * tileSize.width * resolution; + var minY = origin.y + tileCoord.y * tileSize.height * resolution; + var maxX = minX + tileSize.width * resolution; + var maxY = minY + tileSize.height * resolution; + return new ol.Extent(minX, minY, maxX, maxY); +}; + + +/** + * Get the tile coordinate for the given map coordinate and resolution. This + * method considers that coordinates that intersect tile boundaries should be + * assigned the higher tile coordinate. + * + * @param {ol.Coordinate} coordinate Coordinate. + * @param {number} resolution Resolution. + * @return {ol.TileCoord} Tile coordinate. + */ +ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution = function( + coordinate, resolution) { + return this.getTileCoordForCoordAndResolution_(coordinate, resolution); +}; + + +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @param {number} resolution Resolution. + * @param {boolean=} opt_reverseIntersectionPolicy Instead of letting edge + * intersections go to the higher tile coordinate, let edge intersections + * go to the lower tile coordinate. + * @return {ol.TileCoord} Tile coordinate. + * @private + */ +ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution_ = function( + coordinate, resolution, opt_reverseIntersectionPolicy) { + var z = this.getZForResolution(resolution); + var scale = resolution / this.getResolution(z); + var origin = this.getOrigin(z); + var tileSize = this.getTileSize(z); + + var x = scale * (coordinate.x - origin.x) / (resolution * tileSize.width); + var y = scale * (coordinate.y - origin.y) / (resolution * tileSize.height); + + if (!opt_reverseIntersectionPolicy) { + x = Math.floor(x); + y = Math.floor(y); + } else { + x = Math.ceil(x) - 1; + y = Math.ceil(y) - 1; + } + + return new ol.TileCoord(z, x, y); +}; + + +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @param {number} z Z. + * @return {ol.TileCoord} Tile coordinate. + */ +ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndZ = + function(coordinate, z) { + var resolution = this.getResolution(z); + return this.getTileCoordForCoordAndResolution_(coordinate, resolution); +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @return {number} Tile resolution. + */ +ol.tilegrid.TileGrid.prototype.getTileCoordResolution = function(tileCoord) { + goog.asserts.assert(0 <= tileCoord.z && tileCoord.z < this.numResolutions_); + return this.resolutions_[tileCoord.z]; +}; + + +/** + * @param {number} z Z. + * @return {ol.Size} Tile size. + */ +ol.tilegrid.TileGrid.prototype.getTileSize = function(z) { + if (!goog.isNull(this.tileSize_)) { + return this.tileSize_; + } else { + goog.asserts.assert(!goog.isNull(this.tileSizes_)); + goog.asserts.assert(0 <= z && z < this.tileSizes_.length); + return this.tileSizes_[z]; + } +}; + + +/** + * @param {number} resolution Resolution. + * @return {number} Z. + */ +ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) { + return ol.array.linearFindNearest(this.resolutions_, resolution); +}; + + +/** + * @param {ol.Projection} projection Projection. + * @return {ol.tilegrid.TileGrid} Default tile grid for the passed projection. + */ +ol.tilegrid.getForProjection = function(projection) { + var tileGrid = projection.getDefaultTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.createForProjection(projection); + projection.setDefaultTileGrid(tileGrid); + } + return tileGrid; +}; + + +/** + * @param {ol.Projection} projection Projection. + * @param {number=} opt_maxZoom Maximum zoom level. + * @param {ol.Size=} opt_tileSize Tile size. + * @return {ol.tilegrid.TileGrid} TileGrid instance. + */ +ol.tilegrid.createForProjection = + function(projection, opt_maxZoom, opt_tileSize) { + var projectionExtent = projection.getExtent(); + var size = Math.max( + projectionExtent.maxX - projectionExtent.minX, + projectionExtent.maxY - projectionExtent.minY); + var maxZoom = goog.isDef(opt_maxZoom) ? + opt_maxZoom : ol.DEFAULT_MAX_ZOOM; + var tileSize = goog.isDef(opt_tileSize) ? + opt_tileSize : new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE); + var resolutions = new Array(maxZoom + 1); + goog.asserts.assert(tileSize.width == tileSize.height); + size = size / tileSize.width; + for (var z = 0, zz = resolutions.length; z < zz; ++z) { + resolutions[z] = size / Math.pow(2, z); + } + return new ol.tilegrid.TileGrid({ + origin: projectionExtent.getTopLeft(), + resolutions: resolutions, + tileSize: tileSize + }); +}; diff --git a/master/ol/ol/tilegrid/xyztilegrid.exports b/master/ol/ol/tilegrid/xyztilegrid.exports new file mode 100644 index 0000000000..dd5b52245c --- /dev/null +++ b/master/ol/ol/tilegrid/xyztilegrid.exports @@ -0,0 +1 @@ +@exportClass ol.tilegrid.XYZ ol.tilegrid.XYZOptions diff --git a/master/ol/ol/tilegrid/xyztilegrid.js b/master/ol/ol/tilegrid/xyztilegrid.js new file mode 100644 index 0000000000..25270ec0eb --- /dev/null +++ b/master/ol/ol/tilegrid/xyztilegrid.js @@ -0,0 +1,58 @@ +goog.provide('ol.tilegrid.XYZ'); + +goog.require('ol.Coordinate'); +goog.require('ol.Size'); +goog.require('ol.TileRange'); +goog.require('ol.projection'); +goog.require('ol.projection.EPSG3857'); +goog.require('ol.tilegrid.TileGrid'); + + + +/** + * @constructor + * @extends {ol.tilegrid.TileGrid} + * @param {ol.tilegrid.XYZOptions} xyzOptions XYZ options. + */ +ol.tilegrid.XYZ = function(xyzOptions) { + + var resolutions = new Array(xyzOptions.maxZoom + 1); + var z; + var size = 2 * ol.projection.EPSG3857.HALF_SIZE / ol.DEFAULT_TILE_SIZE; + for (z = 0; z <= xyzOptions.maxZoom; ++z) { + resolutions[z] = size / Math.pow(2, z); + } + + goog.base(this, { + origin: new ol.Coordinate(-ol.projection.EPSG3857.HALF_SIZE, + ol.projection.EPSG3857.HALF_SIZE), + resolutions: resolutions, + tileSize: new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE) + }); + +}; +goog.inherits(ol.tilegrid.XYZ, ol.tilegrid.TileGrid); + + +/** + * @inheritDoc + */ +ol.tilegrid.XYZ.prototype.forEachTileCoordParentTileRange = + function(tileCoord, callback, opt_obj) { + var x = tileCoord.x; + var y = tileCoord.y; + var z = tileCoord.z; + var tileRange; + while (true) { + z -= 1; + if (z < 0) { + break; + } + x >>= 1; + y >>= 1; + tileRange = new ol.TileRange(x, y, x, y); + if (callback.call(opt_obj, z, tileRange)) { + break; + } + } +}; diff --git a/master/ol/ol/tilequeue.js b/master/ol/ol/tilequeue.js new file mode 100644 index 0000000000..36316c39a2 --- /dev/null +++ b/master/ol/ol/tilequeue.js @@ -0,0 +1,257 @@ +goog.provide('ol.TilePriorityFunction'); +goog.provide('ol.TileQueue'); + +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('ol.Coordinate'); +goog.require('ol.Tile'); +goog.require('ol.TileState'); + + +/** + * Tile Queue. + * + * The implementation is inspired from the Closure Library's Heap + * class and Python's heapq module. + * + * http://closure-library.googlecode.com/svn/docs/closure_goog_structs_heap.js.source.html + * http://hg.python.org/cpython/file/2.7/Lib/heapq.py + */ + + +/** + * @typedef {function(ol.Tile, string, ol.Coordinate): number} + */ +ol.TilePriorityFunction; + + + +/** + * @constructor + * @param {ol.TilePriorityFunction} tilePriorityFunction + * Tile priority function. + */ +ol.TileQueue = function(tilePriorityFunction) { + + /** + * @private + * @type {ol.TilePriorityFunction} + */ + this.tilePriorityFunction_ = tilePriorityFunction; + + /** + * @private + * @type {number} + */ + this.maxTilesLoading_ = 8; + + /** + * @private + * @type {number} + */ + this.tilesLoading_ = 0; + + /** + * @private + * @type {Array.>} + */ + this.heap_ = []; + + /** + * @private + * @type {Object.} + */ + this.queuedTileKeys_ = {}; + +}; + + +/** + * @const {number} + */ +ol.TileQueue.DROP = Infinity; + + +/** + * Remove and return the highest-priority tile. O(logn). + * @private + * @return {ol.Tile} Tile. + */ +ol.TileQueue.prototype.dequeue_ = function() { + var heap = this.heap_; + goog.asserts.assert(heap.length > 0); + var tile = /** @type {ol.Tile} */ (heap[0][1]); + if (heap.length == 1) { + heap.length = 0; + } else { + heap[0] = heap.pop(); + this.siftUp_(0); + } + var tileKey = tile.getKey(); + delete this.queuedTileKeys_[tileKey]; + return tile; +}; + + +/** + * Enqueue a tile. O(logn). + * @param {ol.Tile} tile Tile. + * @param {string} tileSourceKey Tile source key. + * @param {ol.Coordinate} tileCenter Tile center. + */ +ol.TileQueue.prototype.enqueue = function(tile, tileSourceKey, tileCenter) { + if (tile.getState() != ol.TileState.IDLE) { + return; + } + var tileKey = tile.getKey(); + if (!(tileKey in this.queuedTileKeys_)) { + var priority = this.tilePriorityFunction_(tile, tileSourceKey, tileCenter); + if (priority != ol.TileQueue.DROP) { + this.heap_.push([priority, tile, tileSourceKey, tileCenter]); + this.queuedTileKeys_[tileKey] = true; + this.siftDown_(0, this.heap_.length - 1); + } + } +}; + + +/** + * @protected + */ +ol.TileQueue.prototype.handleTileChange = function() { + --this.tilesLoading_; +}; + + +/** + * Gets the index of the left child of the node at the given index. + * @param {number} index The index of the node to get the left child for. + * @return {number} The index of the left child. + * @private + */ +ol.TileQueue.prototype.getLeftChildIndex_ = function(index) { + return index * 2 + 1; +}; + + +/** + * Gets the index of the right child of the node at the given index. + * @param {number} index The index of the node to get the right child for. + * @return {number} The index of the right child. + * @private + */ +ol.TileQueue.prototype.getRightChildIndex_ = function(index) { + return index * 2 + 2; +}; + + +/** + * Gets the index of the parent of the node at the given index. + * @param {number} index The index of the node to get the parent for. + * @return {number} The index of the parent. + * @private + */ +ol.TileQueue.prototype.getParentIndex_ = function(index) { + return (index - 1) >> 1; +}; + + +/** + * Make _heap a heap. O(n). + * @private + */ +ol.TileQueue.prototype.heapify_ = function() { + for (var i = (this.heap_.length >> 1) - 1; i >= 0; i--) { + this.siftUp_(i); + } +}; + + +/** + * @return {boolean} New loading tiles? + */ +ol.TileQueue.prototype.loadMoreTiles = function() { + var tile; + while (this.heap_.length > 0 && this.tilesLoading_ < this.maxTilesLoading_) { + tile = /** @type {ol.Tile} */ (this.dequeue_()); + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, + this.handleTileChange, false, this); + tile.load(); + ++this.tilesLoading_; + } + return goog.isDef(tile); +}; + + +/** + * @param {number} index The index of the node to move down. + * @private + */ +ol.TileQueue.prototype.siftUp_ = function(index) { + var heap = this.heap_; + var count = heap.length; + var node = heap[index]; + var startIndex = index; + + while (index < (count >> 1)) { + var lIndex = this.getLeftChildIndex_(index); + var rIndex = this.getRightChildIndex_(index); + + var smallerChildIndex = rIndex < count && + heap[rIndex][0] < heap[lIndex][0] ? + rIndex : lIndex; + + heap[index] = heap[smallerChildIndex]; + index = smallerChildIndex; + } + + heap[index] = node; + this.siftDown_(startIndex, index); +}; + + +/** + * @param {number} startIndex The index of the root. + * @param {number} index The index of the node to move up. + * @private + */ +ol.TileQueue.prototype.siftDown_ = function(startIndex, index) { + var heap = this.heap_; + var node = heap[index]; + + while (index > startIndex) { + var parentIndex = this.getParentIndex_(index); + if (heap[parentIndex][0] > node[0]) { + heap[index] = heap[parentIndex]; + index = parentIndex; + } else { + break; + } + } + heap[index] = node; +}; + + +/** + * FIXME empty description for jsdoc + */ +ol.TileQueue.prototype.reprioritize = function() { + var heap = this.heap_; + var i, n = 0, node, priority, tile, tileCenter, tileKey, tileSourceKey; + for (i = 0; i < heap.length; ++i) { + node = heap[i]; + tile = /** @type {ol.Tile} */ (node[1]); + tileSourceKey = /** @type {string} */ (node[2]); + tileCenter = /** @type {ol.Coordinate} */ (node[3]); + priority = this.tilePriorityFunction_(tile, tileSourceKey, tileCenter); + if (priority == ol.TileQueue.DROP) { + tileKey = tile.getKey(); + delete this.queuedTileKeys_[tileKey]; + } else { + node[0] = priority; + heap[n++] = node; + } + } + heap.length = n; + this.heapify_(); +}; diff --git a/master/ol/ol/tilerange.js b/master/ol/ol/tilerange.js new file mode 100644 index 0000000000..76d3d7437c --- /dev/null +++ b/master/ol/ol/tilerange.js @@ -0,0 +1,102 @@ +goog.provide('ol.TileRange'); + +goog.require('goog.asserts'); +goog.require('ol.Rectangle'); +goog.require('ol.TileCoord'); + + + +/** + * A representation of a contiguous block of tiles. A tile range is specified + * by its min/max tile coordinates and is inclusive of coordinates. + * + * @constructor + * @extends {ol.Rectangle} + * @param {number} minX Minimum X. + * @param {number} minY Minimum Y. + * @param {number} maxX Maximum X. + * @param {number} maxY Maximum Y. + */ +ol.TileRange = function(minX, minY, maxX, maxY) { + + /** + * @type {number} + */ + this.minX = minX; + + /** + * @type {number} + */ + this.minY = minY; + + /** + * @type {number} + */ + this.maxX = maxX; + + /** + * @type {number} + */ + this.maxY = maxY; + +}; +goog.inherits(ol.TileRange, ol.Rectangle); + + +/** + * @param {...ol.TileCoord} var_args Tile coordinates. + * @return {!ol.TileRange} Bounding tile box. + */ +ol.TileRange.boundingTileRange = function(var_args) { + var tileCoord0 = arguments[0]; + var tileRange = new ol.TileRange(tileCoord0.x, tileCoord0.y, + tileCoord0.x, tileCoord0.y); + var i, tileCoord; + for (i = 1; i < arguments.length; ++i) { + tileCoord = arguments[i]; + goog.asserts.assert(tileCoord.z == tileCoord0.z); + tileRange.minX = Math.min(tileRange.minX, tileCoord.x); + tileRange.minY = Math.min(tileRange.minY, tileCoord.y); + tileRange.maxX = Math.max(tileRange.maxX, tileCoord.x); + tileRange.maxY = Math.max(tileRange.maxY, tileCoord.y); + } + return tileRange; +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @return {boolean} Contains tile coordinate. + */ +ol.TileRange.prototype.contains = function(tileCoord) { + return this.minX <= tileCoord.x && tileCoord.x <= this.maxX && + this.minY <= tileCoord.y && tileCoord.y <= this.maxY; +}; + + +/** + * @param {ol.TileRange} tileRange Tile range. + * @return {boolean} Contains. + */ +ol.TileRange.prototype.containsTileRange = function(tileRange) { + return this.minX <= tileRange.minX && tileRange.maxX <= this.maxX && + this.minY <= tileRange.minY && tileRange.minY <= this.maxY; +}; + + +/** + * @inheritDoc + * @return {number} Height. + */ +ol.TileRange.prototype.getHeight = function() { + return this.maxY - this.minY + 1; +}; + + +/** + * @inheritDoc + * @return {number} Width. + */ +ol.TileRange.prototype.getWidth = function() { + return this.maxX - this.minX + 1; +}; diff --git a/master/ol/ol/tileurlfunction.js b/master/ol/ol/tileurlfunction.js new file mode 100644 index 0000000000..3c270b80c6 --- /dev/null +++ b/master/ol/ol/tileurlfunction.js @@ -0,0 +1,119 @@ +goog.provide('ol.TileUrlFunction'); +goog.provide('ol.TileUrlFunctionType'); + +goog.require('goog.array'); +goog.require('goog.math'); +goog.require('ol.TileCoord'); +goog.require('ol.source.wms'); +goog.require('ol.tilegrid.TileGrid'); + + +/** + * @typedef {function(ol.TileCoord, ol.tilegrid.TileGrid, ol.Projection): + * (string|undefined)} + */ +ol.TileUrlFunctionType; + + +/** + * @param {string} template Template. + * @return {ol.TileUrlFunctionType} Tile URL function. + */ +ol.TileUrlFunction.createFromTemplate = function(template) { + var match = + /\{(\d)-(\d)\}/.exec(template) || /\{([a-z])-([a-z])\}/.exec(template); + if (match) { + var templates = []; + var startCharCode = match[1].charCodeAt(0); + var stopCharCode = match[2].charCodeAt(0); + var charCode; + for (charCode = startCharCode; charCode <= stopCharCode; ++charCode) { + templates.push(template.replace(match[0], String.fromCharCode(charCode))); + } + return ol.TileUrlFunction.createFromTemplates(templates); + } else { + return function(tileCoord) { + if (goog.isNull(tileCoord)) { + return undefined; + } else { + return template.replace('{z}', tileCoord.z) + .replace('{x}', tileCoord.x) + .replace('{y}', tileCoord.y); + } + }; + } +}; + + +/** + * @param {Array.} templates Templates. + * @return {ol.TileUrlFunctionType} Tile URL function. + */ +ol.TileUrlFunction.createFromTemplates = function(templates) { + return ol.TileUrlFunction.createFromTileUrlFunctions( + goog.array.map(templates, ol.TileUrlFunction.createFromTemplate)); +}; + + +/** + * @param {Array.} tileUrlFunctions Tile URL Functions. + * @return {ol.TileUrlFunctionType} Tile URL function. + */ +ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) { + return function(tileCoord, tileGrid, projection) { + if (goog.isNull(tileCoord)) { + return undefined; + } else { + var index = goog.math.modulo(tileCoord.hash(), tileUrlFunctions.length); + return tileUrlFunctions[index](tileCoord, tileGrid, projection); + } + }; +}; + + +/** + * @param {string} baseUrl Base URL (may have query data). + * @param {Object.} params WMS parameters. + * @return {ol.TileUrlFunctionType} Tile URL function. + */ +ol.TileUrlFunction.createWMSParams = + function(baseUrl, params) { + return function(tileCoord, tileGrid, projection) { + if (goog.isNull(tileCoord)) { + return undefined; + } else { + var size = tileGrid.getTileSize(tileCoord.z); + var extent = tileGrid.getTileCoordExtent(tileCoord); + return ol.source.wms.getUrl( + baseUrl, params, extent, size, projection); + } + }; +}; + + +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @return {string|undefined} Tile URL. + */ +ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord) { + return undefined; +}; + + +/** + * @param {function(ol.TileCoord, ol.tilegrid.TileGrid, ol.Projection): + * ol.TileCoord} transformFn Transform.function. + * @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function. + * @return {ol.TileUrlFunctionType} Tile URL function. + */ +ol.TileUrlFunction.withTileCoordTransform = + function(transformFn, tileUrlFunction) { + return function(tileCoord, tileGrid, projection) { + if (goog.isNull(tileCoord)) { + return undefined; + } else { + return tileUrlFunction( + transformFn(tileCoord, tileGrid, projection), tileGrid, projection); + } + }; +}; diff --git a/master/ol/ol/transformfunction.js b/master/ol/ol/transformfunction.js new file mode 100644 index 0000000000..b5fb315d69 --- /dev/null +++ b/master/ol/ol/transformfunction.js @@ -0,0 +1,12 @@ +goog.provide('ol.TransformFunction'); + + +/** + * A transform function accepts an array of input coordinate values, an optional + * output array, and an optional dimension (default should be 2). The function + * transforms the input coordinate values, populates the output array, and + * returns the output array. + * + * @typedef {function(Array., Array.=, number=): Array.} + */ +ol.TransformFunction; diff --git a/master/ol/ol/vec/mat4.js b/master/ol/ol/vec/mat4.js new file mode 100644 index 0000000000..46535be877 --- /dev/null +++ b/master/ol/ol/vec/mat4.js @@ -0,0 +1,92 @@ +goog.provide('ol.vec.Mat4'); + +goog.require('goog.vec.Mat4'); + + +/** + * @param {!goog.vec.Mat4.Float32} matrix Matrix. + * @param {number} value Brightness value. + * @return {!goog.vec.Mat4.Float32} Matrix. + */ +ol.vec.Mat4.makeBrightness = function(matrix, value) { + goog.vec.Mat4.makeTranslate(matrix, value, value, value); + return matrix; +}; + + +/** + * @param {!goog.vec.Mat4.Float32} matrix Matrix. + * @param {number} value Contrast value. + * @return {!goog.vec.Mat4.Float32} Matrix. + */ +ol.vec.Mat4.makeContrast = function(matrix, value) { + goog.vec.Mat4.makeScale(matrix, value, value, value); + var translateValue = (-0.5 * value + 0.5); + goog.vec.Mat4.setColumnValues(matrix, 3, + translateValue, translateValue, translateValue, 1); + return matrix; +}; + + +/** + * @param {!goog.vec.Mat4.Float32} matrix Matrix. + * @param {number} value Hue value. + * @return {!goog.vec.Mat4.Float32} Matrix. + */ +ol.vec.Mat4.makeHue = function(matrix, value) { + var cosHue = Math.cos(value); + var sinHue = Math.sin(value); + var v00 = 0.213 + cosHue * 0.787 - sinHue * 0.213; + var v01 = 0.715 - cosHue * 0.715 - sinHue * 0.715; + var v02 = 0.072 - cosHue * 0.072 + sinHue * 0.928; + var v03 = 0; + var v10 = 0.213 - cosHue * 0.213 + sinHue * 0.143; + var v11 = 0.715 + cosHue * 0.285 + sinHue * 0.140; + var v12 = 0.072 - cosHue * 0.072 - sinHue * 0.283; + var v13 = 0; + var v20 = 0.213 - cosHue * 0.213 - sinHue * 0.787; + var v21 = 0.715 - cosHue * 0.715 + sinHue * 0.715; + var v22 = 0.072 + cosHue * 0.928 + sinHue * 0.072; + var v23 = 0; + var v30 = 0; + var v31 = 0; + var v32 = 0; + var v33 = 1; + goog.vec.Mat4.setFromValues(matrix, + v00, v10, v20, v30, + v01, v11, v21, v31, + v02, v12, v22, v32, + v03, v13, v23, v33); + return matrix; +}; + + +/** + * @param {!goog.vec.Mat4.Float32} matrix Matrix. + * @param {number} value Saturation value. + * @return {!goog.vec.Mat4.Float32} Matrix. + */ +ol.vec.Mat4.makeSaturation = function(matrix, value) { + var v00 = 0.213 + 0.787 * value; + var v01 = 0.715 - 0.715 * value; + var v02 = 0.072 - 0.072 * value; + var v03 = 0; + var v10 = 0.213 - 0.213 * value; + var v11 = 0.715 + 0.285 * value; + var v12 = 0.072 - 0.072 * value; + var v13 = 0; + var v20 = 0.213 - 0.213 * value; + var v21 = 0.715 - 0.715 * value; + var v22 = 0.072 + 0.928 * value; + var v23 = 0; + var v30 = 0; + var v31 = 0; + var v32 = 0; + var v33 = 1; + goog.vec.Mat4.setFromValues(matrix, + v00, v10, v20, v30, + v01, v11, v21, v31, + v02, v12, v22, v32, + v03, v13, v23, v33); + return matrix; +}; diff --git a/master/ol/ol/view.js b/master/ol/ol/view.js new file mode 100644 index 0000000000..61fba43f46 --- /dev/null +++ b/master/ol/ol/view.js @@ -0,0 +1,66 @@ +goog.provide('ol.View'); +goog.provide('ol.ViewHint'); + +goog.require('goog.array'); +goog.require('ol.IView'); +goog.require('ol.Object'); + + +/** + * @enum {number} + */ +ol.ViewHint = { + ANIMATING: 0, + INTERACTING: 1 +}; + + + +/** + * @constructor + * @implements {ol.IView} + * @extends {ol.Object} + */ +ol.View = function() { + + goog.base(this); + + /** + * @private + * @type {Array.} + */ + this.hints_ = [0, 0]; + +}; +goog.inherits(ol.View, ol.Object); + + +/** + * @return {Array.} Hint. + */ +ol.View.prototype.getHints = function() { + return goog.array.clone(this.hints_); +}; + + +/** + * @inheritDoc + */ +ol.View.prototype.getView2D = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.View.prototype.getView3D = goog.abstractMethod; + + +/** + * @param {ol.ViewHint} hint Hint. + * @param {number} delta Delta. + */ +ol.View.prototype.setHint = function(hint, delta) { + goog.asserts.assert(0 <= hint && hint < this.hints_.length); + this.hints_[hint] += delta; + goog.asserts.assert(this.hints_[hint] >= 0); +}; diff --git a/master/ol/ol/view2d.exports b/master/ol/ol/view2d.exports new file mode 100644 index 0000000000..1b45863062 --- /dev/null +++ b/master/ol/ol/view2d.exports @@ -0,0 +1,3 @@ +@exportClass ol.View2D ol.View2DOptions +@exportProperty ol.View2D.prototype.fitExtent +@exportProperty ol.View2D.prototype.getView2D diff --git a/master/ol/ol/view2d.js b/master/ol/ol/view2d.js new file mode 100644 index 0000000000..d33ac86875 --- /dev/null +++ b/master/ol/ol/view2d.js @@ -0,0 +1,445 @@ +// FIXME getView3D has not return type +// FIXME remove getExtent? + +goog.provide('ol.View2D'); +goog.provide('ol.View2DProperty'); + +goog.require('ol.Constraints'); +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.IView2D'); +goog.require('ol.IView3D'); +goog.require('ol.Projection'); +goog.require('ol.ResolutionConstraint'); +goog.require('ol.RotationConstraint'); +goog.require('ol.Size'); +goog.require('ol.View'); +goog.require('ol.animation'); +goog.require('ol.easing'); +goog.require('ol.projection'); + + +/** + * @enum {string} + */ +ol.View2DProperty = { + CENTER: 'center', + PROJECTION: 'projection', + RESOLUTION: 'resolution', + ROTATION: 'rotation' +}; + + + +/** + * @constructor + * @implements {ol.IView2D} + * @implements {ol.IView3D} + * @extends {ol.View} + * @param {ol.View2DOptions=} opt_view2DOptions View2D options. + */ +ol.View2D = function(opt_view2DOptions) { + goog.base(this); + var view2DOptions = opt_view2DOptions || {}; + + /** + * @type {Object.} + */ + var values = {}; + values[ol.View2DProperty.CENTER] = goog.isDef(view2DOptions.center) ? + view2DOptions.center : null; + values[ol.View2DProperty.PROJECTION] = ol.projection.createProjection( + view2DOptions.projection, 'EPSG:3857'); + if (goog.isDef(view2DOptions.resolution)) { + values[ol.View2DProperty.RESOLUTION] = view2DOptions.resolution; + } else if (goog.isDef(view2DOptions.zoom)) { + var projectionExtent = values[ol.View2DProperty.PROJECTION].getExtent(); + var size = Math.max( + projectionExtent.maxX - projectionExtent.minX, + projectionExtent.maxY - projectionExtent.minY); + values[ol.View2DProperty.RESOLUTION] = + size / (ol.DEFAULT_TILE_SIZE * Math.pow(2, view2DOptions.zoom)); + } + values[ol.View2DProperty.ROTATION] = view2DOptions.rotation; + this.setValues(values); + + /** + * @private + * @type {ol.Constraints} + */ + this.constraints_ = ol.View2D.createConstraints_(view2DOptions); + +}; +goog.inherits(ol.View2D, ol.View); + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getCenter = function() { + return /** @type {ol.Coordinate|undefined} */ ( + this.get(ol.View2DProperty.CENTER)); +}; +goog.exportProperty( + ol.View2D.prototype, + 'getCenter', + ol.View2D.prototype.getCenter); + + +/** + * @param {ol.Size} size Box pixel size. + * @return {ol.Extent} Extent. + */ +ol.View2D.prototype.getExtent = function(size) { + goog.asserts.assert(this.isDef()); + var center = this.getCenter(); + var resolution = this.getResolution(); + var minX = center.x - resolution * size.width / 2; + var minY = center.y - resolution * size.height / 2; + var maxX = center.x + resolution * size.width / 2; + var maxY = center.y + resolution * size.height / 2; + return new ol.Extent(minX, minY, maxX, maxY); +}; + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getProjection = function() { + return /** @type {ol.Projection|undefined} */ ( + this.get(ol.View2DProperty.PROJECTION)); +}; +goog.exportProperty( + ol.View2D.prototype, + 'getProjection', + ol.View2D.prototype.getProjection); + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getResolution = function() { + return /** @type {number|undefined} */ ( + this.get(ol.View2DProperty.RESOLUTION)); +}; +goog.exportProperty( + ol.View2D.prototype, + 'getResolution', + ol.View2D.prototype.getResolution); + + +/** + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Box pixel size. + * @return {number} Resolution. + */ +ol.View2D.prototype.getResolutionForExtent = function(extent, size) { + var xResolution = (extent.maxX - extent.minX) / size.width; + var yResolution = (extent.maxY - extent.minY) / size.height; + return Math.max(xResolution, yResolution); +}; + + +/** + * @return {number} Map rotation. + */ +ol.View2D.prototype.getRotation = function() { + return /** @type {number|undefined} */ ( + this.get(ol.View2DProperty.ROTATION)) || 0; +}; +goog.exportProperty( + ol.View2D.prototype, + 'getRotation', + ol.View2D.prototype.getRotation); + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getView2D = function() { + return this; +}; + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getView2DState = function() { + goog.asserts.assert(this.isDef()); + var center = /** @type {ol.Coordinate} */ (this.getCenter()); + var projection = /** @type {ol.Projection} */ (this.getProjection()); + var resolution = /** @type {number} */ (this.getResolution()); + var rotation = /** @type {number} */ (this.getRotation()); + return { + center: new ol.Coordinate(center.x, center.y), + projection: projection, + resolution: resolution, + rotation: rotation + }; +}; + + +/** + * FIXME return type + */ +ol.View2D.prototype.getView3D = function() { +}; + + +/** + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Box pixel size. + */ +ol.View2D.prototype.fitExtent = function(extent, size) { + this.setCenter(extent.getCenter()); + var resolution = this.getResolutionForExtent(extent, size); + resolution = this.constraints_.resolution(resolution, 0); + this.setResolution(resolution); +}; + + +/** + * @return {boolean} Is defined. + */ +ol.View2D.prototype.isDef = function() { + return goog.isDefAndNotNull(this.getCenter()) && + goog.isDef(this.getResolution()); +}; + + +/** + * @param {ol.Coordinate|undefined} center Center. + */ +ol.View2D.prototype.setCenter = function(center) { + this.set(ol.View2DProperty.CENTER, center); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setCenter', + ol.View2D.prototype.setCenter); + + +/** + * @param {ol.Projection|undefined} projection Projection. + */ +ol.View2D.prototype.setProjection = function(projection) { + this.set(ol.View2DProperty.PROJECTION, projection); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setProjection', + ol.View2D.prototype.setProjection); + + +/** + * @param {number|undefined} resolution Resolution. + */ +ol.View2D.prototype.setResolution = function(resolution) { + this.set(ol.View2DProperty.RESOLUTION, resolution); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setResolution', + ol.View2D.prototype.setResolution); + + +/** + * @param {number|undefined} rotation Rotation. + */ +ol.View2D.prototype.setRotation = function(rotation) { + this.set(ol.View2DProperty.ROTATION, rotation); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setRotation', + ol.View2D.prototype.setRotation); + + +/** + * @param {ol.Map} map Map. + * @param {ol.Coordinate} delta Delta. + * @param {number=} opt_duration Duration. + */ +ol.View2D.prototype.pan = function(map, delta, opt_duration) { + var currentCenter = this.getCenter(); + if (goog.isDef(currentCenter)) { + if (goog.isDef(opt_duration)) { + map.requestRenderFrame(); + map.addPreRenderFunction(ol.animation.pan({ + source: currentCenter, + duration: opt_duration, + easing: ol.easing.linear + })); + } + this.setCenter(new ol.Coordinate( + currentCenter.x + delta.x, currentCenter.y + delta.y)); + } +}; + + +/** + * @param {ol.Map} map Map. + * @param {number|undefined} rotation Rotation. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +ol.View2D.prototype.rotate = + function(map, rotation, opt_anchor, opt_duration) { + rotation = this.constraints_.rotation(rotation, 0); + this.rotateWithoutConstraints(map, rotation, opt_anchor, opt_duration); +}; + + +/** + * @param {ol.Map} map Map. + * @param {number|undefined} rotation Rotation. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +ol.View2D.prototype.rotateWithoutConstraints = + function(map, rotation, opt_anchor, opt_duration) { + if (goog.isDefAndNotNull(rotation)) { + var currentRotation = this.getRotation(); + var currentCenter = this.getCenter(); + if (goog.isDef(currentRotation) && goog.isDef(currentCenter) && + goog.isDef(opt_duration)) { + map.requestRenderFrame(); + map.addPreRenderFunction(ol.animation.rotate({ + rotation: currentRotation, + duration: opt_duration, + easing: ol.easing.easeOut + })); + if (goog.isDef(opt_anchor)) { + map.addPreRenderFunction(ol.animation.pan({ + source: currentCenter, + duration: opt_duration, + easing: ol.easing.easeOut + })); + } + } + if (goog.isDefAndNotNull(opt_anchor)) { + var anchor = opt_anchor; + var oldCenter = /** @type {!ol.Coordinate} */ (this.getCenter()); + var center = new ol.Coordinate( + oldCenter.x - anchor.x, + oldCenter.y - anchor.y); + center.rotate(rotation - this.getRotation()); + center.x += anchor.x; + center.y += anchor.y; + map.withFrozenRendering(function() { + this.setCenter(center); + this.setRotation(rotation); + }, this); + } else { + this.setRotation(rotation); + } + } +}; + + +/** + * @param {ol.Map} map Map. + * @param {number|undefined} resolution Resolution to go to. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +ol.View2D.prototype.zoom = + function(map, resolution, opt_anchor, opt_duration) { + resolution = this.constraints_.resolution(resolution, 0); + this.zoomWithoutConstraints(map, resolution, opt_anchor, opt_duration); +}; + + +/** + * @param {ol.Map} map Map. + * @param {number} delta Delta from previous zoom level. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +ol.View2D.prototype.zoomByDelta = + function(map, delta, opt_anchor, opt_duration) { + var currentResolution = this.getResolution(); + var resolution = this.constraints_.resolution(currentResolution, delta); + this.zoomWithoutConstraints(map, resolution, opt_anchor, opt_duration); +}; + + +/** + * @param {ol.Map} map Map. + * @param {number|undefined} resolution Resolution to go to. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +ol.View2D.prototype.zoomWithoutConstraints = + function(map, resolution, opt_anchor, opt_duration) { + if (goog.isDefAndNotNull(resolution)) { + var currentResolution = this.getResolution(); + var currentCenter = this.getCenter(); + if (goog.isDef(currentResolution) && goog.isDef(currentCenter) && + goog.isDef(opt_duration)) { + map.requestRenderFrame(); + map.addPreRenderFunction(ol.animation.zoom({ + resolution: currentResolution, + duration: opt_duration, + easing: ol.easing.easeOut + })); + if (goog.isDef(opt_anchor)) { + map.addPreRenderFunction(ol.animation.pan({ + source: currentCenter, + duration: opt_duration, + easing: ol.easing.easeOut + })); + } + } + if (goog.isDefAndNotNull(opt_anchor)) { + var anchor = opt_anchor; + var oldCenter = /** @type {!ol.Coordinate} */ (this.getCenter()); + var oldResolution = this.getResolution(); + var x = anchor.x - resolution * (anchor.x - oldCenter.x) / oldResolution; + var y = anchor.y - resolution * (anchor.y - oldCenter.y) / oldResolution; + var center = new ol.Coordinate(x, y); + map.withFrozenRendering(function() { + this.setCenter(center); + this.setResolution(resolution); + }, this); + } else { + this.setResolution(resolution); + } + } +}; + + +/** + * @private + * @param {ol.View2DOptions} view2DOptions View2D options. + * @return {ol.Constraints} Constraints. + */ +ol.View2D.createConstraints_ = function(view2DOptions) { + var resolutionConstraint; + if (goog.isDef(view2DOptions.resolutions)) { + resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions( + view2DOptions.resolutions); + } else { + var maxResolution, numZoomLevels, zoomFactor; + if (goog.isDef(view2DOptions.maxResolution) && + goog.isDef(view2DOptions.numZoomLevels) && + goog.isDef(view2DOptions.zoomFactor)) { + maxResolution = view2DOptions.maxResolution; + numZoomLevels = view2DOptions.numZoomLevels; + zoomFactor = view2DOptions.zoomFactor; + } else { + var projectionExtent = ol.projection.createProjection( + view2DOptions.projection, 'EPSG:3857').getExtent(); + maxResolution = Math.max( + projectionExtent.maxX - projectionExtent.minX, + projectionExtent.maxY - projectionExtent.minY) / ol.DEFAULT_TILE_SIZE; + numZoomLevels = 29; + zoomFactor = 2; + } + resolutionConstraint = ol.ResolutionConstraint.createSnapToPower( + zoomFactor, maxResolution, numZoomLevels - 1); + } + // FIXME rotation constraint is not configurable at the moment + var rotationConstraint = ol.RotationConstraint.createSnapToZero(); + return new ol.Constraints(resolutionConstraint, rotationConstraint); +}; diff --git a/master/ol/ol/webgl/webgl.js b/master/ol/ol/webgl/webgl.js new file mode 100644 index 0000000000..83b6ccfc43 --- /dev/null +++ b/master/ol/ol/webgl/webgl.js @@ -0,0 +1,61 @@ +goog.provide('ol.webgl'); +goog.provide('ol.webgl.WebGLContextEventType'); + + +/** + * @const + * @private + * @type {Array.} + */ +ol.webgl.CONTEXT_IDS_ = [ + 'webgl', + 'webgl-experimental', + 'webkit-3d', + 'moz-webgl' +]; + + +/** + * @enum {string} + */ +ol.webgl.WebGLContextEventType = { + LOST: 'webglcontextlost', + RESTORED: 'webglcontextrestored' +}; + + +/** + * @param {Element} canvas Canvas. + * @param {Object=} opt_attributes Attributes. + * @return {WebGLRenderingContext} WebGL rendering context. + */ +ol.webgl.getContext = function(canvas, opt_attributes) { + var context, i, ii = ol.webgl.CONTEXT_IDS_.length; + for (i = 0; i < ii; ++i) { + try { + context = canvas.getContext(ol.webgl.CONTEXT_IDS_[i], opt_attributes); + if (!goog.isNull(context)) { + return context; + } + } catch (e) { + } + } + return null; +}; + + +/** + * @const + * @type {boolean} Is supported. + */ +ol.webgl.SUPPORTED = (function() { + if (!('WebGLRenderingContext' in goog.global)) { + return false; + } + try { + var canvas = goog.dom.createElement(goog.dom.TagName.CANVAS); + return !goog.isNull(ol.webgl.getContext(canvas)); + } catch (e) { + return false; + } +})();