First of all, thanks for this great module. It's been a lifesaver.
One feature that I am interested in is using HTML5 browser geolocation as the source for latitude/longitude to calculate proximity for map results and sort them. I can get fairly close to satisfying this use case by using an exposed Proximity Filter as the input source for the Proximity Field, but it's not quite what I'm looking for. I've seen other issues that seem related, like #2581031: Make HTML browser location and geocoding widget available as exposed filters and #2841730: Proximity settings source type - static values only?, but they don't quite seem to be the same thing.
If I use the exposed proximity filter without geocoding options, I get fields for latitude/longitude, but the "distance" field seems to be required. Of course, this makes sense for a proximity filter designed to filter results by how close they are to a location, but in my case, I only care about determining the proximity distance and not filtering results based on it.
I've also tried configuring the view to use "user input" as the source for calculating the proximity field distance. This is closer to what I want in that it just provides fields for latitude/longitude, but it seems to require using query parameters to provide values for these fields to the view.
So it seems to me that the most likely solution here would be adding a new source option to the Proximity Field (since I don't need filtering). The source would be "HTML5 Geolocation" and I think it could work something like this:
- Latitude/longitude fields are hidden. Results are hidden by default.
-
Browser requests HTML5 location.
- If successful, coordinates are pushed to latitude/longitude fields and View is reloaded via AJAX, revealing the results with proximity distance.
- If unsuccessful, default View results are shown (proximity distance will be empty).
I notice you outlined somewhat similar functionality in #2822539-13: Order proximity source options. I'm not sure quite how the coordinate data could be received by the view, even via AJAX, since it's not exposed data, but I can look into it.
I'm happy to contribute to make this feature a reality, but any guidance you want to provide on implementation is welcome. Thanks!
Comment | File | Size | Author |
---|---|---|---|
#38 | 2879171-38-location-input.patch | 5.19 KB | ChristianAdamski |
| |||
#36 | 2879171-36-geolocation-html5-proximity.patch | 21.58 KB | albertski |
#34 | 2879171-33-geolocation-html5-proximity.patch | 41.92 KB | albertski |
#28 | 2879171-28-geolocation-html5-proximity.patch | 42.43 KB | welly |
#23 | interdiff-2879171-23-21.txt | 2.58 KB | recrit |
Comments
Comment #2
mrkdboyd CreditAttribution: mrkdboyd commentedAfter testing a few different approaches, I'm attaching a very rough first pass at this. I have added a "Client location" option for the proximity field source, and if this option is chosen, then a form for entering the latitude/longitude appears, the same as if "User input" is chosen.
However, rather than submitting the form via GET for regular "User input", for "Client location", the form submits via POST. Ultimately, the idea is that these form elements would be hidden rather than visible, receive their values dynamically if HTML5 browser geolocation succeeds, and then have the form be submitted via AJAX to update the view.
Comment #3
mrkdboyd CreditAttribution: mrkdboyd commentedUpdate: I was having all sorts of trouble getting the View to successfully refresh via AJAX. So instead, I pivoted to keeping the simple behavior of having proximity coordinates come in via query parameters.
I'm dynamically populating the coordinates from HTML5 geolocation if it is successful and auto-submitting the coordinate input form to refresh the page with proximity distances calculated. And I added a simple drupalSetting to avoid repeating this process if there are already coordinates in the request to avoid an endless page refresh loop.
This approach works, but it's fairly undesirable to refresh someone's page on every visit to a new view with proximity fields. Perhaps one enhancement would be to store the geolocation data somehow so that it could be directly used on subsequent pages without an HTML5 geolocation request, but I think there are some security/privacy concerns there.
Comment #4
mrkdboyd CreditAttribution: mrkdboyd commentedI finally got my head around what I needed to do here and got this working. I also introduce a new library/Drupal behavior for just handling integration with the HTML5 Geolocation API. It would fairly easy to update other uses of the API (common map, HTML5 widget) to use this behavior, but of course only if the changes seems worthwhile to you. Let me know what you think.
Now that the basic functionality is working, the next enhancement I have in mind would be to store the geolocation coordinates in a secure cookie for the current domain only, "HttpOnly = true" so that it cannot be read from Javascript, and only persisting for the length of the session. This would allow the query for proximity distance on subsequent requests to just retrieve the stored geolocation, rather than having to retrieve it again from the client.
Comment #5
mrkdboyd CreditAttribution: mrkdboyd commentedAdded functionality to store the client location in a cookie. Also added some code to ensure AJAX processing works even if the view isn't set to use AJAX.
Comment #6
mrkdboyd CreditAttribution: mrkdboyd commentedSigh...last patch was missing the two JS files I added. Here is an updated patch with a few minor code style fixes.
Comment #8
mrkdboyd CreditAttribution: mrkdboyd commentedComment #9
attishu CreditAttribution: attishu commentedInterested...
Comment #10
mrkdboyd CreditAttribution: mrkdboyd commentedJust realized that it would be better to use the TempStore provided by Drupal core for users to store geolocation data in the session instead of a cookie. I'll work on that and re-roll the patch.
Comment #11
mrkdboyd CreditAttribution: mrkdboyd commentedThere is a bug in Drupal core where the TempStore isn't properly initialized for anonymous users. See #2743931: Saving to the private tempstore doesn't start a session for anonymous users. So I'm putting that re-factor on hold for the moment.
However, I did refactor the JS code for HTML5 geolocation to more closely mimic the behavior of the JS for the geocoder, where arbitrary JS code can "subscribe" to the HTML5 geolocation result by registering a callback. I also updated the code to namespace the drupalSettings to the module.
Comment #12
mrkdboyd CreditAttribution: mrkdboyd commentedRe-rolled patch with a small fix to ensure that views aren't auto-refreshed if they have required exposed filters and there is no input for exposed filters
Comment #13
Ruslan PiskarovHello Mark,
I am testing your patch and trying to implement the following functionality:
I already have the map like this http://take.ms/2HXCR (important things marked as red).
So, then I am typing address, e.g. London and put Destination, I see the centre of London plus 15 miles.
However, by default, without "address" & "destination" I want to see venues near me in radius 15 miles.
Could you explain more about you patch?
Because I found the settings of the 'Client location (HTML5)' there http://take.ms/f3GBd (http://take.ms/jF1Fr) and can not understand how to tie it with "Filter criteria". I believe it should be like this http://take.ms/xBiE8, but my opinion can be wrong. In the result, I got this map http://take.ms/haD9W.
Could you review my comment?
Thank you in advance.
Comment #14
mrkdboyd CreditAttribution: mrkdboyd commented@Ruslan P - So this patch does not integrate with filter criteria. It is only for use when you want to calculate proximity distance, but not to use that distance as filter criteria (which is what you are trying to do). For what you are trying to do, I think you need to change the option here (http://take.ms/jF1Fr) to be "Proximity Filter" instead of "Client location (HTML5)" and then configured it to use your proximity filter on the view.
The "Client location (HTML5)" option that I added for proximity fields is basically an enhancement to the "User input" option. Whereas the "User input" option gives non-filter fields for latitude/longtitude for calculating proximity distance to geolocated entities, this patch provides integration with HTML5 geolocation so that a user's location is automatically determined (if they give permission) and then the view results are refreshed via AJAX with the calculated proximity distances. Also, once the user's geolocation has been determined, it is stored in a secure session cookie so that subsequent visits to pages with geolocated entities can pull the user geolocation from the cookie, rather than requiring another round-trip from the front-end using AJAX.
Comment #15
Ruslan Piskarov@mrkdboyd, thank you. Will try again after your comment.
Comment #16
mrkdboyd CreditAttribution: mrkdboyd commentedRe-rolled patch with a couple updates:
Comment #17
whitelancer CreditAttribution: whitelancer commented@mrkdboyd,
I have been trying to find a way to replicate a function I've used on older Drupal sites -- simply sorting a set of results based on closest to the user, using the HTML5 location / api built into browsers. I am pretty surprised that there just doesn't seem to be anything like this out there, so I'm attempting to use your patch as a starting place to get this going.
I've patched your code, but so far, I've not been able to see this working. This doesn't seem to be prompting the user for their location, and so I'm never getting any geolocation results back (for the user). Was there anything special that needs to be done in order to prompt the user's browser to share the location? In the past I've never had any issues getting this to work, but I'm still working though the changes to Drupal 8.
Also, what would be involved to extend your patch so it can support sorting closest to the user?
Thanks for your contribution!!
[EDIT]
I discovered the issue here. I have been using one list as results, and a map attachment floated to the right, to display the map. I had to remove references to a map from the code, as the promise was never resolving for
mapLoaded
.The only other question at this point would be -- do you have any ideas on how I might display nothing if location is denied or cannot be determined? I'm basically building a directory listing sorted by closest to the user, but it is pointless if the location cannot be determined. I wanted to use a filter when the proximity was 0, but since this code is focused on the field, I wasn't sure the best way to handle that. I'm looking into a few options to refresh and change settings and the like, but I was hoping maybe you had a solution you might recommend.
Thank you!
Comment #18
mrkdboyd CreditAttribution: mrkdboyd commentedRe-rolled patch with a couple updates:
mapLoaded
promise blocking geolocation for views with no maps.GeolocationTempStore
service. Would ultimately like to integrate with the Drupal user private temporary storage once #2743931: Saving to the private tempstore doesn't start a session for anonymous users lands.Comment #19
mrkdboyd CreditAttribution: mrkdboyd commented@whitelancer - Sorry for the delay, but the above patch should address the issue you were seeing with the
mapLoaded
promise.If you want to actually hide the view based on geolocation error, it should be possible to add some code to register custom callbacks in case of HTML5 geolocation failure, the same way that success callbacks are registered in the current patch. Then in your callbacks you could take whatever action you like. I think you would have to go the JS route, since HTML5 geolocation happens on the client.
Comment #20
mrkdboyd CreditAttribution: mrkdboyd commentedMinor update to previous patch to consolidate some logic into the new
GeolocationTempStore
service.Comment #21
mrkdboyd CreditAttribution: mrkdboyd commentedFixing an issue in the previous patch with false positives for stored geolocation in the session which caused geolocation Views to never auto-refresh after receiving coordinates from the browser.
Comment #22
jlballes CreditAttribution: jlballes commentedThe patch works well!
Is it possible do not show results until the ajax request?
Is it going to be merged to the module code?
Thanks!
Comment #23
recrit CreditAttribution: recrit commentedAdded an error callbacks api so that custom JS can respond to errors such as the user denying the location.
Comment #24
galvestor CreditAttribution: galvestor commentedI get "bad git-diff - expected dev/null on line 23" when trying to patch it with git.
Am I missing something here?
Comment #25
galvestor CreditAttribution: galvestor commentedok, resolved part of it. However, I still get the following when trying to apply the last patch:
error: patch failed: js/geolocation-google-maps-api.js:434
error: js/geolocation-google-maps-api.js: patch does not apply
Comment #26
Ruslan Piskarov10 Sep 2017 was new DEV version of the module. Probably we need to update the patch to.
Comment #27
rgeerolfI rolled back to commit #cb68b54 so the patch would apply. I set the client source to 'Client location (HTML5)' but when I check the view I do not get prompted from my browser (tried multiple) for my location. Is there something I'm missing here? I'm just trying to built a list of locations, there is not map involved.
#17 seemed to have a simular problem but it does not look the same issue.
Comment #28
welly CreditAttribution: welly at Fat Beehive commentedI've rerolled the patch to work on the latest version but I can't actually get it working. It never seems to prompt the user for their location. I'll have another look and see if I can see what's occurring (or not in this case) as I definitely need this for a current project.
Comment #29
rgeerolf@welly
The problem for me was that I was in my dev environment and I was not using https. In Firefox 55 or Chrome 50 and higher, only HTTPS pages will be able to request location. Switching to https fixed the issue for me.
Comment #31
welly CreditAttribution: welly at Fat Beehive commentedThanks @rgeerolf, I'll try that out and see if it makes any difference!
Comment #32
SocialNicheGuru CreditAttribution: SocialNicheGuru commentedI think it needs to be rerolled again for the latest 1.x version
Comment #33
joannamay CreditAttribution: joannamay commentedAny updates on this? I'm able to make the changes manually by combing through the patch, but composer chokes on running the patch.
Comment #34
albertski CreditAttribution: albertski at Xeno Media, Inc. commentedI have rerolled the patch but also haven't gotten it to work.
Comment #35
albertski CreditAttribution: albertski at Xeno Media, Inc. commentedI updated the beginning of viewsForm() to this and now I am seeing that it asks for Geo Locations but it still does not work.
@mrkdboyd (or anyone that understands this) I am going through geolcations-html.js and I am not understanding how data gets added to Drupal.geolocation.html5.resultCallbacks (Drupal.geolocation.html5.resultCallbacks is empty so it does not go any further). I don't see anything calling addResultCallback().
Comment #36
albertski CreditAttribution: albertski at Xeno Media, Inc. commentedThe attached patch is #23 rerolled for the latest. I was seeing better results compared to the one from #34. I still wasn't able to quite get the results I wanted so I created a custom field formatter (overwrote ProximityField and extended it) and used 1.1.
In my view:
- Add proximity field as a field. Choose User input
- Make sure to set view to use Ajax
my_module.views.inc:
RangeProximityField.php
mymodule_range_proximity.js
Comment #37
ChristianAdamski CreditAttribution: ChristianAdamski commentedIn #2936637: In "Filter Criteria" the "Proximity" filter does not work (v2) the whole proximity handling was massively reworked. The "client location" behavior as described here is now fairly easy to built. I couldn't though, because my local dev setup does not support client location. Will do so in a bit.
Comment #38
ChristianAdamski CreditAttribution: ChristianAdamski commentedStraight forward location input plugin.
- set client location if available
- optionally hide form
- optionally auto-submit
P.S. The range thingie should go to its issue. It does not really belong here, but would be a nice feature.
Comment #40
ChristianAdamski CreditAttribution: ChristianAdamski commented