Leaflet popup tip not aligned properly - javascript

Popups I have on this leaflet map have a mis aligned tip
Any suggestions on how to fix this?
This the code I have for the markers themselves and the associated popup
var redIcon = new L.Icon({
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1,-34],
shadowSize: [41, 41]
});
var map_data = {!! json_encode($map_data) !!};
map_data.forEach(element => {
console.log('program=' + element.program + ', lat=' + element.gps_lat + ', long=' + element.gps_lon);
data[i] = L.marker([element.gps_lon, element.gps_lat], {icon: redIcon}).addTo(map);
data[i].bindPopup(
// + ' <form action="{{ route("opentraining") }}" method="POST" class="formEditTraining">#csrf<input type="hidden" name="training_id" value='+ element.id + '>'+ element.project +'</form>'
'<strong>' + element.program + '</strong>'
+ '<br />'
+ '<b>Location:</b> ' + element.location + ', ' + element.district + ', ' + element.province
+ '<br />'
+ '<b>Description:</b> ' + element.description
+ '<br /><br />'
+ 'View Record '
).openPopup();
i++;
});

Related

OpenLayers for SVG Images

For my webpage I want an image that I can navigate with drag-Events and scroll-Events similar to Google-Maps. Instead of implementing it myself, I tried to achieve this with OpenLayers, where I want to use this image instead of a map. I've read about the other examples in stackoverflow, but I am still struggling to understand how to pass the image as first layer.
Currently I try to do the following:
testOL(content: string) {
// content is the svg as string
this.map = new Map({
target: 'imageArea',
layers: [
new Image({
source: new ImageStatic({
src: content,
})
})
] ,view : new View({
center: [0,0],
zoom: 1
})
})
}
The target is simply a div without any content.
I've already tried it by passing an url to a svg as source of the image and I already tried to add a Projection and a view in the map, which all did not work.
I would be happy, if anybody could help me with the issue
src is not the correct option name, it should be url, and its value should be a data url. ImageStatic also requires the imageExtent to be specified in projection coordinates.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://openlayers.org/en/v6.4.3/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/v6.4.3/build/ol.js"></script>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="imageArea" class="map"></div>
<script>
const content =
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<svg' +
' xmlns:dc="http://purl.org/dc/elements/1.1/"' +
' xmlns:cc="http://creativecommons.org/ns#"' +
' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"' +
' xmlns:svg="http://www.w3.org/2000/svg"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"' +
' xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"' +
' width="20"' +
' height="20"' +
' version="1.1"' +
' id="svg6"' +
' sodipodi:docname="dot.svg"' +
' inkscape:version="0.92.3 (2405546, 2018-03-11)">' +
' <metadata' +
' id="metadata12">' +
' <rdf:RDF>' +
' <cc:Work' +
' rdf:about="">' +
' <dc:format>image/svg+xml</dc:format>' +
' <dc:type' +
' rdf:resource="http://purl.org/dc/dcmitype/StillImage" />' +
' <dc:title></dc:title>' +
' </cc:Work>' +
' </rdf:RDF>' +
' </metadata>' +
' <defs' +
' id="defs10" />' +
' <sodipodi:namedview' +
' pagecolor="#ffffff"' +
' bordercolor="#666666"' +
' borderopacity="1"' +
' objecttolerance="10"' +
' gridtolerance="10"' +
' guidetolerance="10"' +
' inkscape:pageopacity="0"' +
' inkscape:pageshadow="2"' +
' inkscape:window-width="1533"' +
' inkscape:window-height="845"' +
' id="namedview8"' +
' showgrid="false"' +
' inkscape:zoom="11.8"' +
' inkscape:cx="-35.042373"' +
' inkscape:cy="11.5"' +
' inkscape:window-x="67"' +
' inkscape:window-y="102"' +
' inkscape:window-maximized="1"' +
' inkscape:current-layer="g4"' +
' fit-margin-top="0"' +
' fit-margin-left="0"' +
' fit-margin-right="0"' +
' fit-margin-bottom="0" />' +
' <g' +
' id="g4"' +
' transform="translate(1.5,-1.5)">' +
' <circle' +
' style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"' +
' id="path822"' +
' cx="8.5"' +
' cy="11.5"' +
' r="8.5"' +
' inkscape:export-xdpi="400"' +
' inkscape:export-ydpi="400" />' +
' </g>' +
'</svg>'
const map = new ol.Map({
target: 'imageArea',
layers: [
new ol.layer.Image({
source: new ol.source.ImageStatic({
url: 'data:image/svg+xml,' + encodeURIComponent(content),
imageExtent: [0, 0, 5e6, 5e6],
})
})
] ,view : new ol.View({
center: [0, 0],
zoom: 1,
})
});
</script>
</body>
</html>
Use an svg string as a point feature style:
var svg_string = '<?xml version="1.0" ...><svg>...</svg>'; // your svg content as string
var myStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [16, 48],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: 'data:image/svg+xml,' + encodeURIComponent(svg_string) // add the encoded svg_string as source
}),
});
feature.setStyle(myStyle);

