Dokan Geolocation filtering
-
Hi, I hope youre well!
I know this is a long shot, but we were wondering if there is any way to make the annasta filtering compatible with the dokan geolocation filtering which you can find here.
Using either works on the page, for example if you search only for products near london, the correct products show up, however if you add a filter such as on sale it just grabs from all products and doesn’t respect the added dokan filters to the url.
Additionally, after filtering/changing page with ajax the map with the product dokan_geo_address pins is not updated however this seems more complex to fix
Best,
Leo
The page I need help with: [log in to see the link]
-
Regarding the first point, just setting the ajax mode to enhanced compatibility fixed the issue! Its just the updating the pin location to reflect the filtered products
Hello Leo, welcome back to our support forum!
The enhanced compatibility filtering working in combination with your 3d party is a very good news! As for updating the map, if the Dokan application provides a JS method to reload the existing map to match the current page URL, you can make the AJAX mode work by attaching such map refresh call to the filters’ AJAX update event:
jQuery(document).on('awf_after_ajax_products_update', function () { if ('undefined' !== typeof DokanGeo) { // Map update call. } });
Please contact the Dokan Geolocation developers to ask them if they can provide you with the call that would update the map!
Thank you for that!
I copied the code from dokan-geolocation-locations-map-mapbox.js?ver=3.9.10
to create this:
jQuery(document).on('awf_after_ajax_products_update', function () { if ('undefined' !== typeof DokanGeo) { (()=>{ var e; e = jQuery, DokanGeo.LocationsMaps = { map: null, mapboxId: "dokan-geolocation-locations-map", items: [], data: { type: "FeatureCollection", features: [] }, marker: { image: null, clusterer: null }, modal: e(".dokan-geo-location-modals").iziModal({ closeButton: !0, appendTo: "body", title: "", headerColor: dokan.modal_header_color }), init: function() { var o = this , a = { longitude: 0, latitude: 0 }; if (mapboxgl.accessToken = DokanGeo.mapbox_access_token, o.map = new mapboxgl.Map({ container: o.mapboxId, style: "mapbox://styles/mapbox/streets-v10", center: [DokanGeo.default_geolocation.longitude, DokanGeo.default_geolocation.latitude], zoom: DokanGeo.map_zoom }), o.map.addControl(new mapboxgl.NavigationControl), o.items = e('[name="dokan_geolocation[]"]'), o.items.each((function(t) { e(this).val(); var n = e(this).data("latitude") , i = e(this).data("longitude") , r = { type: "Feature", properties: { id: "dokan-geolocation-item-" + t, info: e(this).data("info") }, geometry: { type: "Point", coordinates: [i, n, 0] } }; o.data.features.push(r), a.longitude += i, a.latitude += n } )), a.longitude && a.latitude) o.map.setCenter([a.longitude / o.items.length, a.latitude / o.items.length]); else { const e = new URLSearchParams(window.location.search) , a = Object.fromEntries(e.entries()); o.map.setCenter([a.longitude, a.latitude]) } o.map.on("load", (function() { o.loadImages("image", DokanGeo.marker.image), o.loadImages("clusterer", DokanGeo.marker.clusterer) } )) }, loadImages: function(e, o) { var a = this; a.map.loadImage(o, (function(o, t) { o || (a.marker[e] = t, a.map.addImage("dokan-marker-" + e, t), a.addMapLayers()) } )) }, addMapLayers: function() { var e = this; e.marker.image && e.marker.clusterer && (e.map.addSource("dokan_geolocation_map_main_data", { type: "geojson", data: e.data, cluster: !0, clusterMaxZoom: 14, clusterRadius: 50 }), e.map.addLayer({ id: "clusters", type: "symbol", source: "dokan_geolocation_map_main_data", filter: ["has", "point_count"], layout: { "icon-image": "dokan-marker-clusterer", "icon-allow-overlap": !0, "text-allow-overlap": !0 } }), e.map.addLayer({ id: "cluster-count", type: "symbol", source: "dokan_geolocation_map_main_data", filter: ["has", "point_count"], layout: { "text-field": "{point_count_abbreviated}", "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"], "text-size": 12 }, paint: { "text-color": "rgb(253, 218, 206)" } }), e.map.addLayer({ id: "unclustered-point", type: "symbol", source: "dokan_geolocation_map_main_data", filter: ["!", ["has", "point_count"]], layout: { "icon-image": "dokan-marker-image", "icon-allow-overlap": !0, "text-allow-overlap": !0 } }), e.map.on("click", "clusters", (function(o) { var a = e.map.queryRenderedFeatures(o.point, { layers: ["clusters"] })[0].properties.cluster_id; e.map.getSource("dokan_geolocation_map_main_data").getClusterLeaves(a, 255, 0, (function(o, t) { if (e.map.getZoom() > 9 && t.length > 1) { var n = '<div class="white-popup dokan-geo-map-info-windows-in-popup">' , i = 0; for (i = 0; i < t.length; i++) n += e.getInfoWindowContent(t[i].properties.info); n += "</div>", e.modal.iziModal("setContent", n.trim()), e.modal.iziModal("open") } else e.map.getSource("dokan_geolocation_map_main_data").getClusterExpansionZoom(a, (function(o, a) { o || e.map.easeTo({ center: t[0].geometry.coordinates, zoom: a }) } )) } )) } )), e.map.on("mouseenter", "clusters", (function() { e.map.getCanvas().style.cursor = "pointer" } )), e.map.on("mouseleave", "clusters", (function() { e.map.getCanvas().style.cursor = "" } )), e.map.on("click", "unclustered-point", (function(o) { var a = e.map.queryRenderedFeatures(o.point, { layers: ["unclustered-point"] })[0].properties.info; a && (e.map.easeTo({ center: o.lngLat }), new mapboxgl.Popup({ closeOnClick: !0 }).setLngLat(o.lngLat).setHTML(e.getInfoWindowContent(a)).setMaxWidth("654px").addTo(e.map)) } ))) }, getInfoWindowContent: function(e) { "string" == typeof e && (e = JSON.parse(e)); var o, a = DokanGeo.info_window_template; for (o in e) a = a.replace("{" + o + "}", e[o]); return a } }, e("#dokan-geolocation-locations-map").length && DokanGeo.mapbox_access_token && DokanGeo.LocationsMaps.init() } )(); } });
and that worked for me, for if anyone else has this issue!
Perhaps dokan will get back to me with a neater way to do this
Best,
Leo
On https://patchy-art.co.uk/local/ if the geolocation filter is used after annasta filters are used, the filters are lost from the url
For example if you search for on-sale products and then narrow it down to those located near Upton, West Yorkshire, England the active filters are lost from the url after geolocation. Though they can be added back to narrow the search afterwards.
Is there anyway to ensure these filters arent lost after a geolocation search?
Also it seems that if you go to the next page of results after using the geolocation the images are blank. For example if you search for products near York, England and then go to the second page
Best,
Leo
Hello Leo,
Thank you so much for sharing the working fix for the Dokan Geolocation compatibility with the users of our plugin!
As for the loss of filtering parameters after Dokan AJAX string search, unfortunately this can only be fixed on their side. You need the combination of an analogue of our 3d party parameters support option and the enhanced compatibility AJAX mode (which applies the 3d party parameters during AJAX queries).
You could ask the Dokan developers if they provide such an AJAX mode, but in case they don’t, then at least the filtering URL parameters preservation would suffice if you could simultaneously set up the Dokan string + location search to reload the page instead of querying via AJAX. Page reloads during Dokan search would resolve almost your issues: geolocation + filters seems to work well on page reloads, plus the image lazy load problem arising after the Dokan AJAX usage also doesn’t seem to appear after the page reload.
The only issue that I have run into during my tests of Dokan search reloads on your site was the pagination: for some reason the Dokan map markers limit their results count to the amount set by the products per page setting. This was happening when I was adding the annasta products per page variable, but do they provide support at least for the native WooCommerce pagination settings? You would have to check that as well.
Thank you for your help!
I’m working on preserving the location filter + product filters, though i think setting up a mouse over event listener on the geolocation submit button to check / store filter parameters and then reloading the page with them after button click should do the trick!
Here is a way I figured to make sure any placeholder images are replaced after the ajax search:
jQuery(document).on('awf_after_ajax_products_update', function () { //check if placeholder catalog images are present checkExists("a.woo_catalog_media_images > img[src*='data:image/svg']"); //check if placeholder featured badges are present checkExists("div.wpcbm-badge > div > img[src*='data:image/svg']"); function checkExists(query_string){ let temp_nodes =document.querySelectorAll(query_string); if(temp_nodes){ temp_nodes.forEach(element => {element.src = element.getAttribute("data-src"); }); } } });
Regarding the map pins, I believe it is just that way by dokans design unfortunately, and I haven’t looked into how to just place all of them yet.
Finally, we have switched to the load more product list style and were wondering if there is anyway to add a simple message at the bottom of the product list if that is the end of the products found?
Best,
Leo
- This reply was modified 8 months ago by patchyart.
Also, is it possible to set the ajax filtering mode on a per filter basis? Or is it just the overall setting which is possible?
Thanks
Hello Leo,
Here is the code that worked on my test site for the message display in the “Load More” mode:
jQuery( document ).on( 'awf_after_ajax_products_update', function( event, $response ) { if ( ( 'ajax_pagination_end_reached' in awf_data ) && awf_data.ajax_pagination_end_reached ) { jQuery( '<div>Your message here</div>' ).insertAfter( a_w_f.products_wrappers.find( awf_data.products_container ) ); } } );
The message is displayed under the products list when there don’t exist any more products to load.
As for your second question about setting the AJAX mode on per filter basis, there actually exists an option to do the opposite: you can have your preset set to an AJAX mode and force separate filters into reloading the page with the help of the Force page reloads option. If you have your preset working in the AJAX button submitted mode, you can also add the dedicated submit button to the needed filter to make its submission more intuitive for the users.
Thank you for that!
I added some checks to remove the message after clearing, or filtering for something else if anyone stumbles across this thread:
jQuery( document ).on( 'awf_after_ajax_products_update', function( event, $response ) { if ( ( 'ajax_pagination_end_reached' in awf_data ) && awf_data.ajax_pagination_end_reached ) { const clearButtonNone =document.querySelector("div.awf-reset-btn-container.awf-bottom-reset-btn-container > button"); const filterButtonNone = document.querySelector("div.awf-btn-container > button"); clearButtonNone .addEventListener('click', ()=> removeMsg()); filterButtonNone .addEventListener('click', ()=> removeMsg()); function removeMsg(){ if(document.querySelector("#end-of-results")){ document.querySelector("#end-of-results").remove(); }; }; if(!document.querySelector("#end-of-results")){ jQuery( "<div id='end-of-results' class='end-result-msg'>No more products found.</div>").insertAfter( a_w_f.products_wrappers.find( awf_data.products_container ) ); } } } );
About the AJAX mode per filter preset, I meant more for example having dedicated AJAX on one preset and enhanced compatibility on another as our default browse page doesn’t need the enhanced compatibility but our geolocation one does
Best,
Leo
Leo, thank you so much for sharing the production version of the end of “Load More” message attachment code with other users!
As for switching the dedicated and compatibility AJAX mode between the filters.. never tried that, but theoretically, you could attempt changing the awf_data.ajax_mode variable on filter “click” or “change” events. Set it to either the ‘dedicated_ajax’ or ‘compatibility_mode’ string.
The only obvious potential problem for this case scenario that can be predicted from now is the delayed submission cases: if the filters set to different modes are in the same button-submitted preset, the last changed filter will dictate the AJAX mode during button submission. In any case, you could certainly try and test this, and search for workarounds. If it’s not too much of trouble, please let us know here if you ever manage to make this work!
Hi,
As we have the different filters on separate pages ‘browse-art’ and ‘local-art’ wouldn’t a simple:
<script> if(window.location.pathname.includes('/browse-art/')){ awf_data.ajax_mode = 'dedicated_ajax'; } </script>
do the trick?
Sure, Leo!
I thought that you meant to alternate the AJAX mode for the filters of the same page. If the needed mode can be figured out already on page load, then of course it makes more sense to attach the AJAX mode change to the document load or ready event!
Hi,
We’ve found that after AJAX filtering the countdown timer for auctions is not reinitiliased (e.g. see here)
Have you guys run into this before?
Thanks
Good morning, Leo,
Yes, I remember a couple of cases when people tried to re-attach the auctions’ counter events after AJAX filtering! They had different 3d party providers, and I believe, at least in one of the cases the developers of the auctioning plugin eventually provided them with the solution.
If you like, contact, the developers of your auctions component, and tell them that you wish to re-initialize the counters on awf_after_ajax_products_update event:
// annasta Woocommerce Product Filters: reinitialize after AJAX load $( document ).on( 'awf_after_ajax_products_update', function() { // Initialization procedure });
If they also need to destroy the old auction instances prior to reinitialization, they can do it on awf_ajax_filter event:
// annasta Woocommerce Product Filters: destroy old instances before AJAX load $( document ).on( 'awf_ajax_filter', function() { // Destruction procedure });
Hope this helps!
Thank you!
And how would we make sure this function only runs after the infinite scroll filtering ajax
jQuery(document ).on( 'awf_ajax_filter', function() { jQuery( "<div id='loading-of-results' class='loading-result-msg'>Loading More Products <i class='fa fa-spinner fa-spin'></i></div>").insertAfter( a_w_f.products_wrappers.find( awf_data.products_container ) ); });
This works it just fire on any ajax filtering
- This reply was modified 7 months, 3 weeks ago by patchyart.
- You must be logged in to reply to this topic.