On a map with 300+ markers, each with their own info box & imagery & data, loading the entire map & all the markers at once causes page speed issues.
here's an example - www.naturesoundmap.com/listing-type/nature-soundscape
What I would like to do is: Have the markers served dynamically based on a starting location & pre-determined zoom level.
See the above link for an example starting location - in this case I want the map to only load the 20 or so markers viewable on screen, not the 300+ markers from the entire planet. As the user scrolls to new areas of the map, new markers should load dynamically as their location comes into view.
I am using a Wordpress theme 'Explorable' by Elegant Themes so the following code is already a part of the theme.
As simple an explanation as possible would be much appreciated as I am a novice!
Thanks
Marc
Currently, this is the code I have (this is an excerpt - let me know if you need to see the entire file)
mapTypeId: google.maps.MapTypeId.<?php echo esc_js( strtoupper( et_get_option( 'explorable_map_type', 'Roadmap' ) ) ); ?>,
zoomControl: true,
zoomControlOptions: {
position : google.maps.ControlPosition.LEFT_BOTTOM,
style : google.maps.ZoomControlStyle.LARGE},
panControl: false,
streetViewControlOptions: {},
overviewMapControl: false,
overviewMapControlOptions: {
opened : false
},
scrollwheel: true,
streetViewControl: false,
mapTypeControl: false,
mapTypeControlOptions: {}
}
}
});
function et_add_marker( marker_order, marker_lat, marker_lng, marker_description ){
var marker_id = 'et_marker_' + marker_order;
$et_main_map.gmap3({
marker : {
id : marker_id,
latLng : [marker_lat, marker_lng],
options: {
icon : "<?php echo get_template_directory_uri(); ?>/images/red-marker.png"
},
events : {
click: function( marker ){
if ( et_active_marker ){
et_active_marker.setAnimation( null );
et_active_marker.setIcon( '<?php echo get_template_directory_uri(); ?>/images/red-marker.png' );
}
et_active_marker = marker;
marker.setAnimation(google.maps.Animation.BOUNCE);
setTimeout(function(){ marker.setAnimation(null); }, 3750);
marker.setIcon( '<?php echo get_template_directory_uri(); ?>/images/blue-marker.png' );
$(this).gmap3("get").panTo( marker.position );
$.fn.et_simple_slider.external_move_to( marker_order );
},
mouseover: function( marker ){
$( '#' + marker_id ).css( { 'display' : 'block', 'opacity' : 0 } ).stop(true,true).animate( { bottom : '15px', opacity : 1 }, 500 );
},
mouseout: function( marker ){
$( '#' + marker_id ).stop(true,true).animate( { bottom : '50px', opacity : 0 }, 500, function() {
$(this).css( { 'display' : 'none' } );
} );
}
}
},
overlay : {
latLng : [marker_lat, marker_lng],
options : {
content : marker_description,
offset : {
y:-42,
x:-122
}
}
}
});
}
It looks like you're calling et_add_marker() each time for the 320 or so points. Perhaps if you can figure out a way to load the point data in a KML file and iterate through each item that would boost speed?
How are the data points managed - in Wordpress as a custom post, or are you hard coding them into your theme?
Related
I'm trying to change the background color of an event (in Day View) of fullcalendar v4. I've spent hours trying to implement eventRender, to no avail. This has led me to find other workarounds, but now, I'm striking out!
I'm trying to figure out the solution explained here: [Fullcalendar - change event color based on value ..
But, every time the search for the word 'yes' is TRUE, I get an error in chrome console saying 'Failure parsing JSON'. If I change the search query to something that will create 'false', I do not get this error. To me, this means that the search is working, but the event render function is failing somehow.
my code:
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'resourceDayGrid', 'resourceTimeGrid' ],
defaultView: 'resourceTimeGridDay',
defaultDate: '<?php echo $startdate?>',
validRange: {
start: '<?php echo $startdate?>',
end: '<?php echo $maxdaycal?>'
},
height: 700,
...
...
eventSources: [
{
url: 'getevents2.php?festid=<?php echo $festid?>&room=<?php echo $roomabv?>',
cache: false,
},
{
url: 'getbreaks2.php?festid=<?php echo $festid?>&room=<?php echo $roomabv?>',
cache: false,
color: 'grey',
editable: false,
}
],
eventRender: function(info) {
if(info.event.extendedProps.desc == "yes") {
element.style.css('background-color', '#000');
}
},
....
});
calendar.render();
});
My goal: Search for the word "Accomp" in the title of the element (probably in info.event.title) .. and have the background change to a different color .. like red .. or something.
I've also tried to show an Icon in this field if the word Accomp is present, but -- I had to show it in a modal, because I couldnt get eventrender to show html.
I think this is because of the differences in FC v4 .. but I'm not sure.
I've also tried: [Is it possible to assign the background colour of a FullCalendar event based on its title? .. but I couldn't get that sorted out either.
UPDATE: The search function is working, as I can see it in the console log, but whenever I try to set the css, the calendar does not render.
eventRender: function(info) {
console.log(info.event.title);
if(-1 != info.event.title.indexOf("Accomp")) {
console.log(info.event.title);
fc-title.css('background-color', '#000');
}
},
This is based on some other answers that areavailable, but it appears that there are differences in FC4... This works for me!
eventRender: function(info) {
if(-1 != info.event.title.indexOf("Accomp")) {
info.el.style.backgroundColor = "red";
}
},
i have developed aspx page
on it i have image galley using owl-carousel
now when i added magnific-popup plugin and used gallery option
then i noticed when i click on image on carousel it get popup successfully but images get duplicated (inside popup)
Owl-Carousel gallery
First popup
Duplicated Image
my aspx code :
<div class="owl-carousel">
<asp:ListView runat="server" ID="lvDesrtProgramGallery" ItemType="SharedKernel.Core.Model.ProgramPhoto" SelectMethod="lvDesrtProgramGallery_GetData">
<ItemTemplate>
<div class="item">
<a class="desert-safari-gallery" href="<%# Item.PhotoPath %>">
<img src="<%# Item.MediumPhotoPath %>" alt="" />
<div class="overlay">
<i class="fa fa-search-plus"></i>
</div>
</a>
</div>
</ItemTemplate>
</asp:ListView>
</div>
Js code
$('.desert-safari .owl-carousel').owlCarousel({
items: 3,
dots: false,
nav: true,
loop: true,
margin: 10,
autoplay: true,
navText: ['<i class="fa fa-angle-left fa-4x"></i>', '<i class="fa fa-angle-right fa-4x"></i>'],
onInitialized: callback,
responsiveClass: true,
responsive: {
0: {
items: 1,
nav: false,
margin: 80
},
570: {
items: 1,
nav: false
},
768: {
items: 2,
nav: false
},
992: {
items: 3,
nav: false,
},
1200: {
items: 3,
nav: true,
loop: false
}
}
});
function callback(event) {
$(".desert-safari-gallery").magnificPopup({
type: "image",
removalDelay: 160,
loop: false,
preloader: false,
fixedContentPos: true,
showCloseBtn: false,
gallery: {
enabled: true
}
})
}
I just ran into this problem so I thought I'd give you my answer/solution.
The Reason:
Since your using owl carousel to loop, owl carousel is cloning items. Because your cloning the items within your carousel you're now feeding duplicates into the popup gallery. What a hassle right? There are two seemingly obvious solutions.
Solution 1: Don't use owl-carousel's loop.
This may not be the preferred solution if you want the looping feature of your carousel but this will no longer cause the popup to receive duplicate entries.
Solution 2: Create an array of objects based on the resulting elements, remove the duplicates, then use magnific's items property to set the gallery items.
Here is a working script I had to create based off a similar scenario I'm sure you can dissect what the process is:
(function( $ ) {
'use strict';
$( window ).load(function(){
var GalleryItems = [];
$('.gallery img').each(function(i){
var src = $(this).attr('href');
var theSrc = {
src: src,
type: 'image'
};
GalleryItems.push(theSrc);
});
var GalleryItems = GalleryItems.reduce(function(previous, current) {
var object = previous.filter(object => object.src === current.src);
if (object.length == 0) {
previous.push(current);
}
return previous;
}, []);
theGallery();
function theGallery(){
$('gallery').magnificPopup({
type: 'image',
gallery: {
enabled:true
},
items:GalleryItems,
});
}
});
})( jQuery );
I found that #Chris Stage's answer works perfectly, but for some n00bs who try to use the code verbatim may run into issues. I can't just leave a comment or accept the answer so I am posting my revision in hopes that it provides someone else with the correct code.
The one issue I found was that in the .each() function, that you have to target the wrapping a tag's URL to the larger image, not the image's URL itself due to the fact that the one used in the carousel may be a thumbnail or equivalent, and the larger one to the "larger image" to open in a popup may be a separate URL.
(function( $ ) {
'use strict';
$( window ).load(function(){
var GalleryItems = [];
$('.photo-gallery .item a').each(function(i){ //Target your wrapping a tag
var src = $(this).attr('href');
var theSrc = {
src: src,
type: 'image'
};
GalleryItems.push(theSrc);
});
var GalleryItems = GalleryItems.reduce(function(previous, current) {
var object = previous.filter(object => object.src === current.src);
if (object.length == 0) {
previous.push(current);
}
return previous;
}, []);
theGallery();
function theGallery(){
$('.photo-gallery').magnificPopup({ //Target parent carousel container
type: 'image',
gallery: {
enabled:true
},
items:GalleryItems,
removalDelay: 300,
mainClass: 'mfp-fade' //Adds magnific's fade effect
});
}
});
})( jQuery );
This solution worked perfectly with Owl's issue with "cloned" images and thanks to #Chris Stage for coming up with this. His answer should be the "Accepted Answer" but I'd also love an Upvote for the clarification so I can earn some Rep points :)
For future reference, here is a much simpeler solution:
$('.owl-item:not(.cloned) * .desert-safari-gallery').magnificPopup(..
Change your selector so that it will not be used for children of elements with the 'owl-item cloned' class.
You can use this little fix.
$('.owl-carousel.with-mfp').each(function () {
var $mfp = $(this);
$mfp.on('click', '.owl-item.cloned a', function (event) {
event.preventDefault();
var self = $(this);
// Dependency on image positions in owl and on unique a.href attrs
$mfp.find('.owl-item:not(.cloned) a').each(function (index) {
if ($(this).attr('href') === self.attr('href')) {
$mfp.magnificPopup('open', index);
}
});
});
$mfp.magnificPopup({
type: 'image',
delegate: '.owl-item:not(.cloned) a',
gallery: {
enabled: true
}
});
I'm trying to replace the icons with a RichMarker as seen here: https://google-maps-utility-library-v3.googlecode.com/svn/trunk/richmarker/examples/richmarker.html
Here's the following code I'm using:
marker: {
values: [
{foreach $items as $item}
{
latLng: [{ifset $item->optionsDir['gpsLatitude']}{!$item->optionsDir['gpsLatitude']}{else}0{/ifset},{ifset $item->optionsDir['gpsLongitude']}{!$item->optionsDir['gpsLongitude']}{else}0{/ifset}],
content: "<div class='cluster-bg'><div class='cluster'><span>1</span></div></div>",
data: '<div class="marker-holder"><div class="marker-content{ifset $item->thumbnailDir} with-image"><img src="{thumbnailResize $item->thumbnailDir, w => 120, h => 160}" alt="">{else}">{/ifset}<div class="map-item-info"><div class="title">'+{ifset $item->post_title}{$item->post_title}+{/ifset}'</div>{if $item->rating}<div class="rating">{for $i=1; $i <= $item->rating["max"]; $i++}<div class="star{if $i <= $item->rating["val"]} active{/if}"></div>{/for}</div>{/if}<div class="address">'+{ifset $item->optionsDir["address"]}{$item->optionsDir["address"]|nl2br}+{/ifset}'</div>' + {__ 'VIEW MORE'} + '</div><div class="arrow"></div><div class="close"></div></div></div></div>'
}
{if !($iterator->last)},{/if}
{/foreach}
],
I understand how to add a rich marker to a single marker, but here I'm dynamically creating markers under "values." I have no idea where to add the:
= new RichMarker ({
Is this possible with these two plugins or should I look elsewhere?
Thanks
Here is the code that you must add:
jQuery("YOUR_SELECT").gmap3({
defaults:{
classes:{
Marker:RichMarker
}
},
map:{
options: {
zoom: 11,
},
marker: {
options: {
content: '<div>ADD your Custom HTML code</div>',
}
}
})
Using GMAP3 Google Map API 3 class. Cannot quite figure out how to trigger the click event on a marker from an external link via javascript. I have tried the v3 api syntax but suspect that I am missing something in relation to the GMAP3 library. Could anyone help me out here?
I am showing a map with markers and infobox data from an ajax request with a resulting JSON array. Works great. I assign a click event to the marker and it works fine. I am using parsing that same JSON array to populate a datatable with a Click Me
X is actually the incrementing marker counter I used when building the JSON array, so it would start with 0 and build to whatever value represents all my markers. I am expecting to use this value to tell GMAP3 which marker I want to pass the click event to... if this though process is wrong then I am really confused.
My JSON array object is stored in markerlist and passed to the function below... which works great but I cannot seem to trigger those clicks from my datatable links... (see my jquery code below to grab those clicks and attempt to pass them along to the map)
My map code is:
function display( markerlist ) {
$("#map").gmap3({action:'clear'});
$("#map").gmap3(
{action: 'init',
options:{
center:true,
zoom:13,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
navigationControl: true,
scrollwheel: true,
streetViewControl: true
}
},
{action: 'addMarkers',
radius:100,
markers: markerlist,
clusters:{
maxZoom: 10,
// This style will be used for clusters with more than 0 markers
20: {
content: '<div class="cluster cluster-1">CLUSTER_COUNT</div>',
width: 53,
height: 52
},
// This style will be used for clusters with more than 20 markers
50: {
content: '<div class="cluster cluster-2">CLUSTER_COUNT</div>',
width: 56,
height: 55
},
// This style will be used for clusters with more than 50 markers
100: {
content: '<div class="cluster cluster-3">CLUSTER_COUNT</div>',
width: 66,
height: 65
}
},
marker: {
options: {
clickable: true
},
events:{
click: function(marker,event,data) {
$(this).gmap3({action: 'clear', name : 'infowindow'});
$(this).gmap3({action: 'addinfowindow', anchor: marker, options: { content:
'<div class="text"><strong><div style="color:navy;">' + data.itype + '</strong><br/><div id="address" snum="' + data.streetnum + '" snam="' + data.streetnam + '" styp="' + data.streettyp + '">'+ data.iaddress +'</div><br/>' + data.inum + '<br/>'+ data.datetime +'</div><hr>'+data.notes+'</div>'} })
},
mouseover: function(marker, event, data){
$(this).gmap3(
{ action:'clear', name:'overlay'},
{ action:'addOverlay',
latLng: marker.getPosition(),
content: '<div class="infobulle">' +
'<div class="bg"></div>' +
'<div class="text">' + data.itype +'</div>' +
'</div>' +
'<div class="arrow"></div>',
offset: {
x:-46,
y:-73
}
});
},
mouseout: function(){
$(this).gmap3({action:'clear', name:'overlay'});
}
}, //end events
callback: function(result){
if (result){
//not doing anything with a callback at this time
} else {
alert('Bad callback...');
}
} //end callbacks
} // end marker
}
,{action:"autofit"} //end action
);
$("a#link").live('click',function(markerlist){ // this works and I can get my arid ok, but the trigger won't work
var arid = $(this).attr('arid');
google.maps.event.trigger(markerlist[arid], 'click');
return false;
});
};
Any help would really be appreciated and am sure will be useful to others!
I think the problem is markerlist is not a global variable, it's local to your display function? What do you get if you write markerlist to the console in your click event handler?
Trying to figure out how to reinitialize Easy FancyBox when new content is loaded in with infinite scroll. I tried $.fancybox.init(), but this doesn't seem to be enough. In the head section the script that calls easy fancybox is:
jQuery(document).ready(function($){
var fb_timeout = null;
var fb_opts = { 'overlayShow' : true, 'centerOnScroll' : true, 'showCloseButton' : true, 'showNavArrows' : true, 'onCleanup' : function() { if(fb_timeout) { window.clearTimeout(fb_timeout); fb_timeout = null; } } };
/* IMG */
var fb_IMG_select = 'a[href$=".jpg"]:not(.nofancybox),a[href$=".JPG"]:not(.nofancybox),a[href$=".gif"]:not(.nofancybox),a[href$=".GIF"]:not(.nofancybox),a[href$=".png"]:not(.nofancybox),a[href$=".PNG"]:not(.nofancybox)';
$(fb_IMG_select).addClass('fancybox').attr('rel', 'gallery');
$('a.fancybox, area.fancybox').fancybox( $.extend({}, fb_opts, { 'transitionIn' : 'elastic', 'easingIn' : 'easeOutBack', 'transitionOut' : 'elastic', 'easingOut' : 'easeInBack', 'opacity' : false, 'titleShow' : true, 'titlePosition' : 'over', 'titleFromAlt' : true }) );
/* Auto-click */
$('#fancybox-auto').trigger('click');
});
/* ]]> */
Any Ideas how I can reinitialize something like this, bound specifically to new content loaded into #content div.post? Thank you for any help.
Check this thread, it may help (EasyFancybox uses fancybox v1.3.4)
Update: I just recalled that the thread of reference (above) will work for single new added elements, but not for galleries. If you have a set of galleries (using the rel attribute) then you may prefer to upgrade to jQuery 1.7+ (if not yet) and use jQuery on() instead of delegate(), that will allow you to initialize your existing and dynamically added elements.
I made an example page here that shows how to use jQuery on() to solve the issue of dynamically added elements and fancybox (v1.3.x), if you want to have a look.
Based on the example page, I guess in your specific case, you may try tweaking your code this way:
jQuery(document).ready(function($){
var fb_timeout = null;
var fb_opts = { 'overlayShow' : true, 'centerOnScroll' : true, 'showCloseButton' : true, 'showNavArrows' : true, 'onCleanup' : function() { if(fb_timeout) { window.clearTimeout(fb_timeout); fb_timeout = null; } } };
/* IMG */
$("#content div.post").on("focusin", function(){
var fb_IMG_select = 'a[href$=".jpg"]:not(.nofancybox),a[href$=".JPG"]:not(.nofancybox),a[href$=".gif"]:not(.nofancybox),a[href$=".GIF"]:not(.nofancybox),a[href$=".png"]:not(.nofancybox),a[href$=".PNG"]:not(.nofancybox)';
$(fb_IMG_select).addClass('fancybox').attr({'rel': 'gallery', 'tabindex': '1'});
$('a.fancybox, area.fancybox').fancybox( $.extend({}, fb_opts, {
'transitionIn' : 'elastic',
'easingIn' : 'easeOutBack',
'transitionOut' : 'elastic',
'easingOut' : 'easeInBack',
'opacity' : false,
'titleShow' : true,
'titlePosition' : 'over',
'titleFromAlt' : true
}) );
/* Auto-click */
$('#fancybox-auto').trigger('click');
}); // on
}); // ready
Of course, jQuery 1.7+ is required.