How to print items in an object array

I am returning an object from a site which apart from other parameters also contains an array of objects.
If I do console.log(req.body.cart) I print this [ { title: 'iphone 6', cost: '650' } ]
which I need only the title. I tried stringify, which is not what I want and parse which returned an 500 error.
router.post('/itemstobuy', function(req, res, next){
if(!req.body.name || !req.body.lastname || !req.body.address
|| !req.body.email || !req.body.cart){
return res.status(400).json({message: 'Please fill out all fields'});
}
var mailOptions={
from: 'anEmail#gmail.com',
to: 'anotherEmail#gmail.com',
subject: 'Subject',
html: '<p>Name: ' + req.body.name + '</p>' +
'<p>LastName: ' + req.body.lastname + '</p>' +
'<p>Address: ' + req.body.address + '</p>' +
'<p>Email: ' + req.body.email + '</p>' +
'<p>Cart: ' + JSON.stringify(req.body.cart) + '</p>'
}
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
return res.status(200);
});
I need to show the items by their title at
'<p>Cart: ' + JSON.stringify(req.body.cart) + '</p>'
The above works but there are lots of ugly data and need just the titles of the items.
As suggested in the comments:
'<p>Cart: ' +
(req.body.cart || []) //Just to make things not crash and burn if we have no cart
//Take the title from each of the items
.map(function(item){ return item.title; })
//Create a comma-separated string from the titles
.join(', ') +
'</p>'
Try this. '<p>Cart: ' + JSON.parse(req.body.cart).title + '</p>'
In case you have multiple items in the cart you can iterate through these otherwise you can access it directly req.body.cart[0].title
var cart = req.body.cart;
var html: '<p>Name: ' + req.body.name + '</p>' +
'<p>LastName: ' + req.body.lastname + '</p>' +
'<p>Address: ' + req.body.address + '</p>' +
'<p>Email: ' + req.body.email + '</p>';
html += '<p>Cart:<ul> '+
for(var i=0;i<cart.length;i++) html +='<li> ' + cart[i].title + '</li>';
html +='</ul></p>';
var cart = [ { title: 'iphone 6', cost: '650' }, { title: 'iphone 5', cost: '550' } ];
document.write( '<p>Cart:<ul> ');
for(var i=0;i<cart.length;i++) document.write('<li> ' + cart[i].title + '</li>');
document.write('</ul></p>');

bootstrap collapsible not collapsing after expanded

