Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GoogleGeocoderComboBox should inherit from GeoExt.form.GeocoderComboBox #155

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 6 additions & 13 deletions examples/google-geocoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,17 @@ var map = new OpenLayers.Map({
zoom: 12
});

var gg = new OpenLayers.Projection("EPSG:4326");
var sm = map.getProjectionObject();
var listeners = {
select: function(combo, record) {
var bounds = record.get("viewport").transform(gg, sm);
map.zoomToExtent(bounds, true);
}
};

var combo1 = new gxp.form.GoogleGeocoderComboBox({
renderTo: "combo1",
width: 200,
listeners: listeners
valueField: "viewport", /* zoom to bounds */
map: map,
width: 200
});

var combo2 = new gxp.form.GoogleGeocoderComboBox({
renderTo: "combo2",
valueField: "viewport",
bounds: new OpenLayers.Bounds(-74.04167, 40.69547, -73.86589, 40.87743),
width: 200,
listeners: listeners
map: map,
width: 200
});
35 changes: 1 addition & 34 deletions src/script/plugins/GoogleGeocoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,9 @@ gxp.plugins.GoogleGeocoder = Ext.extend(gxp.plugins.Tool, {
/** api: ptype = gxp_googlegeocoder */
ptype: "gxp_googlegeocoder",

/** api: config[updateField]
* ``String``
* If value is specified, when an item is selected in the combo, the map
* will be zoomed to the corresponding field value in the selected record.
* If ``null``, no map navigation will occur. Valid values are the field
* names described for the :class:`gxp.form.GoogleGeocoderComboBox`.
* Default is "viewport".
*/
updateField: "viewport",

init: function(target) {

var combo = new gxp.form.GoogleGeocoderComboBox(Ext.apply({
listeners: {
select: this.onComboSelect,
scope: this
}
}, this.outputConfig));
var combo = new gxp.form.GoogleGeocoderComboBox(this.outputConfig);

var bounds = target.mapPanel.map.restrictedExtent;
if (bounds && !combo.bounds) {
Expand All @@ -74,24 +59,6 @@ gxp.plugins.GoogleGeocoder = Ext.extend(gxp.plugins.Tool, {
*/
addOutput: function(config) {
return gxp.plugins.GoogleGeocoder.superclass.addOutput.call(this, this.combo);
},

/** private: method[onComboSelect]
* Listener for combo's select event.
*/
onComboSelect: function(combo, record) {
if (this.updateField) {
var map = this.target.mapPanel.map;
var location = record.get(this.updateField).clone().transform(
new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject()
);
if (location instanceof OpenLayers.Bounds) {
map.zoomToExtent(location, true);
} else {
map.setCenter(location);
}
}
}

});
Expand Down
153 changes: 52 additions & 101 deletions src/script/widgets/form/GoogleGeocoderComboBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
* of the license.
*/

/**
* @requires GeoExt/widgets/form/GeocoderComboBox.js
*/

/** api: (define)
* module = gxp.form
* class = GoogleGeocoderComboBox
* base_link = `Ext.form.ComboBox <http://extjs.com/deploy/dev/docs/?class=Ext.form.ComboBox>`_
* base_link = `GeoExt.form.GeocoderComboBox <http://dev.geoext.org/docs/lib/GeoExt/widgets/form/GeocoderComboBox.html>`_
*/
Ext.namespace("gxp.form");

Expand All @@ -26,16 +30,11 @@ Ext.namespace("gxp.form");
* * viewport - ``OpenLayers.Bounds`` Recommended viewing bounds.
*
*/
gxp.form.GoogleGeocoderComboBox = Ext.extend(Ext.form.ComboBox, {
gxp.form.GoogleGeocoderComboBox = Ext.extend(GeoExt.form.GeocoderComboBox, {

/** api: xtype = gxp_googlegeocodercombo */
xtype: "gxp_googlegeocodercombo",

/** api: config[queryDelay]
* ``Number`` Delay before the search occurs. Default is 100ms.
*/
queryDelay: 100,

/** api: config[bounds]
* ``OpenLayers.Bounds | Array`` Optional bounds (in geographic coordinates)
* for restricting search.
Expand All @@ -44,19 +43,26 @@ gxp.form.GoogleGeocoderComboBox = Ext.extend(Ext.form.ComboBox, {
/** api: config[valueField]
* ``String``
* Field from selected record to use when the combo's ``getValue`` method
* is called. Default is "location". Possible value's are "location",
* "viewport", or "address". The location value will be an
* ``OpenLayers.LonLat`` object that corresponds to the geocoded address.
* The viewport value will be an ``OpenLayers.Bounds`` object that is
* the recommended viewport for viewing the resulting location. The
* address value will be a string that is the formatted address.
* is called. Default is "location". Possible values are "location",
* "viewport", or "address". The location value will be an ``Array`` with 2
* items that corresponds to the geocoded address.
* The viewport value will be an ``Array`` with 4 values that is
* the recommended viewport for viewing the resulting location. The
* address value will be a string that is the formatted address. If
* valueField is set to "location" or "viewport" the map will center /
* zoom when an item from the combobox is selected. If valueField is set
* to "address" instead, no zooming will occur.
*/
valueField: "viewport",
valueField: "location",

/** private: config[displayField]
*/
displayField: "address",

/** private: config[locationField]
*/
locationField: "location",

/** private: method[initComponent]
* Override
*/
Expand All @@ -83,107 +89,52 @@ gxp.form.GoogleGeocoderComboBox = Ext.extend(Ext.form.ComboBox, {
}).createDelegate(this), 0);
}

var me = this;

this.store = new Ext.data.JsonStore({
root: "results",
root: null,
fields: [
{name: "address", type: "string"},
{name: "location"}, // OpenLayers.LonLat
{name: "viewport"} // OpenLayers.Bounds
{name: "address", mapping: "formatted_address"},
{name: "location", convert: function(v, rec) {
var latLng = rec.geometry.location;
return [latLng.lng(), latLng.lat()];
}},
{name: "viewport", convert: function(v, rec) {
var ne = rec.geometry.viewport.getNorthEast(),
sw = rec.geometry.viewport.getSouthWest();
return [sw.lng(), sw.lat(), ne.lng(), ne.lat()];
}}
],
autoLoad: false
});

this.on({
focus: function() {
this.clearValue();
},
scope: this
proxy: new (Ext.extend(Ext.data.DataProxy, {
doRequest: function(action, rs, params, reader, callback, scope, options) {
var bounds = null;
if (me.bounds) {
var boundsArray = (me.bounds instanceof OpenLayers.Bounds) ?
me.bounds.toArray() : me.bounds;
bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(boundsArray[1], boundsArray[0]),
new google.maps.LatLng(boundsArray[3], boundsArray[2])
);
}
me.geocoder.geocode({address: params.q, bounds: bounds}, function(results, status) {
var readerResult = reader.readRecords(results);
callback.call(scope, readerResult, options, !!readerResult);
});
}
}))({api: {read: true}})
});

return gxp.form.GoogleGeocoderComboBox.superclass.initComponent.apply(this, arguments);

},

/** private: method[prepGeocoder]
*/
prepGeocoder: function() {
var geocoder = new google.maps.Geocoder();


// create an async proxy for getting geocoder results
var api = {};
api[Ext.data.Api.actions.read] = true;
var proxy = new Ext.data.DataProxy({api: api});
var combo = this;

// TODO: unhack this - this is due to the the tool output being generated too early
var getBounds = (function() {
// optional bounds for restricting search
var bounds = this.bounds;
if (bounds) {
if (bounds instanceof OpenLayers.Bounds) {
bounds = bounds.toArray();
}
bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(bounds[1], bounds[0]),
new google.maps.LatLng(bounds[3], bounds[2])
);
}
return bounds;
}).createDelegate(this);

proxy.doRequest = function(action, rs, params, reader, callback, scope, options) {
// Assumes all actions read.
geocoder.geocode(
{address: params.query, bounds: getBounds()},
function(results, status) {
var readerResult;
if (status === google.maps.GeocoderStatus.OK ||
status === google.maps.GeocoderStatus.ZERO_RESULTS) {
try {
results = combo.transformResults(results);
readerResult = reader.readRecords({results: results});
} catch (err) {
combo.fireEvent("exception", combo, "response", action, options, status, err);
}
} else {
combo.fireEvent("exception", combo, "remote", action, options, status, null);
}
if (readerResult) {
callback.call(scope, readerResult, options, true);
} else {
callback.call(scope, null, options, false);
}
}
);
};

this.store.proxy = proxy;
this.geocoder = new google.maps.Geocoder();
if (this.initialConfig.disabled != true) {
this.enable();
}
},

/** private: method[transformResults]
* Transform an array of results so values are OpenLayers objects.
*/
transformResults: function(gResults) {
var num = gResults.length;
var olResults = new Array(num);
var item, latLng, bounds, ne, sw;
for (i=0; i<num; ++i) {
item = gResults[i];
latLng = item.geometry.location;
bounds = item.geometry.viewport;
ne = bounds.getNorthEast();
sw = bounds.getSouthWest();
olResults[i] = {
address: item.formatted_address,
location: new OpenLayers.LonLat(latLng.lng(), latLng.lat()),
viewport: new OpenLayers.Bounds(sw.lng(), sw.lat(), ne.lng(), ne.lat())
};
}
return olResults;
}

});
Expand Down
2 changes: 1 addition & 1 deletion tests/script/widgets/form/GoogleGeocoderComboBox.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
function test_GoogleGeocoderComboBox(t) {
t.plan(1);

var instance = new gxp.form.GoogleGeocoderComboBox();
var instance = new gxp.form.GoogleGeocoderComboBox({map: new OpenLayers.Map()});

t.ok(instance instanceof gxp.form.GoogleGeocoderComboBox, "Instance created successfully");

Expand Down