I am following this mapbox example (https://www.mapbox.com/help/building-a-store-locator/) and trying to fit it inside a Django web app. I believe my problem is in base.html because in the Mapbox tutorial they do not have a navbar or use template inheritance. base.html may be causing problems because it uses content from Home.html. In my screen shot you can see that the map and sidebar div do not fill the content-section div height wise. The map also only takes up half of the div it is inside of. I have tried many times to figure out the problem but cannot get it.
base.html
{% load static %}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<!-- Bootstrap CSS, and other meta html -->
</head>
<body>
<header class="site-header">
<!-- header for website containing navbar config -->
</header>
<main role="main" class="container">
<div class="row">
<div class="col-md" align="center">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% block content %}{% endblock %}
</div>
</div>
</main>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
Home.html
{% extends "geotracker/base.html" %}
{% load static %}
{% block content %}
<body>
<div class="content-section">
<div class='sidebar'>
<div class='heading'>
<h1>Our locations</h1>
</div>
<div id='listings' class='listings'></div>
</div>
<div id='map' class='map'> </div>
</div>
<script>
// This will let you use the .remove() function later on
if (!('remove' in Element.prototype)) {
Element.prototype.remove = function() {
if (this.parentNode) {
this.parentNode.removeChild(this);
}
};
}
mapboxgl.accessToken = 'myTokenHere';
// This adds the map
var map = new mapboxgl.Map({
// container id specified in the HTML
container: 'map',
// style URL
style: 'mapbox://styles/mapbox/light-v9',
// initial position in [long, lat] format
center: [-77.034084142948, 38.909671288923],
// initial zoom
zoom: 13,
scrollZoom: false
});
var stores = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-77.043959498405,
38.903883387232
]
},
"properties": {
"phoneFormatted": "(202) 331-3355",
"phone": "2023313355",
"address": "1901 L St. NW",
"city": "Washington DC",
"country": "United States",
"crossStreet": "at 19th St",
"postalCode": "20036",
"state": "D.C."
}
}]
};
// This adds the data to the map
map.on('load', function (e) {
// Add the data to your map as a layer
map.addLayer({
"id": "locations",
"type": "symbol",
// Add a GeoJSON source containing place coordinates and information.
"source": {
"type": "geojson",
"data": stores
},
"layout": {
"icon-image": "restaurant-15",
"icon-allow-overlap": true,
}
});
});
// This is where your interactions with the symbol layer used to be
// Now you have interactions with DOM markers instead
stores.features.forEach(function(marker, i) {
// Create an img element for the marker
var el = document.createElement('div');
el.id = "marker-" + i;
el.className = 'marker';
// Add markers to the map at all points
new mapboxgl.Marker(el, {offset: [0, -23]})
.setLngLat(marker.geometry.coordinates)
.addTo(map);
el.addEventListener('click', function(e){
// 1. Fly to the point
flyToStore(marker);
// 2. Close all other popups and display popup for clicked store
createPopUp(marker);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
e.stopPropagation();
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
var listing = document.getElementById('listing-' + i);
listing.classList.add('active');
});
});
function flyToStore(currentFeature) {
map.flyTo({
center: currentFeature.geometry.coordinates,
zoom: 15
});
}
function createPopUp(currentFeature) {
var popUps = document.getElementsByClassName('mapboxgl-popup');
if (popUps[0]) popUps[0].remove();
var popup = new mapboxgl.Popup({closeOnClick: false})
.setLngLat(currentFeature.geometry.coordinates)
.setHTML('<h3>Sweetgreen</h3>' +
'<h4>' + currentFeature.properties.address + '</h4>')
.addTo(map);
}
function buildLocationList(data) {
for (i = 0; i < data.features.length; i++) {
var currentFeature = data.features[i];
var prop = currentFeature.properties;
var listings = document.getElementById('listings');
var listing = listings.appendChild(document.createElement('div'));
listing.className = 'item';
listing.id = "listing-" + i;
var link = listing.appendChild(document.createElement('a'));
link.href = '#';
link.className = 'title';
link.dataPosition = i;
link.innerHTML = prop.address;
var details = listing.appendChild(document.createElement('div'));
details.innerHTML = prop.city;
if (prop.phone) {
details.innerHTML += ' · ' + prop.phoneFormatted;
}
link.addEventListener('click', function(e){
// Update the currentFeature to the store associated with the clicked link
var clickedListing = data.features[this.dataPosition];
// 1. Fly to the point
flyToStore(clickedListing);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedListing);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
this.parentNode.classList.add('active');
});
}
}
</script>
<style>
body {
color:#404040;
-webkit-font-smoothing:antialiased;
}
* {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
.sidebar {
position:absolute;
width:33.3333%;
height:100%;
top:0;left:0;
overflow:hidden;
border-right:1px solid rgba(0,0,0,0.25);
}
.pad2 {
padding:20px;
}
.map {
position:absolute;
left:33.3333%;
width:66.6666%;
top:0;bottom:0;
}
h1 {
font-size:22px;
margin:0;
font-weight:400;
line-height: 20px;
padding: 20px 2px;
}
a {
color:#404040;
text-decoration:none;
}
a:hover {
color:#101010;
}
.heading {
background:#fff;
border-bottom:1px solid #eee;
min-height:60px;
line-height:60px;
padding:0 10px;
background-color: #00853e;
color: #fff;
}
.listings {
height:100%;
overflow:auto;
padding-bottom:60px;
}
.listings .item {
display:block;
border-bottom:1px solid #eee;
padding:10px;
text-decoration:none;
}
.listings .item:last-child { border-bottom:none; }
.listings .item .title {
display:block;
color:#00853e;
font-weight:700;
}
.listings .item .title small { font-weight:400; }
.listings .item.active .title,
.listings .item .title:hover { color:#8cc63f; }
.listings .item.active {
background-color:#f8f8f8;
}
::-webkit-scrollbar {
width:3px;
height:3px;
border-left:0;
background:rgba(0,0,0,0.1);
}
::-webkit-scrollbar-track {
background:none;
}
::-webkit-scrollbar-thumb {
background:#00853e;
border-radius:0;
}
.marker {
border: none;
cursor: pointer;
height: 56px;
width: 56px;
background-image: url(marker.png);
background-color: rgba(0, 0, 0, 0);
}
.clearfix { display:block; }
.clearfix:after {
content:'.';
display:block;
height:0;
clear:both;
visibility:hidden;
}
/* Marker tweaks */
.mapboxgl-popup {
padding-bottom: 50px;
}
.mapboxgl-popup-close-button {
display:none;
}
.mapboxgl-popup-content {
font:400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
padding:0;
width:180px;
}
.mapboxgl-popup-content-wrapper {
padding:1%;
}
.mapboxgl-popup-content h3 {
background:#91c949;
color:#fff;
margin:0;
display:block;
padding:10px;
border-radius:3px 3px 0 0;
font-weight:700;
margin-top:-15px;
}
.mapboxgl-popup-content h4 {
margin:0;
display:block;
padding: 10px 10px 10px 10px;
font-weight:400;
}
.mapboxgl-popup-content div {
padding:10px;
}
.mapboxgl-container .leaflet-marker-icon {
cursor:pointer;
}
.mapboxgl-popup-anchor-top > .mapboxgl-popup-content {
margin-top: 15px;
}
.mapboxgl-popup-anchor-top > .mapboxgl-popup-tip {
border-bottom-color: #91c949;
}
</style>
</body>
{% endblock %}
Sidebar and Map div inside content-section div
Related
I am using JWplayer 7 (HTML5 render mode) in my site.
I created a player with custom playlist, but cannot highlight current playing video when it has been clicked.
Is there any solution to add a custom class, like .active when click on a item of list.
This is my code to setup JWplayer.
var playerInstance = jwplayer("videoCont");
playerInstance.setup({
image: "{PLAYLIST_IMAGE}",
autostart: false,
aspectratio: "16:9",
playlist : "{NV_BASE_SITEURL}{MODULE_NAME}/player/{RAND_SS}{PLAYLIST_ID}-{PLIST_CHECKSS}-{RAND_SS}{FAKE_ID}/",
controls: true,
displaydescription: true,
displaytitle: true,
flashplayer: "{NV_BASE_SITEURL}themes/default/modules/{MODULE_NAME}/jwplayer/jwplayer.flash.swf",
primary: "html5",
repeat: false,
skin: {"name": "stormtrooper"},
stagevideo: false,
stretching: "uniform",
visualplaylist: true,
width: "100%"
});
And following code to generate custom player
var list = document.getElementById("show-list");
var html = list.innerHTML;
html +="<ul class='list-group'>"
playerInstance.on('ready',function(){
var playlist = playerInstance.getPlaylist();
for (var index=0;index<playlist.length;index++){
var playindex = index +1;
html += "<li class='list-group-item'><span>"+playlist[index].title+"</span><span class='pull-right'><label onclick='javascript:playThis("+index+")' title='Phát "+playlist[index].title+"' class='btn btn-default btn-xs'><i class='fa fa-play'></i></label><label class='btn btn-default btn-xs' href='"+playlist[index].link+"' title='Xem ở cửa sổ mới' target='_blank'><i class='fa fa-external-link-square'></i></label></span></li>"
list.innerHTML = html;
}
html +="</ul>"
});
function playThis(index) {
playerInstance.playlistItem(index);
}
SOLUTION : Based on an idea of #zer00ne
Add following code :
playerInstance.on('playlistItem', function() {
var playlist = playerInstance.getPlaylist();
var index = playerInstance.getPlaylistIndex();
var current_li = document.getElementById("play-items-"+index);
for(var i = 0; i < playlist.length; i++) {
$('li[id^=play-items-]').removeClass( "active" )
}
current_li.classList.add('active');
});
before
function playThis(index) {
playerInstance.playlistItem(index);
}
And edit html generate like this :
html += "<li id='play-items-"+index+"' class='list-group-item'><span>"+playlist[index].title+"</span><span class='pull-right'><label onclick='javascript:playThis("+index+")' title='"+lang_play+" "+playlist[index].title+"' class='btn btn-primary btn-xs mgr_10'><i class='fa fa-play'></i></label><a href='"+playlist[index].link+"' title='"+lang_new_window+"' target='_blank'><label class='btn btn-default btn-xs'><i class='fa fa-external-link-square'></i></label></a></span></li>"
With adding id='play-items-"+index+"' to identify unique class for each item of list.
Thanks for idea of #zer00ne !
Your code not total works with my site but it give a solution.
playerInstance.on('playlistItem', function() {
var playlist = playerInstance.getPlaylist();
var index = playerInstance.getPlaylistIndex();
var current_li = document.getElementById("play-items-"+index);
for(var i = 0; i < playlist.length; i++) {
$('li[id^=play-items-]').removeClass( "active" )
}
current_li.classList.add('active');
});
This code will remove all "active" from each li element and find the ID is correct with current playing Index, then add "active" class.
UPDATE
Firefox has a problem with li[i], since it's a HTMLCollection (nodeList) and not live coming from querySelectorAll(). One extra step needs to be added in order to convert li[i] to a true Array. The update involves a function called nodeList2Array(sel).
UPDATE
I misinterpreted the OP's request:
Is there any solution to add a custom class, like .active when click on a item of list.
So what is needed is manipulation of the generated <li>s of the custom playlist.
SOLUTION
Add this after the the rest of the script:
jw.on('playlistItem', function() {
var playlist = jw.getPlaylist();
var idx = jw.getPlaylistIndex();
//var li = document.querySelectorAll('.group-list-item');
var li = nodeList2Array('.group-list-item');
for(var i = 0; i < playlist.length; i++) {
if(i === idx) {
li[i].classList.add('active');
}
else {
li[i].classList.remove('active');
}
}
});
function nodeList2Array(sel) {
var li = Array.prototype.slice.call(document.querySelectorAll(sel));
return li;
}
DEMO
!!!IMPORTANT PLEASE READ THIS!!!
The following demo DEFINITELY WORKS, but you need to enter your own key in order for it to function. JW7 does not have a free version like JW6 does.
var jw = jwplayer("media1");
jw.setup({
playlist: "https://content.jwplatform.com/feeds/13ShtP5m.rss",
displaytitle: false,
width: 680,
height: 360
});
var list = document.querySelector(".group-list");
var html = list.innerHTML;
jw.on('ready', function() {
var playlist = jw.getPlaylist();
for (var idx = 0; idx < playlist.length; idx++) {
html += "<li class='group-list-item' title='" + playlist[idx].title + "'><a href='javascript:playThis(" + idx + ");'><img height='75' width='120' src='" + playlist[idx].image + "'><figcaption>" + playlist[idx].title + "</figcaption></a></li>";
list.innerHTML = html;
}
});
//SOLUTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
jw.on('playlistItem', function() {
var playlist = jw.getPlaylist();
var idx = jw.getPlaylistIndex();
var li = document.querySelectorAll('.group-list-item');
for (var i = 0; i < playlist.length; i++) {
if (i === idx) {
li[i].classList.add('active');
} else {
li[i].classList.remove('active');
}
}
});
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function playThis(idx) {
jw.playlistItem(idx);
}
html {
box-sizing: border-box;
font: 400 16px/2 small-caps"Trebuchet MS";
height: 100vh;
width: 100vw;
}
*,
*:before,
*:after {
box-sizing: inherit;
margin: 0;
padding: 0;
border: 0 solid transparent;
outline: 0;
text-indent: 0;
}
body {
height: 100%;
width: 100%;
background: #000;
color: #FFF;
position: relative;
}
#main {
margin: auto;
width: 680px;
}
#frame1 {
position: absolute;
top: 12.5%;
left: 25%;
}
.jwp {
position: relative;
}
.group-list {
position: relative;
list-style-type: none;
list-style-position: inside;
}
.group-list li {
list-style: none;
display: inline-block;
float: left;
padding: 15px 0 0 11px;
line-height: 2;
}
.group-list a {
text-decoration: none;
display: inline-block;
background: #000;
border: 1px solid #666;
border-radius: 8px;
height: 75px;
width: 120px;
text-align: center;
}
.group-list a:hover,
.group-list a:active {
border: 1px solid #ff0046;
border-radius: 8px;
color: #FFF;
background: hsla(180, 60%, 50%, .4);
}
img {
display: block;
}
.active {
background: hsla(180, 60%, 50%, .4);
outline: 3px solid #0FF;
}
.active figcaption {
color: #000;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JWplayer 7 - Add active class to current playing video</title>
<meta name="SO33252950" content="http://stackoverflow.com/questions/33252950/jwplayer-7-add-active-class-to-current-playing-video">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://d1jtvmpy1cspce.cloudfront.net/lib/jw/7/jwplayer.js"></script>
<script>
jwplayer.key = "/*........::::::45_Alphanumerics::::::........*/"
</script>
</head>
<body>
<main id="main">
<section id="frame1" class="frame">
<div id="media1" class="jwp">Loading...</div>
<ul id="list1" class="group-list"></ul>
</section>
</main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
OLD
Sure it's possible to add a class such as .active then apply styles that way, but JW7 has extensive CSS Skin documentation. I styled the skin using the technique detailed here:
http://support.jwplayer.com/customer/en/portal/articles/2092249-sample-css-file
DEMO
https://glpro.s3.amazonaws.com/_util/smpte/jwp.html
/* Allows you to adjust the color of the playlist item when hovering and has a different active style.*/
.jw-skin-stormtrooper .jw-playlist-container .jw-option:hover,
.jw-skin-stormtrooper .jw-playlist-container .jw-option.jw-active-option {
background-color: hsla(210,100%,20%,1);
}
/* Changes the color of the label when hovering.*/
.jw-skin-stormtrooper .jw-playlist-container .jw-option:hover .jw-label {
color: #0080ff;
}
/* Sets the color of the play icon of the currently playing playlist item.*/
.jw-skin-stormtrooper .jw-playlist-container .jw-label .jw-icon-play {
color: #0080ff;
}
/* Sets the color of the playlist title */
.jw-skin-stormtrooper .jw-tooltip-title {
background-color: #000;
color: #fff
}
/* Style for playlist item, current time, qualities, and caption text.*/
.jw-skin-stormtrooper .jw-text {
color: #aed4ff;
}
/* Color for all buttons when they are inactive. This is over-ridden with the
inactive configuration in the skin block.*/
.jw-skin-stormtrooper .jw-button-color {
color: #cee2ec;
}
/* Color for all buttons for when they are hovered on. This is over-ridden with the
active configuration in the skin block.*/
.jw-skin-stormtrooper .jw-button-color:hover {
color: #00e;
}
/* Color for when HD/CD icons are toggled on. */
.jw-skin-stormtrooper .jw-toggle {
color: #0080ff;
}
/* Color for when HD/CD icons are toggled off. */
.jw-skin-stormtrooper .jw-toggle.jw-off {
color: #ffffff;
}
I started out with a .js file and revised it so that it would:
1. Filter the data in the geoJSON (top right buttons)
2. Show popups with relevant data when you click the marker
3. Shows a list of stores based on the markers that are inbounds or the markers that are currently showing on the map. When you zoom in, there will be less markers and also less items listed on the left.
Now I can't get these 2 to work:
Div class with 'item' changes so that it adds "active" to the
classname
List item when I click the links in the list on the lefthand side, it doesn't pan to the marker that is clicked on and show the popup anymore. Instead it shows the markers for all of the locations in the list one at a a time, ending with the very last one. I'm sure it has something to do with locations.eachLayer, but I don't know how to fix it so that it will show the data or select the data that I want to. I have a feeling I may not be using the event handler in the right order as well.
Visual
OLD FILE: When I click on an item in the list on the left, the map automatically pans to and opens up that marker and popup.
NEW FILE (in progress): Trying to get it to work
// *****This is the map
L.mapbox.accessToken = 'pk.eyJ1IjoiamVubmlmZXJwaGFtIiwiYSI6Ijc3NmJkZWE1YjM0ZDc0MWU2Yzc0MWM0YWQ5NzRiNzliIn0.OaKjiklBTRs_Saoh1wSglw';
var map = L.mapbox.map('map', 'glidewell.jno36i2l');
// END of the map
$( document ).ready(function() {
// ******This code zooms to the country locations listed on the page
document.getElementById('navigation').onclick = function(e) {
e.preventDefault();
var pos = e.target.getAttribute('data-position');
var zoom = e.target.getAttribute('data-zoom');
if (pos && zoom) {
var loc = pos.split(',');
var zoo = parseInt(zoom);
map.setView(loc, zoo);
return false;
}
}
// END of that code
//this calls the <div id="listings>
var listings = document.getElementById('listings');
// *****This brings in the locations or GEO JSON file
var locations = L.mapbox.featureLayer().addTo(map);
var listing = $('div.item');
var link = $('a.title');
//this is the file that the data comes from
locations.loadURL('js/testingdummydata.geojson');
// END of that code
// ****** This code zooms to the point on hr map when a selection is made from the list
function setActive(el) {
var siblings = listings.getElementsByTagName('div');
for (var i = 0; i < siblings.length; i++) {
siblings[i].className = siblings[i].className
.replace(/active/, '').replace(/\s\s*$/, '');
}
el.className += ' active';
}
// END of that code
// *****This code merges the Map and the list together
locations.on('ready', makepopup).on('ready', showMarkersinBound)
.on('ready', goToMarker);
function makepopup() {
locations.eachLayer(function (locale) {
var prop = locale.feature.properties;
// Shorten locale.feature.properties to just `prop` so we're not
// writing this long form over and over again.
var popup = '<h3>' + prop.title + '</h3><div>' + prop.address + '<br>' + prop.city + ', ' + prop.state + '<br>' + prop.phone + '<br>' + '' + prop.website + '';
if (prop.crossStreet) {
// link.innerHTML += '<br /><small class="quiet">' + prop.crossStreet + '</small>';
popup += '<br /><small class="quiet">' + prop.crossStreet + '</small>';
};
// Marker interaction
locale.on('click', function (e) {
// 1. center the map on the selected marker.
map.panTo(locale.getLatLng());
// 2. Set active the markers associated listing.
setActive(listing);
});
popup += '</div>';
locale.bindPopup(popup);
});
};
function goToMarker(){
locations.eachLayer(function (locale) {
$("a[href='#'][class='title']").click(function () {
setActive(listing);
// When a menu item is clicked, animate the map to center
// its associated locale and open its popup.
map.setView(locale.getLatLng(), 16);
locale.openPopup();
return false;
});
});
};
// *****Filters
$('.menu-ui-btn a').on('click', function() {
//adds "active" class to the link being clicked on and removes active class from the other links in menu
$(this).addClass('active').siblings().removeClass('active');
// For each filter link, get the 'data-filter' attribute value and assign it to a variable called filter.
var filter = $(this).data('filter');
// The setFilter function takes a GeoJSON feature object
// and returns true to show it or false to hide it.
locations.setFilter(function(feature) {
return (filter === 'all') ? true : feature.properties[filter] === true;
});
makepopup();
showMarkersinBound();
return false;
});
//*******LIST OF MARKERS INSIDE VIEW
function showMarkersinBound() {
// Construct an empty list to fill with onscreen markers.
var inBounds = [];
// Get the map bounds - the top-left and bottom-right locations.
var bounds = map.getBounds();
// For each marker, consider whether it is currently visible by comparing
// with the current map bounds.
locations.eachLayer(function (marker, locale) {
if (bounds.contains(marker.getLatLng())) {
var oneListing;
var prop = marker.toGeoJSON().properties;
oneListing= '<div class="item">' + prop.title + '' + prop.city;
if (prop.state) {
oneListing += ', ' + prop.state;
};
oneListing += '</div>';
inBounds.push(oneListing); //adds the oneListing item into inBounds array
} //closes if statement
});
// Display a list of markers in id="listings" on the DOM.
listings.innerHTML = inBounds.join('');
};
//when map moves, trigger showMarkersinBound function
map.on('move', showMarkersinBound);
});
/* google.com/fonts import files go above this line ^
/* Nav / Menus
================= */
.menu-ui-btn {
background:#fff;
position:absolute;
top:10px;right:10px;
z-index:1;
border-radius:3px;
width:120px;
border:1px solid rgba(0,0,0,0.4);
}
.menu-ui-btn a {
font-size:13px;
color:#404040;
display:block;
margin:0;padding:0;
padding:10px;
text-decoration:none;
border-bottom:1px solid rgba(0,0,0,0.25);
text-align:center;
}
.menu-ui-btn a:first-child {
border-radius:3px 3px 0 0;
}
.menu-ui-btn a:last-child {
border:none;
border-radius:0 0 3px 3px;
}
.menu-ui-btn a:hover {
background:#f8f8f8;
color:#404040;
}
.menu-ui-btn a.active,
.menu-ui-btn a.active:hover {
background:#3887BE;
color:#FFF;
}
/* Content
================= */
#marker-list {
position:absolute;
top:0; right:0;
width:200px;
bottom:0;
overflow-x:auto;
background:#fff;
margin:0;
padding:5px;
height: 400px;
z-index: 50;
background-color: white;
}
#marker-list li {
padding:5px;
margin:0;
list-style-type:none;
}
#marker-list li:hover {
background:#eee;
}
.sidebar {
position:absolute;
width:25%;
height:100%;
top:0;left:0;
overflow:hidden;
border-right:1px solid rgba(0,0,0,0.25);
}
.pad2 {
padding:20px;
}
.quiet {
color:#888;
}
.map {
position:absolute;
left:25%;
width:75%;
top:0;bottom:0;
}
.heading {
background:#fff;
border-bottom:1px solid #eee;
padding:0 10px;
}
.listings {
height:100%;
overflow:auto;
padding-bottom:60px;
}
.listings .item {
display:block;
border-bottom:1px solid #eee;
padding:10px;
text-decoration:none;
}
.listings .item:last-child { border-bottom:none; }
.listings .item .title {
display:block;
color:#BA222B;
font-weight:700;
}
.listings .item .title small { font-weight:400; }
.listings .item.active .title,
.listings .item .title:hover { color:#bbb; }
.listings .item.active {
background-color:#f8f8f8;
}
::-webkit-scrollbar {
width:22px;
height:3px;
border-left:0;
background:rgba(0,0,0,0.1);
}
::-webkit-scrollbar-track {
background:none;
}
::-webkit-scrollbar-thumb {
background:#BA222B;
border-radius:0;
height: 60px;
}
.clearfix { display:block; }
.clearfix:after {
content:'.';
display:block;
height:0;
clear:both;
visibility:hidden;
}
/* Marker tweaks
====================*/
.leaflet-popup-close-button {
display:none;
}
.leaflet-popup-content {
font:400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
padding:0;
width: auto;
}
.leaflet-popup-content-wrapper {
padding:0;
}
.leaflet-popup-content h3 {
background:#BA222B;
color:#fff;
margin:0;
display:block;
border-radius:3px 3px 0 0;
font-weight:700;
margin-top:-15px;
}
.leaflet-popup-content div {
padding:10px;
}
.leaflet-container .leaflet-marker-icon {
cursor:pointer;
}
/**********************************************************
Media Querys (480px, 768px, 990px, 1200px, 1500px, 2000px)
***********************************************************/
/* Smaller than
================= */
/* Applied to resolutions less than 2000 (3x) */
#media (max-width: 2000px) {
}
/* Applied to resolutions less than 1740 (2x) */
#media (max-width: 1740px) {
}
/* Applied to resolutions less than 1500 (Xl) */
#media (max-width: 1500px) {
}
/* Applied to resolutions less than 1200 (lg) */
#media (max-width: 1200px) {
}
/* Applied to resolutions less than 990 (md) */
#media (max-width: 990px) {
}
/* Applied to resolutions less than 768 (sm) */
#media (max-width: 768px) {
}
/* Applied to resolutions less than 568 (sm) */
#media only screen and (max-width: 568px) {
.sidebar {
position: absolute;
width: 100%;
height: 60%;
bottom: 0;
left: 0;
overflow: hidden;
border-right: 1px solid rgba(0,0,0,0.25);
top: inherit;
}
.map {
position: absolute;
bottom: 60%;
width: 100%;
top: 0;
left: 0;
}
.heading {
background: #fff;
border-bottom: 1px solid #eee;
height: 60px;
padding: 3px 10px;
}
.leaflet-container .leaflet-control-attribution {
display: none;
}
.listings {
height: 233px;
}
}
/* Applied to resolutions less than 480 (XS) */
#media (max-width: 480px) {
}
/* Larger than
================= */
/* Applied to resolutions larger than 2000 (3x) */
#media (min-width: 2001px) {
}
/* Applied to resolutions larger than 1500 (2x) */
#media (min-width: 1501px) {
}
/* Applied to resolutions larger than 1200 (xl) */
#media (min-width: 1201px) {
}
/* Applied to resolutions larger than 990 (lg) */
#media (min-width: 991px) {
}
/* Applied to resolutions larger than 768 (sm) */
#media (min-width: 769px) {
}
/* Applied to resolutions larger than 480 (xs) */
#media (min-width: 481px) {
}
/***************************************
Default Style Sheet created as part of - The Maui Toolbox
For more information visit: www.mauitoolbox.com
pub-20150501
***************************************/
#coordinates {
height:450px;
overflow:auto;
padding-bottom:60px;
}
#coordinates .item {
display:block;
border-bottom:1px solid #eee;
padding:10px;
text-decoration:none;
}
#coordinates .item:last-child { border-bottom:none; }
#coordinates .item .title {
display:block;
color:#BA222B;
font-weight:700;
}
#coordinates .item .title small { font-weight:400; }
#coordinates .item.active .title,
#coordinates .item .title:hover { color:#bbb; }
#coordinates .item.active {
background-color:#f8f8f8;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="Description" content="#"> <!-- (Example: Compelling description to be displayed on Search Engine) -->
<meta name="author" content="#"> <!-- (example: Developers Name) -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>[PAGE TITLE]</title>
<!-- (Extrenal) Default Style Sheets =========== -->
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="http://gl-dev-staticweb.s3.amazonaws.com/blimp.css">
<link rel="stylesheet" type="text/css" href="http://gl-dev-staticweb.s3.amazonaws.com/maui.css">
<!-- Style Sheets ============================== -->
<link rel="stylesheet" type="text/css" href="css/map-styles.css">
<!-- Additional Style Sheets =================== -->
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700' rel='stylesheet'>
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.9/mapbox.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.1.9/mapbox.css' rel='stylesheet' />
</head>
<body>
<div class='sidebar'>
<div class='heading'>
<h1>ABC Company</h1>
<div class="dropdown">
<a id="dLabel" data-target="#" href="http://example.com" data-toggle="dropdown" aria-haspopup="true" role="button" aria-expanded="false">
Select Country
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" id='navigation'>
<li><a href='#' data-zoom="5" data-position='37.0,-95.7'>USA</a></li>
<li><a href='#' data-zoom="8" data-position='56.1,9.5'>DNK</a></li>
<li><a href='#' data-zoom="8" data-position='55.3,-3.4'>GB</a></li>
<li><a href='#' data-zoom="6" data-position='46.2,2.2'>FRA</a></li>
<li><a href='#' data-zoom="7" data-position='41.8,12.5'>ITA</a></li>
<li><a href='#' data-zoom="6" data-position='-30.5,22.9'>ZAF</a></li>
<li><a href='#' data-zoom="6" data-position='20.5,78.9'>IN</a></li>
<li><a href='#' data-zoom="8" data-position='39.0,21.8'>GRC</a></li>
<li><a href='#' data-zoom="6" data-position='26.8,30.8'>EGY</a></li>
<li><a href='#' data-zoom="8" data-position='60.4,8.4'>NOR</a></li>
<li><a href='#' data-zoom="8" data-position='48.6,19.6'>SVK</a></li>
<li><a href='#' data-zoom="5" data-position='-25.3,133.7'>AUS</a></li>
<li><a href='#' data-zoom="8" data-position='-40.9,174.8'>NZ</a></li>
<li><a href='#' data-zoom="5" data-position='35.4,104.1'>CHN</a></li>
<li><a href='#' data-zoom="8" data-position='15.8,100.9'>THA</a></li>
<li><a href='#' data-zoom="8" data-position='52.1,5.2'>NLD</a></li>
<li><a href='#' data-zoom="8" data-position='9.7,-83.7'>CR</a></li>
<li><a href='#' data-zoom="6" data-position='23.6,-102.5'>MX</a></li>
</ul>
</div>
</div>
<div id='listings' class='listings'></div>
</div>
<!-- Filter buttons - filters markers on map-->
<nav class='menu-ui-btn'>
Show all
Mills
Labs
</nav>
<!-- Map is displayed here -->
<div id='map' class='map'></div>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
2 relevant examples on Mapbox documentation:
1. List markers and pan to clicked items
2. Listing markers in view
I've spent 2 whole days looking at this over and over, and I could really use someone's help with expert Javascript knowledge and possibly even mapbox.js experience.
Nevermind I got it to work:
I added data-name attribute to the html being shown in the DOM so that I could get the unique name of the item in the list (added it to "oneListing" variable).
function showMarkersinBound() {
// Construct an empty list to fill with onscreen markers.
var inBounds = [];
// Get the map bounds - the top-left and bottom-right locations.
var bounds = map.getBounds();
// For each marker, consider whether it is currently visible by comparing
// with the current map bounds.
locations.eachLayer(function (marker) {
if (bounds.contains(marker.getLatLng())) {
var oneListing;
var prop = marker.toGeoJSON().properties;
//oneListing= '<div class="item">' + prop.title + '<br>' + prop.address + '<br>' + prop.city + ', ' + prop.state + '<br>' + prop.phone + '<br>' + '' + prop.website + '</div>';
oneListing= '<div class="item">' + prop.title + '' + prop.city;
if (prop.state) {
oneListing += ', ' + prop.state;
};
oneListing += '</div>';
inBounds.push(oneListing); //adds the oneListing item into inBounds array
} //closes if statement
});
// Display a list of markers in id="listings" on the DOM.
listings.innerHTML = inBounds.join('');
}; //closes function
Then function goes through all layers, and I made an if else statement so that it only changes the view and pans to the marker if the name of the link being clicked on is same as the title of that layer.
function goToMarker() {
locations.eachLayer(function (layer) {
var itsTitle = layer.toGeoJSON().properties.title;
// var prop = locale.feature.properties;
$(".title").click(function () {
if (($(this).data('name')) === itsTitle) {
// When a menu item is clicked, animate the map to center
// its associated locale and open its popup.
map.setView(layer.getLatLng(), 16);
layer.openPopup();
return false;
};
});
});
}
Then I added them as event listeners when location was ready.
var locations = L.mapbox.featureLayer().addTo(map);
locations.loadURL('js/testingdummydata.geojson');
locations.on('ready', makepopup).on('ready', howMarkersinBound).on('ready', goToMarker);
//when map moves, trigger showMarkersinBound function
map.on('move', showMarkersinBound).on('move', goToMarker);
I'm developing a map using mapbox an have run into a road block. I am trying to use custom markers and have buttons in the map to filter my markers so only certain markers will show depending on which button is active. The problem is I seem to be able to get one OR the other to work and not both. I can have a map with custom markers but no filters or a map with built in markers and working filters. I know almost no code beyond HTML and have been developing the map following mapboxes examples. If someone can take a look at this and let me know what I am doing wrong and how I can fix it I would greatly appreciate it.
These are the two examples I am following:
https://www.mapbox.com/mapbox.js/example/v1.0.0/markers-with-multiple-filters/
https://www.mapbox.com/mapbox.js/example/v1.0.0/custom-marker/
This is my code with working Icons and no working filter(I removed about 10 markers since it was the same code):
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Custom marker icons</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.6/mapbox.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.1.6/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
.menu-ui {
background:#A2A19F;
position:absolute;
bottom:50px;
left:50%;
margin-left:-110px;
z-index:1;
border-radius:3px;
width:auto;
border:1px solid rgba(0,0,0,0.4);
}
.menu-ui a {
font-size:22px;
color:#fff;
display:table-cell;
padding:10px;
text-decoration:none;
border-bottom:1px solid rgba(0,0,0,0.25);
text-align:center;
}
.menu-ui a:first-child {
border-radius:3px 3px 0 0;
}
.menu-ui a:last-child {
border:none;
border-radius:0 0 3px 3px;
}
.menu-ui a:hover {
background:#f8f8f8;
color:#404040;
}
.menu-ui a.active,
.menu-ui a.active:hover {
background:#DB3E3A;
color:#FFF;
}
.popup {
text-align:center;
}
.popup .slideshow .image { display:none; }
.popup .slideshow .image.active { display:block; }
.popup .slideshow img {
width:100%;
}
.popup .slideshow .caption {
background:#eee;
padding:10px;
}
.popup .cycle {
padding:10px 0 20px;
}
.popup .cycle a.prev { float:left; }
.popup .cycle a.next { float:right; }
</style>
<nav class='menu-ui'>
<a href='#' class='active' data-filter='Development'>Development</a>
<a href='#' data-filter='Land'>Land</a>
</nav>
<div id='map'></div>
<!-- jQuery is required for this example. -->
<script src='https://code.jquery.com/jquery-1.11.0.min.js'></script>
<script>
L.mapbox.accessToken = 'pk.eyJ1Ijoib21uaXVzbm93IiwiYSI6ImFlZ0pNSXMifQ.VNyOy9GaRZ1cAS2nDTp3tw';
var southWest = L.latLng(21.284438,-131.265625),
northEast = L.latLng(51.606163, -62.929688),
bounds = L.latLngBounds(southWest, northEast);
var map = L.mapbox.map('map', 'omniusnow.lcfl92fp', {
// set that bounding box as maxBounds to restrict moving the map
// see full maxBounds documentation:
// http://leafletjs.com/reference.html#map-maxbounds
maxBounds: bounds,
maxZoom: 16,
minZoom: 5
});
// zoom the map to that bounding box
map.fitBounds(bounds);
var myLayer = L.mapbox.featureLayer().addTo(map);
var geoJson = [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.190583, 25.767619]
},
"properties": {
"title": "Test location",
//this should let the button code know whether this is a development or a
//land catagory, IT IS CASE SENSATIVE!!
"Development":true,
"Land":false,
"icon": {
"iconUrl": "https://cdn1.iconfinder.com/data/icons/Map-Markers-Icons-Demo-PNG/256/Map-Marker-Flag--Chartreuse.png",
"iconSize": [50,50], // size of the icon
"iconAnchor": [50,50], // point of the icon which will correspond to marker's location
"popupAnchor": [0, -25], // point from which the popup should open relative to the iconAnchor
"className": "dot"
},
'images': [
['http://upload.wikimedia.org/wikipedia/commons/0/04/Garfield_Building_Detroit.jpg','<p><b>Descriptive text goes here'],
['http://upload.wikimedia.org/wikipedia/commons/2/2f/Greist_Building.JPG','More descriptive text goes here'],
['http://detroit1701.org/Graphics/Dime%20Building.jpg','A link to more info goes here']
]
}
},{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-82.356899, 29.633012]
},
"properties": {
"title": "Test location 2",
"Development":false,
"Land":true,
"icon": {
"iconUrl": "https://cdn1.iconfinder.com/data/icons/Map-Markers-Icons-Demo-PNG/256/Map-Marker-Flag--Chartreuse.png",
"iconSize": [50,50], // size of the icon
"iconAnchor": [50,50], // point of the icon which will correspond to marker's location
"popupAnchor": [0, -25], // point from which the popup should open relative to the iconAnchor
"className": "dot"
},
'images': [
['http://upload.wikimedia.org/wikipedia/commons/0/04/Garfield_Building_Detroit.jpg','<p><b>Descriptive text goes here'],
['http://upload.wikimedia.org/wikipedia/commons/2/2f/Greist_Building.JPG','More descriptive text goes here'],
['http://detroit1701.org/Graphics/Dime%20Building.jpg','A link to more info goes here']
]
}
}];
// Set a custom icon on each marker based on feature properties.
myLayer.on('layeradd', function(e) {
var marker = e.layer;
var feature = marker.feature;
var images = feature.properties.images
var slideshowContent = '';
marker.setIcon(L.icon(feature.properties.icon));
for(var i = 0; i < images.length; i++) {
var img = images[i];
slideshowContent += '<div class="image' + (i === 0 ? ' active' : '') + '">' +
'<img src="' + img[0] + '" />' +
'<div class="caption">' + img[1] + '</div>' +
'</div>';
}
// Create custom popup content
var popupContent = '<div id="' + feature.properties.id + '" class="popup">' +
'<h2>' + feature.properties.title + '</h2>' +
'<div class="slideshow">' +
slideshowContent +
'</div>' +
'<div class="cycle">' +
'« Previous' +
'Next »' +
'</div>'
'</div>';
// http://leafletjs.com/reference.html#popup
marker.bindPopup(popupContent,{
closeButton: false,
minWidth: 400
});
});
// Add features to the map
myLayer.setGeoJSON(geoJson)
.addTo(map);
//button stuff
$('.menu-ui a').on('click', function() {
// For each filter link, get the 'data-filter' attribute value.
var filter = $(this).data('filter');
$(this).addClass('active').siblings().removeClass('active');
markers.setFilter(function(f) {
// If the data-filter attribute is set to "all", return
// all (true). Otherwise, filter on markers that have
// a value set to true based on the filter name.
return (filter === 'Development') ? true : f.properties[filter] === true;
});
return false;
});
//end button stuff
$('#map').on('click', '.popup .cycle a', function() {
var $slideshow = $('.slideshow'),
$newSlide;
if ($(this).hasClass('prev')) {
$newSlide = $slideshow.find('.active').prev();
if ($newSlide.index() < 0) {
$newSlide = $('.image').last();
}
} else {
$newSlide = $slideshow.find('.active').next();
if ($newSlide.index() < 0) {
$newSlide = $('.image').first();
}
}
$slideshow.find('.active').removeClass('active').hide();
$newSlide.addClass('active').show();
return false;
});
</script>
</body>
</html>
And here is my code without custom markers but with filters working.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Multiple filters on markers</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.7/mapbox.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.1.7/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
.menu-ui {
background:#A2A19F;
position:absolute;
bottom:50px;
left:50%;
margin-left:-110px;
z-index:1;
border-radius:3px;
width:auto;
border:1px solid rgba(0,0,0,0.4);
}
.menu-ui a {
font-size:22px;
color:#fff;
display:table-cell;
padding:10px;
text-decoration:none;
border-bottom:1px solid rgba(0,0,0,0.25);
text-align:center;
}
.menu-ui a:first-child {
border-radius:3px 3px 0 0;
}
.menu-ui a:last-child {
border:none;
border-radius:0 0 3px 3px;
}
.menu-ui a:hover {
background:#f8f8f8;
color:#404040;
}
.menu-ui a.active,
.menu-ui a.active:hover {
background:#DB3E3A;
color:#FFF;
}
</style>
<!-- jQuery is required for this example. -->
<script src='https://code.jquery.com/jquery-1.11.0.min.js'></script>
<nav class='menu-ui'>
<a href='#' class='active' data-filter='Development'>Development</a>
<a href='#' data-filter='Land'>Land</a>
</nav>
<div id='map'></div>
<script>
L.mapbox.accessToken = 'pk.eyJ1Ijoib21uaXVzbm93IiwiYSI6ImFlZ0pNSXMifQ.VNyOy9GaRZ1cAS2nDTp3tw';
var southWest = L.latLng(21.284438,-131.265625),
northEast = L.latLng(51.606163, -62.929688),
bounds = L.latLngBounds(southWest, northEast);
var geojson = [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.190583, 25.767619]
},
"properties": {
"title": "Test location",
//this should let the button code know whether this is a development or a
//land catagory, IT IS CASE SENSATIVE!!
"Development":true,
"Land":false,
"marker-size": "large",
"marker-symbol": "city"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-82.356899, 29.633012]
},
"properties": {
"title": "Test location 2",
"Development":false,
"Land":true,
"marker-size": "large",
"marker-symbol": "city"
}
},
];
var map = L.mapbox.map('map', 'omniusnow.lcfl92fp', {
// set that bounding box as maxBounds to restrict moving the map
// see full maxBounds documentation:
// http://leafletjs.com/reference.html#map-maxbounds
maxBounds: bounds,
maxZoom: 16,
minZoom: 5
});
// zoom the map to that bounding box
map.fitBounds(bounds);
var markers = L.mapbox.featureLayer()
.setGeoJSON(geojson)
.addTo(map);
$('.menu-ui a').on('click', function() {
// For each filter link, get the 'data-filter' attribute value.
var filter = $(this).data('filter');
$(this).addClass('active').siblings().removeClass('active');
markers.setFilter(function(f) {
// If the data-filter attribute is set to "all", return
// all (true). Otherwise, filter on markers that have
// a value set to true based on the filter name.
return (filter === 'all') ? true : f.properties[filter] === true;
});
return false;
});
</script>
</body>
</html>
I feel like I'm missing something small(maybe just syntax) but my lack of experience and knowledge with this language is preventing me from finding it. Any help is greatly appreciated.
On your not-working code listing, line 204, change markers.setFilter(function(f) { to myLayer.setFilter(function(f) {.
Can anyone see what in this code is preventing the tooltips in my map from functioning? Ie they function in normal map but not when I add the layers to this map with a toggle button. I assume it's something with the onclick function, but can't figure it out specifically, and what a workaround might be.
Thank you
<style>
.menu-ui {
background:#fff;
position:absolute;
bottom:10px;left:10px;
z-index:1;
border-radius:3px;
width:120px;
border:1px solid rgba(0,0,0,0.4);
}
.menu-ui a {
font-size:13px;
color:#404040;
display:block;
margin:0;padding:0;
padding:10px;
text-decoration:none;
border-bottom:1px solid rgba(0,0,0,0.25);
text-align:center;
}
.menu-ui a:first-child {
border-radius:3px 3px 0 0;
}
.menu-ui a:last-child {
border:none;
border-radius:0 0 3px 3px;
}
.menu-ui a:hover {
background:#f8f8f8;
color:#404040;
}
.menu-ui a.active {
background:#3887BE;
color:#FFF;
}
.menu-ui a.active:hover {
background:#3074a4;
}
</style>
<nav id='menu-ui' class='menu-ui'></nav>
<div id='map'></div>
<script>
var map = L.map('map').setView([10.8229,-84.2116], 12);
var layers = document.getElementById('menu-ui');
addLayer(L.mapbox.tileLayer('XXXX.XXXX'), 'Photo Points', 4);
addLayer(L.mapbox.tileLayer('XXXX.XXXX'), 'River KMs', 3);
addLayer(L.mapbox.tileLayer('XXXX.XXXXX'), 'December 2013 (0.5m)', 2);
addLayer(L.mapbox.tileLayer('XXXXXX.XXXXXX'), 'February 2014 (1.5m)', 1);
function addLayer(layer, name, zIndex) {
layer
.setZIndex(zIndex)
.addTo(map);
// Create a simple layer switcher that
// toggles layers on and off.
var link = document.createElement('a');
link.href = '#';
link.className = 'active';
link.innerHTML = name;
link.onclick = function(e) {
e.preventDefault();
e.stopPropagation();
if (map.hasLayer(layer)) {
map.removeLayer(layer);
this.className = '';
} else {
map.addLayer(layer);
this.className = 'active';
}
};
layers.appendChild(link);
}
</script>
Did you add interactivity via TileMill? If so, you'll need to add the gridLayer and gridControl to the map, not just a tileLayer.
I made a script (using mootools library) that is supposed to overlay an image with a table grid and when each grid cell is clicked/dragged over its background color changes 'highlighting' the cell.
Current code creates a table and positions it over the element (el, image in this case). Table was used since I am planning to add rectangle select tool later on, and it seemed easiest way to do it.
<html>
<head>
<title></title>
<script type="text/javascript" src="mootools.js"></script>
<script type="text/javascript">
var SetGrid = function(el, sz, nr, nc){
//get number of rows/columns according to the 'grid' size
numcols = el.getSize().x/sz;
numrows = el.getSize().y/sz;
//create table element for injecting cols/rows
var gridTable = new Element('table', {
'id' : 'gridTable',
'styles' : {
'width' : el.getSize().x,
'height' : el.getSize().y,
'top' : el.getCoordinates().top,
'left' : el.getCoordinates().left
}
});
//inject rows/cols into gridTable
for (row = 1; row<=numrows; row++){
thisRow = new Element('tr', {
'id' : row,
'class' : 'gridRow'
});
for(col = 1; col<=numcols; col++){
thisCol = new Element('td', {
'id' : col,
'class' : 'gridCol0'
});
//each cell gets down/up over event... down starts dragging|up stops|over draws area if down was fired
thisCol.addEvents({
'mousedown' : function(){
dragFlag = true;
startRow = this.getParent().get('id');
startCol = this.get('id');
},
'mouseup' : function(){
dragFlag = false;
},
'mouseover' : function(){
if (dragFlag==true){
this.set('class', 'gridCol'+$$('#lvlSelect .on').get('value'));
}
},
'click' : function(){
//this.set('class', 'gridCol'+$$('#lvlSelect .on').get('id').substr(3, 1) );
str = $$('#lvlSelect .on').get('id');
alert(str.substr(2, 3));
}
});
thisCol.inject(thisRow, 'bottom');
};
thisRow.inject(gridTable, 'bottom');
};
gridTable.inject(el.getParent());
}
//sens level selector func
var SetSensitivitySelector = function(el, sz, nr, nc){
$$('#lvlSelect ul li').each(function(el){
el.addEvents({
'click' : function(){
$$('#lvlSelect ul li').set('class', '');
this.set('class', 'on');
},
'mouseover' : function(){
el.setStyle('cursor','pointer');
},
'mouseout' : function(){
el.setStyle('cursor','');
}
});
});
}
//execute
window.addEvent('load', function(){
SetGrid($('imagetomap'), 32);
SetSensitivitySelector();
});
</script>
<style>
#imagetomapdiv { float:left; display: block; }
#gridTable { border:1px solid red; border-collapse:collapse; position:absolute; z-index:5; }
#gridTable td { opacity:0.2; filter:alpha(opacity=20); }
#gridTable .gridCol0 { border:1px solid gray; background-color: none; }
#gridTable .gridCol1 { border:1px solid gray; background-color: green; }
#gridTable .gridCol2 { border:1px solid gray; background-color: blue; }
#gridTable .gridCol3 { border:1px solid gray; background-color: yellow; }
#gridTable .gridCol4 { border:1px solid gray; background-color: orange; }
#gridTable .gridCol5 { border:1px solid gray; background-color: red; }
#lvlSelect ul {float: left; display:block; position:relative; margin-left: 20px; padding: 10px; }
#lvlSelect ul li { width:40px; text-align:center; display:block; border:1px solid black; position:relative; padding: 10px; list-style:none; opacity:0.2; filter:alpha(opacity=20); }
#lvlSelect ul li.on { opacity:1; filter:alpha(opacity=100); }
#lvlSelect ul #li0 { background-color: none; }
#lvlSelect ul #li1 { background-color: green; }
#lvlSelect ul #li2 { background-color: blue; }
#lvlSelect ul #li3 { background-color: yellow; }
#lvlSelect ul #li4 { background-color: orange; }
#lvlSelect ul #li5 { background-color: red; }
</style>
</head>
<body>
<div id="imagetomapdiv">
<img id="imagetomap" src="1.png">
</div>
<div id="lvlSelect">
<ul>
<li value="0" id="li0">0</li>
<li value="1" id="li1">1</li>
<li value="2" id="li2">2</li>
<li value="3" id="li3">3</li>
<li value="4" id="li4">4</li>
<li value="5" id="li5" class="on">5</li>
</ul>
</div>
</body>
</html>
There are two problems: while it works just fine in FF, IE and Chrome do not create the table if the page is refreshed. If you go back to directory root and click on the link to the file the grid table is displayed, if you hit 'refresh' button -- the script runs but the table is not injected.
Secondly, although the table HTML is injected in IE, it does not display it. I tried adding nbsp's to make sure its not ignored -- to no avail.
Any suggestions on improving code or help with the issues is appreciated.
Thanks!
Try adding a docType dec at the top of the page IE:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">