Mapbox- reset a popup offset dynamcally - dynamic

I have a Mapbox feature layer (with a geoJSON as source) with popups for each marker (with a divIcon). We are resizing the marker icon on different zoom levels (using css). How can I reset the offset of the popup on different zoom levels?
Here is the initial setup of the marker and popup (this all works):
var curOffset = [0,1];
Markers.on('layeradd', function(la) {
var Icon = la.layer,
feature = Icon.feature;
var popupContent = "<some html>"
var popupOptions = {
autoPan:true,
closeButton: false,
minWidth: 220,
maxWidth: 220,
zoomAnimation:true,
offset: curOffset
};
Icon.setIcon(L.divIcon(Iconfeature.properties.icon));
Markers.bindPopup(popupContent, popupOptions);
});
I tried to reset the offset on a zoom event like so, but it doesn't work:
map.on('zoomend', function(e) {
if (layerOn == true) {
size = map.getZoom();
switch (size){
case 14: console.log("14"); curOffset = [0,5]; break;
...
}
}
});
Do I need to close and then open the popup perhaps? I tried something along those lines but I got an error.
I received this suggestion from the a Leaflet Github contributor, but I haven't been able to get this to work either/
'Update the popup.options.offset, then call the private method popup._updatePosition.'

The GitHub Leaflet contributor also suggested looking into just changing the css for the popup on an event..once my co-worker and I found the right rule to modify, it worked:
map.on('zoomend', function(e) {
switch (size){ // zoom level
case 14: $('.leaflet-popup.leaflet-zoom-animated').css('bottom', '-5px'); $('.leaflet-popup .leaflet-zoom-animated').css('left', '-28px'); break;
...
I also had to add an additional check in case the layer was turned off during the zoom, with similar code.

Related

Bootstrap affix smooth scroll

I have been working on bootstrap scrollspy (affix) and it worked fine. I added a script for a smooth movement whenever you click sections.
But it doesn't seem to be working properly.
When you click "section3", it's not move section3.
When you double click, it goes wrong section.
fix nav is not fixed and not showing on responsive.
This is an example page, with the following code:
$(document).ready(function() {
// Add scrollspy to <body>. changed to half-right-wrap
$('div.half-right-wrap').scrollspy({
target: ".navbar",
offset: 50
});
// Add smooth scrolling on all links inside the navbar
$("#myNavbar a").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('div.half-right-content').animate({
scrollTop: $(hash).offset().top
}, 600, function() {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
** Please have a look at PC size to see "affix nav"
How can we make it properly? I guess I added wrong selector in js. It was "body" and add my own selector.

Google map ignoring marker size for retina icons

I have a Google map driven by Advanced Custom Fields. I have created an iconType to dictate which icon is used as the marker depending on the custom field.
My marker images are 80px square but I want to force them to 40px square for retina reasons. I have tried lots of variations of code I've found via google etc but nothing works and the size gets ignored showing my markers at the larger 80px. My guess is because I have the 2 icons depending on iconType?
Can anyone help me force the size of these markers to 40px square please...
function add_marker( $marker, map ) {
// var
var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng'));
var iconType = $marker.attr('data-icon');
var iconBase = '<?php echo get_template_directory_uri(); ?>/assets/';
var size = new google.maps.Size(40, 40);
if (iconType === 'Costa') {
iconName = 'costa#2x.png';
} else {
iconName = 'starbucks#2x.png';
}
// create marker
var marker = new google.maps.Marker({
position : latlng,
map : map,
clickable: false,
animation: google.maps.Animation.DROP,
icon: iconBase + iconName,
});
// add to array
map.markers.push( marker );
// if marker contains HTML, add it to an infoWindow
if( $marker.html() )
{
// create info window
var infowindow = new google.maps.InfoWindow({
content : $marker.html()
});
}
}
I did something like this recently, and I believe you'll need to use the new Icon object to specify your custom Icon properties, and use the size and scaledSize properties. I fixed my issues following this guide:
How to add retina ready pin marker to your Google maps?

Panning the map to certain extent javascript API

I want to limit map extent to the initial extent of the map and limit user from panning more than certain extent.
I tried following but nothing has changed:
map = new Map( "map" , {
basemap: "gray",
center: [-85.416, 49.000],
zoom : 6,
logo: false,
sliderStyle: "small"
});
dojo.connect(map, "onExtentChange", function (){
var initExtent = map.extent;
var extent = map.extent.getCenter();
if(initExtent.contains(extent)){}
else{map.setExtent(initExtent)}
});
Just to flesh out Simon's answer somewhat, and give an example. Ideally you need two variables at the same scope as map:
initExtent to store the boundary of your valid extent, and
validExtent to store the last valid extent found while panning, so that you can bounce back to it.
I've used the newer dojo.on event syntax as well for this example, it's probably a good idea to move to this as per the documentation's recommendation - I assume ESRI will discontinue the older style at some point.
var map;
var validExtent;
var initExtent;
[...]
require(['dojo/on'], function(on) {
on(map, 'pan', function(evt) {
if ( !initExtent.contains(evt.extent) ) {
console.log('Outside bounds!');
} else {
console.log('Updated extent');
validExtent = evt.extent;
}
});
on(map, 'pan-end', function(evt) {
if ( !initExtent.contains(evt.extent) ) {
map.setExtent(validExtent);
}
});
});
You can do the same with the zoom events, or use extent-change if you want to trap everything. Up to you.
It looks like your extent changed function is setting the initial extent variable to the maps current extent and then checking if that extent contains the current extents centre point - which of course it always will.
Instead, declare initExtent at the same scope of the map variable. Then, change the on load event to set this global scope variable rather than a local variable. In the extent changed function, don't update the value of initExtent, simply check the initExtent contains the entire of the current extent.
Alternatively you could compare each bound of the current extent to each bound of the initExtent, e.g. is initExtent.xmin < map.extent.xmin and if any are, create a new extent setting any exceeded bounds to the initExtent values.
The only problem is these techniques will allow the initExtent to be exceeded briefly, but will then snap the extent back once the extent changed function fires and catches up.
I originally posted this solution on gis.stackexchange in answer to this question: https://gis.stackexchange.com/a/199366
Here's a code sample from that post:
//This function limits the extent of the map to prevent users from scrolling
//far away from the initial extent.
function limitMapExtent(map) {
var initialExtent = map.extent;
map.on('extent-change', function(event) {
//If the map has moved to the point where it's center is
//outside the initial boundaries, then move it back to the
//edge where it moved out
var currentCenter = map.extent.getCenter();
if (!initialExtent.contains(currentCenter) &&
event.delta.x !== 0 && event.delta.y !== 0) {
var newCenter = map.extent.getCenter();
//check each side of the initial extent and if the
//current center is outside that extent,
//set the new center to be on the edge that it went out on
if (currentCenter.x < initialExtent.xmin) {
newCenter.x = initialExtent.xmin;
}
if (currentCenter.x > initialExtent.xmax) {
newCenter.x = initialExtent.xmax;
}
if (currentCenter.y < initialExtent.ymin) {
newCenter.y = initialExtent.ymin;
}
if (currentCenter.y > initialExtent.ymax) {
newCenter.y = initialExtent.ymax;
}
map.centerAt(newCenter);
}
});
}
And here's a working jsFiddle example: http://jsfiddle.net/sirhcybe/aL1p24xy/

In Extjs4 how to set scrollbar position to bottom of form panel

i am working in extjs4. i have form panel with autoscroll true. I have 20-25 fields with fileUpload field at bottom. When i am uploading file, form's scroll is going to top by default. i want to keep scroll of form as it is on where it was while uploading file. So how to set this scrollBar at bottom of or at upload field section in extjs4
You can try by adding the following method to your form declaration:
scrollToField: function(fieldId) {
var field = Ext.get(fieldId);
field.el.scrollIntoView(this.body.el);
}
Here you have a working sample
IMHO,it will be better, however, to group fields using tabs or something similar to avoid having a long a and hard to read / fill form
I have solve this problem into Ext js 4.2 for Ext.form.panel
See the following code. It will helpful to you.
onRender function call on render event
onRender: function () {
this.callParent(arguments);
if (!this.restoreScrollAfterLayout) {
this.mon(Ext.get(this.getEl().dom.lastElementChild), 'scroll', this.onScroll, this);
this.restoreScrollAfterLayout = true;
}
},
onScroll: function (e ,t, eOpts) {
this.scroll = Ext.get(this.getEl().dom.lastElementChild).getScroll();
},
afterLayout: function () {
this.callParent(arguments);
if (this.restoreScrollAfterLayout && this.scroll) {
var el = Ext.get(this.getEl().dom.lastElementChild),
scroll = this.scroll;
el.scrollTo('left', scroll.left);
el.scrollTo('top', scroll.top);
}
}

How to add background-color to text navigation on image slider?

I have an image slider that is controlled by text navigation. The text is highlighted orange when it's relative slide is current in the gallery. I would like the other text to have an inactive state with a black background but cannot get this to work!
(In case that didn't make much sense! Basically, I want background-color orange when current, background-color black when inactive.) THANKS
$(document).ready(function(){
$('.slider').each(function(e){
if(e == 0){
$(this).addClass('current');
}
$(this).attr('id', 'handle' + e);
})
$('.tabs li').each(function(e){
if(e == 0){
$(this).addClass('current'); //adds class current to 1st li
}
$(this).wrapInner('<a class="title"></a>'); //wraps list items in anchor tag
$(this).children('a').attr('href', '#handle' + e);//adds href to the anchors
t = $(this).children('a').text();
$('#handle' + e).append('<h2>' + t + '</h2>'); //adds h2 and text to big images
})
$('.tabs li a').click(function(){
c = $(this).attr('href');
if($(c).hasClass('current')){
return false;
}else{
showImage($(c), 20);
$('.tabs li').removeClass('current');
$(this).parent().addClass('current');
return false;
}
})
runRotateImages();
$("#featured").hover(
function(){
clearTimeout(xx);
},
function(){
runRotateImages();
}
)
})
function showImage(img, duration){
$('.slider').removeClass('current').css({
"opacity" : 0.0,
"zIndex" : 2
});
img.animate({opacity:1.0}, duration, function(){
$(this).addClass('current').css({zIndex:1});
});
}
function rotateImages(){
var curPhoto = $("div.current");
var nxtPhoto = curPhoto.next();
var curTab = $(".tabs li.current");
var nxtTab = curTab.next();
if (nxtPhoto.length == 0) {
nxtPhoto = $('#featured div:first');
nxtTab = $('.tabs li:first-child');
}
curTab.removeClass('current');
nxtTab.addClass('current');
showImage(nxtPhoto, 300);
}
function runRotateImages(){
xx = setInterval("rotateImages()", 5000);
}
I have added a jsfiddle - http://jsfiddle.net/n5EPM/3/
However, on jsfiddle it does not seem to automatically cycle through the images, not sure why, have no problems in browser.
Try using not() method: http://api.jquery.com/not/
Basically, you need to create a new class disabled
.disabled{
background-color:#000000;
}
Then, add the following line to your tabs.li's each loop:
$(".tabs li").not(".current").addClass('disabled'); //add disabled class for non-current tabs
At last you need to remove disabled class in the rotateimage() function before assigning current and then disable non-current again. like this:
curTab.removeClass('current');
nxtTab.removeClass('disabled'); //remove diabled class
nxtTab.addClass('current');
$(".tabs li").not(".current").addClass('disabled'); // disable non-current again
Working jsfiddle here: http://jsfiddle.net/n5EPM/9/
This might not be the perfect solution but you will need to tweak it a little bit.
Hope this helps.