Whether you are using AIMS 2014 or MapGuide OpenSource 2.5, there is a way to automatically zoom and highlight objects.
I will do this demo using FUSION or Flexible Web Layouts.
We want to be able to pass parameters to the template like the following.
The parameters are:
- LAYERNAME
- KEYNAME
- KEY
- ISSTRING
The LAYERNAME is the layer name in the map (i.e. Roads)
The KEYNAME is the column you want to search by (i.e. ID)
The KEY is the comma delimited list of matches (i.e. 644,684)
The ISSTRING flag tells whether the KEYNAME is String or Number.
I am using the SLATE template in MapGuide/AIMS, found in C:\Program Files\Autodesk\Autodesk Infrastructure Web Server Extension 2014\www\fusion\templates\mapguide\slate\index.html
To start the process, we need to trigger a javascript function once the map is loaded, around line 174, add a call to a function called zoomToObject()
var initPanelHandler = function() {
zoomToObject();
if(isTaskPaneRegistered) return;
Next create a zoomToObject() function that will pass all the parameters to a PHP Page to get the selectionXML, (paste this above the var showOverviewMap = function() { line):
function zoomToObject()
{
var mapWidget = Fusion.getMapById('Map');
var SESSION =mapWidget.aMaps[0].getSessionID();
var MAPNAME = mapWidget.aMaps[0].getMapName();
var KEY=getParam('KEY');
var ISSTRING=getParam('ISSTRING');
var KEYNAME=getParam('KEYNAME');
var LAYERNAME=getParam('LAYERNAME');
//The GETSELECTIONXML.php returns the XML of selected features.
var AJAXURL = "/mapserver2014/GETSELECTIONXML.php?MAPNAME=" + MAPNAME;
AJAXURL = AJAXURL + "&SESSION=" + SESSION;
AJAXURL = AJAXURL + "&KEYNAME=" + KEYNAME;
AJAXURL = AJAXURL + "&LAYERNAME=" + LAYERNAME;
AJAXURL = AJAXURL + "&KEY=" + KEY;
AJAXURL = AJAXURL + "&ISSTRING=" + ISSTRING;
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
mapWidget.setSelection(xmlhttp.responseText, true);
}
}
xmlhttp.open("GET",AJAXURL,true);
xmlhttp.send();
}
we also need the getParam() function to harvest the parameters sent to the page:
function getParam(sname)
{
var params = location.search.substr(location.search.indexOf("?")+1);
var sval = "";
params = params.split("&");
// split param and value into individual pieces
for (var i=0; i<params.length; i++)
{
temp = params[i].split("=");
if ( [temp[0]] == sname ) { sval = temp[1]; }
}
return sval;
}
Finally, the GETSELECTIONXML.php (I put this in the www folder of C:\Program Files\Autodesk\Autodesk Infrastructure Web Server Extension 2014\www\)
<?php
$configFilePath = "C:\Program Files\Autodesk\Autodesk Infrastructure Web Server Extension 2014\www\webconfig.ini";
$session = urldecode($_REQUEST["SESSION"]);
$mapName = urldecode($_REQUEST["MAPNAME"]);
$keyName = urldecode(stripslashes($_REQUEST["KEYNAME"]));
$layerName = urldecode(stripslashes($_REQUEST["LAYERNAME"]));
$isString = urldecode(stripslashes($_REQUEST["ISSTRING"]));
$key = urldecode(stripslashes($_REQUEST["KEY"]));
if($isString == true)
{
$key = $key . ',0';
$key = str_replace(",", "','", $key);
$key = "'" . $key . "'";
}
try
{
MgInitializeWebTier($configFilePath);
$userInfo = new MgUserInformation($session);
$siteConnection = new MgSiteConnection();
$siteConnection->Open($userInfo);
$featureService = $siteConnection->CreateService(2);
$resourceService = $siteConnection->CreateService(0);
$map = new MgMap($siteConnection);
$map->Open($mapName);
$queryOptions = new MgFeatureQueryOptions();
$queryOptions->SetFilter($keyName . " in (" . $key . ")");
$layer = $map->GetLayers()->GetItem($layerName);
$parcelDataResId = new MgResourceIdentifier($layer->GetFeatureSourceId());
$featureClassName = $layer->GetFeatureClassName();
$featureReader = $featureService->SelectFeatures($parcelDataResId, $featureClassName, $queryOptions);
$selection = new MgSelection($map);
$selection->AddFeatures($layer, $featureReader, 0);
$selectionXml = $selection->ToXml();
$selection->Save($resourceService, $map->GetName());
//dump the XML out to a JAVASCRIPT variable
echo $selectionXml;
}
catch (MgException $e)
{
echo $e->GetMessage();
echo $e->GetDetails();
}
?>
That’s it. It will work with the sample data that comes with MapGuide and AIMS, Sheboygan, or with any map you wish.
This will work with any FUSION application (flexible web layout), on any version of mapguide. The only thing you have to change is this line:
$configFilePath = “C:\Program Files\Autodesk\Autodesk Infrastructure Web Server Extension 2014\www\webconfig.ini”;
Just point it to the correct www folder.
Did the KEY filed is the value of object ID when KEYNAME=ID.
Does the final URL is:
http://localhost/mapserver2014/fusion/templates/mapguide/slate/index.html?LAYERNAME=Roads&KEYNAME=ID&KEY=644684&ISSTRING=1?ApplicationDefinition=Library…………
&KEY should have two IDs in there in this example: KEY=644,684
That way it selects both items. If the KEY=644 it would only select a single Road with an (ID=644)
But how final URl looks like, is it like I describet in previous post. I just cant this working.
Do I have to add map name and location in index.html: MAPNAME= Library://Map.MapDefinition
and code:
var AJAXURL = “/mapserver2014/GETSELECTIONXML.php?MAPNAME=Library://Map.MapDefinition” + MAPNAME;
In index.html file can I just copy all code from you post after: if(isTaskPaneRegistered) return;
My code after row 173 is:
var initPanelHandler = function() {
zoomToObject();
if(isTaskPaneRegistered) return;
function zoomToObject()
{
var mapWidget = Fusion.getMapById(‘Map’);
var SESSION =mapWidget.aMaps[0].getSessionID();
var MAPNAME = mapWidget.aMaps[0].getMapName();
var KEY=getParam(‘KEY’);
var ISSTRING=getParam(‘ISSTRING’);
var KEYNAME=getParam(‘KEYNAME’);
var LAYERNAME=getParam(‘LAYERNAME’);
//The GETSELECTIONXML.php returns the XML of selected features.
var AJAXURL = “/mapguide/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
AJAXURL = AJAXURL + “&SESSION=” + SESSION;
AJAXURL = AJAXURL + “&KEYNAME=” + KEYNAME;
AJAXURL = AJAXURL + “&LAYERNAME=” + LAYERNAME;
AJAXURL = AJAXURL + “&KEY=” + KEY;
AJAXURL = AJAXURL + “&ISSTRING=” + ISSTRING;
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
mapWidget.setSelection(xmlhttp.responseText, true);
}
}
xmlhttp.open(“GET”,AJAXURL,true);
xmlhttp.send();
}
//we also need the getParam() function to harvest the parameters sent to the page:
function getParam(sname)
{
var params = location.search.substr(location.search.indexOf(“?”)+1);
var sval = “”;
params = params.split(“&”);
// split param and value into individual pieces
for (var i=0; i<params.length; i++)
{
temp = params[i].split(“=”);
if ( [temp[0]] == sname ) { sval = temp[1]; }
}
return sval;
}
//register this with MAP_LOADED so that the initial layout will remain
Fusion.registerForEvent(Fusion.Event.TASK_PANE_LOADED, showTaskPane);
isTaskPaneRegistered = true;
http://localhost/mapserver2014/fusion/templates/mapguide/slate/index.html?ApplicationDefinition=Library%3a%2f%2fSamples%2fSheboygan%2fLayouts%2fslate.ApplicationDefinition
&LAYERNAME=Parcels
&KEYNAME=ID
&KEY=630813
&ISSTRING=true
works for me.
Just remember, the two functions should be stand alone. Paste them at the bottom of the index page (just above the tag).
Reblogged this on Sutoprise Avenue, A SutoCom Source.
I put both functions at the bottom of the index page just above but still not working, really dont know what I doing wrong. I’m using opensource Mapguide 2,5 version.
Can you past here your index.html full code.
It may be your GETSELECTIONXML.php , did you change the Webconfig path?
My webconfig.ini file is in www folder and in GETSELECTIONXML.php I have $configFilePath = “C:\Program Files\OSGeo\MapGuide\Web\www\webconfig.ini”;
so its seems correct.
Remember when copying from WordPress. Your Quotes may get assigned left and right, you may have to put them back to up and down.
Also, in the GETSELECTIONXML.php, you may want to swap the double quotes with single quotes:
From:
$key = $key . “,0”;
To:
$key = $key . ‘,0’;
also, make sure that in the index.htm for slate, that you have
var AJAXURL = “/mapguide/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
instead of:
var AJAXURL = “/mapserver2014/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
Thanks Gordon, i got this working. Problem was php, I had emty fist row in php file.
If I want just to use this zoomto object function without selecting object when map is loading.
Can you suggest me how to change this php or code in index.html.
Try http://trac.osgeo.org/fusion/wiki/URLParams
I have the javascript working I put some alerts in the code to see, but I get no results on selecting the key from the url. I copied all code from this page and did what you said and nada. using AIMS 2014 with a .net install.
Befor the mapWidget.setSelection(xmlhttp.responseText, true); line alert the responseText to see if you are selecting objects:
alert(xmlhttp.responseText);
If you get back an XML without and in there, your query might be incorrect….
no alert popping up??
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alert(xmlhttp.responseText);
mapWidget.setSelection(xmlhttp.responseText, true);
}
}
xmlhttp.open(“GET”,AJAXURL,true);
xmlhttp.send();
}
How about after the:
xmlhttp.open(“GET”,AJAXURL,true);
use:
window.open(AJAXURL);
to view what is being sent and returned…
I get The webpage cannot be found
sorry iam moving up from mapguide 6.3 so I am lost I have all coding in aspx,javascript and vb.net… learned as I went
aaa I changed the var AJAXURL = “/mapserver2014//GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
to var AJAXURL = “/mapserver2014/www/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
and got
An exception occurred in FDO component. Error occurred in Feature Source (Library://Data/parcels.FeatureSource): String does not represent a valid filter. (Cause: String incorrectly formatted. , Root Cause: String incorrectly formatted. )
So the AJAXURL is incorrect….it assumes you are using AIMS 2014, if not, you will have to change your code from:
var AJAXURL = “/mapserver2014/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
to
var AJAXURL = “/mapguide/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
or wherever you put the GETSELECTIONXML.php page……
Also, you may watch the URL. Is the key a Numeric or a String? the URL Parameter asks?
&ISSTRING=1 – which is true
– if it is numeric then
&ISSTRING=0
this is what I was trying
it come from a connected sdf file
http://localhost/mapserver2014//fusion/templates/mapguide/slate/index.html?ApplicationDefinition=Library%3a%2f%2fparcels.ApplicationDefinition
&LAYERNAME=parcels
&KEYNAME=PARCEL_LINK
&KEY=PAR_1234
&ISSTRING=0
Great Blog, Gordon. Keep up the good work! Do you have anything about creating REST connections? I’ve already seen your videos from AU
Gordon, Thanks for sharing this procedure. I would like to share my experience applying this code:
1. The curly brakets in the initial function call are not closed in the original article,
2. In the php code, when you copy and paste the code, the lines with double quotes must be reviewed and quotes has to be corrected. looks like wordpress uses openning and clossing quotes, all quotes must follow standard ascii format [ ” ” ] not [ “ ” ]
var AJAXURL = “/mapguide/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
3. taking care of these points and previous Gordon’s notes related to the location of files. It must run like a charm. I used OS Mapguide 2.6 on Apache and it works!.
Gordon, a question for you: could you please, illustrate how to include a zoom factor in the code?
If you want to change the scale, you can add the following to the index.html (templates like Slate).
script type=”text/javascript” src=”../../../layers/MapGuide/MapGuideViewerApi.js”></script
Then you can use the Zoom to View:
ZoomToView(centerX, centerY, scale, true);
You will have to figure out the x and y (I would just get the current map center and set the scale):
var theLon=iFrameMap.Fusion.getWidgetById('Map').oMapOL.getCenter().lat;
var theLat=iFrameMap.Fusion.getWidgetById('Map').oMapOL.getCenter().lon;
Gordon thxs for your Help. This is a great point of support for what I’m working on.
Hi, I just starting working with AIMS 2014 and I’m exactly trying to get the “highlight objects in the map” feature working. I followed your example, and it’s working as expected. Now, I wanna do the same but with my own deployed map, which I uploaded through the Infrastructure Studio and created a Flexible Layout. The URL that I’m getting for my app is as follows:
http://localhost/mapserver2014//fusion/templates/mapguide/slate/index.html?ApplicationDefinition=Library%3a%2f%2fskyMain%2fSKyCurrentMapLayout.ApplicationDefinition
As you can see, I’m using the slate template too, but I don’t know how exactly I should complete the URL in order to get objects selected as in your example.
Another question(and probably the most important for me) is: How do you know the exact ID’s of the objects? I can’t seem to find such ID’s anywhere.
Note: The map that I’m using is using a dwg file as datasource, so, I’m kinda lost about identifying any proper ‘object Id’.
Any comments that could guide me to find a solution would be really appreciated,
Thanks in advance.
You really have to know your data. If you have a layer that you want to search on, you can put the column you need and its value.
So if you have a layer called “Roads” and it has a column called “ROAD_NAME” you can search for “Main St.” with the following URL:
http://whateverserveryouhavenamedorinstalled/mapserver2014/fusion/templates/mapguide/slate/index.html?LAYERNAME=Roads&KEYNAME=ROAD_NAME&KEY=Main St.&ISSTRING=1
So you have to know your data to get it to work or perhaps you have a “Parcel” layer with a column called “ROLLNUMBER” with a value of “12345” then you might have the following URL:
http://someotherpowerfulserveryouinstalled/mapserver2014/fusion/templates/mapguide/slate/index.html?LAYERNAME=Parcel&KEYNAME=ROLLNUMBER&KEY12345&ISSTRING=0
Thanks for the quick answer Gordon. I understand the logic of the search, the layer name, the property and its value in order to do the search, that’s no problem at all. My problem is that our map is created in Autodesk Autocad(2015) and, as you may know, the resulting file from there is a .dwg, which I upload afterwards to the AIMS as my data(source) through the Infrastructure Studio and the layers are generated automatically. When I edit any layer generated from the dwg into the Infrastructure Studio, the only properties(columns) shown are just default geometric ones, such as “handle”, “layerhandle”, “lineweight”, “linetypescale”, etc. The ‘handle’ property work as ‘ID’, but the problem is that I have no control on its value, seems to be automatically generated once the dwg file is uploaded into the Infrastructure Studio. In your case, your example is using .sdf files as data sources to get all the properties that you need, such as the “ID”.
I know it seems that I’m going off topic but please understand that in order to get my own Map to do what you are explaining in this tutorial it’s completely necessary for me to understand how the data used to create the map is actually being uploaded.
Could you give me a hint on what application/software/tool was used to create the example map?
And if you have any idea about how to customize the object properties from the Autodesk Autocad and carry them when saved as .dwg file, it would be huge help.
Thanks in advance, and sorry if my comments are unclear.
Oh, if your source data does not have columns to search by then you can’t use this method.
If you are using DWG, and you are using AutoCAD Map 3D (or Civil 3D) you can add Object Data as custom properties.
Otherwise the dumb DWG is not capable of having custom properties.
The example uses files such as SDF or SHP with are GIS files that have searchable columns such as Parcel_ID or Road_number.
The data is everything. Smart data, smart GIS. The source data needs attribute data if you want to use the search.
Thanks for answering, Gordon. As you explained, my mistake was that I tried to use a DWG file that was not carrying any “real” data that I could work with besides the default geometric info of the drawing. I switched to Autocad Map 3D, connected to an SQL database and created some template links so the objects actually get data that can be more useful. Your example works correctly, with my drawing too, but I’m facing another problem and I hope you can guide me a little bit on that; Here is the case:
– My drawing was initially created in Autocad, which is just a raw DWG.
– I open the drawing in Autocad Map 3D and I set additional attributes via template links to a data base.
– In order to deploy it into Infrastructure Map Server, I had to export the drawing into an SDF which creates a feature class for each layer and it successfully carries the objects’ linked data.
– The problem is that the generated map doesn’t keep the original drawing ‘shapes’, in other words, if my drawing was originally colored and some objects were using some specific geometry, they become a black and white Map with default geometry for each object, such as basic square, circle, triangle, etc.
– If I only export the dwg without exporting into SDF, the drawing keeps all its characteristics, shapes, colors, etc, BUT it doesn’t carry the data from the template links.
– I know that I can ‘retouch’ the layers in the Infrastructure studio and set some design for each layer, but this is like doing my drawing two times.
Is there any way available in which I can export my DWG (with data from template links) into Infrastructure Map Server without losing its original attributes (colors, geometry shapes, data)?
Thanks in advance, great blog, you are doing an excellent work here, cheers to you.
Hi Gordon, would this work with the Basic Layout(Ajax viewer)?
Thanks.
The JavaScript part would not work as they have different apis.
But with some tweaking it could work..
I tried with Fusion viewers(Aqua, Slate, etc) and it works perfectly. As you said, it didn’t work on Basic Layout when I tried following the same steps. By any chance, do you have any tutorial or guide on how to accomplish the same on Basic Layout?
Thanks for your advises.
Not yet. But it should be fairly easy.
Check out this link
https://trac.osgeo.org/mapguide/wiki/CodeSamples/JavaScript/AJAXViewerEventHooking
Thanks a lot for the quick response. I’m gonna give it a try. 🙂
Followed everything, but im getting an error. Invalid Characters. Ajax Callback
Any help will do. my code is like this var AJAXURL = “/MapGuide/fusion/widgets/Redline/GETSELECTIONXML.php?MAPNAME=” + MAPNAME;
AJAXURL = AJAXURL + “&SESSION=” + SESSION;
AJAXURL = AJAXURL + “&KEYNAME=EmployeeId”;
AJAXURL = AJAXURL + “&LAYERNAME=Office Assignments”;
AJAXURL = AJAXURL + “&KEY=2686”;
AJAXURL = AJAXURL + “&ISSTRING=1”;
Perhaps get rid of the spaces in the layer name called Office Assignments…maybe “OFFICE_ASSIGNMENTS”
Thanks Gordon for the quick response. I did this and still the same. Funny thing is, the xml result when doing this code and the xmlresult on the build-in fusion task query feature is the same. But this gets me an error of invalid characters.
I tried using the mapWidget.query(option), but searching with polygons or points always highlight 2 objects. If i use .filter =’featid=1844′ i get invalid character error again.. driving me nuts..
Check your GETSELECTIONXML.php and make sure you do not have any weird ECHOs or Returns…
Hi, I’m trying your code for the StandardFusionViewer. The code is slightly different from the SlateTemplate, and in fact I’m not able to trigger the javascript function once the map is loaded because I’m not able to intercept WHEN the map is loaded. Have you experienced that? How can be solved this? Thanks! A.R. Gaeta
The only part that is the same as the Fusion would be the PHP part.
Check out how to get the onload event here.
https://trac.osgeo.org/mapguide/wiki/CodeSamples/JavaScript/AJAXViewerEventHooking
Thanks a lot for your response. I’m gonna give it a try.