X-Git-Url: https://dev.renevier.net/gitweb.cgi?p=syp.git;a=blobdiff_plain;f=js%2Fsyp.js;h=0f7785491f15a681bc556a81d0e089e7e39376a3;hp=afb53bc0db9d2116a14379a4d40d24f51991ca15;hb=42ad41096b29573ca0429b316d364195eac02e8e;hpb=a34fe8cb1b7f571577d4af4399d6a850fef07041 diff --git a/js/syp.js b/js/syp.js index afb53bc..0f77854 100644 --- a/js/syp.js +++ b/js/syp.js @@ -1,9 +1,76 @@ /* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD * license. */ +/* + * With canvas rendering engine, externalgraphics are drawn by loading and + * Image javascript object and drawing it with drawImage once it has been + * loaded. If matching feature is deleted while image is loading, redraw + * function will be called before drawImage and therefore, feature is removed, + * but image is still drawn on the screen. We fix it with locks: when an image is + * loading, we defer redraw method. + */ +OpenLayers.Renderer.Canvas.prototype = OpenLayers.Util.extend({ + needsRedraw: false, + imagesLoading: 0 +}, OpenLayers.Renderer.Canvas.prototype); +OpenLayers.Renderer.Canvas.prototype.oldRedraw = OpenLayers.Renderer.Canvas.prototype.redraw; +OpenLayers.Renderer.Canvas.prototype.redraw = function() { + if (this.imagesLoading > 0) { + this.needsRedraw = true; + return; + } + OpenLayers.Renderer.Canvas.prototype.oldRedraw.apply(this, arguments); +} +OpenLayers.Renderer.Canvas.prototype.drawExternalGraphic = function(pt, style) { + var img = new Image(); + img.src = style.externalGraphic; + + if(style.graphicTitle) { + img.title=style.graphicTitle; + } + + var width = style.graphicWidth || style.graphicHeight; + var height = style.graphicHeight || style.graphicWidth; + width = width ? width : style.pointRadius*2; + height = height ? height : style.pointRadius*2; + var xOffset = (style.graphicXOffset != undefined) ? + style.graphicXOffset : -(0.5 * width); + var yOffset = (style.graphicYOffset != undefined) ? + style.graphicYOffset : -(0.5 * height); + var opacity = style.graphicOpacity || style.fillOpacity; + + var context = { img: img, + x: (pt[0]+xOffset), + y: (pt[1]+yOffset), + width: width, + height: height, + canvas: this.canvas }; + + var self = this; + this.imagesLoading++; + img.onerror = function() { + self.imagesLoading--; + if ((self.imagesLoading == 0) && (self.needsRedraw)) { + self.needsRedraw = false; + self.redraw(); + } + } + img.onload = OpenLayers.Function.bind( function() { + self.imagesLoading--; + if ((self.imagesLoading == 0) && (self.needsRedraw)) { + self.needsRedraw = false; + self.redraw(); + } else { + this.canvas.drawImage(this.img, this.x, + this.y, this.width, this.height); + } + }, context); +} + + OpenLayers.Control.SypAttribution = OpenLayers.Class (OpenLayers.Control.Attribution, { updateAttribution: function() { - var attributions = [SypStrings.propulsedByLink]; + var attributions = [SypStrings.poweredByLink]; if (this.map && this.map.layers) { for(var i=0, len=this.map.layers.length; i 1) ? feature.attributes.count: ""; } } }); @@ -111,8 +188,8 @@ var SYP = { } var map = this.map; - if (map.getControlsByClass("OpenLayers.Control.ArgParser")[0].lat - == undefined) { // map center was not set in ArgParser control. + if (map.getControlsByClass("OpenLayers.Control.ArgParser")[0].center + == null) { // map center was not set in ArgParser control. var orig = this.Utils.mbr (this.dataLayer); var centerBounds = new OpenLayers.Bounds(); @@ -169,11 +246,36 @@ var SYP = { } }, + onZoomClusterEnd: function(arg) { + var map = arg.object; + var point = new OpenLayers.Geometry.Point(this.lonlat.lon, this.lonlat.lat); + var center = map.getCenter(); + for (var i = this.layer.features.length; i-->0;) { + var feature = this.layer.features[i]; + if (feature.geometry.equals(point) && + (feature.attributes.count == this.count)) { + var self = this; + window.setTimeout(function() { map.setCenter(self.lonlat, map.zoom + 1)}, 500); + return; + } + } + SYP.selectControl.activate(); + map.events.unregister("zoomend", this, SYP.onZoomClusterEnd); + }, + onFeatureSelect: function(feature) { var map = feature.layer.map; + if (feature.attributes.count > 1) { this.unselect(feature); var lonlat = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y); + var args = { + lonlat: lonlat, + layer: feature.layer, + count: feature.attributes.count + } + map.events.register("zoomend", args, SYP.onZoomClusterEnd); + SYP.selectControl.deactivate(); map.setCenter(lonlat, map.zoom + 1); return; } @@ -212,8 +314,9 @@ var SYP = { } var contentHTML; if (feature.cluster[0].attributes.name) { + // escaping name is necessary because it's not enclosed in another html tag. contentHTML = "