Collapsible did not collapse after being expanded. It is dynamically created in popover.
Here is my jsFiddle:
$('.tooltiphelp').tooltip();
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="popover"]').popover();
$('[data-toggle="collapse"]').collapse();
jQuery('document').ready(function() {
jQuery('#accordionRank').on('show hide', function() {
jQuery(this).css('height', 'auto');
});
jQuery('#accordionRank').collapse({ parent: true, toggle: true });
});
var popover = $("#noteListDiv").find('.positive').popover({
trigger: 'click',
placement: 'bottom',
content: function () {
return func_getRank($(this).closest('tr').prop('id'));
}
});
var func_getRank = function (ID) {
var Rankdata = {"Rank":[{"ID": "114077", "NL": "1 of 25", "OF": "1 of 30", "MLB": "1 of 240"}]};
var cshtml;
cshtml = '<div>'
+ '<div class="accordion" id="accordionRank">'
+ '<div class="accordion-group">'
+ '<div class="accordion-heading">'
+ '<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordionRank" href="#collapseNL">'
+ 'NL Rank: ' + Rankdata.Rank[0].NL
+ '</a>'
+ '</div>'
+ '<div id="collapseNL" class="accordion-body collapse">'
+ '<div class="accordion-inner">'
+ 'Anim pariatur cliche...'
+ '</div>'
+ '</div>'
+ '</div>'
+ '<div class="accordion-group">'
+ '<div class="accordion-heading">'
+ '<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordionRank" href="#collapseOF">'
+ 'OF Rank: ' + Rankdata.Rank[0].OF
+ '</a>'
+ '</div>'
+ '<div id="collapseOF" class="accordion-body collapse">'
+ '<div class="accordion-inner">'
+ 'Anim pariatur cliche...'
+ '</div>'
+ '</div>'
+ '</div>'
+ '<div class="accordion-group">'
+ '<div class="accordion-heading">'
+ '<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordionRank" href="#collapseMLB">'
+ 'MLB Rank: ' + Rankdata.Rank[0].MLB
+ '</a>'
+ '</div>'
+ '<div id="collapseMLB" class="accordion-body collapse">'
+ '<div class="accordion-inner">'
+ '<table id="MiniLeaderboard">'
+ '<thead><tr>'
+ '<th>Rank</th>'
+ '<th>Hitter</th>'
+ '<th>BAVG</th>'
+ '<th>Hits/AB</th>'
+ '</tr></thead>'
+ '<tbody><tr>'
+ '<td>1</td>'
+ '<td>Christian Yelich</td>'
+ '<td>.470</td>'
+ '<td>39-for-83</td>'
+ '</tr>'
+ '<tr>'
+ '<td>2</td>'
+ '<td>Ryan Braun</td>'
+ '<td>.397</td>'
+ '<td>27-for-68</td>'
+ '</tr>'
+ '<tr>'
+ '<td>3</td>'
+ '<td>Adam Eaton</td>'
+ '<td>.370</td>'
+ '<td>37-for-100</td>'
+ '</tr>'
+ '<tr>'
+ '<td>4</td>'
+ '<td>Joey Votto</td>'
+ '<td>.369</td>'
+ '<td>31-for-84</td>'
+ '</tr>'
+ '<tr>'
+ '<td>5</td>'
+ '<td>Edwin Encarnation</td>'
+ '<td>.364</td>'
+ '<td>28-for-77</td>'
+ '</tr></tbody>'
+ '</table>'
+ '</div>'
+ '</div>'
+ '</div>'
+ '</div>'
+ '</div>'
;
return $(cshtml).html();
};
Data text should come from JSON.
Here is the issue, please watch this screen cast.
Please help! Thanks in forward for your help.
I've updated my jsFiddle and it's now working. Maybe not a good idea but looks good for now.
$(document).on('click', '.accordion-toggle', function(e) {
$(e.target).css('text-decoration','none');
var $_this = $(e.target).parent().next("div");
var $_inner = $_this.find('div:first-child');
if($_inner.hasClass('in')){
$_inner.removeClass("in");
$_this.removeClass("in");
}
else {
$_inner.addClass("in");
$_this.addClass("in");
}
func_accordionToggle(e.target);
});
var func_accordionToggle = function (e) {
var $_this = $(e).parent().parent();
var id = $(e).parent().next("div").attr('id');
switch(id) {
case 'collapseNL':
$('#collapseOF').removeClass("in");
$('#collapseMLB').removeClass("in");
$('#collapseOF').find('div:first-child').removeClass("in");
$('#collapseMLB').find('div:first-child').removeClass("in");
break;
case 'collapseOF':
$('#collapseNL').removeClass("in");
$('#collapseMLB').removeClass("in");
$('#collapseNL').find('div:first-child').removeClass("in");
$('#collapseMLB').find('div:first-child').removeClass("in");
break;
case 'collapseMLB':
$('#collapseNL').removeClass("in");
$('#collapseOF').removeClass("in");
$('#collapseNL').find('div:first-child').removeClass("in");
$('#collapseOF').find('div:first-child').removeClass("in");
break;
};
}
Thanks for all the help Guys.

