I have shop names, type, lng, lat, etc stored in the database.
Some of the shops are of more than one type, so the type field is like this:
Shoe & Footwear|*|Children & Baby Wear.
My search form works for searching everything except for using the Multiselect to narrow down the results.
How can I get it to narrow down the results, depending on which Multiselect options are selected.
I have removed some of the search fields:
<form id="advanced-search" class="advanced-search search-collapsed clearfix" method="POST">
<select id="advsearch-boutiquetype" size="5" multiple="multiple" name="bform[boutique-drop-advanced][]" title="Boutique Dropdown">
<option id="Bridal_Shops_Designers_box" value="Bridal_Shops_Designers">Bridal Shops & Designers</option>
<option id="Children_Baby_Wear_box" value="Children_Baby_Wear">Children & Baby Wear</option>
<option id="Ladies_Fashions_box" value="Ladies_Fashions">Ladies Fashions</option>
<option id="Lingerie_box" value="Lingerie">Lingerie</option>
<option id="Maternity_Wear_box" value="Maternity_Wear">Maternity Wear</option>
<option id="Men's_Wear_box" value="Men's_Wear">Men's Wear</option>
<option id="Shoe_Footwear_box" value="Shoe_Footwear">Shoe & Footwear</option>
</select>
<input id="advsearch-submit-button" class="submit" type="submit" value="search" onclick="update();">
</form>
The update() function:
function update() {
var km_miles = jQuery("#km_miles").val();
var distance = jQuery("#distance-input").val();
var street = jQuery("#advsearch-street").val();
var city = jQuery("#advsearch-city").val();
var county = jQuery("#countyLocationAdvanced").val();
var country = 'Ireland';
var type = jQuery("#advsearch-boutiquetype").val();
var search_address = street + ' ' + city + ' ' + county + ' ' + country;
if (km_miles === 'km') {
var cal_km_miles = '6371';
} else {
var cal_km_miles = '3959';
}
if(street || city || county){
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': search_address }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
document.getElementById("countyLocation").value = county;
jQuery('#countyLocation').val(county);
getBoutiques(distance, results[0].geometry.location, cal_km_miles, type);
} else {
alert('Geocode error: ' + status);
}
});
}
}
The function getBoutiques():
function getBoutiques(dst, center, cal_dst, btypes){
// Read the data
if (typeof center != 'undefined') {
var centerlat = center.lat();
var centerlng = center.lng();
}
downloadUrl("index.php?option=com_boutiques_manager&view=boutiquesxml&county=" + document.getElementById("countyLocation").value.replace(/\s/g, '') + "&distance=" + dst + "¢erlat=" + centerlat + "¢erlng=" + centerlng + "&km_miles=" + cal_dst, function(doc) {
var xmlDoc = xmlParse(doc);
// Clear previous overlays
marker = null;
marker = new Array();
var markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// obtain the attribues of each marker
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat,lng);
// create the marker
var marker = createMarker(point);
}
});
}
The downloadUrl() is returning this:
<markers>
<marker name="Test1" types="Ladies Fashions|*|Children & Baby Wear" profiletype="basic" city="Dublin 14" county="Co. Dublin" lat="53.29294764" lng="-6.229290545" count="" boutiqueimage="" link="boutique/page/1036/1"></marker>
<marker name="Test2" types="Ladies Fashions" profiletype="basic" city="Dublin 2" county="Co. Dublin" lat="53.342819" lng="-6.261962" count="" boutiqueimage="" link="boutique/page/1037/1"></marker>
<marker name="Test3" types="Men's Wear" profiletype="basic" city="Dublin 2" county="Co. Dublin" lat="53.345013" lng="-6.262699" count="" boutiqueimage="" link="boutique/page/1188/1"></marker>
</markers>
Database Query:
$county = str_replace('.', '. ', $_GET['county']);
$dst = (int) $_GET['distance'];
$km_miles = $_GET['km_miles'];
$btypes = $_GET['btypes'];
$mylat = $_GET['centerlat'];
$mylng = $_GET['centerlng'];
// Initialize variables.
$query = $db->getQuery(true);
$query->select(
'c.cb_profiletype, cp.user_id, cp.cbp_user_profile_id, cp.cbp_banned, cp.cbp_boutiquename, cp.cbp_city, '
. 'cp.cbp_countylist, cp.cbp_boutiquetypes, cp.cbp_maplng as lng, cp.cbp_maplat as lat, cp.cbp_boutiqueimage, pt.b_max, null AS total, '
. '( '.$km_miles.' * acos( cos( radians('.$mylat.') ) * cos( radians( cp.cbp_maplat ) ) * cos( radians( cp.cbp_maplng ) - radians('.$mylng.') ) + sin( radians('.$mylat.') ) * sin( radians( cp.cbp_maplat ) ) ) ) AS distance'
);
$query->from('#__comprofiler c');
$query->join('INNER', '#__comprofiler_profiles cp ON cp.user_id = c.id');
$query->join('INNER', '#__cb_profiletypes pt ON pt.alias = c.cb_profiletype');
$query->where('cp.cbp_boutiquetypes <> \'\' AND cp.cbp_maplng <> \'\' AND cp.cbp_maplat <> \'\' AND cp.cbp_countylist <> \'\' AND cp.cbp_banned = \'0\' AND cp.cbp_enableboutique = \'Yes\' AND cp.cbp_countylist = \''.$county.'\'');
$query->having('distance < \''.$dst.'\'');
$query->order('cp.cbp_boutiquename ASC');
$db->setQuery($query);
$tmpList = $db->loadObjectList();
// Set some values to make nested HTML rendering easier.
foreach ($tmpList as $item) {
if(trim($item->lat)!='' && trim($item->lng)!='' && $item->cbp_user_profile_id <= $item->b_max) {
$list[][$item->user_id] = $item;
}
}
The types are in cp.cbp_boutiquetypes
Related
i made some code for google maps api that calculates the distance from one place to another, but i have a problem with adding the output to the woocommerce price (also displaying it as a product). this is the code i wrote:
The thought was.. that when i press submit, to have a product that would get values from the output of the distance and price, and then add it as a product.
` function add_fixed_text_product_to_cart( $cost ) {
global $woocommerce;
$product_id = 1825; //the ID of fixed text product
$product = wc_get_product( $product_id );
if ( $product ) {
$woocommerce->cart->add_to_cart( $product_id, 1, 0, array(), array( 'cost' => $cost ) );
}
}
add_action( 'wp_ajax_add_fixed_text_product_to_cart', 'add_fixed_text_product_to_cart' );
add_action( 'wp_ajax_nopriv_add_fixed_text_product_to_cart', 'add_fixed_text_product_to_cart' );
function add_custom_price_to_cart_item( $cart_object ) {
if ( is_admin() ) {
return;
}
foreach ( $cart_object->cart_contents as $key => $value ) {
if ( isset( $value['cost'] ) ) {
$value['data']->set_price( $value['cost'] );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price_to_cart_item', 10, 1 );
function zip_code_input_shortcode()
{
ob_start();
?>
<input id="address" type="text" placeholder="Enter address" style="text-align: center;">
<div id="address-dropdown"></div>
<div id="output">
<span id="distance_result"></span>
<br><br>
<span id="cost_result"></span>
<br><br>
<button id="submit_zipcode">Submit</button>
</div>
<script>
jQuery(document).ready(function() {
jQuery('#submit_zipcode').click(function() {
// Get the calculated cost
var cost = parseFloat(jQuery('#cost_result').text().split(' ')[1].replace(',', '.'));
// Add the information to the WooCommerce cart as a fixed text
jQuery.ajax({
url: '/wp-admin/admin-ajax.php',
data: {
'action': 'add_fixed_text_product_to_cart',
'cost': cost
},
success: function(data) {
console.log(data);
}
});
});
});
function initMap() {
var startingLocation = new google.maps.LatLng(55.84336022202228, 9.835100295423425);
var input = document.getElementById('address');
var options = {
types: ['address'],
componentRestrictions: { country: 'dk' }
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
autocomplete.addListener('place_changed', function () {
var place = autocomplete.getPlace();
var destination = place.formatted_address;
var destination_lat = place.geometry.location.lat();
var destination_lng = place.geometry.location.lng();
var postal_code = "";
// Get the postal code from the address components
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (addressType === "postal_code") {
postal_code = place.address_components[i].long_name;
}
}
// Check if the postal code is within the range of 1000 to 4999
if (postal_code >= 999 && postal_code <= 4999) {
alert("Vi montere desværre ikke varmepumper på Sjælland.");
return;
}
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [startingLocation],
destinations: [destination],
travelMode: 'DRIVING',
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status === 'OK') {
var distance_result = response.rows[0].elements[0].distance.text;
var distance_value = response.rows[0].elements[0].distance.value / 1000;
distance_value = distance_value.toFixed(2);
if (distance_value <= 25) {
var cost = 0;
} else {
var cost = (distance_value - 25) * 5.95;
cost = cost.toFixed(2);
}
document.getElementById('distance_result').innerHTML = 'Distance: ' + distance_result;
document.getElementById('cost_result').innerHTML = 'Cost: ' + cost.toString().replace('.', ',') + ' Danish kroner';
} else {
alert('Error: ' + status);
}
});
});
}
</script>`
(i dident include the API for this)
i tried to create some JS for this, but it dident work..
`jQuery(document).ready(function() {
jQuery('#submit_zipcode').click(function() {
// Get the calculated cost
var cost = parseFloat(jQuery('#cost_result').text().split(' ')[1].replace(',', '.'));
// Add the information to the WooCommerce cart as a fixed text
jQuery.ajax({
url: '/wp-admin/admin-ajax.php',
data: {
'action': 'add_fixed_text_product_to_cart',
'cost': cost
},
success: function(data) {
console.log(data);
}
});
});
});`
I've got an issue that I can't fix, it's been weeks I'm trying to do so but I just can't figure out what I'm doing wrong, or if there's something wrong in the Parse PHP SDK.
I have built a website with Parse Server as the backend, it's a listing website with location detection, and I'm working on Chrome (I've tried Firefox and Safari as well, I get the same issue).
My steps:
When you got to the home page, the browser asks you to allow location detection, I allow it.
If you click on the location button, you can open a Google map into a modal and place the pin on click to the desired location, you can also set the distance range by moving a slider. I select London, UK
I get the right console messages in Chrome:
DISTANCE: 87 Km
MARKER LAT: 51.522497992110246 - MARKER LNG: -0.12863733794108612
The issue comes here, the website shows only some of the posted Ads, those ones that I have posted through a mobile app (my own source code too, with Parse iOS and Android SDKs), it doesn't display those ads I've submitted through the website. Weird thing, if I post ads from the website and I open my mobile app, I can see them!
And if I check my database, the GeoPoint coordinates of my ads are correctly stored, whether I submitted ads through the website or the mobile apps.
Lastly, If I perform a search by keywords with the search bar on the top of the page, I can find those ads I've posted through the website. So, basically, no keywords, no ads posted through the website...
Here's my PHP code to query ads (NOTE; the variables that start with $ADS_ are simple strings declared in another file, ex. $ADS_LOCATION = "ads_location", etc):
/*--- variables ---*/
$isFollowing = $_GET['isFollowing'];
$option = $_GET['option'];
$upObjID = $_GET['upObjID'];
$latitude = $_GET['lat']; // 51.522497992110246
$longitude = $_GET['lng']; // -0.12863733794108612
$dist = $_GET['distance'];
$distance = (int)$dist; // 50
$category = $_GET['category'];
$sortBy = str_replace(' ', '', $_GET['sortBy']);
$keywords = preg_split('/\s+/', $_GET['keywords']);
// query Ads
try {
$query = new ParseQuery($ADS_CLASS_NAME);
$query->equalTo($ADS_IS_REPORTED, false);
// it's following.php
if ($isFollowing == true) {
$currentUser = ParseUser::getCurrentUser();
$cuObjIdArr = array();
array_push($cuObjIdArr, $currentUser->getObjectId());
$query->containedIn($ADS_FOLLOWED_BY, $cuObjIdArr);
// it's User profile page
} else if ($upObjID != null) {
$userPointer = new ParseUser($USER_CLASS_NAME, $upObjID);
$userPointer->fetch();
$query->equalTo($ADS_SELLER_POINTER, $userPointer);
if ($option == 'selling'){ $query->equalTo($ADS_IS_SOLD, false);
} else if ($option == 'sold'){ $query->equalTo($ADS_IS_SOLD, true);
} else if ($option == 'liked'){ $query->containedIn($ADS_LIKED_BY, array($userPointer->getObjectId())); }
// it's index.php
} else {
// nearby Ads
if ($latitude != null && $longitude != null) {
$currentLocation = new ParseGeoPoint($latitude, $longitude);
$query->withinKilometers("location", $currentLocation, $distance);
// nearby DEFAULT LOCATION COORDINATES
} else {
$defaultLocation = new ParseGeoPoint($DEFAULT_LOCATION_LATITUDE, $DEFAULT_LOCATION_LONGITUDE);
$query->withinKilometers($ADS_LOCATION, $defaultLocation, $DISTANCE_IN_KM);
}
// keywords
if (count($keywords) != 0) { $query->containedIn($ADS_KEYWORDS, $keywords); }
// category
if ($category != "All") { $query->equalTo($ADS_CATEGORY, $category); }
// sort by
switch ($sortBy) {
case 'Newest': $query->descending("createdAt");
break;
case 'Price:lowtohigh': $query->ascending($ADS_PRICE);
break;
case 'Price:hightolow': $query->descending($ADS_PRICE);
break;
case 'MostLiked': $query->descending($ADS_LIKES);
break;
default: break;
}// ./ sort by
}// ./ If
// perform query
$adsArray = $query->find();
if (count($adsArray) != 0) {
for ($i = 0; $i < count($adsArray); $i++) {
// Parse Obj
$adObj = $adsArray[$i];
// image 1
$adImg = $adObj->get($ADS_IMAGE1);
// title
$adTitle = substr ($adObj->get($ADS_TITLE), 0, 24).'...';
// currency
$adCurrency = $adObj->get($ADS_CURRENCY);
// price
$adPrice = $adObj->get($ADS_PRICE);
echo '
<!-- Ad card -->
<div class="col-lg-3 col-md-5 portfolio-item">
<div class="card">
';
// Sold badge
$isSold = $adObj->get($ADS_IS_SOLD);
if ($isSold) { echo '<div class="card-sold-badge"><img src="assets/images/sold-badge.png"></div>'; }
echo '
<img src="'.$adImg->getURL().'">
<div class="card-body">
<p class="card-title">'.$adTitle.'</p>
<p class="card-price">'.$adCurrency.' '.$adPrice.'</p>
</div>
</div>
</div>
';
}// ./ For
// no ads
} else {
echo '
<div class="col-lg-12 col-md-12">
<div class="text-center" style="margin-top: 40px; font-weight: 600">No Ads found.</div>
</div>
';
}
// error
} catch (ParseException $e){ echo $e->getMessage(); }
The above code comes from a separate file called query-ads.php and it gets displayed in a div:
<div class="row" id="adsGrid"></div>
I perform an AJAX function to call query-ads.php:
function queryAds(catName, keywords) {
// category
if (catName == null) { catName = "All"; }
document.getElementById("categoryName").innerHTML = '<h5 id="categoryName"><strong>' + catName + '</strong></h5>';
// keywords
if (keywords == null) { keywords = ''; }
// console.log('KEYWORDS: ' + keywords);
// console.log('LAT: ' + latitude + ' -- LNG: ' + longitude);
console.log('DISTANCE: ' + distance + ' Km');
// console.log('SORT BY: ' + sortBy);
$.ajax({
url:'query-ads.php',
data: 'lat=' + latitude + '&lng=' + longitude + '&distance=' + distance + '&category=' + catName + '&keywords=' + keywords + '&sortBy=' + sortBy,
type: 'GET',
success:function(data) {
document.getElementById("adsGrid").innerHTML = data;
},
// error
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
swal(err.Message);
}});
}
And here's my JavaScript code as well:
var cityStateButton = document.getElementById("cityState");
/*--- variables --*/
// localStorage.clear();
var latitude = localStorage.getItem('latitude');
var longitude = localStorage.getItem('longitude');
var distance = localStorage.getItem('distance');
if (distance == null) { distance = 50; }
var map;
var markers = [];
var geocoder;
var sortBy = document.getElementById('sortByBtn').innerHTML;
console.log("1st LATITUDE: " + latitude + " -- 1st LONGITUDE: " + longitude + ' -- 1st DISTANCE: ' + distance + ' -- 1st SORT BY: ' + sortBy);
// Call functions
if (latitude == null) { getCurrentLocation();
} else { getAddress(); }
// ------------------------------------------------
// MARK: - GET CURRENT LOCATION
// ------------------------------------------------
function getCurrentLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(getPosition, showError);
} else {
swal("Geolocation is not supported by this browser.");
// set default location coordinates
latitude = <?php echo $DEFAULT_LOCATION_LATITUDE ?>;
longitude = <?php echo $DEFAULT_LOCATION_LONGITUDE ?>;
getAddress();
}
}
function getPosition(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
getAddress();
}
function showError(error) {
switch(error.code) {
case error.PERMISSION_DENIED:
swal("You have denied your current Location detection.");
break;
case error.POSITION_UNAVAILABLE:
swal("Location information is unavailable.");
break;
case error.TIMEOUT:
swal("The request to get your current location timed out.");
break;
case error.UNKNOWN_ERROR:
swal("An unknown error occurred.");
break;
}
// set default location
latitude = <?php echo $DEFAULT_LOCATION_LATITUDE ?>;
longitude = <?php echo $DEFAULT_LOCATION_LONGITUDE ?>;
getAddress();
}
function getAddress () {
// geocoding API
var geocodingAPI = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + latitude + "," + longitude + "&key=<?php echo $GOOGLE_MAP_API_KEY ?>";
$.getJSON(geocodingAPI, function (json) {
if (json.status == "OK") {
var result = json.results[0];
var city = "";
var state = "";
for (var i = 0, len = result.address_components.length; i < len; i++) {
var ac = result.address_components[i];
if (ac.types.indexOf("locality") >= 0) { city = ac.short_name; }
if (ac.types.indexOf("country") >= 0) { state = ac.short_name; }
}// ./ For
// show city, state
cityStateButton.innerHTML = '<i class="fas fa-location-arrow"></i> ' + city + ', ' + state;
// call query
queryAds();
// save gps coordinates
localStorage.setItem('latitude', latitude);
localStorage.setItem('longitude', longitude);
// console.log("LAT (getAddress): " + latitude + " -- LNG (getAddress): " + longitude);
// call function
initMap();
}// ./ If
});
}
//---------------------------------
// MARK - INIT GOOGLE MAP
//---------------------------------
var mapZoom = 12;
function initMap() {
var location = new google.maps.LatLng(latitude, longitude);
map = new google.maps.Map(document.getElementById('map'), {
zoom: mapZoom,
center: location,
mapTypeId: 'roadmap',
disableDefaultUI: true,
mapTypeControl: false,
scaleControl: false,
zoomControl: false
});
// call addMarker() when the map is clicked.
map.addListener('click', function(event) {
addMarker(event.latLng);
});
// Add a marker in the center of the map.
addMarker(location);
}
function addMarker(location) {
clearMarkers();
var marker = new google.maps.Marker({
position: location,
map: map
});
markers.push(marker);
// set lat & lng based on marker's coordinates
latitude = marker.getPosition().lat();
longitude = marker.getPosition().lng();
console.log("MARKER LAT: " + latitude + " - MARKER LNG: " + longitude);
// zoom & center map based on pin
metersPerPx = 156543.03392 * Math.cos(latitude * Math.PI / 180) / Math.pow(2, mapZoom)
map.setZoom(metersPerPx/2.6);
map.setCenter(marker.getPosition());
}
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}// ./ For
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
markers = [];
}
//---------------------------------
// MARK - GET GPS COORDS FROM ADDRESS
//---------------------------------
function getCoordsFromAddress(address) {
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == 'OK') {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
markers.push(marker);
// set coordinates
latitude = results[0].geometry.location.lat();
longitude = results[0].geometry.location.lng();
// save gps coordinates
localStorage.setItem('latitude', latitude);
localStorage.setItem('longitude', longitude);
// console.log("SEARCH LOCATION LAT: " + latitude + " - SEARCH LOCATION LNG: " + longitude);
initMap();
// error
} else { swal('Geocode was not successful for the following reason: ' + status);
}});
}
I thought it was an issue with ParseGeoPoint, but it's not, because if I make a text search for keywords, I can find Ads.
Found the solution, I'm posting it just in case someone else will encounter such issue on the Parse PHP SDK, because it's there since early 2018.
In my script that saves Ads in my database, I was storing lowercase keywords based on the description and title of submitted items:
$kStr = $description. " " .$title. " " .$currentUser->getUsername();
$keywords = explode( " ", strtolower($kStr) );
Which was working fine, but since the PHP ParseQuery with a keywords filter needs at least an empty item in the array of keywords, I had to add this simple line below the above code:
array_push($keywords, "");
In this way, the database stores all proper keywords + an empty one: "", here's an example of how the keywords Arrat-type field looks like in the database:
[
"lorem",
"ad",
"ipsum",
"johndoe",
"" <-- this is the empty item that the SDK needs to properly perform a query in case of additional filters (in my case, a ParseGeopoint one)
]
This may be just a temporary trick until Parse Server's developers will fix this issue. It works, so why not ;)
I already have a working map where it generates a valid xml and can generate a marker on my map. Now what I want to do is to upon generating of maps for each loop in the xml I can create asynchronously a check box for each name. here is the code that generates the xml
function searchNearLocations(radius){
clearLocations();
var searchUrl = './designIncludes/phpLogicIncludes/searchMarkers.php?lat=' + userLat +'&lng=' + userLng + '&radius=' + radius;
downloadUrl(searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var info = markerNodes[i].getAttribute("info");
var tts = markerNodes[i].getAttribute("tts");
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createMarker(latlng, name, address,info,tts);
createCheckboxes(name);
bounds.extend(latlng);
}
map.fitBounds(bounds);
});
}
My createMarker()
function createMarker(latlng, name, address,info,tts) {
var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts;
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
I'm not that good in javascript but I have a marker=[] array global variable. Can I use that variable to generate a checkbox with it?by the way I also have a pre made marker before invoking the searchNearLocations function and I want to add it on the latlng bounds. Is it possible to insert it on the loop?
Okay
Everything not having to do with the checkboxes, I ignored. You'll have to put it back in your code.
I wrote a functioning example, you can copy/paste this as is.
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript">
var markers = [];
var map;
/* I don't have that XML. I'll just insert a few locations hard coded. You can ignore this; it doesn't affect your question */
var markerNodes = [
{latlng: new google.maps.LatLng(50.896328544032805,4.4825010816688), name: 'Brussels Airport', address: 'A201, 1930 Zaventem', info: 'National airport of Brussels', tts: 'foo'},
{latlng: new google.maps.LatLng(50.8957080950929,4.334064952575659), name: 'Football stadion', address: 'Marathonlaan', info: 'Football stadion of the Red Devils', tts: 'foo'},
{latlng: new google.maps.LatLng(50.82302545625156,4.39255052014533), name: 'VUB campus', address: 'Pleinlaan 2', info: 'University of Brussels', tts: 'foo'}
];
function initialize() {
var position = new google.maps.LatLng(50.84499325563654,4.349978498661017);
var myOptions = {
zoom: 11,
center: position
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
searchNearLocations(null); // I ignore the radius part. I presume this searches for locations in a DB, or something...
}
/* never mind most of the changes I made here, it's just to ignore the xml part of the code */
function searchNearLocations(radius) {
clearLocations();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<markerNodes.length; i++) {
var latlng = markerNodes[i].latlng,
name = markerNodes[i].name,
address = markerNodes[i].address,
info = markerNodes[i].info,
tts = markerNodes[i].tts;
createMarker(latlng, name, address, info, tts);
createCheckbox(name, i); // the most important thing is to pass the i; then markers[i] corresponds with checkboxes[i]
bounds.extend(latlng);
}
map.fitBounds(bounds);
}
function createMarker(latlng, name, address, info, tts) {
// var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts;
var marker = new google.maps.Marker({
map: map,
title: name, // You should add this
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
/* I'll ignore the infoWindow */
});
markers.push(marker);
}
function clearLocations() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers=[];
}
function checkboxChanged(i, checked) {
if(checked) {
markers[i].setMap(map);
}
else {
markers[i].setMap(null);
}
}
function createCheckbox(name, i) {
document.getElementById('checkboxes').innerHTML +=
'<input type="checkbox" checked="checked" onclick="checkboxChanged(' + i + ', this.checked);"> ' + name + '<br>';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#map-canvas {
width: 500px;
height: 400px;
}
</style>
<div id="map-canvas"></div>
<div id="checkboxes"></div>
Can you manage to include this in your code?
EDIT:
Here is an example of locations in a DB; I bypass xml and communicate through JSON.
It gives you (kind of) a combination of your questions;
I have a different table on my DB, but that shouldn't be a problem.
I add jQuery, just for ajax.
CREATE TABLE IF NOT EXISTS stations (
id bigint(15) NOT NULL AUTO_INCREMENT,
lat decimal(12,10) DEFAULT NULL,
lng decimal(12,10) DEFAULT NULL,
name varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
INSERT INTO stations (id, lat, lng, name) VALUES
(1, '50.8456035000', '4.3568658000', 'Brussel-Centraal'),
(2, '50.8413140000', '4.3490830000', 'Brussel-Kapellekerk'),
(3, '50.8517507000', '4.3623635000', 'Brussel-Congres'),
(4, '50.8604931000', '4.3607035000', 'Brussel-Noord'),
(5, '50.8348278000', '4.3365303000', 'Brussel-Zuid');
index.php
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript">
var markers = [];
var map;
// settings, to pass to the DB
var lat = 50.84499325563654;
var lng = 4.349978498661017;
var radius = 1.5; /* set this to more than 1.5 to see more locations */
function initialize() {
var position = new google.maps.LatLng(50.84499325563654, 4.349978498661017);
var myOptions = {
zoom: 11,
center: position
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
searchNearLocations(lat, lng, radius);
}
function searchNearLocations(lat, lng, radius) {
document.getElementById('checkboxes').innerHTML = '';
// we start an Ajax call.
$.ajax({
url: 'ajax.php',
data: {lat: lat, lng: lng, radius: radius},
dataType: 'json',
success: function(data) {
// the request has returned data. Now we can proceed
clearLocations();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<data.length; i++) {
var latlng = new google.maps.LatLng(data[i].lat, data[i].lng),
name = data[i].name;
/* add what ever extra data you need */
createMarker(latlng, name, null, null, null);
createCheckbox(name, i); // the most important thing is to pass the i; then markers[i] corresponds with checkboxes[i]
bounds.extend(latlng);
}
map.fitBounds(bounds);
}
});
}
function createMarker(latlng, name, address, info, tts) {
/* var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts; */
var marker = new google.maps.Marker({
map: map,
title: name, // You should add this
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
/* I'll ignore the infoWindow */
});
markers.push(marker);
}
function clearLocations() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers=[];
}
function checkboxChanged(i, checked) {
if(checked) {
markers[i].setMap(map);
}
else {
markers[i].setMap(null);
}
}
function createCheckbox(name, i) {
document.getElementById('checkboxes').innerHTML +=
'<input type="checkbox" checked="checked" onclick="checkboxChanged(' + i + ', this.checked);"> ' + name + '<br>';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#map-canvas {
width: 500px;
height: 400px;
}
</style>
<div id="map-canvas"></div>
<div id="checkboxes"></div>
ajax.php
<?php
$link = mysqli_connect('localhost', 'root', '', 'stackoverflow'); /* put your settings back */
if(!$link) {
die ('unable to connect to the database' . mysqli_connect_error());
}
//Get parameters from URL
$myLat = (isset ($_GET['lat']) ? $_GET['lat'] : 0.0); // give it some default
$myLng = (isset ($_GET['lng']) ? $_GET['lng'] : 0.0);
$calcDistance = (isset ($_GET['radius']) ? $_GET['radius'] : 1.0);
//Search the rows in the markers table
/* I have a slightly different table; I'll continue with mine; it's easy to put everything back */
// $query = sprintf("SELECT siteName,address,lat,lng,info,tts, (6371 * acos(cos(radians('%s')) * cos(radians(lat)) * cos(radians(lng) - radians ('%s')) + sin(radians('%s')) * sin(radians(lat))))AS distance FROM mapTable HAVING distance < '%s' ORDER BY distance LIMIT 0, 50",
$query = sprintf("SELECT id, lat, lng, name, (6371 * acos(cos(radians('%s')) * cos(radians(lat)) * cos(radians(lng) - radians ('%s')) + sin(radians('%s')) * sin(radians(lat)))) AS distance FROM stations HAVING distance < '%s' ORDER BY distance LIMIT 0, 50",
mysqli_real_escape_string($link, $myLat),
mysqli_real_escape_string($link, $myLng),
mysqli_real_escape_string($link,$myLat),
mysqli_real_escape_string($link, $calcDistance));
$result = mysqli_query($link, $query);
$row_cnt = mysqli_num_rows($result);
if(!$result) {
die("Invalid query: " . mysqli_error());
}
header("content-type: application/json; charset=utf-8");
$items = array();
//iterate through the rows,
while($row = mysqli_fetch_assoc($result)) {
$items[] = $row;
}
echo json_encode($items); // this can immediatly be read by javascript
exit;
?>
You can add links/buttons, whith something like
<div onclick="searchNearLocations(50.80, 4.35, 20)">click: 20 km radius from (50.80, 4.35)</div>
To add the position of the client, check out my answer here
google getLocation function not work in my script
Hi i have this price calculator which calculates the price according to the distance. but i want an additional £11.50 charge to be added if the location is central london.
Calculator in use:
http://unicornlogistics.com/price-calculator
and here is the js code:
//global map variable;
$(window).ready(function () {
initialize();
$('#calculateform .submitbtn').on({
click: getPriceAndDistance
});
});
function getPriceAndDistance(event) {
event.preventDefault();
//validating Input
var state = 1;
var form = $('#calculateform');
var validateable = form.find('input');
validateable.each(function () {
elem = $(this);
$(elem).removeClass('invalid');
if (elem.val().length < 2) {
$(elem).addClass('invalid');
state = 0;
}
})
//doing the actual stuff
if(state == 1)
{
var from = form.find('#from').val().trim().replace(/[^a-z0-9\s]/gi, '');
var to = form.find('#to').val().trim().replace(/[^a-z0-9\s]/gi, '');
var travelMode = form.find('#travelMode option:selected').val();
var travelModeText = form.find('#travelMode option:selected').text();
var price = Number(form.find('#travelMode option:selected').attr('price')).valueOf();
var err = '';
var locationFrom;
var locationTo;
$('#map-canvas').html('');
var mapOptions = {
center: new google.maps.LatLng(55.378051, -3.43597299999999),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
$(form).find('p.msg').remove();
$(form).find('p.loading').remove();
loading = '<p class="loading">Loading Please Wait...<p>';
$(form).append(loading);
//initiate gecoder
geocoder = new google.maps.Geocoder();
if(geocoder)
{
geocoder.geocode({ 'address': from }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
locationFrom = results[0].geometry.location;
if (locationFrom)
{
geocoder.geocode({ 'address': to }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
locationTo = results[0].geometry.location;
if (locationTo) {
updateMap();
}
else {
err = '<p class="invalid msg">Destination location is not found.<p>';
$(form).append(err);
}
}
else {
$(form).find('.loading').remove();
err = '<p class="invalid msg">Geocoding failed due to following reasons ' + status + '.<p>';
$(form).append(err);
}
});
}
else{
err = '<p class="invalid msg">Starting location is not found.<p>';
$(form).append(err);
}
}
else {
//err = '<p class="invalid msg">Geocoding failed due to following reasons ' + status + '.<p>';
err = '<p class="invalid msg">Sorry there seems to be some problem.<p>';
errmsg = '<p class="invalid msg">Please check the location that you entered and try again.<p>';
$(form).append(err);
$(form).append(errmsg);
}
});
function updateMap()
{
latlngCen = new google.maps.LatLng((locationFrom.lat()+locationTo.lat())/2,(locationFrom.lng()+locationTo.lng())/2);
map.panTo(latlngCen);
map.setZoom(1);
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
var req = {
origin:locationFrom,
destination:locationTo
}
if (travelMode == 'driving')
{
req.travelMode = google.maps.DirectionsTravelMode.DRIVING;
}
else if (travelMode == 'transit')
{
req.travelMode = google.maps.DirectionsTravelMode.TRANSIT;
}
directionsService.route(req, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
if (response.routes[0].legs[0].distance) {
console.log('here');
var d = response.routes[0].legs[0].distance.value / 1609;
var estTotal = d * price;
$(form).find('.loading').remove();
dText = "The distance between <strong>" + from + "</strong> and <strong>" + to + "</strong> is <strong>" + d.toFixed(2) + " miles</strong>";
pText = "The estimated price via <strong>" + travelModeText + "</strong> is <strong>£ " + estTotal.toFixed(2) + "</strong>";
$(form).prepend('<p class="valid msg">' + pText + '.</p>');
$(form).prepend('<p class="valid msg">' + dText + '.</p>');
$('html, body').animate({
scrollTop: 240
}, 200);
}
else {
$(form).find('.loading').remove();
err = '<p class="invalid msg">Sorry there seems to be some problem. You can contact us here.</p>'
$(form).append(err);
}
}
});
}
}
}
};
function initialize() {
// declaring map variable;
var mapOptions = {
center: new google.maps.LatLng(55.378051, -3.43597299999999),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map;
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
};
//google.maps.event.addDomListener(window, 'load', initialize);
Here is the html code:
<div id="map-holder">
<div class="container">
<div id="map-canvas"></div>
</div>
</div>
<div id="main">
<div class="container">
<div class="maintext">
<h2>Instant Quote for Same Day deliveries Across UK mainland</h2>
</div>
<div id="calculateform" class="form">
<p>Use the following form to calculate the estimated travel distance and price for your courier.</p>
<p class="instructions">You may search by Postcode,Street and/or City.
<br/>For Example: 10 Downing Street.
</p>
<form>
<p class="label">From</p>
<input id="from" class="" type="text" name="from">
<p class="label">To</p>
<input id="to" class="" type="text" name="to">
<p class="label">Mode of Transport</p>
<select id="travelMode">
<option value="driving" price=".80">Bike/Car</option>
<option value="driving" price=".85">Small Van</option>
<option value="driving" price=".95">Medium Van</option>
<option value="driving" price="1.05">Large Van</option>
<option value="driving" price="1.15">Extra Large Van</option>
</select>
<div class="clearfix"></div>
<input class="submitbtn" type="submit" value="Submit" />
</form>
</div>
</div>
</div>
The geocoder will always return the same coordinates if you query London, so you could just mark that down and then compare the new coordinates from the query with the saved ones. If they match you increase the costs.
I've set up google map API that loads data from mysql database and display markers. the problem I am facing is that all the markers shows up at once no matter whatever I input in search location field.............. I want to show only the searched area and markers in that area. It shouldn't display all the markers at once but only the marker in the searched area.
I mean I want to zoom the map to the searched area. Currently if I've only one marker map zoom in to show that but if I've many markers the map zoom out to show all the markers. Here is the map I'm working on "http://funfeat.com/clients/gmap/gmap3.html" NOW I've set markers very very far and the map is still showing all the markers by zooming out.
The gmap.php is the file that provide xml results from mysql database. and the below code is what I am using to display map
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<title>Google Maps AJAX + mySQL/PHP Example</title>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var map;
var markers = [];
var infoWindow;
var locationSelect;
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(40, -100),
zoom: 10,
mapTypeId: 'roadmap',
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
});
infoWindow = new google.maps.InfoWindow();
locationSelect = document.getElementById("locationSelect");
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
if (markerNum != "none"){
google.maps.event.trigger(markers[markerNum], 'click');
}
};
}
function searchLocations() {
var address = document.getElementById("addressInput").value;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
searchLocationsNear(results[0].geometry.location);
} else {
alert(address + ' not found');
}
});
}
function clearLocations() {
infoWindow.close();
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers.length = 0;
locationSelect.innerHTML = "";
var option = document.createElement("option");
option.value = "none";
option.innerHTML = "See all results:";
locationSelect.appendChild(option);
}
function searchLocationsNear(center) {
clearLocations();
var radius = document.getElementById('radiusSelect').value;
var searchUrl = 'gmap.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
downloadUrl(searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createOption(name, distance, i);
createMarker(latlng, name, address);
bounds.extend(latlng);
}
map.fitBounds(bounds);
locationSelect.style.visibility = "visible";
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
google.maps.event.trigger(markers[markerNum], 'click');
};
});
}
function createMarker(latlng, name, address) {
var html = "<b>" + name + "</b> <br/>" + address;
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
function createOption(name, distance, num) {
var option = document.createElement("option");
option.value = num;
option.innerHTML = name + "(" + distance.toFixed(1) + ")";
locationSelect.appendChild(option);
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request.responseText, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function parseXml(str) {
if (window.ActiveXObject) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.loadXML(str);
return doc;
} else if (window.DOMParser) {
return (new DOMParser).parseFromString(str, 'text/xml');
}
}
function doNothing() {}
//]]>
</script>
</head>
<body style="margin:0px; padding:0px;" onLoad="load()">
<div>
<input type="text" id="addressInput" size="10"/>
<select id="radiusSelect">
<option value="25" selected>25mi</option>
<option value="100">100mi</option>
<option value="200">200mi</option>
</select>
<input type="button" onClick="searchLocations()" value="Search"/>
</div>
<div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
<div id="map" style="width: 100%; height: 80%"></div>
</body>
</html>
http://funfeat.com/clients/gmap/gmap.php?lat=47&lng=-122&radius=2 produces valid XML but your query must be wrong .It pulls out 10 markers, 9 of which are correct but the 10th produces <marker name="Pakistan" address="Chowk Azam, Layyah" lat="31.008364" lng="71.224342" type="cITY"/> which is certainly not within 2 miles of the coordinates. Your query should not pick up the last marker from the database.
As the use of mysql_ functions are discouraged the following code uses PDO can be used
//dependant on your setup
$host= "WWW";
$username="XXX";
$password="YYY";
$database="ZZZ";
// Get parameters from URL
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
// Start XML file, create parent node
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
//Connect to database
$dbh = new PDO("mysql:host=$host;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
// Prepare statement
$stmt = $dbh->prepare("SELECT name, lat, lng, ( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance FROM gbstn HAVING distance < ? ORDER BY distance ASC LIMIT 0 , 20");
// Assign parameters
$stmt->bindParam(1,$center_lat);
$stmt->bindParam(2,$center_lng);
$stmt->bindParam(3,$center_lat);
$stmt->bindParam(4,$radius);
//Execute query
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
EDIT Added to catch error if no records found
if ($stmt->rowCount()==0) {
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", "No Records Found");
$newnode->setAttribute("lat", $center_lat);//Sends marker to search location
$newnode->setAttribute("lng", $center_lng);
$newnode->setAttribute("distance", 0);
}
else {
End of EDIT
// Iterate through the rows, adding XML nodes for each
while($row = $stmt->fetch()) {
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat']);
$newnode->setAttribute("lng", $row['lng']);
$newnode->setAttribute("distance", $row['distance']);
}
}
echo $dom->saveXML();
}
catch(PDOException $e) {
echo "I'm sorry I'm afraid you can't do that.". $e->getMessage() ;// Remove or modify after testing
file_put_contents('PDOErrors.txt',date('[Y-m-d H:i:s]').", gmap.php, ". $e->getMessage()."\r\n", FILE_APPEND);
}
//Close the connection
$dbh = null;
The part of the query above HAVING distance < '%s' is the part that should weed out the last marker.
I have added Error catch if no records are found in search and Map sent to lat/lng 0,0. See My Implementation Here