" + - feature.cluster[0].attributes.name + + SYP.Utils.escapeHTML(feature.cluster[0].attributes.name) + "

" + feature.cluster[0].attributes.description; } else { @@ -241,11 +344,12 @@ var SYP = { }, showBigImage: function (href) { - try { - document.getElementById('bigimg_container').style.display = "table"; - } catch(e) { + if (OpenLayers.Util.getBrowserName() == "msie") { document.getElementById('bigimg_container').style.display = "block"; + } else { + document.getElementById('bigimg_container').style.display = "table"; } + var maxHeight = document.body.clientHeight * 0.9; var maxWidth = document.body.clientWidth * 0.9; document.getElementById('bigimg').style.height = ""; @@ -263,9 +367,18 @@ var SYP = { } } + var offsetTop = this.offsetTop; + var offsetLeft = this.offsetLeft; + var par = this.offsetParent; + var ismsie = OpenLayers.Util.getBrowserName() == "msie"; + while (par && !ismsie) { + offsetTop += par.offsetTop; + offsetLeft += par.offsetLeft; + par = par.offsetParent; + } var icon = document.getElementById('bigimg_close'); - icon.style.top = this.offsetTop; - icon.style.left = this.offsetLeft + this.clientWidth - icon.clientWidth; + icon.style.top = offsetTop; + icon.style.left = offsetLeft + this.clientWidth - icon.clientWidth; }; document.getElementById('bigimg').src = href; @@ -383,6 +496,18 @@ var SYP = { } div.style.display = "block"; div.appendChild(textNode); + }, + + escapeHTML: function (str) { + if (!str) { + return ""; + } + return str. + replace(/&/gm, '&'). + replace(/'/gm, '''). + replace(/"/gm, '"'). + replace(/>/gm, '>'). + replace(/" + - this.contentDiv.innerHTML + - ""; - - var containerElement = (this.map) ? this.map.layerContainerDiv - : document.body; - var realSize = OpenLayers.Util.getRenderedDimensions( - preparedHTML, null, { - displayClass: this.displayClass, - containerElement: containerElement + var self = this; + + window.setTimeout(function() { // timeout added by SYP + + // determine actual render dimensions of the contents by putting its + // contents into a fake contentDiv (for the CSS) and then measuring it + var preparedHTML = "
" + + self.contentDiv.innerHTML + + "
"; + + var containerElement = (self.map) ? self.map.layerContainerDiv + : document.body; + var realSize = OpenLayers.Util.getRenderedDimensions( + preparedHTML, null, { + displayClass: self.displayClass, + containerElement: containerElement + } + ); + + /* + * XXX: next four lines are added by SYP! + */ + if (self.contentDiv) { + realSize.w = Math.max (realSize.w, self.contentDiv.scrollWidth); + realSize.h = Math.max (realSize.h, self.contentDiv.scrollHeight); } - ); - - /* - * XXX: next four lines are added by SYP! - */ - if (this.contentDiv) { - realSize.w = Math.max (realSize.w, this.contentDiv.scrollWidth); - realSize.h = Math.max (realSize.h, this.contentDiv.scrollHeight); - } - // is the "real" size of the div is safe to display in our map? - var safeSize = this.getSafeContentSize(realSize); + // is the "real" size of the div is safe to display in our map? + var safeSize = self.getSafeContentSize(realSize); - var newSize = null; - if (safeSize.equals(realSize)) { - //real size of content is small enough to fit on the map, - // so we use real size. - newSize = realSize; + var newSize = null; + if (safeSize.equals(realSize)) { + //real size of content is small enough to fit on the map, + // so we use real size. + newSize = realSize; - } else { + } else { - //make a new OL.Size object with the clipped dimensions - // set or null if not clipped. - var fixedSize = new OpenLayers.Size(); - fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null; - fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null; + //make a new OL.Size object with the clipped dimensions + // set or null if not clipped. + var fixedSize = new OpenLayers.Size(); + fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null; + fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null; if (fixedSize.w && fixedSize.h) { //content is too big in both directions, so we will use @@ -455,7 +584,7 @@ OpenLayers.Popup.Anchored.prototype.updateSize = function() { // run getRenderedDimensions() again with a fixed dimension var clippedSize = OpenLayers.Util.getRenderedDimensions( preparedHTML, fixedSize, { - displayClass: this.contentDisplayClass, + displayClass: self.contentDisplayClass, containerElement: containerElement } ); @@ -467,7 +596,7 @@ OpenLayers.Popup.Anchored.prototype.updateSize = function() { // adjust for that. // var currentOverflow = OpenLayers.Element.getStyle( - this.contentDiv, "overflow" + self.contentDiv, "overflow" ); if ( (currentOverflow != "hidden") && (clippedSize.equals(safeSize)) ) { @@ -479,8 +608,9 @@ OpenLayers.Popup.Anchored.prototype.updateSize = function() { } } - newSize = this.getSafeContentSize(clippedSize); + newSize = self.getSafeContentSize(clippedSize); } } - this.setSize(newSize); + self.setSize(newSize); + }, 0); }