Ticket #49: patch-49-r476-A0.diff
| File patch-49-r476-A0.diff, 24.8 kB (added by elemoine, 1 year ago) |
|---|
-
build/apidoc_config/Menu.txt
old new 59 59 60 60 File: MapPanel (GeoExt/widgets/MapPanel.js) 61 61 62 Group: Form { 63 File: SearchAction (GeoExt/widgets/form/Form.js) 64 File: BasicForm (GeoExt/widgets/form/Form.js) 65 File: FormPanel (GeoExt/widgets/form/Form.js) 66 } # Group: Form 67 62 68 Group: Index { 63 69 64 70 Index: Everything -
tests/lib/GeoExt/widgets/form/Form.html
old new 1 <!DOCTYPE html> 2 <html debug="true"> 3 <head> 4 <script type="text/javascript" src="../../../../../../openlayers/lib/OpenLayers.js"></script> 5 <script type="text/javascript" src="../../../../../../ext/adapter/ext/ext-base.js"></script> 6 <script type="text/javascript" src="../../../../../../ext/ext-all-debug.js"></script> 7 <script type="text/javascript" src="../../../../../lib/GeoExt.js"></script> 8 9 <script type="text/javascript"> 10 11 function test_filterFromForm(t) { 12 t.plan(27); 13 14 /* 15 * Set up 16 */ 17 18 var form, filter, fields = []; 19 20 fields.push(new Ext.form.TextField({ 21 name: "foo0", 22 value: "bar0" 23 })); 24 25 fields.push(new Ext.form.TextField({ 26 name: "foo1__eq", 27 value: "bar1" 28 })); 29 30 fields.push(new Ext.form.TextField({ 31 name: "foo2__ne", 32 value: "bar2" 33 })); 34 35 fields.push(new Ext.form.TextField({ 36 name: "foo3__lt", 37 value: "bar3" 38 })); 39 40 fields.push(new Ext.form.TextField({ 41 name: "foo4__le", 42 value: "bar4" 43 })); 44 45 fields.push(new Ext.form.TextField({ 46 name: "foo5__gt", 47 value: "bar5" 48 })); 49 50 fields.push(new Ext.form.TextField({ 51 name: "foo6__ge", 52 value: "bar6" 53 })); 54 55 fields.push(new Ext.form.TextField({ 56 name: "foo7__like", 57 value: "bar7" 58 })); 59 60 form = new Ext.form.FormPanel({ 61 renderTo: "form", 62 items: fields 63 }); 64 65 /* 66 * Test 67 */ 68 69 // 26 tests 70 filter = GeoExt.form.filterFromForm(form); 71 72 t.ok(filter instanceof OpenLayers.Filter.Logical, 73 "GeoExt.form.filterFormForm returns a logical filter"); 74 75 t.eq(filter.type, OpenLayers.Filter.Logical.AND, 76 ["GeoExt.form.filterFormForm returns a logical AND filter if", 77 "logicalOp is undefined"].join(" ")); 78 79 t.eq(filter.filters[0].type, OpenLayers.Filter.Comparison.EQUAL_TO, 80 "GeoExt.form.filterFormForm creates correct filter type"); 81 t.eq(filter.filters[0].property, "foo0", 82 "GeoExt.form.filterFormForm creates correct filter prop"); 83 t.eq(filter.filters[0].value, "bar0", 84 "GeoExt.form.filterFormForm creates correct filter value"); 85 86 t.eq(filter.filters[1].type, OpenLayers.Filter.Comparison.EQUAL_TO, 87 "GeoExt.form.filterFormForm creates correct filter type (__eq)"); 88 t.eq(filter.filters[1].property, "foo1", 89 "GeoExt.form.filterFormForm creates correct filter prop (__eq)"); 90 t.eq(filter.filters[1].value, "bar1", 91 "GeoExt.form.filterFormForm creates correct filter value (__eq)"); 92 93 t.eq(filter.filters[2].type, OpenLayers.Filter.Comparison.NOT_EQUAL_TO, 94 "GeoExt.form.filterFormForm creates correct filter type (__ne)"); 95 t.eq(filter.filters[2].property, "foo2", 96 "GeoExt.form.filterFormForm creates correct filter prop (__ne)"); 97 t.eq(filter.filters[2].value, "bar2", 98 "GeoExt.form.filterFormForm creates correct filter value (__ne)"); 99 100 t.eq(filter.filters[3].type, OpenLayers.Filter.Comparison.LESS_THAN, 101 "GeoExt.form.filterFormForm creates correct filter type (__lt)"); 102 t.eq(filter.filters[3].property, "foo3", 103 "GeoExt.form.filterFormForm creates correct filter prop (__lt)"); 104 t.eq(filter.filters[3].value, "bar3", 105 "GeoExt.form.filterFormForm creates correct filter value (__lt)"); 106 107 t.eq(filter.filters[4].type, OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO, 108 "GeoExt.form.filterFormForm creates correct filter type (__le)"); 109 t.eq(filter.filters[4].property, "foo4", 110 "GeoExt.form.filterFormForm creates correct filter prop (__le)"); 111 t.eq(filter.filters[4].value, "bar4", 112 "GeoExt.form.filterFormForm creates correct filter value (__le)"); 113 114 t.eq(filter.filters[5].type, OpenLayers.Filter.Comparison.GREATER_THAN, 115 "GeoExt.form.filterFormForm creates correct filter type (__gt)"); 116 t.eq(filter.filters[5].property, "foo5", 117 "GeoExt.form.filterFormForm creates correct filter prop (__gt)"); 118 t.eq(filter.filters[5].value, "bar5", 119 "GeoExt.form.filterFormForm creates correct filter value (__gt)"); 120 121 t.eq(filter.filters[6].type, OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO, 122 "GeoExt.form.filterFormForm creates correct filter type (__ge)"); 123 t.eq(filter.filters[6].property, "foo6", 124 "GeoExt.form.filterFormForm creates correct filter prop (__ge)"); 125 t.eq(filter.filters[6].value, "bar6", 126 "GeoExt.form.filterFormForm creates correct filter value (__ge)"); 127 128 t.eq(filter.filters[7].type, OpenLayers.Filter.Comparison.LIKE, 129 "GeoExt.form.filterFormForm creates correct filter type (__like)"); 130 t.eq(filter.filters[7].property, "foo7", 131 "GeoExt.form.filterFormForm creates correct filter prop (__like)"); 132 t.eq(filter.filters[7].value, "bar7", 133 "GeoExt.form.filterFormForm creates correct filter value (__like)"); 134 135 // 1 test 136 filter = GeoExt.form.filterFromForm(form, 137 OpenLayers.Filter.Logical.OR); 138 139 t.eq(filter.type, OpenLayers.Filter.Logical.OR, 140 ["GeoExt.form.filterFormForm returns a logical OR filter if", 141 "logicalOp is OpenLayers.Filter.Logical.OR"].join(" ")); 142 } 143 144 function test_SearchAction_constructor(t) { 145 t.plan(1); 146 147 /* 148 * Set up 149 */ 150 151 var form, action, protocol; 152 153 form = new Ext.form.BasicForm(Ext.get("form")); 154 protocol = new OpenLayers.Protocol(); 155 action = new GeoExt.form.SearchAction(form, {protocol: protocol}); 156 157 /* 158 * Test 159 */ 160 161 t.ok(action.options.protocol == protocol, 162 "SearchAction constructor properly sets protocol in options"); 163 } 164 165 function test_SearchAction_run(t) { 166 t.plan(1); 167 168 /* 169 * Set up 170 */ 171 172 var field, form, action, protocol; 173 174 var field = new Ext.form.TextField({ 175 name: "foo__eq", 176 value: "bar" 177 }); 178 179 form = new Ext.form.FormPanel({ 180 renderTo: "form", 181 items: [field] 182 }); 183 184 protocol = new OpenLayers.Protocol({ 185 read: function(options) { 186 t.ok(options.filter instanceof OpenLayers.Filter.Logical, 187 "run calls protocol.read with a logical filter"); 188 } 189 }); 190 191 action = new GeoExt.form.SearchAction(form.getForm(), { 192 protocol: protocol, 193 clientValidation: false 194 }); 195 196 /* 197 * Test 198 */ 199 action.run(); 200 } 201 202 function test_BasicForm_constructor(t) { 203 t.plan(1); 204 205 /* 206 * Set up 207 */ 208 209 var protocol, form; 210 211 protocol = new OpenLayers.Protocol(); 212 213 form = new GeoExt.form.BasicForm(Ext.get("form"), { 214 protocol: protocol 215 }); 216 217 /* 218 * Test 219 */ 220 221 t.ok(form.protocol == protocol, 222 "BasicForm constructor properly sets protocol in the instance"); 223 } 224 225 function test_BasicForm_doAction(t) { 226 t.plan(3); 227 228 /* 229 * Set up 230 */ 231 232 var protocol, form; 233 234 protocol = new OpenLayers.Protocol({ 235 read: function(options) { 236 t.ok(options.filter instanceof OpenLayers.Filter.Logical, 237 ["doAction calls read on the form's protocol, read", 238 "is passed a logical filter"].join(" ")); 239 } 240 }); 241 242 form = new GeoExt.form.BasicForm(Ext.get("form"), { 243 protocol: protocol, 244 getValues: function() { 245 return {"foo0__eq": "bar0", "foo1__like": "bar1"}; 246 } 247 }); 248 249 /* 250 * Test 251 */ 252 253 // 1 test 254 var tmp = form.doAction("search"); 255 t.ok(tmp == form, 256 "doAction returns the form instance"); 257 t.wait_result(1); 258 259 // 1 test 260 protocol = new OpenLayers.Protocol({ 261 read: function(options) { 262 t.ok(options.filter instanceof OpenLayers.Filter.Logical, 263 ["doAction calls read on the protocol it is given,", 264 "read is passed a logical filter"].join(" ")); 265 } 266 }); 267 form.doAction("search", {protocol: protocol}); 268 t.wait_result(1); 269 } 270 271 function test_FormPanel_constructor(t) { 272 t.plan(3); 273 274 /* 275 * Set up 276 */ 277 278 var protocol, form; 279 280 protocol = new OpenLayers.Protocol(); 281 282 form = new GeoExt.form.FormPanel({ 283 renderTo: "form", 284 protocol: protocol 285 }); 286 287 t.ok(form.protocol == protocol, 288 "FormPanel constructor sets protocol in the instance"); 289 t.ok(form.getForm() instanceof GeoExt.form.BasicForm, 290 ["FormPanel constructor creates a GeoExt.form.BasicForm as", 291 "its internal form"].join(" ")); 292 t.ok(form.getForm().protocol == protocol, 293 "FormPanel constructor sets protocol in internal form"); 294 } 295 296 </script> 297 <body> 298 <div id="form"></div> 299 </body> 300 </html> -
tests/list-tests.html
old new 10 10 <li>lib/GeoExt/data/WMSCapabilitiesReader.html</li> 11 11 <li>lib/GeoExt/widgets/MapPanel.html</li> 12 12 <li>lib/GeoExt/widgets/Popup.html</li> 13 <li>lib/GeoExt/widgets/form/Form.html</li> 13 14 </ul> -
lib/GeoExt.js
old new 70 70 "GeoExt/data/WMSCapabilitiesStore.js", 71 71 "GeoExt/data/ProtocolProxy.js", 72 72 "GeoExt/widgets/MapPanel.js", 73 "GeoExt/widgets/Popup.js" 73 "GeoExt/widgets/Popup.js", 74 "GeoExt/widgets/form/Form.js" 74 75 ); 75 76 76 77 var agent = navigator.userAgent; -
lib/GeoExt/widgets/form/Form.js
old new 1 /* Copyright (C) 2008-2009 The Open Source Geospatial Foundation 2 * Published under the BSD license. 3 * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text 4 * of the license. 5 * 6 * pending approval */ 7 8 Ext.namespace("GeoExt.form"); 9 10 /** 11 * Function: GeoExt.form.filterFromForm 12 * Create an {OpenLayers.Filter} object from a {Ext.form.BasicForm} 13 * instance or a {Ext.form.FormPanel}. 14 * 15 * Parameters: 16 * form - {Ext.form.BasicForm|Ext.form.FormPanel} 17 * logicalOp - {String} Either {OpenLayers.Filter.Logical.AND} 18 * or {OpenLayers.Filter.Logical.OR}, set to 19 * {OpenLayers.Filter.Logical.AND} if null or 20 * undefined. 21 * 22 * Returns: 23 * {OpenLayers.Filter} 24 */ 25 GeoExt.form.filterFromForm = function(form, logicalOp) { 26 if(form instanceof Ext.form.FormPanel) { 27 form = form.getForm(); 28 } 29 var filters = [], values = form.getValues(false); 30 for(var prop in values) { 31 var s = prop.split("__"); 32 33 var value = values[prop], type; 34 35 if(s.length > 1 && 36 (type = GeoExt.form.filterFromForm.FILTER_MAP[s[1]]) !== undefined) { 37 prop = s[0]; 38 } else { 39 type = OpenLayers.Filter.Comparison.EQUAL_TO; 40 } 41 42 filters.push( 43 new OpenLayers.Filter.Comparison({ 44 type: type, 45 value: value, 46 property: prop 47 }) 48 ); 49 } 50 51 return new OpenLayers.Filter.Logical({ 52 type: logicalOp || OpenLayers.Filter.Logical.AND, 53 filters: filters 54 }); 55 }; 56 57 /** 58 * Constant: GeoExt.form.filterFromForm.FILTER_MAP 59 * An object mapping operator strings as found in field names to 60 * {OpenLayers.Filter.Comparison} types. 61 */ 62 GeoExt.form.filterFromForm.FILTER_MAP = { 63 "eq": OpenLayers.Filter.Comparison.EQUAL_TO, 64 "ne": OpenLayers.Filter.Comparison.NOT_EQUAL_TO, 65 "lt": OpenLayers.Filter.Comparison.LESS_THAN, 66 "le": OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO, 67 "gt": OpenLayers.Filter.Comparison.GREATER_THAN, 68 "ge": OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO, 69 "like": OpenLayers.Filter.Comparison.LIKE 70 }; 71 72 /** 73 * Class: GeoExt.form.SearchAction 74 * An specific {Ext.form.Action} to be used when using a form to do 75 * trigger search requests througn an {OpenLayers.Protocol}. 76 * 77 * This action builds an {OpenLayers.Filter} from the form and passes 78 * this filter to its protocol's read method. The form fields must be 79 * named after a specific convention so that an appropriate 80 * {OpenLayers.Filter.Comparison} filter is created for each 81 * field. For example a field with the name "foo__like" would 82 * result in an {OpenLayers.Filter.Comparison} of type 83 * {OpenLayers.Filter.Comparison.LIKE}. Here is the convention: 84 * * <name>__eq: {OpenLayers.Filter.Comparison.EQUAL_TO} 85 * * <name>__ne: {OpenLayers.Filter.Comparison.NOT_EQUAL_TO} 86 * * <name>__lt: {OpenLayers.Filter.Comparison.LESS_THAN} 87 * * <name>__le: {OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO} 88 * * <name>__gt: {OpenLayers.Filter.Comparison.GREATER_THAN} 89 * * <name>__ge: {OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO} 90 * * <name>__like: {OpenLayers.Filter.Comparison.LIKE} 91 * 92 * In most cases your would not directly create {GeoExt.form.SearchAction} 93 * objects, but use {<GeoExt.form.FormPanel>} instead. 94 * 95 * Example: 96 * 97 * (start code) 98 * var formPanel = new Ext.form.Panel({ 99 * renderTo: "formpanel", 100 * items: [{ 101 * xtype: "textfield", 102 * name: "name__like", 103 * value: "mont" 104 * }, { 105 * xtype: "textfield", 106 * name: "elevation__ge", 107 * value: "2000" 108 * }] 109 * }); 110 * 111 * var searchAction = new GeoExt.form.SearchAction(formPanel.getForm(), { 112 * protocol: new OpenLayers.Protocol.WFS({ 113 * url: "http://publicus.opengeo.org/geoserver/wfs", 114 * featureType: "tasmania_roads", 115 * featureNS: "http://www.openplans.org/topp" 116 * }) 117 * }); 118 * 119 * formPanel.getForm().doAction(searchAction, { 120 * callback: function(response) { 121 * // response.features includes the features read 122 * // from the server through the protocol 123 * } 124 * }); 125 * (end) 126 * 127 */ 128 GeoExt.form.SearchAction = Ext.extend(Ext.form.Action, { 129 /** 130 * Property: type 131 * {String} The action type string. 132 */ 133 type: "search", 134 135 /** 136 * APIProperty: response 137 * {OpenLayers.Protocol.Response} A read-only reference to the 138 * OpenLayers.Protocol.Response object resulting from the 139 * search request. 140 */ 141 response: null, 142 143 /** 144 * Constructor: GeoExt.form.SearchAction 145 * Creates a SearchAction instance. 146 * 147 * Parameters: 148 * form - {Ext.form.BasicForm} The form. 149 * options - {Object} The options passed to the internal 150 * protocol's read method. 151 */ 152 constructor: function(form, options) { 153 GeoExt.form.SearchAction.superclass.constructor.call(this, form, options); 154 }, 155 156 /** 157 * Method: run 158 * Run the action. 159 */ 160 run: function() { 161 var o = this.options; 162 var f = GeoExt.form.filterFromForm(this.form); 163 if(o.clientValidation === false || this.form.isValid()){ 164 this.response = o.protocol.read( 165 Ext.applyIf({ 166 filter: f, 167 callback: this.handleResponse, 168 scope: this 169 }, o) 170 ); 171 } else if(o.clientValidation !== false){ 172 // client validation failed 173 this.failureType = Ext.form.Action.CLIENT_INVALID; 174 this.form.afterAction(this, false); 175 } 176 }, 177 178 /** 179 * Method: handleResponse 180 * Handle the response to the search query. 181 * 182 * Parameters: 183 * response - {OpenLayers.Protocol.Response} The OpenLayers response 184 * object. 185 */ 186 handleResponse: function(response) { 187 if(response.success()) { 188 this.form.afterAction(this, true); 189 } else { 190 this.form.afterAction(this, false); 191 } 192 var o = this.options; 193 if(o.callback) { 194 o.callback.call(o.scope, response); 195 } 196 } 197 }); 198 199 /** 200 * Class: GeoExt.form.BasicForm 201 * A specific {Ext.form.BasicForm} whose doAction method creates 202 * a {<GeoExt.form.SearchOption>} if it is passed the string 203 * "search" as its first argument. 204 * 205 * In most cases one would not use this class directly, one 206 * would use {<GeoExt.form.FormPanel>} instead. 207 */ 208 GeoExt.form.BasicForm = Ext.extend(Ext.form.BasicForm, { 209 /** 210 * Property: protocol 211 * {OpenLayers.Protocol} The protocol configured in this 212 * instance. 213 */ 214 protocol: null, 215 216 /** 217 * APIMethod: doAction 218 * Performs the action, if the string "search" is passed as the 219 * first argument then a {<GeoExt.form.SearchAction>} is created. 220 * 221 * Parameters: 222 * action - {String|Ext.form.Action} Either the name of the action 223 * or a {Ext.form.Action} instance. 224 * options - {Object} The options passed to the Action constructor. 225 */ 226 doAction: function(action, options) { 227 if(action == "search") { 228 options = Ext.applyIf(options || {}, {protocol: this.protocol}); 229 action = new GeoExt.form.SearchAction(this, options); 230 } 231 return GeoExt.form.BasicForm.superclass.doAction.call( 232 this, action, options 233 ); 234 } 235 }); 236 237 /** 238 * Class: GeoExt.form.FormPanel 239 * 240 * A specific {Ext.form.FormPanel} whose internal form is a 241 * {<GeoExt.form.BasicForm>} instead of {Ext.form.BasicForm}. 242 * One would use this form to do search requests through 243 * an {OpenLayers.Protocol} object ({OpenLayers.Protocol.WFS} 244 * for example). 245 * 246 * Look at {<GeoExt.form.SearchAction>} to understand how 247 * form fields must be named for appropriate filters to be 248 * passed to the protocol. 249 * 250 * Example: 251 * 252 * (start code) 253 * var formPanel = new GeoExt.form.Panel({ 254 * protocol: new OpenLayers.Protocol.WFS({ 255 * url: "http://publicus.opengeo.org/geoserver/wfs", 256 * featureType: "tasmania_roads", 257 * featureNS: "http://www.openplans.org/topp" 258 * }) 259 * renderTo: "formpanel", 260 * items: [{ 261 * xtype: "textfield", 262 * name: "name__ilike", 263 * value: "mont" 264 * }, { 265 * xtype: "textfield", 266 * name: "elevation__ge", 267 * value: "2000" 268 * }], 269 * listeners: { 270 * actioncomplete: function(form, action) { 271 * // this listener triggers when the search request 272 * // is complete, the OpenLayers.Protocol.Response 273 * // resulting from the request is available 274 * // through "action.response" 275 * } 276 * } 277 * }); 278 * (end) 279 */ 280 GeoExt.form.FormPanel = Ext.extend(Ext.form.FormPanel, { 281 /** 282 * APIProperty: protocol 283 * {OpenLayers.Protocol} The protocol instance this form panel 284 * is configured with; actions resulting from this form 285 * will be performed through the protocol. 286 */ 287 protocol: null, 288 289 /** 290 * Method: createForm 291 * Create the internal {<GeoExt.form.BasicForm>} instance. 292 */ 293 createForm: function() { 294 delete this.initialConfig.listeners; 295 return new GeoExt.form.BasicForm(null, this.initialConfig); 296 } 297 }); 298 299 Ext.reg("gx_formpanel", GeoExt.form.FormPanel); -
examples/search-form.js
old new 1 2 var formPanel; 3 4 Ext.onReady(function() { 5 6 // create a protocol, this protocol is used by the form 7 // to send the search request, this protocol's read 8 // method received an OpenLayers.Filter instance, 9 // which is derived from the content of the form 10 var protocol = new OpenLayers.Protocol({ 11 read: function(options) { 12 var f, 13 f = options.filter; 14 OpenLayers.Console.log(f.CLASS_NAME, ",", f.type); 15 f = options.filter.filters[0]; 16 OpenLayers.Console.log(f.CLASS_NAME, ",", f.type, ",", f.property, ":", f.value); 17 f = options.filter.filters[1]; 18 OpenLayers.Console.log(f.CLASS_NAME, ",", f.type, ",", f.property, ":", f.value); 19 } 20 }); 21 22 // create a GeoExt form panel (configured with an OpenLayers.Protocol 23 // instance) 24 formPanel = new GeoExt.form.FormPanel({ 25 width: 300, 26 height: 200, 27 protocol: protocol, 28 items: [{ 29 xtype: "textfield", 30 name: "name__like", 31 fieldLabel: "name" 32 }, { 33 xtype: "textfield", 34 name: "elevation__ge", 35 fieldLabel: "maximum elevation" 36 }], 37 listeners: { 38 actioncomplete: function(form, action) { 39 // this listener triggers when the search request 40 // is complete, the OpenLayers.Protocol.Response 41 // resulting from the request is available 42 // through "action.response" 43 } 44 } 45 }); 46 47 formPanel.addButton({ 48 text: "search", 49 handler: function() { 50 // trigger search request, the options passed to doAction 51 // are passed to the protocol's read method, so one 52 // can register a read callback here 53 var o = { 54 callback: function(response) { 55 } 56 }; 57 this.getForm().doAction("search", o); 58 }, 59 scope: formPanel 60 }); 61 62 formPanel.render("formpanel"); 63 }); -
examples/search-form.html
old new 1 <html> 2 <head> 3 <link rel="stylesheet" type="text/css" href="../../ext/resources/css/ext-all.css"></link> 4 <link rel="stylesheet" type="text/css" href="../../ext/examples/shared/examples.css"></link> 5 <script type="text/javascript" src="../../openlayers/lib/Firebug/firebug.js"></script> 6 <script type="text/javascript" src="../../openlayers/lib/OpenLayers.js"></script> 7 <script type="text/javascript" src="../../ext/adapter/ext/ext-base.js"></script> 8 <script type="text/javascript" src="../../ext/ext-all.js"></script> 9 <script type="text/javascript" src="../lib/GeoExt.js"></script> 10 <script type="text/javascript" src="search-form.js"></script> 11 </head> 12 <body> 13 <h1>Example of a search form using GeoExt.form.FormPanel</h1> 14 15 <p>This example shows how to create a search form based on 16 GeoExt.form.FormPanel. GeoExt.form.FormPanel itself uses an 17 OpenLayers.Protocol object for sending search requests. In this 18 example a fake protocol is used, in a real-life scenario a specific 19 protocol like OpenLayers.Protocol.WFS would be used.</p> 20 21 <p>If you use FireBug open the console to see the OpenLayers.Filter 22 objects created when the search button is hit.</p> 23 24 <p>The js is not minified so it is readable. See <a 25 href="search-form.js">search-form.js</a></p> 26 27 <div id="formpanel"></div> 28 29 </body> 30 </html>