1 (function ($, undefined) {
2 $.geo._serviceTypes.tiled = (function () {
4 create: function (map, serviceContainer, service, index) {
5 var serviceState = $.data(service, "geoServiceState");
13 var scHtml = '<div data-geo-service="tiled" style="-webkit-transform:translateZ(0); position:absolute; left:0; top:0; width:8px; height:8px; margin:0; padding:0;"></div>';
15 serviceContainer.append(scHtml);
17 serviceState.serviceContainer = serviceContainer.children( ":last" );
19 $.data(service, "geoServiceState", serviceState);
22 return serviceState.serviceContainer;
25 destroy: function (map, serviceContainer, service) {
26 var serviceState = $.data(service, "geoServiceState");
28 serviceState.serviceContainer.remove();
30 $.removeData(service, "geoServiceState");
33 interactiveTransform: function ( map, service, center, pixelSize ) {
34 //console.log( "tiled.interactiveTransform( " + center.join( ", " ) + ", " + pixelSize + ")" );
35 var serviceState = $.data( service, "geoServiceState" ),
36 tilingScheme = map.options[ "tilingScheme" ];
39 this._cancelUnloaded( map, service );
41 serviceState.serviceContainer.children( ).each( function ( i ) {
42 var $scaleContainer = $(this),
43 scalePixelSize = $scaleContainer.data("pixelSize"),
44 scaleRatio = scalePixelSize / pixelSize;
46 if ( scalePixelSize > 0 ) {
47 scaleRatio = Math.round(scaleRatio * 1000) / 1000;
49 var oldMapCoord = $scaleContainer.data("scaleOrigin"),
50 newPixelPoint = map._toPixel(oldMapCoord, center, pixelSize);
52 $scaleContainer.css( {
53 left: Math.round(newPixelPoint[0]) + "px",
54 top: Math.round(newPixelPoint[1]) + "px",
55 width: tilingScheme.tileWidth * scaleRatio,
56 height: tilingScheme.tileHeight * scaleRatio
60 if ( $("body")[0].filters !== undefined ) {
61 $scaleContainer.children().each( function ( i ) {
62 $( this ).css( "filter", "progid:DXImageTransform.Microsoft.Matrix(FilterType=bilinear,M11=" + scaleRatio + ",M22=" + scaleRatio + ",sizingmethod='auto expand')" );
71 refresh: function (map, service, force) {
72 //console.log( "tiled.refresh( " + map._center.join( ", " ) + ", " + map._pixelSize + ")" );
73 var serviceState = $.data( service, "geoServiceState" );
75 this._cancelUnloaded(map, service);
77 if ( serviceState && force ) {
78 // if hidden atm, we want to make sure we reload this service after it becomes visible
79 serviceState.reloadTiles = true;
82 if ( serviceState && service && service.style.visibility === "visible" && !( serviceState.serviceContainer.is( ":hidden" ) ) ) {
83 var bbox = map._getBbox(),
84 pixelSize = map._pixelSize,
87 $serviceContainer = serviceState.serviceContainer,
89 contentBounds = map._getContentBounds(),
90 mapWidth = contentBounds["width"],
91 mapHeight = contentBounds["height"],
93 image = map.options[ "axisLayout" ] === "image",
94 ySign = image ? +1 : -1,
96 tilingScheme = map.options["tilingScheme"],
97 tileWidth = tilingScheme.tileWidth,
98 tileHeight = tilingScheme.tileHeight,
100 tileX = Math.floor((bbox[0] - tilingScheme.origin[0]) / (pixelSize * tileWidth)),
101 tileY = Math.max( Math.floor( ( image ? bbox[1] - tilingScheme.origin[1] : tilingScheme.origin[1] - bbox[ 3 ] ) / (pixelSize * tileHeight) ), 0 ),
102 tileX2 = Math.ceil((bbox[2] - tilingScheme.origin[0]) / (pixelSize * tileWidth)),
103 tileY2 = Math.ceil( ( image ? bbox[3] - tilingScheme.origin[1] : tilingScheme.origin[1] - bbox[ 1 ] ) / (pixelSize * tileHeight) ),
105 bboxMax = map._getBboxMax(),
106 pixelSizeAtZero = map._getPixelSize(0),
107 ratio = pixelSizeAtZero / pixelSize,
108 fullXAtScale = Math.floor((bboxMax[0] - tilingScheme.origin[0]) / (pixelSizeAtZero * tileWidth)) * ratio,
109 fullYAtScale = Math.floor((tilingScheme.origin[1] + ySign * bboxMax[3]) / (pixelSizeAtZero * tileHeight)) * ratio,
111 fullXMinX = tilingScheme.origin[0] + (fullXAtScale * tileWidth) * pixelSize,
112 fullYMinOrMaxY = tilingScheme.origin[1] + ySign * (fullYAtScale * tileHeight) * pixelSize,
114 serviceLeft = Math.round((fullXMinX - bbox[0]) / pixelSize),
115 serviceTop = Math.round( ( image ? fullYMinOrMaxY - bbox[1] : bbox[3] - fullYMinOrMaxY ) / pixelSize),
117 scaleContainers = $serviceContainer.children().show(),
118 scaleContainer = scaleContainers.filter("[data-pixel-size='" + pixelSize + "']").appendTo($serviceContainer),
120 opacity = service.style.opacity,
124 loadImageDeferredDone = function( url ) {
125 // when a Deferred call is done, add the image to the map
126 // a reference to the correct img element is on the Deferred object itself
127 serviceObj._loadImage( $.data( this, "img" ), url, pixelSize, map, serviceState, opacity );
130 loadImageDeferredFail = function( ) {
131 $.data( this, "img" ).remove( );
132 serviceState.loadCount--;
133 map._requestComplete();
136 if (serviceState.reloadTiles) {
137 scaleContainers.find("img").attr("data-dirty", "true");
140 if (!scaleContainer.size()) {
141 $serviceContainer.append("<div style='-webkit-transform:translateZ(0);position:absolute; left:" + serviceLeft % tileWidth + "px; top:" + serviceTop % tileHeight + "px; width:" + tileWidth + "px; height:" + tileHeight + "px; margin:0; padding:0;' data-pixel-size='" + pixelSize + "'></div>");
142 scaleContainer = $serviceContainer.children(":last").data("scaleOrigin", map._toMap( [ (serviceLeft % tileWidth), (serviceTop % tileHeight) ] ) );
145 left: (serviceLeft % tileWidth) + "px",
146 top: (serviceTop % tileHeight) + "px"
147 }).data("scaleOrigin", map._toMap( [ (serviceLeft % tileWidth), (serviceTop % tileHeight) ] ) );
149 scaleContainer.children().each(function (i) {
152 tile = $img.attr("data-tile").split(",");
155 left: Math.round(((parseInt(tile[0], 10) - fullXAtScale) * 100) + (serviceLeft - (serviceLeft % tileWidth)) / tileWidth * 100) + "%",
156 top: Math.round(((parseInt(tile[1], 10) - fullYAtScale) * 100) + (serviceTop - (serviceTop % tileHeight)) / tileHeight * 100) + "%"
160 $img.fadeTo(0, opacity);
165 for (x = tileX; x < tileX2; x++) {
166 for (y = tileY; y < tileY2; y++) {
167 var tileStr = "" + x + "," + y,
168 $img = scaleContainer.children("[data-tile='" + tileStr + "']").removeAttr("data-dirty");
170 if ($img.size() === 0 || serviceState.reloadTiles) {
172 tilingScheme.origin[0] + (x * tileWidth) * pixelSize,
173 tilingScheme.origin[1] + ySign * (y * tileHeight) * pixelSize
177 tilingScheme.origin[0] + ((x + 1) * tileWidth - 1) * pixelSize,
178 tilingScheme.origin[1] + ySign * ((y + 1) * tileHeight - 1) * pixelSize
181 tileBbox = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]],
183 urlProp = ( service.hasOwnProperty( "src" ) ? "src" : "getUrl" ),
188 zoom: map._getZoom(),
193 index: Math.abs(y + x)
195 isFunc = $.isFunction( service[ urlProp ] ),
199 imageUrl = service[ urlProp ]( urlArgs );
201 $.templates( "geoSrc", service[ urlProp ] );
202 imageUrl = $.render[ "geoSrc" ]( urlArgs );
205 serviceState.loadCount++;
206 map._requestQueued();
208 if (serviceState.reloadTiles && $img.size() > 0) {
209 $img.attr("src", imageUrl);
211 var imgMarkup = "<img style='-webkit-transform:translateZ(0);position:absolute; " +
212 "left:" + (((x - fullXAtScale) * 100) + (serviceLeft - (serviceLeft % tileWidth)) / tileWidth * 100) + "%; " +
213 "top:" + (((y - fullYAtScale) * 100) + (serviceTop - (serviceTop % tileHeight)) / tileHeight * 100) + "%; ";
215 imgMarkup += "width: 100%; height: 100%;";
219 if ($("body")[0].filters === undefined) {
220 imgMarkup += "width: 100%; height: 100%;";
224 imgMarkup += "margin:0; padding:0; -khtml-user-select:none; -moz-user-select:none; -webkit-user-select:none; user-select:none; display:none;' unselectable='on' data-tile='" + tileStr + "' />";
226 scaleContainer.append(imgMarkup);
227 $img = scaleContainer.children(":last");
230 if ( typeof imageUrl === "string" ) {
231 serviceObj._loadImage( $img, imageUrl, pixelSize, map, serviceState, opacity );
232 } else if ( imageUrl ) {
234 $.data( imageUrl, "img", $img );
235 imageUrl.done( loadImageDeferredDone ).fail( loadImageDeferredFail );
243 scaleContainers.find("[data-dirty]").remove();
244 serviceState.reloadTiles = false;
248 resize: function (map, service) {
251 opacity: function ( map, service ) {
252 var serviceState = $.data( service, "geoServiceState" );
253 serviceState.serviceContainer.find( "img" ).stop( true ).fadeTo( "fast", service.style.opacity );
256 toggle: function ( map, service ) {
257 var serviceState = $.data( service, "geoServiceState" );
258 serviceState.serviceContainer.css( "display", service.style.visibility === "visible" ? "block" : "none" );
261 _cancelUnloaded: function (map, service) {
262 var serviceState = $.data( service, "geoServiceState" );
264 if (serviceState && serviceState.loadCount > 0) {
265 serviceState.serviceContainer.find("img:hidden").remove();
266 while (serviceState.loadCount > 0) {
267 serviceState.loadCount--;
268 map._requestComplete();
273 _loadImage: function ( $img, url, pixelSize, map, serviceState, opacity ) {
274 var serviceContainer = serviceState.serviceContainer;
276 $img.load(function (e) {
278 $(e.target).fadeTo(0, opacity);
283 serviceState.loadCount--;
284 map._requestComplete();
286 if (serviceState.loadCount <= 0) {
287 serviceContainer.children(":not([data-pixel-size='" + pixelSize + "'])").remove();
288 serviceState.loadCount = 0;
290 }).error(function (e) {
291 $(e.target).remove();
292 serviceState.loadCount--;
293 map._requestComplete();
295 if (serviceState.loadCount <= 0) {
296 serviceContainer.children(":not([data-pixel-size='" + pixelSize + "'])").remove();
297 serviceState.loadCount = 0;