Jquery / Javascript: There is a NaN on my HTML

I am writing an HTML loop using javascript. It will loop through a series of images and display them with additional information. It appears that there is always a NaN showing on the HTML output as shown here.
Here is the javascript in question:
var caption = '<p></p>';
if($.isEmptyObject(data[i].caption) !== true)
{
caption = '<p class="caption" style="top:'+data[i].height+'px;">'+
data[i].caption +
'</p>';
}
var li = '<li data-uk-modal="{target:#modal-open-image}"'
+ 'class="open"'
+ 'image="'+ data[i].photo +'"'
+ 'caption_height="'+ data[i].height +'"'
+ 'caption="'+ data[i].caption +'">'
+ '<a href="#" class="uk-thumbnail uk-overlay-toggle">'
+ '<div class="uk-overlay">'
+ '<img src="'+ data[i].photo +'" width="250px"/>'
+ caption +
+ '<div class="uk-overlay-caption">'
+ '<p> Sender: ' + data[i].sender + '</p>'
+ '<p> Date: ' + data[i].date + '</p>'
+ '<p> limit: '+ data[i].limit + '</p>'
+ '<p> counter: ' + data[i].counter + '</p>'
+ '</div>'
+ '</div>'
+ '</a>'
+'</li>';
$photo.append(li);
I would think the problem would lie on the caption variable. the data[i] is an array of from a database query.
I need to check if there is something on the data[i].caption. I tried using length, but that doesn't work, so I check if the object exist. Though I am not sure if that works.
My question, is how to display properly check if the caption is empty, and if none it will not add anything on the var li.
Thanks.
You can code it in one line:
( (data && data[i] && data[i].caption) ? " your stuff " : "")
But pay attention that checking 'data[i].caption' in javascript means that: zero is false, empty string is false.
Furthermore if you referring a number you can add a condition using the method isNaN
Please use this one in place of the '+ caption +'
isNaN(data[i].caption) ? '' : data[i].caption
or if(isNaN(data[i].caption)==true){
//do somthing
}else{
//do somthing
}
Thanks for the feedback. I manage to gobble up the solutions you game me and I ended up with this.
var height = (data[i].height == null)?0:data[i].height;
var caption= (data[i].caption== null)?'':data[i].caption;
var li = '<li data-uk-modal="{target:\'#modal-open-image\'}"'
+ 'class="open"'
+ 'image="'+ data[i].photo +'"'
+ 'caption_height="'+ height +'"'
+ 'caption="'+ caption +'">'
+ '<a href="#" class="uk-thumbnail uk-overlay-toggle">'
+ '<div class="uk-overlay">'
+ '<img src="'+ data[i].photo +'" width="250px"/>'
+ '<p class="caption" style="top:' + height +'px;">'
+ caption
+ '</p>'
+ '<div class="uk-thumbnail-caption">'
+ '<p> Sender: ' + data[i].sender + '</p>'
+ '<p> Reciever: '+ data[i].reciever + '</p>'
+ '<p> Date: ' + data[i].date + '</p>'
+ '<p> limit: '+ data[i].limit + '</p>'
+ '</div>'
+ '</div>'
+ '</a>'
+'</li>';

JSON and Tumblr

