/**
* пользовательский интерфейс пакета openLayers
* Package: openLayers
*
* @author Maltsev Alexey, Galkin Kirill
* @version 0.3, 17.07.2009
* @since gefest v.1.0.0-RC1
* @copyright (c) 2009 2energies LTD
*/
/**
* читалка "продвинутого" GeoRSS на основе штатной от OpenLayers
*/
OpenLayers.Format.GeoRSSAdv = OpenLayers.Class(OpenLayers.Format.GeoRSS,
{
createFeatureFromItem: function(item) {
var geometry = this.createGeometryFromItem(item);
/* Provide defaults for title and description */
var title = this.getChildValue(item, '*', 'title', this.featureTitle);
var address = this.getChildValue(item, '*', 'address', this.featureTitle);
/* First try RSS descriptions, then Atom summaries */
var description = this.getChildValue
(
item, '*', 'description',
this.getChildValue
(
item,
'*',
'content',
this.getChildValue(item, '*', 'summary', this.featureDescription)
)
);
/* If no link URL is found in the first child node, try the href attribute */
var link = this.getChildValue(item, '*', 'link');
if (!link) {
try {
link = this.getElementsByTagNameNS(item, '*', 'link')[0].getAttribute('href');
}
catch(e) {
link = null;
}
}
var icon = this.getChildValue(item, '*', 'icon');
var thumbnail = this.getChildValue(item, '*', 'thumbnail');
var id = this.getChildValue(item, '*', 'id', null);
var data =
{
'title': title,
'description': description,
'address': address,
'link': link,
'icon': icon,
'thumbnail': thumbnail
};
var feature = new OpenLayers.Feature.Vector(geometry, data);
feature.fid = id;
return feature;
},
CLASS_NAME: 'OpenLayers.Format.GeoRSSAdv'
});
/**
* слой "продвинутого" GeoRSS на основе штатного от OpenLayers
*/
OpenLayers.Layer.GeoRSSAdv = OpenLayers.Class(OpenLayers.Layer.GeoRSS,
{
parseData: function(ajaxRequest) {
var doc = ajaxRequest.responseXML;
if (!doc || !doc.documentElement)
doc = OpenLayers.Format.XML.prototype.read(ajaxRequest.responseText);
if (this.useFeedTitle) {
var name = null;
try {
name = doc.getElementsByTagNameNS('*', 'title')[0].firstChild.nodeValue;
}
catch(e) {
name = doc.getElementsByTagName('title')[0].firstChild.nodeValue;
}
if (name)
this.setName(name);
}
var options = {};
OpenLayers.Util.extend(options, this.formatOptions);
if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
options.externalProjection = this.projection;
options.internalProjection = this.map.getProjectionObject();
}
var format = new OpenLayers.Format.GeoRSSAdv(options);
var features = format.read(doc);
for (var i = 0, len = features.length; i < len; i++) {
var data = {};
var feature = features[i];
// no Martini - no party
if (!feature.geometry)
continue;
var title = feature.attributes.title ? feature.attributes.title : 'Untitled';
var description = feature.attributes.description ? feature.attributes.description : 'No description.';
var address = feature.attributes.address ? feature.attributes.address : 'Организация не оставила свой адрес';
var link = feature.attributes.link ? feature.attributes.link : '';
var location = feature.geometry.getBounds().getCenterLonLat();
var icon = feature.attributes.icon ? feature.attributes.icon : '';
var thumbnail = feature.attributes.thumbnail ? feature.attributes.thumbnail : '/upload/photo/l/null.jpg';
data.icon = icon ? this.getMarkerIcon(icon) : OpenLayers.Marker.defaultIcon();
data.popupSize = this.popupSize ? this.popupSize.clone() : new OpenLayers.Size(265, 123);
/* Вычитаем размер margin сверху и снизу */
data.AncoredBubble = new OpenLayers.Popup.AnchoredBubble(null);
if (title || address) {
var adr = window.location.pathname.toString();
adr = adr.split('/');
adr = adr[1];
var lp = 'Перейти на страницу объекта';
if (adr == 'en') lp = 'Jump to page object';
if (adr == 'de') lp = 'Wechseln zu Seitenobjekt';
if (adr == 'fr') lp = 'Aller à la page objet';
if (adr == 'cn') lp = '跳轉到頁物件';
data.title = title;
data.description = description;
data.address = address;
//for design
var contentHTML = '
';
//var contentHTML = '';
//contentHTML += '
';
contentHTML += '';
//изображение
//if(thumbnail)
contentHTML += '
';
//заголовок
if (link)
contentHTML += '';
contentHTML += '' + title + '
';
if (link)
contentHTML += '';
contentHTML += '';
if (link)
contentHTML += ''+ lp +'';
contentHTML += '';
contentHTML += '';
data['popupContentHTML'] = contentHTML;
}
var feature = new OpenLayers.Feature(this, location, data);
this.features.push(feature);
var marker = feature.createMarker();
marker.events.register('click', feature, this.markerClick);
this.addMarker(marker);
}
this.events.triggerEvent('loadend');
},
markerClick: function(evt) {
var sameMarkerClicked = (this == this.layer.selectedFeature);
this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
for (var i = 0, len = this.layer.map.popups.length; i < len; i++) {
this.layer.map.removePopup(this.layer.map.popups[i]);
}
if (!sameMarkerClicked) {
var popup = this.createPopup();
/* Исправление для нормального отображения круглых уголков */
popup.groupDiv.style.overflow = 'visible';
popup.groupDiv.style.padding = '1px 0';
OpenLayers.Event.observe
(
popup.div,
'click',
OpenLayers.Function.bind
(
function() {
for (var i = 0, len = this.layer.map.popups.length; i < len; i++) {
this.layer.map.removePopup(this.layer.map.popups[i]);
}
},
this
)
);
this.layer.map.addPopup(popup);
}
OpenLayers.Event.stop(evt);
},
getMarkerIcon: function(url) {
//TODO: перед присваиванием src нужно предварительно закешировать картинку, чтобы правильно определить размер
var image = new Image();
image.src = url;
/* kinda hack:
We cannot determine icon size by its URL, before image is loaded,
but we need to give something non-empty to Openlayers.Icon (as otherwise it
will set w/h to 20px by default). So we give some crap, that will not be parsed
by browser, and w/h will be set to 'auto'
We cannot pass null instead of size, because Openlayers.Icon will set it to default size
*/
var width = "auto ";
var height = "auto ";
if (image.width)
width = image.width;
if (image.height)
height = image.height;
var size = new OpenLayers.Size(width, height);
var calculateOffset = function(size) {
return new OpenLayers.Pixel(-19, -61);
// we don't know image size, how can we calculate it ?
//return new OpenLayers.Pixel(-size.w/2, -size.h);
};
return new OpenLayers.Icon(url, size, null, calculateOffset);
},
CLASS_NAME: 'OpenLayers.Layer.GeoRSSAdv'
});
//Грязный хак
//OpenLayers.ImgPath = '/scripts/modules/openLayers/core/img/';
OpenLayers._getScriptLocation = function() {
return '/scripts/modules/openLayers/core/';
}
/**
* общий управляющий класс
*/
openLayersMap = function() {
this.map = null;
this.busy = false;
this.name = 'Map';
this.overlays = [];//заданные оверлеи
this.loadedParts = {};//кэш загруженных оверлеев
this.minSizeX = 500;//минимальный размер загружаемой области по X, px
this.minSizeY = 500;//минимальный размер загружаемо области по Y, px
this.precisionX = 1000;//точность по X, 1/deg
this.precisionY = 1000;//точность по Y, 1/deg
this.overlayPreloadX = 100;//размер области подкачки вне видимой области по X, px
this.overlayPreloadY = 100;//размер области подкачки вне видимой области по Y, px
this.show = function(nodeID) {
var options = arguments.length > 1 ? arguments[1] : null;
var extent = options && options.extent ? options.extent : [-180, -90, 180, 90];
var center = options && options.center ? options.center : [0, 0];
var minZoom = options && options.minZoom ? options.minZoom : 0;
var maxZoom = options && options.maxZoom ? options.maxZoom : 12;
var zoom = options && options.zoom ? options.zoom : minZoom;
var controls = options && options.controls ? options.controls : null;
var _this = this;
this.map = new OpenLayers.Map
(
nodeID,
{
minZoom: minZoom,
maxZoom: maxZoom,
controls: controls,
projection: new OpenLayers.Projection('EPSG:900913'),
displayProjection: new OpenLayers.Projection('EPSG:4326'),
units: 'm',
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
isValidZoomLevel: function(zoomLevel) {
return zoomLevel != null && zoomLevel >= this.minZoom && zoomLevel <= this.maxZoom;
},
eventListeners:
{
'moveend': function(e) {
_this.onMoveEnd(e);
},
'zoomend': function(e) {
_this.onZoomEnd(e);
}
}
}
);
this.map.restrictedExtent = this.fromLongLat(new OpenLayers.Bounds(extent[0], extent[1], extent[2], extent[3]));
this.map.addControl(new OpenLayers.Control.Navigation({'zoomWheelEnabled': true}));
//this.map.addControl(new OpenLayers.Control.MousePosition());
//this.map.addControl(new OpenLayers.Control.LayerSwitcher());
/*var baseLayer = new OpenLayers.Layer.TMS
(
"OpenStreetMap",
"http://tile.openstreetmap.org/",
{
type: 'png',
getURL: this.getTMSTileURL,
displayOutsideMaxExtent: true
}
);*/
var baseLayer = new OpenLayers.Layer.TMS
(
this.name,
'/openLayers/map/tms',
{
type: 'jpg',
getURL: this.getTMSTileURL,
displayOutsideMaxExtent: true
}
);
this.map.addLayer(baseLayer);
this.map.baseLayer.numZoomLevels = 1 + this.maxZoom;
if (center)
this.map.setCenter(this.fromLongLat(new OpenLayers.LonLat(center[0], center[1])), zoom);
else
this.map.zoomToMaxExtent();
}
this.addSegmentedOverlay = function(type, title) {
var url = arguments.length > 2 ? arguments[2] : '';
var params = arguments.length > 3 ? arguments[3] : {};
var overlay =
{
type: type,
title: title,
url: url,
params: params
};
this.overlays.push(overlay);
return overlay;
}
this.refresh = function() {
this.clearOverlaysData();
this.buildOverlaysData();
}
this.buildOverlaysData = function() {
if (this.busy) {
var _this = this;
setTimeout
(
function() {
_this.buildOverlaysData();
},
500
);
}
var _this = this;
var bounds = this.map.getExtent();
this.toLongLat(bounds);
var mapSizePxX = this.map.getSize().w;//ширина карты, px
var mapSizePxY = this.map.getSize().h;//высота карты, px
var mapSizeDegX = bounds.getWidth();//ширина карты, deg
var mapSizeDegY = bounds.getHeight();//высота карты, deg
var xFactor = mapSizeDegX / mapSizePxX;// deg на px
var yFactor = mapSizeDegY / mapSizePxY;// deg на px
var xCount = Math.round((2 * this.overlayPreloadX + mapSizePxX) / this.map.getTileSize().w);//количество областей по X
var yCount = Math.round((2 * this.overlayPreloadY + mapSizePxY) / this.map.getTileSize().h);//количество областей по Y
var sizeX = Math.round(this.precisionX * xFactor * Math.max(this.minSizeX, Math.round(mapSizePxX / xCount))) / this.precisionX;//размер области по X, deg
var sizeY = Math.round(this.precisionY * xFactor * Math.max(this.minSizeY, Math.round(mapSizePxY / yCount))) / this.precisionY;//размер области по Y, deg
var left = Math.round(this.precisionX * (bounds.left - xFactor * this.overlayPreloadX)) / this.precisionX;//левый край загружаемой области, deg
var right = Math.round(this.precisionX * (bounds.right + xFactor * this.overlayPreloadX)) / this.precisionX;//правый край загружаемой области, deg
var bottom = Math.round(this.precisionY * (bounds.bottom - yFactor * this.overlayPreloadY)) / this.precisionY;//нижний край загружаемой области, deg
var top = Math.round(this.precisionY * (bounds.top + yFactor * this.overlayPreloadY)) / this.precisionY;//верхний край загружаемой области, deg
for (var x = left; x < right; x += sizeX) {
for (var y = bottom; y < top; y += sizeY) {
var key = x + '_' + y;
if (!this.loadedParts[key]) {
this.loadedParts[key] = true;
var bounds = new OpenLayers.Bounds();
bounds.extend(new OpenLayers.LonLat(x, y));
bounds.extend(new OpenLayers.LonLat(x + sizeX, y + sizeY));
for (var i = 0; i < this.overlays.length; i++) {
var overlay = this.overlays[i];
var title = overlay.title + ' (' + x + ',' + y + ')';
var url = overlay.url;
if (url.indexOf('?') < 1)
url += '?';
url += '&BBOX=' + bounds.toBBOX();
if (overlay.params)
for (var i in overlay.params)
url += '&' + i + '=' + overlay.params[i];
overlay.params.projection = this.map.displayProjection;
var newOverlay = null;
switch (overlay.type) {
case 'GeoRSS':
newOverlay = new OpenLayers.Layer.GeoRSS
(
title,
url,
overlay.params
);
break;
case 'GeoRSSAdv':
newOverlay = new OpenLayers.Layer.GeoRSSAdv
(
title,
url,
overlay.params
);
break;
case 'Text':
newOverlay = new OpenLayers.Layer.Text
(
title,
{location: url, params: overlay.params}
);
break;
}
if (newOverlay) {
this.map.addLayer(newOverlay);
this.loadedParts[key] = newOverlay;
}
}
}
}
}
}
this.clearOverlaysData = function() {
this.busy = true;
for (var i in this.loadedParts) {
if (this.loadedParts[i].div)
this.map.removeLayer(this.loadedParts[i], false);
}
this.loadedParts = {};
this.busy = false;
}
this.centerToObject = function(objectID, callback) {
var _this = this;
OpenLayers.Request.GET
({
'url': '/openLayers/map/object/data/' + objectID,
'success': function(request) {
eval('var data = ' + request.responseText);
if (data && data.longitude) {
var longLat = _this.fromLongLat(new OpenLayers.LonLat(data.longitude, data.latitude));
_this.map.setCenter(longLat);
if (callback)
callback(data, longLat);
}
}
})
}
this.saveObjectLocation = function(objectID, longLat, callback) {
OpenLayers.Request.GET
({
'url': '/openLayers/map/location/save/' + objectID,
'params':
{
longitude: longLat[0],
latitude: longLat[1]
},
'success': function(request) {
eval('var data = ' + request.responseText);
var result = data && data.success;
if (callback)
callback(result, data);
}
})
}
this.setDragableObject = function(longLat, dragCallback) {
var long = longLat[0];
var lat = longLat[1];
var _this = this;
if (!this.objectLayer) {
this.objectLayer = new OpenLayers.Layer.Vector
(
'Object',
{
projection: this.map.displayProjection,
styleMap: new OpenLayers.StyleMap
({
pointRadius: 15,
externalGraphic: '/scripts/modules/openLayers/images/marker.png',
cursor: 'pointer'
})
}
);
this.map.addLayer(this.objectLayer);
this.map.addControl(new OpenLayers.Control.MousePosition());
this.dragControl = new OpenLayers.Control.DragFeature(this.objectLayer);
this.dragControl.onComplete = function(feature, pixel) {
var location = feature.geometry.getBounds().getCenterLonLat();
_this.toLongLat(location);
if (dragCallback)
dragCallback(location, feature);
}
this.map.addControl(this.dragControl);
}
//перемещаем маркер в зону видимости, если он за пределами карты
var maxExt = this.map.getMaxExtent();
if (!maxExt.containsLonLat(this.fromLongLat(new OpenLayers.LonLat(long, lat)))) {
var mapLongLat = this.map.getCenter().clone();
this.toLongLat(mapLongLat);
long = mapLongLat.lon;
lat = mapLongLat.lat;
}
var longLat = new OpenLayers.LonLat(long, lat);
this.fromLongLat(longLat);
this.map.setCenter(longLat);
if (this.objectMarker)
this.objectLayer.removeFeatures([this.objectMarker]);
this.objectMarker = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(longLat.lon, longLat.lat));
this.objectLayer.addFeatures([this.objectMarker]);
return this.objectMarker;
}
this.getDragableObject = function() {
return this.objectMarker ? this.objectMarker : null;
}
this.getDragableObjectLongLat = function() {
return this.objectMarker ? this.toLongLat(this.objectMarker.geometry.getBounds().getCenterLonLat()) : null;
}
this.enableDragableObject = function() {
this.dragControl.activate();
//перемещаем маркер в зону видимости, если он за ее пределами
var mapExt = this.map.getExtent();
if (!mapExt.containsLonLat(new OpenLayers.LonLat(this.objectMarker.geometry.x, this.objectMarker.geometry.y))) {
var mapCenter = mapExt.getCenterLonLat();
if (this.objectMarker)
this.objectLayer.removeFeatures([this.objectMarker]);
this.objectMarker = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(mapCenter.lon, mapCenter.lat));
this.objectLayer.addFeatures([this.objectMarker]);
}
}
this.disableDragableObject = function() {
this.dragControl.deactivate();
}
this.getTMSTileURL = function(bounds) {
var res = this.map.getResolution();
var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
var z = this.map.getZoom();
var limit = Math.pow(2, z);
x = ((x % limit) + limit) % limit;
return this.url + '?zoom=' + z + '&x=' + x + '&y=' + y + '&type=' + this.type;
}
this.toLongLat = function(object) {
return object.transform(this.map.projection, this.map.displayProjection);
}
this.fromLongLat = function(object) {
return object.transform(this.map.displayProjection, this.map.projection);
}
this.onMoveEnd = function(event) {
this.buildOverlaysData();
}
this.onZoomEnd = function(event) {
this.clearOverlaysData();
}
}