1
|
<!--
|
2
|
Copyright (c) 2006 TOPP - www.openplans.org. All rights reserved.
|
3
|
This code is licensed under the GPL 2.0 license, availible at the root
|
4
|
application directory.
|
5
|
|
6
|
|
7
|
@author Brent Owens
|
8
|
-->
|
9
|
|
10
|
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
|
11
|
<%@ taglib uri="/tags/struts-html" prefix="html" %>
|
12
|
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
|
13
|
|
14
|
<html>
|
15
|
<head></head>
|
16
|
|
17
|
<!-- color chooser -->
|
18
|
<link rel="stylesheet" href="js_color_picker_v2.css" media="screen">
|
19
|
<script type="text/javascript" src="color_functions.js"></script>
|
20
|
<script type="text/javascript" src="js_color_picker_v2.js"></script>
|
21
|
|
22
|
<!-- ================================ -->
|
23
|
<!-- ---------- JAVASCRIPT ---------- -->
|
24
|
<!-- ================================ -->
|
25
|
<script language="JavaScript" type="text/JavaScript">
|
26
|
<!--
|
27
|
|
28
|
|
29
|
/** global variables **/
|
30
|
var SERVERHOSTNAME = "sigma.openplans.org";//window.location.host;
|
31
|
|
32
|
var SERVERURL = "http://"+SERVERHOSTNAME+"/geoserver/";
|
33
|
|
34
|
var geo_xmlhttp = null; // AJAX-ness
|
35
|
|
36
|
|
37
|
var featureTypeName = ""; // our feature type that the style will go to
|
38
|
|
39
|
var geomType = ""; // the type of geometry we are making a style for
|
40
|
|
41
|
var columnNames; // the names of the columns of the feature type
|
42
|
|
43
|
|
44
|
/**
|
45
|
* Setup
|
46
|
*
|
47
|
* This will search through the feature type info and determine
|
48
|
* what kind of geometry it uses. This is based on geoserver
|
49
|
* output and not tested with anything else.
|
50
|
*/
|
51
|
function setup()
|
52
|
{
|
53
|
log("setup");
|
54
|
|
55
|
// we need an interval to read the jsp results.
|
56
|
// javascript will load before the jsp code so we need to wait to use it.
|
57
|
var myInterval = window.setInterval(function cheese(a,b) {
|
58
|
ft = document.getElementById('span_ftName').innerHTML;
|
59
|
// if doesn't equal 'undefined'
|
60
|
log("ft = "+ft);
|
61
|
if (ft != "undefined")
|
62
|
{
|
63
|
featureTypeName = document.getElementById('span_ftName').innerHTML;
|
64
|
log("interval; featureTypeName = "+featureTypeName);
|
65
|
ftInfo = document.getElementById('hidden_ft_attrs').innerHTML;
|
66
|
log("ft info: "+ftInfo);
|
67
|
columnNames = document.getElementById('hidden_ft_attrNames').innerHTML;
|
68
|
|
69
|
ftInfoSplit = ftInfo.split(",");
|
70
|
for(i=0;i<ftInfoSplit.length;i++)
|
71
|
{
|
72
|
var g = ftInfoSplit[i].split(":")[1];
|
73
|
if (g == "multiPointProperty" || g == "pointProperty" ) {
|
74
|
geomType = "point";
|
75
|
break;
|
76
|
}
|
77
|
else if (g == "multiLineStringProperty" || g == "lineStringProperty" ) {
|
78
|
geomType = "line";
|
79
|
break;
|
80
|
}
|
81
|
else if (g == "multiPolygonProperty" || g == "polygonProperty" ) {
|
82
|
geomType = "polygon";
|
83
|
break;
|
84
|
}
|
85
|
}
|
86
|
log("geomType = "+geomType);
|
87
|
|
88
|
|
89
|
setScreenEditMenu(geomType); // set the appropriate html for editing
|
90
|
|
91
|
clearInterval(myInterval); // cancel the interval timer
|
92
|
}
|
93
|
else
|
94
|
log("undefined");
|
95
|
|
96
|
},300);
|
97
|
|
98
|
}
|
99
|
|
100
|
|
101
|
function setScreenEditMenu(geomType)
|
102
|
{
|
103
|
editForm = "";
|
104
|
if (geomType == "point")
|
105
|
editForm = generatePointForm();
|
106
|
else if (geomType == "line")
|
107
|
editForm = generateLineForm();
|
108
|
else if (geomType == "polygon")
|
109
|
editForm = generatePolygonForm();
|
110
|
|
111
|
document.getElementById('mainEditDiv').innerHTML = editForm;
|
112
|
}
|
113
|
|
114
|
function generatePointForm()
|
115
|
{
|
116
|
result = "";
|
117
|
result += '<tr><td colspan=4><b><u><font size="+1">Label names for the points:</font></u></b><br></td></tr>';
|
118
|
result += '<tr><td width=200 colspan=4><b>Name Field:</b> '+generateNameSelect()+' <i><font color="#92AEFF" size="-1">(This field is the label that will appear on the geometry.)</font></i></td></tr>';
|
119
|
result += '<tr><td width=200 colspan=4><b>Text Color:</b> '+generateColorPicker("labelColor")+' <i><font color="#92AEFF" size="-1">(This is the color of the label.)</font></i></td></tr>';
|
120
|
|
121
|
result += '<tr><td colspan=4><br><hr><b><u><font size="+1">Color of the points:</font></u></b></td></tr>';
|
122
|
|
123
|
result += '<tr><td width=120 align="right"><b>Color:</b></td><td width=100>'+generateColorPicker("fillColor")+'</td>';
|
124
|
result += '<td width=120 align="right"><b>Opacity:</b></td><td width=140><input type="text" id="fillOpacity" size=3 maxlength=3 value="1"></input> <i><font color="#92AEFF" size="-1">(0.0 - 1.0)</font></i></td></tr>';
|
125
|
|
126
|
result += '<tr><td colspan=4><br><hr><b><u><font size="+1">Point size and shape:</font></u></b><br></td></tr>';
|
127
|
|
128
|
result += '<tr><td width=200 colspan=4><b>Point Size:</b> <input type="text" id="pointSize" size=6 maxlength=6></input> <i><font color="#92AEFF" size="-1">(The diameter of the point in pixels.)</font></i><br> </td></tr>';
|
129
|
result += '<tr><td width=200 colspan=4><b>Point Shape:</b> <select name="pointShape" id="pointShape"> ';
|
130
|
result += '<option>circle</option>';
|
131
|
result += '<option>square</option>';
|
132
|
result += '</select>';
|
133
|
result += '</td></tr>';
|
134
|
|
135
|
return result;
|
136
|
}
|
137
|
|
138
|
function generateLineForm()
|
139
|
{
|
140
|
result = "";
|
141
|
result += '<tr><td colspan=4><b><u><font size="+1">Label names for the lines:</font></u></b><br></td></tr>';
|
142
|
result += '<tr><td width=200 colspan=4><b>Name Field:</b> '+generateNameSelect()+' <i><font color="#92AEFF" size="-1">(This field is the label that will appear on the geometry.)</font></i></td></tr>';
|
143
|
result += '<tr><td width=200 colspan=4><b>Text Color:</b> '+generateColorPicker("labelColor")+' <i><font color="#92AEFF" size="-1">(This is the color of the label.)</font></i></td></tr>';
|
144
|
|
145
|
result += '<tr><td colspan=4><br><hr><b><u><font size="+1">Color of the lines:</font></u></b><br></td></tr>';
|
146
|
|
147
|
result += '<tr><td width=150 align="right"><b>Color:</b></td><td width=100>'+generateColorPicker("lineColor")+'</td>';
|
148
|
result += '<td width=150 align="right"><b>Opacity:</b></td><td width=140><input type="text" id="lineOpacity" size=3 maxlength=3 value="1"></input> <i><font color="#92AEFF" size="-1">(0.0 - 1.0)</font></i></td></tr>';
|
149
|
|
150
|
result += '<tr><td colspan=4><br><hr><b><u><font size="+1">Line dimentions:</font></u></b><br></td></tr>';
|
151
|
|
152
|
result += '<tr><td width=200 colspan=4><b>Line width:</b> <input type="text" id="lineWidth" size=6 maxlength=6></input> <i><font color="#92AEFF" size="-1">(The width, or thickness, of the line in pixles.)</font></i><br> </td></tr>';
|
153
|
|
154
|
return result;
|
155
|
}
|
156
|
|
157
|
function generatePolygonForm()
|
158
|
{
|
159
|
result = "";
|
160
|
result += '<tr><td colspan=4><b><u><font size="+1">Label names for the polygons:</font></u></b><br></td></tr>';
|
161
|
result += '<tr><td width=200 colspan=4><b>Name Field:</b> '+generateNameSelect()+' <i><font color="#92AEFF" size="-1">(This field is the label that will appear on the geometry.)</font></i><br> </td></tr>';
|
162
|
result += '<tr><td width=200 colspan=4><b>Text Color:</b> '+generateColorPicker("labelColor")+' <i><font color="#92AEFF" size="-1">(This is the color of the label.)</font></i></td></tr>';
|
163
|
|
164
|
result += '<tr><td colspan=4><br><hr><b><u><font size="+1">Color inside the polygons:</font></u></b><br></td></tr>';
|
165
|
|
166
|
result += '<tr><td width=120 align="right"><b>Fill Color:</b></td><td width=150>'+generateColorPicker("fillColor")+' </td>';
|
167
|
result += '<td width=120 align="right"><b>Fill Opacity:</b></td><td><input type="text" id="fillOpacity" size=3 maxlength=3 value="1"></input> <i><font color="#92AEFF" size="-1">(0.0 - 1.0)</font></i></td></tr>';
|
168
|
|
169
|
result += '<tr><td colspan=4><br><hr><b><u><font size="+1">Outline color of the polygons:</font></u></b><br></td></tr>';
|
170
|
|
171
|
result += '<tr><td width=120 align="right"><b>Outline Color:</b></td><td width=150>'+generateColorPicker("lineColor")+' </td>';
|
172
|
result += '<td width=120 align="right"><b>Outline Opacity:</b></td><td><input type="text" id="lineOpacity" size=3 maxlength=3 value="1"></input> <i><font color="#92AEFF" size="-1">(0.0 - 1.0)</font></i></td></tr>';
|
173
|
|
174
|
return result;
|
175
|
}
|
176
|
|
177
|
|
178
|
function generateColorPicker(colorFieldName)
|
179
|
{
|
180
|
|
181
|
result = '<input name="'+colorFieldName+'" id="'+colorFieldName+'" size="7" ';
|
182
|
result += 'onChange="relateColor(\''+colorFieldName+'\', this.value);"> ';
|
183
|
result += '<script language="javascript">relateColor(\'pick'+colorFieldName+'\', getObj(\''+colorFieldName+'\').value);</scr'+'ipt> ';
|
184
|
result += '<a href="javascript:pickColor(\''+colorFieldName+'\');" id="pick'+colorFieldName+'" name="pick'+colorFieldName+'" style="border: 1px solid #000000; font-family:Verdana; font-size:10px; background=#FFFF33; ';
|
185
|
result += 'text-decoration: none; " ><img src="colorpicker.jpg" width=12 height=12 border="none"></a>';
|
186
|
|
187
|
return result;
|
188
|
}
|
189
|
|
190
|
/**
|
191
|
* Generates the <select> form field for column names based on feature type column names.
|
192
|
*/
|
193
|
function generateNameSelect()
|
194
|
{
|
195
|
formCode = '<select name="propertyName" id="propertyName">';
|
196
|
formCode += '<option>none</option>';
|
197
|
|
198
|
colNamesSplit = columnNames.split(",");
|
199
|
for(i=0;i<colNamesSplit.length-1;i++)
|
200
|
{
|
201
|
if (colNamesSplit[i] != null && colNamesSplit[i] != "")
|
202
|
{
|
203
|
formCode += '<option>'+colNamesSplit[i]+'</option>';
|
204
|
}
|
205
|
}
|
206
|
|
207
|
formCode += "</select>";
|
208
|
|
209
|
return formCode;
|
210
|
}
|
211
|
|
212
|
|
213
|
/**
|
214
|
*
|
215
|
* This is the main function that reads in the form fields and generates
|
216
|
* the SLD.
|
217
|
*
|
218
|
*/
|
219
|
function generateSLD()
|
220
|
{
|
221
|
featureTypeName = document.getElementById('span_ftName').innerHTML;
|
222
|
//alert("featureTypeName: "+featureTypeName);
|
223
|
|
224
|
hideSuccessMessage(); // hide the SLD success message
|
225
|
|
226
|
SLD="";
|
227
|
SLD += createSLDHeader(featureTypeName);
|
228
|
|
229
|
SLDcore = ""
|
230
|
if (geomType == "point")
|
231
|
SLDcore += generatePointSLD();
|
232
|
else if (geomType == "line")
|
233
|
SLDcore += generateLineSLD();
|
234
|
else if (geomType == "polygon")
|
235
|
SLDcore += generatePolygonSLD();
|
236
|
|
237
|
matches = SLDcore.match("ERROR:");
|
238
|
if (matches != null && matches.length > 0)
|
239
|
{
|
240
|
alert(SLDcore); // alert the user with the error and return
|
241
|
return;
|
242
|
}
|
243
|
|
244
|
|
245
|
SLD += SLDcore; // append the code if there were no errors
|
246
|
|
247
|
SLD += createSLDFooter();
|
248
|
|
249
|
log("SLD:\n"+SLD);
|
250
|
saveStyle(SLD); // send it using PutStyles request
|
251
|
}
|
252
|
|
253
|
/**
|
254
|
* Point SLD generation
|
255
|
*/
|
256
|
function generatePointSLD()
|
257
|
{
|
258
|
propertyName = document.getElementById('propertyName').value;
|
259
|
labelColor = document.getElementById('labelColor').value;
|
260
|
fillColor = document.getElementById('fillColor').value;
|
261
|
fillOpacity = document.getElementById('fillOpacity').value;
|
262
|
pointSize = document.getElementById('pointSize').value;
|
263
|
pointShape = document.getElementById('pointShape').value;
|
264
|
|
265
|
if (labelColor.length == 6)
|
266
|
labelColor = '#'+labelColor;
|
267
|
if (fillColor.length == 6)
|
268
|
fillColor = '#'+fillColor;
|
269
|
|
270
|
var font;
|
271
|
var halo;
|
272
|
|
273
|
// check values to make sure they are in range and valid
|
274
|
if (propertyName != "none" && (labelColor == null || labelColor == "") )
|
275
|
return "ERROR: label name specified, but no text color specified.";
|
276
|
if (labelColor == null || labelColor == "")
|
277
|
return "ERROR: Label color cannot be empty";
|
278
|
if (labelColor.length != 7)
|
279
|
return "ERROR: Label color must be 7 characters long in hexadecimal (#00ff23).";
|
280
|
if (fillColor == null || fillColor == "")
|
281
|
return "ERROR: Point color cannot be empty";
|
282
|
if (fillColor.length != 7)
|
283
|
return "ERROR: Point color must be 7 characters long in hexadecimal (#00ff23).";
|
284
|
if (fillOpacity == null || fillOpacity == "")
|
285
|
return "ERROR: Point opacity cannot be empty";
|
286
|
if (fillOpacity < 0.0 || fillOpacity > 1.0)
|
287
|
return "ERROR: Point opacity must be between 0.0 and 1.0";
|
288
|
if (pointSize == null || pointSize == "")
|
289
|
return "ERROR: Point size cannot be empty";
|
290
|
|
291
|
|
292
|
// create stroke
|
293
|
var stroke;
|
294
|
//stroke = createStroke(lineColor, lineOpacity);
|
295
|
|
296
|
pointFill = createFill(fillColor, fillOpacity);
|
297
|
graphicMark = createGraphic(pointShape, pointFill, stroke, pointSize, 1.0);
|
298
|
|
299
|
SLDr = createSLDPointSymbolizer(graphicMark);
|
300
|
|
301
|
textFont = createFont("Times New Roman", "Normal", 12);
|
302
|
|
303
|
textFill = createFill(labelColor, 1.0);
|
304
|
|
305
|
if (propertyName != null && propertyName != "none")
|
306
|
SLDr += createTextSymbolizer(propertyName, textFont, halo, textFill);
|
307
|
|
308
|
return SLDr;
|
309
|
}
|
310
|
|
311
|
/**
|
312
|
* Line SLD generation
|
313
|
*/
|
314
|
function generateLineSLD()
|
315
|
{
|
316
|
propertyName = document.getElementById('propertyName').value;
|
317
|
labelColor = document.getElementById('labelColor').value;
|
318
|
lineColor = document.getElementById('lineColor').value;
|
319
|
lineOpacity = document.getElementById('lineOpacity').value;
|
320
|
lineWidth = document.getElementById('lineWidth').value;
|
321
|
|
322
|
if (labelColor.length == 6)
|
323
|
labelColor = '#'+labelColor;
|
324
|
if (lineColor.length == 6)
|
325
|
lineColor = '#'+lineColor;
|
326
|
|
327
|
var halo;
|
328
|
|
329
|
// check values to make sure they are in range and valid
|
330
|
if (propertyName != "none" && (labelColor == null || labelColor == "") )
|
331
|
return "ERROR: label name specified, but no text color specified.";
|
332
|
if (labelColor == null || labelColor == "")
|
333
|
return "ERROR: Label color cannot be empty";
|
334
|
if (labelColor.length != 7)
|
335
|
return "ERROR: Label color must be 7 characters long in hexadecimal (#00ff23).";
|
336
|
if (lineColor == null || lineColor == "")
|
337
|
return "ERROR: Line color cannot be empty";
|
338
|
if (lineColor.length != 7)
|
339
|
return "ERROR: Line color must be 7 characters long in hexadecimal (#00ff23).";
|
340
|
if (lineOpacity == null || lineOpacity == "")
|
341
|
return "ERROR: Line opacity cannot be empty";
|
342
|
if (lineOpacity < 0.0 || lineOpacity > 1.0)
|
343
|
return "ERROR: Line opacity must be between 0.0 and 1.0";
|
344
|
if (lineWidth == null || lineWidth == "")
|
345
|
return "ERROR: Line width cannot be empty";
|
346
|
if (lineWidth < 0)
|
347
|
return "ERROR: Line width must be a positive number";
|
348
|
|
349
|
|
350
|
// create stroke
|
351
|
stroke = createStroke(lineColor, lineOpacity, lineWidth);
|
352
|
|
353
|
SLDr = createSLDLineSymbolizer(stroke);
|
354
|
|
355
|
textFont = createFont("Times New Roman", "Normal", 12);
|
356
|
|
357
|
textFill = createFill(labelColor, 1.0);
|
358
|
|
359
|
if (propertyName != null && propertyName != "none")
|
360
|
SLDr += createTextSymbolizer(propertyName, textFont, halo, textFill);
|
361
|
|
362
|
return SLDr;
|
363
|
}
|
364
|
|
365
|
function generatePolygonSLD()
|
366
|
{
|
367
|
propertyName = document.getElementById('propertyName').value;
|
368
|
labelColor = document.getElementById('labelColor').value;
|
369
|
fillColor = document.getElementById('fillColor').value;
|
370
|
fillOpacity = document.getElementById('fillOpacity').value;
|
371
|
lineColor = document.getElementById('lineColor').value;
|
372
|
lineOpacity = document.getElementById('lineOpacity').value;
|
373
|
|
374
|
if (labelColor.length == 6)
|
375
|
labelColor = '#'+labelColor;
|
376
|
if (fillColor.length == 6)
|
377
|
fillColor = '#'+fillColor;
|
378
|
if (lineColor.length == 6)
|
379
|
lineColor = '#'+lineColor;
|
380
|
|
381
|
var halo;
|
382
|
|
383
|
// check values to make sure they are in range and valid
|
384
|
if (propertyName != "none" && (labelColor == null || labelColor == "") )
|
385
|
return "ERROR: label name specified, but no text color specified.";
|
386
|
if (labelColor == null || labelColor == "")
|
387
|
return "ERROR: Label color cannot be empty";
|
388
|
if (labelColor.length != 7)
|
389
|
return "ERROR: Label color must be 7 characters long in hexadecimal (#00ff23).";
|
390
|
if (fillColor == null || fillColor == "")
|
391
|
return "ERROR: Polygon fill color cannot be empty";
|
392
|
if (fillColor.length != 7)
|
393
|
return "ERROR: Polygon fill color must be 7 characters long in hexadecimal (#00ff23).";
|
394
|
if (fillOpacity == null || fillOpacity == "")
|
395
|
return "ERROR: Polygon color opacity cannot be empty";
|
396
|
if (fillOpacity < 0.0 || fillOpacity > 1.0)
|
397
|
return "ERROR: Polygon fill opacity must be between 0.0 and 1.0";
|
398
|
if (lineColor == null || lineColor == "")
|
399
|
return "ERROR: Polygon outline color cannot be empty";
|
400
|
if (lineColor.length != 7)
|
401
|
return "ERROR: Polygon outline color must be 7 characters long in hexadecimal (#00ff23).";
|
402
|
if (lineOpacity == null || lineOpacity == "")
|
403
|
return "ERROR: Polygon outline opacity cannot be empty";
|
404
|
if (lineOpacity < 0.0 || lineOpacity > 1.0)
|
405
|
return "ERROR: Polygon outline opacity must be between 0.0 and 1.0";
|
406
|
|
407
|
// create fill
|
408
|
polygonFill = createFill(fillColor, fillOpacity);
|
409
|
|
410
|
// create stroke
|
411
|
stroke = createStroke(lineColor, lineOpacity);
|
412
|
|
413
|
XMLr = createSLDPolygonSymbolizer(polygonFill, stroke);
|
414
|
|
415
|
textFill = createFill(labelColor, 1.0);
|
416
|
|
417
|
textFont = createFont("Times New Roman", "Normal", 12);
|
418
|
|
419
|
if (propertyName != null && propertyName != "none")
|
420
|
XMLr += createTextSymbolizer(propertyName, textFont, halo, textFill);
|
421
|
|
422
|
return XMLr;
|
423
|
}
|
424
|
|
425
|
/**
|
426
|
* Perform the putStyles request
|
427
|
*/
|
428
|
function saveStyle(SLD)
|
429
|
{
|
430
|
log("Saving style");
|
431
|
//kill any current requests!
|
432
|
if (geo_xmlhttp !=null)
|
433
|
{
|
434
|
geo_xmlhttp.abort();
|
435
|
geo_xmlhttp = null;
|
436
|
}
|
437
|
|
438
|
// build XML POST query
|
439
|
URL = "../../wms?request=putstyles";//"http://"+SERVERHOSTNAME+"/
|
440
|
|
441
|
getXML(URL,SLD,XMLProgressFunction);
|
442
|
|
443
|
}
|
444
|
|
445
|
function createSLDHeader(featureType)
|
446
|
{
|
447
|
log("Making sld for: "+featureType);
|
448
|
XML = '<?xml version="1.0" encoding="UTF-8"?>'+"\n";
|
449
|
XML += '<StyledLayerDescriptor version="1.0.0"'+"\n";
|
450
|
XML += ' xmlns:gml="http://www.opengis.net/gml"'+"\n";
|
451
|
XML += ' xmlns:ogc="http://www.opengis.net/ogc"'+"\n";
|
452
|
XML += ' xmlns="http://www.opengis.net/sld">'+"\n";
|
453
|
XML += ' <NamedLayer>'+"\n";
|
454
|
XML += ' <Name>'+featureType+'</Name>'+"\n";
|
455
|
XML += ' <UserStyle>'+"\n";
|
456
|
XML += ' <Name>'+featureType+'_style</Name>'+"\n";
|
457
|
XML += ' <Title>geoserver style</Title>'+"\n";
|
458
|
XML += ' <Abstract>Generated by GeoServer</Abstract>'+"\n";
|
459
|
XML += ' <FeatureTypeStyle>'+"\n";
|
460
|
XML += ' <Rule>'+"\n";
|
461
|
//log(XML);
|
462
|
return XML;
|
463
|
}
|
464
|
|
465
|
|
466
|
function createSLDFooter()
|
467
|
{
|
468
|
XML = ' </Rule>'+"\n";
|
469
|
XML += ' </FeatureTypeStyle>'+"\n";
|
470
|
XML += ' </UserStyle>'+"\n";
|
471
|
XML += ' </NamedLayer>'+"\n";
|
472
|
XML += '</StyledLayerDescriptor>';
|
473
|
|
474
|
return XML;
|
475
|
}
|
476
|
|
477
|
function createSLDPointSymbolizer(graphic)
|
478
|
{
|
479
|
XML = ' <PointSymbolizer>'+"\n";
|
480
|
XML += ' '+graphic+"\n";
|
481
|
XML += ' </PointSymbolizer>'+"\n";
|
482
|
|
483
|
return XML;
|
484
|
|
485
|
}
|
486
|
|
487
|
function createSLDLineSymbolizer(stroke)
|
488
|
{
|
489
|
XML = ' <LineSymbolizer>'+"\n";
|
490
|
XML += stroke;
|
491
|
XML += ' </LineSymbolizer>'+"\n";
|
492
|
|
493
|
return XML;
|
494
|
}
|
495
|
|
496
|
function createSLDPolygonSymbolizer(fill, stroke)
|
497
|
{
|
498
|
XML = ' <PolygonSymbolizer>'+"\n";
|
499
|
XML += fill;
|
500
|
XML += stroke;
|
501
|
XML += ' </PolygonSymbolizer>'+"\n";
|
502
|
|
503
|
return XML;
|
504
|
}
|
505
|
|
506
|
function createFill(color, opacity)
|
507
|
{
|
508
|
// add # to front of 'color'
|
509
|
if(color.charAt(0) != "#")
|
510
|
color = "#"+color;
|
511
|
|
512
|
XML = ' <Fill>'+"\n";
|
513
|
XML += ' <CssParameter name="fill">'+color+'</CssParameter>'+"\n";
|
514
|
XML += ' <CssParameter name="fill-opacity">'+opacity+'</CssParameter>'+"\n";
|
515
|
XML += ' </Fill>'+"\n";
|
516
|
|
517
|
return XML;
|
518
|
}
|
519
|
|
520
|
function createStroke(color, opacity, width, linecap, linejoin, dasharray)
|
521
|
{
|
522
|
// add # to front of 'color'
|
523
|
if(color.charAt(0) != "#")
|
524
|
color = "#"+color;
|
525
|
|
526
|
XML = ' <Stroke>'+"\n";
|
527
|
if(color) XML += ' <CssParameter name="stroke">'+color+'</CssParameter>'+"\n";
|
528
|
if(opacity) XML += ' <CssParameter name="stroke-opacity">'+opacity+'</CssParameter>'+"\n";
|
529
|
if(width) XML += ' <CssParameter name="stroke-width">'+width+'</CssParameter>'+"\n";
|
530
|
if(linecap) XML += ' <CssParameter name="stroke-linecap">'+linecap+'</CssParameter>'+"\n";
|
531
|
if(linejoin)XML += ' <CssParameter name="stroke-linejoin">'+linejoin+'</CssParameter>'+"\n";
|
532
|
if(dasharray)XML += ' <CssParameter name="stroke-dasharray">'+dasharray+'</CssParameter>'+"\n";
|
533
|
XML += ' </Stroke>'+"\n";
|
534
|
|
535
|
return XML;
|
536
|
}
|
537
|
|
538
|
// a note to figure out all possible line caps
|
539
|
function getLineCaps()
|
540
|
{
|
541
|
|
542
|
}
|
543
|
|
544
|
// a note to figure out all possible line joins
|
545
|
function getLineJoins()
|
546
|
{
|
547
|
|
548
|
}
|
549
|
|
550
|
function createGraphic(shape, fill, stroke, size, opacity)
|
551
|
{
|
552
|
XML = '<Graphic>'+"\n";
|
553
|
XML += ' <Mark>'+"\n";
|
554
|
XML += ' <WellKnownName>'+shape+'</WellKnownName>'+"\n";
|
555
|
XML += fill;
|
556
|
if(stroke) XML += stroke;
|
557
|
XML += ' </Mark>'+"\n";
|
558
|
XML += ' <Opacity>'+opacity+'</Opacity>'+"\n";
|
559
|
XML += ' <Size>'+size+'</Size>'+"\n";
|
560
|
XML += '</Graphic>'+"\n";
|
561
|
|
562
|
return XML;
|
563
|
}
|
564
|
|
565
|
|
566
|
function createTextSymbolizer(columnName, font, halo, fill)
|
567
|
{
|
568
|
XML = ' <TextSymbolizer>'+"\n";
|
569
|
XML += ' <Label>'+"\n";
|
570
|
XML += ' <ogc:PropertyName>'+columnName+'</ogc:PropertyName>'+"\n";
|
571
|
XML += ' </Label>'+"\n";
|
572
|
if(font) XML += font;
|
573
|
if(halo) XML += halo;
|
574
|
if(fill) XML += fill;
|
575
|
XML += ' </TextSymbolizer>'+"\n";
|
576
|
|
577
|
|
578
|
return XML;
|
579
|
}
|
580
|
|
581
|
function createFont(name, style, size, weight)
|
582
|
{
|
583
|
XML = ' <Font>'+"\n";
|
584
|
XML += ' <CssParameter name="font-family">'+name+'</CssParameter>'+"\n";
|
585
|
XML += ' <CssParameter name="font-style">'+style+'</CssParameter>'+"\n";
|
586
|
XML += ' <CssParameter name="font-size">'+size+'</CssParameter>'+"\n";
|
587
|
if (weight)XML += ' <CssParameter name="font-weight">'+weight+'</CssParameter>'+"\n";
|
588
|
XML += ' </Font>'+"\n";
|
589
|
|
590
|
return XML;
|
591
|
}
|
592
|
|
593
|
function createHalo(radius, fill)
|
594
|
{
|
595
|
XML = ' <Halo>'+"\n";
|
596
|
XML += ' <Radius>'+"\n";
|
597
|
XML += ' <ogc:Literal>'+radius+'</ogc:Literal>'+"\n";
|
598
|
XML += ' </Radius>'+"\n";
|
599
|
XML += fill;
|
600
|
XML += ' </Halo>'+"\n";
|
601
|
|
602
|
return XML;
|
603
|
}
|
604
|
|
605
|
|
606
|
function createMinScaleDenominator(scale)
|
607
|
{
|
608
|
XML = '<MinScaleDenominator>'+scale+'</MinScaleDenominator>'+"\n";
|
609
|
|
610
|
return XML;
|
611
|
}
|
612
|
|
613
|
function createMaxScaleDenominator(scale)
|
614
|
{
|
615
|
XML = '<MaxScaleDenominator>'+scale+'</MaxScaleDenominator>'+"\n";
|
616
|
|
617
|
return XML;
|
618
|
}
|
619
|
|
620
|
|
621
|
/**
|
622
|
* Send the XML request to GeoServer. Hands off control to procfunction method passed in.
|
623
|
*/
|
624
|
function getXML(url,post,procfunction)
|
625
|
{
|
626
|
try {
|
627
|
|
628
|
if (window.ActiveXObject)
|
629
|
{
|
630
|
// IE
|
631
|
log("getXML through IE");
|
632
|
geo_xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
633
|
geo_xmlhttp.onreadystatechange = procfunction;
|
634
|
geo_xmlhttp.open("POST", url, true);
|
635
|
geo_xmlhttp.setRequestHeader('Content-Type', 'text/xml'); //correct request type
|
636
|
geo_xmlhttp.setRequestHeader('Cache-Control', 'no-cache'); // don't cache the requests!!!
|
637
|
//geo_xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
638
|
geo_xmlhttp.send(post);
|
639
|
}
|
640
|
else if (window.XMLHttpRequest)
|
641
|
{
|
642
|
|
643
|
// Mozilla and others
|
644
|
//log("getXML through Mozilla etc.");
|
645
|
geo_xmlhttp = new XMLHttpRequest();
|
646
|
//geo_xmlhttp.overrideMimeType('text/xml'); // <- bad? caused some serious problems at one point
|
647
|
geo_xmlhttp.onreadystatechange = procfunction;
|
648
|
geo_xmlhttp.open("POST", url, true);
|
649
|
geo_xmlhttp.setRequestHeader('Content-Type', 'text/xml'); //correct request type
|
650
|
geo_xmlhttp.setRequestHeader('Cache-Control', 'no-cache'); // don't cache the requests!!!
|
651
|
geo_xmlhttp.send(post);
|
652
|
}
|
653
|
else
|
654
|
log("Invalid browser format: not expecting this kind of browser.");
|
655
|
}
|
656
|
catch(e)
|
657
|
{
|
658
|
alert(e);
|
659
|
alert("If you just got a security exception, its because you need to serve the .html file from the same server as where you're sending the XML requests to!");
|
660
|
}
|
661
|
}
|
662
|
|
663
|
|
664
|
|
665
|
/**
|
666
|
* Waits for requests and handles them.
|
667
|
*/
|
668
|
function XMLProgressFunction()
|
669
|
{
|
670
|
if (geo_xmlhttp != null)
|
671
|
{ // add 'working' animation
|
672
|
hideSuccessMessage();
|
673
|
}
|
674
|
|
675
|
if ( (geo_xmlhttp.readyState == 4) && (geo_xmlhttp.status == 200) )
|
676
|
{
|
677
|
log("XML reponse received");
|
678
|
//we got a good response. We need to process it!
|
679
|
if (geo_xmlhttp.responseXML == null)
|
680
|
{
|
681
|
log("XMLProgressFunction(): abort 1");
|
682
|
//document.getElementById('working_anim_gnis_span').innerHTML = ''; // remove 'working' animation
|
683
|
return;
|
684
|
}
|
685
|
|
686
|
log("response:\n"+geo_xmlhttp.responseText);
|
687
|
|
688
|
// ug, temporary hack just so I can get it working
|
689
|
if (window.ActiveXObject)
|
690
|
{
|
691
|
val = geo_xmlhttp.responseText.indexOf("success");
|
692
|
|
693
|
if (val > -1)
|
694
|
{
|
695
|
enableSuccessMessage();
|
696
|
log("PutStyles successful");
|
697
|
}
|
698
|
}
|
699
|
else
|
700
|
{
|
701
|
success_node = getElements(geo_xmlhttp.responseXML,"sld","success")[0];
|
702
|
if (success_node != null)
|
703
|
{
|
704
|
enableSuccessMessage();
|
705
|
log("PutStyles successful");
|
706
|
}
|
707
|
}
|
708
|
}
|
709
|
else
|
710
|
log("waiting for response...");
|
711
|
}
|
712
|
|
713
|
/**
|
714
|
* Browser capabilities: prefixes for IE
|
715
|
* Inspect for IE first. If you do mozilla first, it will just be mozilla and IE will die
|
716
|
*/
|
717
|
function getElements(node,tag_prefix,tag_name)
|
718
|
{
|
719
|
if (window.ActiveXObject)
|
720
|
{
|
721
|
//IE has no idea of namespaces/prefixes
|
722
|
log("parsing IE");
|
723
|
return node.getElementsByTagName(tag_prefix+":"+tag_name);
|
724
|
}
|
725
|
else if (window.XMLHttpRequest)
|
726
|
{
|
727
|
//mozilla
|
728
|
return node.getElementsByTagName(tag_name);
|
729
|
}
|
730
|
else
|
731
|
log("Unsupported browser format: not expecting this kind of browser.");
|
732
|
|
733
|
}
|
734
|
|
735
|
function enableSuccessMessage()
|
736
|
{
|
737
|
if (document.all) // if IE
|
738
|
{
|
739
|
log("ie put");
|
740
|
doc = document.getElementById('sld_success').getElementsByTagName('span')[0];
|
741
|
doc.innerHTML = '<b><font color="#22ff33" size="+1">Success</font></b>';
|
742
|
|
743
|
}
|
744
|
else
|
745
|
document.getElementById('inner_sld_success').innerHTML = "<b><font color=\"#22ff33\" size=\"+1\">Success</font></b>";
|
746
|
}
|
747
|
|
748
|
function hideSuccessMessage()
|
749
|
{
|
750
|
if (document.all) // if IE
|
751
|
{
|
752
|
doc = document.getElementById('sld_success').getElementsByTagName('span')[0];
|
753
|
doc.innerHTML = '';
|
754
|
}
|
755
|
else
|
756
|
document.getElementById('inner_sld_success').innerHTML = "";
|
757
|
}
|
758
|
|
759
|
/**
|
760
|
* Log to screen
|
761
|
*/
|
762
|
function log(text)
|
763
|
{
|
764
|
IFrameElement = document.getElementsByName("logFrame")[0];
|
765
|
|
766
|
//get doc
|
767
|
if (IFrameElement.contentDocument)
|
768
|
{
|
769
|
IFrameDoc = IFrameElement.contentDocument;
|
770
|
}
|
771
|
else if (IFrameElement.contentWindow)
|
772
|
{
|
773
|
IFrameDoc = IFrameElement.contentWindow.document;
|
774
|
}
|
775
|
else if (IFrameElement.document)
|
776
|
{
|
777
|
IFrameDoc = IFrameElement.document;
|
778
|
}
|
779
|
else
|
780
|
{
|
781
|
return true;
|
782
|
}
|
783
|
|
784
|
|
785
|
//put a <div><pre></pre></div>
|
786
|
if (IFrameDoc.body.getElementsByTagName("div")[0] ==null)
|
787
|
{
|
788
|
|
789
|
divNode = IFrameDoc.createElement("div");
|
790
|
preNode = IFrameDoc.createElement("pre");
|
791
|
preNode.appendChild(IFrameDoc.createTextNode(""));
|
792
|
divNode.appendChild(preNode);
|
793
|
|
794
|
IFrameDoc.body.appendChild(divNode);
|
795
|
|
796
|
|
797
|
//alert(IFrameDoc.body.getElementsByTagName("div")[0] );
|
798
|
}
|
799
|
|
800
|
|
801
|
// add the text
|
802
|
//<div><pre> text<br> </pre></div>
|
803
|
preNode = IFrameDoc.body.getElementsByTagName("pre")[0];
|
804
|
|
805
|
textNode = IFrameDoc.createTextNode(text) ;
|
806
|
|
807
|
preNode.appendChild( textNode );
|
808
|
preNode.appendChild( IFrameDoc.createElement("br") );
|
809
|
// textNode.scrollIntoView(true);
|
810
|
}
|
811
|
|
812
|
/**
|
813
|
* For killing form 'action' functionality. Cheap hack, I'm sure there are better ways to do it.
|
814
|
* Also for killing link tags.
|
815
|
*/
|
816
|
function nothing()
|
817
|
{
|
818
|
}
|
819
|
|
820
|
|
821
|
|
822
|
// Flooble Color Picker
|
823
|
// Color Picker Script from Flooble.com
|
824
|
// For more information, visit
|
825
|
// http://www.flooble.com/scripts/colorpicker.php
|
826
|
// Copyright 2003 Animus Pactum Consulting inc.
|
827
|
// You may use and distribute this code freely, as long as
|
828
|
// you keep this copyright notice and the link to flooble.com
|
829
|
// if you chose to remove them, you must link to the page
|
830
|
// listed above from every web page where you use the color
|
831
|
// picker code.
|
832
|
//---------------------------------------------------------
|
833
|
var perline = 15;
|
834
|
var divSet = false;
|
835
|
var curId;
|
836
|
var colorLevels = Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
|
837
|
var colorArray = Array();
|
838
|
var ie = false;
|
839
|
var nocolor = 'none';
|
840
|
if (document.all) { ie = true; nocolor = ''; }
|
841
|
function getObj(id) {
|
842
|
if (ie) { return document.all[id]; }
|
843
|
else { return document.getElementById(id); }
|
844
|
}
|
845
|
|
846
|
function addColor(r, g, b) {
|
847
|
var red = colorLevels[r];
|
848
|
var green = colorLevels[g];
|
849
|
var blue = colorLevels[b];
|
850
|
addColorValue(red, green, blue);
|
851
|
}
|
852
|
|
853
|
function addColorValue(r, g, b) {
|
854
|
colorArray[colorArray.length] = '#' + r + r + g + g + b + b;
|
855
|
}
|
856
|
|
857
|
function setColor(color) {
|
858
|
var link = getObj('pick'+curId);
|
859
|
var field = getObj(curId);// + 'field'
|
860
|
var picker = getObj('colorpicker');
|
861
|
field.value = color;
|
862
|
if (color == '') {
|
863
|
link.innerHTML=" ";
|
864
|
link.style.background = nocolor;
|
865
|
link.style.color = nocolor;
|
866
|
color = nocolor;
|
867
|
} else {
|
868
|
link.innerHTML=" ";
|
869
|
link.style.background = color;
|
870
|
link.style.color = color;
|
871
|
}
|
872
|
picker.style.display = 'none';
|
873
|
eval(getObj(curId).title);// + 'field'
|
874
|
}
|
875
|
|
876
|
function setDiv() {
|
877
|
if (!document.createElement) { return; }
|
878
|
var elemDiv = document.createElement('div');
|
879
|
if (typeof(elemDiv.innerHTML) != 'string') { return; }
|
880
|
genColors();
|
881
|
elemDiv.id = 'colorpicker';
|
882
|
elemDiv.style.position = 'absolute';
|
883
|
elemDiv.style.display = 'none';
|
884
|
elemDiv.style.border = '#000000 1px solid';
|
885
|
elemDiv.style.background = '#FFFFFF';
|
886
|
elemDiv.innerHTML = '<span style="font-family:Verdana; font-size:11px;">Pick a color: '
|
887
|
+ '(<a href="javascript:setColor(\'\');">No color</a>)<br>'
|
888
|
+ getColorTable()
|
889
|
+ '<center><a href="http://www.flooble.com/scripts/colorpicker.php"'
|
890
|
+ ' target="_blank">color picker</a> by <a href="http://www.flooble.com" target="_blank"><b>flooble</b></a></center></span>';
|
891
|
|
892
|
document.body.appendChild(elemDiv);
|
893
|
divSet = true;
|
894
|
}
|
895
|
|
896
|
function pickColor(id) {
|
897
|
if (!divSet) { setDiv(); }
|
898
|
var picker = getObj('colorpicker');
|
899
|
if (id == curId && picker.style.display == 'block') {
|
900
|
picker.style.display = 'none';
|
901
|
return;
|
902
|
}
|
903
|
curId = id;
|
904
|
var thelink = getObj(id);
|
905
|
picker.style.top = getAbsoluteOffsetTop(thelink) + 20;
|
906
|
picker.style.left = getAbsoluteOffsetLeft(thelink);
|
907
|
picker.style.display = 'block';
|
908
|
}
|
909
|
|
910
|
function genColors() {
|
911
|
addColorValue('0','0','0');
|
912
|
//addColorValue('1','1','1');
|
913
|
addColorValue('2','2','2');
|
914
|
addColorValue('3','3','3');
|
915
|
addColorValue('4','4','4');
|
916
|
addColorValue('5','5','5');
|
917
|
addColorValue('6','6','6');
|
918
|
addColorValue('7','7','7');
|
919
|
addColorValue('8','8','8');
|
920
|
addColorValue('9','9','9');
|
921
|
addColorValue('A','A','A');
|
922
|
addColorValue('B','B','B');
|
923
|
addColorValue('C','C','C');
|
924
|
addColorValue('D','D','D');
|
925
|
addColorValue('E','E','E');
|
926
|
addColorValue('F','F','F');
|
927
|
|
928
|
for (a = 1; a < colorLevels.length; a++)
|
929
|
addColor(0,0,a);
|
930
|
for (a = 1; a < colorLevels.length - 1; a++)
|
931
|
addColor(a,a,5);
|
932
|
|
933
|
for (a = 1; a < colorLevels.length; a++)
|
934
|
addColor(0,a,0);
|
935
|
for (a = 1; a < colorLevels.length - 1; a++)
|
936
|
addColor(a,5,a);
|
937
|
|
938
|
for (a = 1; a < colorLevels.length; a++)
|
939
|
addColor(a,0,0);
|
940
|
for (a = 1; a < colorLevels.length - 1; a++)
|
941
|
addColor(5,a,a);
|
942
|
|
943
|
|
944
|
for (a = 1; a < colorLevels.length; a++)
|
945
|
addColor(a,a,0);
|
946
|
for (a = 1; a < colorLevels.length - 1; a++)
|
947
|
addColor(5,5,a);
|
948
|
|
949
|
for (a = 1; a < colorLevels.length; a++)
|
950
|
addColor(0,a,a);
|
951
|
for (a = 1; a < colorLevels.length - 1; a++)
|
952
|
addColor(a,5,5);
|
953
|
|
954
|
for (a = 1; a < colorLevels.length; a++)
|
955
|
addColor(a,0,a);
|
956
|
for (a = 1; a < colorLevels.length - 1; a++)
|
957
|
addColor(5,a,5);
|
958
|
|
959
|
return colorArray;
|
960
|
}
|
961
|
function getColorTable() {
|
962
|
var colors = colorArray;
|
963
|
var tableCode = '';
|
964
|
tableCode += '<table border="0" cellspacing="1" cellpadding="1">';
|
965
|
for (i = 0; i < colors.length; i++) {
|
966
|
if (i % perline == 0) { tableCode += '<tr>'; }
|
967
|
tableCode += '<td bgcolor="#000000"><a style="outline: 1px solid #000000; color: '
|
968
|
+ colors[i] + '; background: ' + colors[i] + ';font-size: 10px;" title="'
|
969
|
+ colors[i] + '" href="javascript:setColor(\'' + colors[i] + '\');"> </a></td>';
|
970
|
if (i % perline == perline - 1) { tableCode += '</tr>'; }
|
971
|
}
|
972
|
if (i % perline != 0) { tableCode += '</tr>'; }
|
973
|
tableCode += '</table>';
|
974
|
return tableCode;
|
975
|
}
|
976
|
function relateColor(id, color) {
|
977
|
var link = getObj(id);
|
978
|
if (color == '') {
|
979
|
link.style.background = nocolor;
|
980
|
link.style.color = nocolor;
|
981
|
color = nocolor;
|
982
|
} else {
|
983
|
link.style.background = color;
|
984
|
link.style.color = color;
|
985
|
}
|
986
|
eval(getObj(id + 'field').title);
|
987
|
}
|
988
|
function getAbsoluteOffsetTop(obj) {
|
989
|
var top = obj.offsetTop;
|
990
|
var parent = obj.offsetParent;
|
991
|
while (parent != document.body) {
|
992
|
top += parent.offsetTop;
|
993
|
parent = parent.offsetParent;
|
994
|
}
|
995
|
return top;
|
996
|
}
|
997
|
|
998
|
function getAbsoluteOffsetLeft(obj) {
|
999
|
var left = obj.offsetLeft;
|
1000
|
var parent = obj.offsetParent;
|
1001
|
while (parent != document.body) {
|
1002
|
left += parent.offsetLeft;
|
1003
|
parent = parent.offsetParent;
|
1004
|
}
|
1005
|
return left;
|
1006
|
}
|
1007
|
|
1008
|
|
1009
|
|
1010
|
-->
|
1011
|
</script>
|
1012
|
<!-- ================================ -->
|
1013
|
<!-- --- END -- JAVASCRIPT ---------- -->
|
1014
|
<!-- ================================ -->
|
1015
|
|
1016
|
|
1017
|
|
1018
|
|
1019
|
<body onload="setup()" text="#AAC0FF">
|
1020
|
|
1021
|
<font color="#08809F" size="+2"><b>Create new SLD for FeatureType: <i><span id="span_ftName" name="span_ftName"><bean:write property='<%= "typeName" %>' name="typesEditorForm"/></span></font></i></b>
|
1022
|
<br> <br>
|
1023
|
|
1024
|
<span id="hidden_ft_attrs" name="hidden_ft_attrs" style="display:none"><bean:write property='<%= "attributes" %>' name="typesEditorForm" /></span>
|
1025
|
|
1026
|
<span id="hidden_ft_attrNames" name="hidden_ft_attrNames" style="display:none">
|
1027
|
<logic:iterate id="attribute" indexId="index" name="typesEditorForm" property="attributes">
|
1028
|
<bean:write name="attribute" property="name"/>,
|
1029
|
</logic:iterate>
|
1030
|
</span>
|
1031
|
|
1032
|
|
1033
|
|
1034
|
<!--bean:write property="<%= "attributes" %>" name="typesEditorForm" /-->
|
1035
|
<form action="javascript:nothing()">
|
1036
|
<table width=650 bgcolor="#7C8DBF">
|
1037
|
<tr><td>
|
1038
|
<div id="mainEditDiv" name="mainEditDiv">
|
1039
|
</div>
|
1040
|
</td></tr>
|
1041
|
</table>
|
1042
|
<i><font color="#770000">* All fields are required.</font></i><br> <br>
|
1043
|
|
1044
|
<input type="submit" value="Apply Style" onclick="generateSLD()">
|
1045
|
<div id="sld_success"><span id="inner_sld_success" name="inner_sld_success"></span></div>
|
1046
|
</form>
|
1047
|
|
1048
|
|
1049
|
<font color="#222222"><i>You must apply the style before it will be saved.<br>
|
1050
|
Hit the 'Apply Style' button above'.</i></font><be>
|
1051
|
|
1052
|
<!-- finished button "back to FeatureType editor" -->
|
1053
|
<form action="./typeEditor.do">
|
1054
|
<input type="submit" value="Finished">
|
1055
|
</form>
|
1056
|
|
1057
|
<p> <br>
|
1058
|
<span><iframe width=90% height=150px name=logFrame></iframe></span><!-- style="display:none"-->
|
1059
|
<br>
|
1060
|
|
1061
|
|
1062
|
|
1063
|
|
1064
|
</body>
|
1065
|
|
1066
|
</html>
|