Okay, so I'm trying to create a "Order Posts by Type" using jQuery JSON to get the data... All the post types works in Chrome, Safari, FF. But in IE, video / audio posts will not display (perhaps something to do with the embedding?) when I filter through the posts using JSON.
Does anyone have a clue what's going on?! Here's the code:
<script>
$('#order_by ul li').find('a').click(function() {
var postType = this.className;
var count = 0;
byCategory(postType);
return false;
function byCategory(postType, callback) {
$.getJSON('{URL}/api/read/json?type=' + postType + '&callback=?', function(data) {
var article = [];
$.each(data.posts, function(i, item) {
// i = index
// item = data for a particular post
switch(item.type) {
case 'photo':
article[i] = '<div class="post_wrap"><div class="photo"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/0yplawef6/link_photo.png" /></a><a href="'
+ item.url
+ '"><img src="'
+ item['photo-url-1280']
+ '"alt="image" /></a></div></div>';
count = 1;
break;
case 'video':
article[i] = '<div class="post_wrap"><div class="video"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/FWAlawenw/link_video.png" /></a><span><br />'
+ item['video-player']
+ '</span><div class="video_desc">'
+ item['video-caption']
+ '</div></div></div>';
count = 1;
console.log(article[i]);
break;
case 'audio':
article[i] = '<div class="post_wrap"><div class="audio"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/e8Zlawemi/link_audio.png" /></a><h2 class="heading"><a href="'
+ item.url + '">'
+ item['id3-artist']
+' - '
+ item['id3-title']
+ '</a></h2><div class="player"><br />'
+ item['audio-player']
+ '<p>' + item['id3-artist'] + ' - ' + item['id3-title'] + '</p>'
+ '<p>' + item['audio-plays'] + ' plays</p>'
+ '</div><div class="audio_desc">'
+ item['audio-caption']
+ '</div><div class="clear"></div></div></div>';
count = 1;
break;
case 'regular':
article[i] = '<div class="post_wrap"><div class="regular"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/LH3laweb7/link_text.png" /></a><h2 class="heading"><a href="'
+ item.url
+ '">' + item['regular-title']
+ '</a><div class="description_container">'
+ item['regular-body']
+ '</div></div></div>';
count = 1;
break;
case 'quote':
article[i] = '<div class="post_wrap"><div class="quote"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/1Lwlaweh7/link_quote.png" /></a><blockquote>'
+ item['quote-text']
+ '</blockquote><cite>- '
+ item['quote-source']
+ '</cite></div></div>';
count = 1;
break;
case 'conversation':
article[i] = '<div class="post_wrap"><div class="chat"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/NZ9lawekt/link_chat.png" /></a><h2 class="heading"><a href="'
+ item.url
+ '">' + item['conversation-title']
+ '</a></h2></div></div>';
count = 1;
break;
case 'link':
article[i] = '<div class="post_wrap"><div class="link"><a href="'
+ item.url
+ '" title="View Full Post" class="type_icon"><img src="http://static.tumblr.com/ewjv7ap/G1zlaweir/link_link.png" /></a><h2 class="heading"><a href="'
+ item['link-url']
+ '">' + item['link-text']
+ '</a></h2></div></div>';
count = 1;
break;
default:
alert('No Entries Found.');
};
}) // end each
if (!(count == 0)) {
$('#main_content')
.fadeOut('fast')
.html('<div class="post_wrap"><div class="regular"><h2 class="heading">Displaying '
+ postType
+ ' Posts Only</h2></div></div>'
+ '<div class="post_wrap"'
+ article.join('')
+ '</div>'
).fadeIn('fast')
$('div.video').each(function() {
var video_container_height = $(this).innerHeight();
video_container_height = (video_container_height - 60)
$(this).children('div.video_desc').css(
{'position': 'absolute',
'top': '40px',
'right': '20px',
'width': '380px',
'height': video_container_height}
).jScrollPane({
verticalGutter: 25
});
});
$('div.audio div.audio_desc').each(function() {
var container_width = $('div.audio').outerWidth(true);
var player_width = $('div.audio div.player').outerWidth(true);
var audio_desc_width = (container_width - player_width);
$(this).css(
{'position': 'absolute',
'top': '75px',
'right': '20px',
'height': '125px',
'width': (audio_desc_width - 50 /*The size of the left and right margin*/)})
.jScrollPane({
verticalGutter: 25
});
});
} else {
$('#main_content')
.fadeOut('fast')
.html('<div class="post_wrap"><div class="regular"><h2 class="heading">Whoops! There are no '
+ postType
+ ' Posts To Display</h2></div></div>'
).fadeIn('fast')
} // end IF
}); // end getJSON
}; // end byCategory
}); // end click
</script>
To check out the live version, head on over to http://minimus.tumblr.com
I think you problem is caused by a tiny error at line 1690:
$('#main_content')
.fadeOut('fast')
.html('<div class="post_wrap"><div class="regular"><h2 class="heading">Displaying '
+ postType
+ ' Posts Only</h2></div></div>'
+ '<div class="post_wrap"' // line 1690: you are missing a '>'
+ article.join('')
+ '</div>'
).fadeIn('fast')

Categories

Resources