MapBox API exclusive layer switcher - javascript

I have thoroughly searched MapBox support and Stack Overflow for an answer on how to create an exclusive layer switcher using the latest MapBox API (1.6.1 as of now). Exclusive in this case means that only 1 layer can be visible/active at a time. I do not want to use the Leaflet Layers Control for design reasons.
With a little help, I have come up with this example, which almost works:
http://bl.ocks.org/sarahkhank/0e5d81998d2d0876856c
For some reason, adding and removing the gridControl breaks the loop. If you use this structure to just add/remove the tileLayer with no gridLayer or gridControl, it works fine. But when you add the grid elements, the last element in the array doesn't show up and messes up the rest of the loop. (In this case 'far'.)
Does anyone have any idea why this is happening? This type of layer switcher is often asked about on MapBox support, so I'm sure many people would be happy to see this come to life. Thanks for your help!!
Posting full code here at the bottom in case my bl.ocks link ever breaks.
<html>
<head>
<title>DC Zoning Map</title>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src='http://api.tiles.mapbox.com/mapbox.js/v1.6.1/mapbox.js'></script>
<link href='http://api.tiles.mapbox.com/mapbox.js/v1.6.1/mapbox.css' rel='stylesheet' />
</head>
<body>
<style>
#zoning-map-container {
position:relative;
float: right;
display: inline;
}
#map_zoning {
position: relative;
float: left;
clear: both;
width:45%;
min-width: 500px;
height: 500px;
right:20px;
margin-top: 10px;
margin-right: 10px;
border: 1px solid #bbb;
}
#map-ui-zoning {
position:relative;
float: left;
list-style:none;
margin:0;padding:0;
left: -20px;
}
#map-ui-zoning a {
font-family: 'Carrois Gothic', sans-serif;
font-size: 12px;
font-weight: 400;
background:#FFF;
color:#5698D0;
float: left;
margin:0;
border:1px solid #BBB;
border-width: 1px 1px 1px 0;
max-width:100px;
padding:8px;
text-decoration:none;
}
#map-ui-zoning li {
display: inline;
}
#map-ui-zoning a:hover { background:#ECF5FA; }
#map-ui-zoning li:last-child a {
border-bottom-width:1px;
-webkit-border-radius:0 3px 3px 0;
border-radius:0 3px 3px 0;
}
#map-ui-zoning li:first-child a {
border-left-width: 1px;
-webkit-border-radius:3px 0 0 3px;
border-radius:3px 0 0 3px;
}
#map-ui-zoning a.active {
background:#5698D0;
border-color:#5698D0;
border-top-color:#BBB;
color:#FFF;
}
.map-tooltip .zone {
font-size: 10px;
line-height: 13px;
font-weight: bold;
}
.map-tooltip .desc {
font-size: 10px;
line-height: 13px;
padding-bottom: 3px;
}
.map-tooltip .focus {
font-size: 13px;
line-height: 16px;
font-weight: bold;
}
.map-tooltip .info {
font-size: 11px;
line-height: 16px;
}
</style>
<div id='zoning-map-container'>
<ul id='map-ui-zoning'>
<li>Maximum Stories</li>
<li>Maximum Height</li>
<li>Maximum FAR</li>
</ul>
<div id='map_zoning'></div>
</div>
<script type='text/javascript'>
var map = L.mapbox.map('map_zoning');
var stamenLayer = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'
}).addTo(map);
map.setView([38.908, -77.029], 11);
var ui = document.getElementById('map-ui-zoning');
var stories = L.mapbox.tileLayer('sarah.28n6ogvi');
var storiesGrid = L.mapbox.gridLayer('sarah.28n6ogvi');
var storiesGridControl = L.mapbox.gridControl(storiesGrid, {follow: false});
var height = L.mapbox.tileLayer('sarah.ofjsv2t9');
var heightGrid = L.mapbox.gridLayer('sarah.ofjsv2t9');
var heightGridControl = L.mapbox.gridControl(heightGrid, {follow: false});
var far = L.mapbox.tileLayer('sarah.2w9x80k9');
var farGrid = L.mapbox.gridLayer('sarah.2w9x80k9');
var farGridControl = L.mapbox.gridControl(farGrid, {follow: false});
var layers = [{
'name': 'stories',
'layer': stories,
'gridLayer': storiesGrid,
'gridControl': storiesGridControl
},
{
'name': 'height',
'layer': height,
'gridLayer': heightGrid,
'gridControl': heightGridControl
},
{
'name': 'far',
'layer': far,
'gridLayer': farGrid,
'gridControl': farGridControl
}
];
$(document).ready(function(layer){
map.addLayer(stories);
map.addLayer(storiesGrid);
map.addControl(storiesGridControl);
});
$('#map-ui-zoning li a').on('click', function() {
$('#map-ui-zoning li a').removeClass('active');
var $el = $(this);
layers.forEach(function(layer) {
if ($el.data('name') !== layer['name']){
map.removeLayer(layer['layer']);
map.removeLayer(layer['gridLayer']);
map.removeControl(layer['gridControl']);
}
else {
map.addLayer(layer['layer']);
map.addLayer(layer['gridLayer']);
map.addControl(layer['gridControl']);
$el.addClass('active');
}
});
});
</script>

I think that when you call map.removeControl(layer['gridControl']) or more generally map.removeLayer you dont test if the layer is already added to the map because otherwise it mapboxjs will try to delete an element that does not exist and this is where your code gets broken .
if ($el.data('name') !== layer['name'])
needs to become
if ($el.data('name') !== layer['name'] && map.hasLayer(layer))
of course you need to change your else statement accordingly .
here is your example running
http://bl.ocks.org/radproject/31c48b1a7610e353d495

Related

Mapbox + jsFiddle + Wordpress

I apologize in advance for my very limited knowledge of coding. I've been trying to add a custom search bar linked to Mapbox on my Wordpress site without any luck. I created, or actually I edited a jsFiddle that I found. Where I'm having trouble is adding the Javascript from jsFiddle to Wordpress...
Here's the working jsFiddle: https://jsfiddle.net/erinlink/4q9brvkt/16/
L.mapbox.accessToken = 'pk.eyJ1IjoiZXJpbmxpbmsiLCJhIjoiWnpiWXQ5RSJ9.hy5rpmPf-gpFRaNG7GHfAA';
var geocoder = L.mapbox.geocoder('mapbox.places'),
map = null;
var map = L.mapbox.map('mapbox', 'erinlink.bee96628').setView([30.267153, -97.74306079999997], 12);
var featureLayer = L.mapbox.featureLayer('erinlink.bee96628')
.addTo(map);
/*
var featureLayer = L.mapbox.featureLayer()
.addTo(map);
featureLayer.loadID('your_id');
*/
// both versions to add the featurelayer work
function showMap(err, data) {
// The geocoder can return an area, like a city, or a
// point, like an address. Here we handle both cases,
// by fitting the map bounds to an area or zooming to a point.
if (!map) {
map = L.mapbox.map('mapbox', 'erinlink.bee96628');
}
if (data.lbounds) {
map.fitBounds(data.lbounds);
} else if (data.latlng) {
map.setView([data.latlng[0], data.latlng[1]], 12);
}
}
function geocodeThis() {
var text = document.getElementById('searchMap').value;
if (text.length >= 5) {
geocoder.query(text, showMap);
}
}
body {
margin: 0;
padding: 0;
}
#mapbox {
width: 100%;
height: 100%;
border: 0px solid transparent;
}
#searchMap {
z-index: 10000 !important;
position: relative;
float: right;
text-overflow: ellipsis;
padding: 2px 0px 2px 6px;
background-color: #fff;
color: gray;
font-size: 12pt;
font-family: Trebuchet MS;
height: 24px;
width: 200px;
border: 0px solid transparent;
border-radius: 4px 4px 4px 4px;
margin: 0px 120px 10px 10px;
}
.mapbox_header {
color: white;
text-align: right;
font-size: 10pt;
font-family: Trebuchet MS;
font-style: italic;
font-weight: 100;
margin: 10px 120px 10px 0;
}
<link href="https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.js"></script>
<div style="margin-top:1px; padding: 4px 40px 0px 0px; background: #77bc1f; width:100%; height:10%;">
<div>
<ul>
<input type='text' oninput='geocodeThis()' id='searchMap' placeholder='Enter address or zip'>
<br>
<br>
<p class="mapbox_header">Looking for a particular flavor or bottle size in your area? Contact us for more info.</p>
</ul>
</div>
</div>
<div>
<div id='mapbox' style="height:400px; width:100%;"></div>
</div>
Here's the page I've been trying to get it working on (the current
map on this page is not linked to the search bar):
http://yellowbirdsauce.com/locations/
Thanks in advance for any help!!

CartoDB: Buttons switching between layers

sorry, I am very new to this. I want something similar to this here CartoDB multiple layer toggle,
only that I am not adding a SQL queried layer, but one from an URL. Each button should make one layer active, one layer at a time and always only one layer visible.
Thanks for any hint!
Best, Wolfram
<html>
<head>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<script src="http://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v2/themes/css/cartodb.ie.css" />
<![endif]-->
<style>
html, body {width:100%; height:100%; padding: 0; margin: 0;}
#cartodb-map { width: 100%; height:100%; background: black;}
#menu { position: absolute; top: 5px; right: 10px; width: 400px; height:60px; background: transparent; z-index:10;}
#menu a {
margin: 15px 10px 0 0;
float: right;
vertical-align: baseline;
width: 100px;
padding: 10px;
text-align: center;
font: bold 11px "Helvetica",Arial;
line-height: normal;
color: #555;
border-radius: 4px;
border: 1px solid #777777;
background: #ffffff;
text-decoration: none;
cursor: pointer;
}
#menu a.selected,
#menu a:hover {
color: #F84F40;
}
</style>
<script>
var map;
function init(){
// initiate leaflet map
map = new L.Map('cartodb-map', {
center: [-22.8,-43.15],
zoom: 10
})
L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
attribution: ' '
}).addTo(map);
}
var layerUrl1 = 'https://riomapia.cartodb.com/api/v2/viz/d79239a6-51af-11e5-ba37-0e853d047bba/viz.json';
var layerUrl2 = 'https://riomapia.cartodb.com/api/v2/viz/633f93e0-51b0-11e5-b512-0e4fddd5de28/viz.json';
var layerUrl3 = 'https://riomapia.cartodb.com/api/v2/viz/4fa846f0-51b1-11e5-bd3c-0e853d047bba/viz.json';
function showLayer(layerToShow) {
//turn off all layers
layer.forEach(function(i) {
i.hide()
});
switch (layerToShow.id) {
case "Renda1":
layer.show(layerUrl1);
break;
case "Renda2":
layer.show(layerUrl2);
break;
case "Renda3":
layer.show(layerUrl3);
break;
}
return true;
}
</script>
</head>
<body onload="init()">
<div id='cartodb-map'></div>
<div id='menu'>
Renda domiciliar por pessoa
Pessoas < R$ 140
Pessoas < R$ 70
</div>
</body>
</html>
I'm not sure that you can do this (but I'm not certain) - however, I looked at the json files that you are linking to, and I see that the data is from Open Street Map. Have you tried looking at this tutorial?
http://docs.cartodb.com/tutorials/osm.html
Maybe that will help?

Mapbox.js exclusive layer switcher toggle

Asking for help. My mapbox.js code is all fine except I'm unable to finish the one last thing: I want the toggle to work in a way so that only one layer/button is active at a time. So that when a new button is pushed the other one goes silent.
Probably a pretty simple thing for someone familiar with js. Note that there both tilelayers, tooltips interaction and legends coupled with the buttons.
If someone could lead me in the right direction I'd be so grateful. Code below:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Russian Waterways</title>
<script src='http://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.js'></script>
<link href='http://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
#map-ui {
position: absolute;
top: 15px;
left: 10px;
list-style: none;
margin: 0;
padding: 0;
z-index: 100;
}
#map-ui a {
font: normal 13px/18px 'Helvetica Neue', Helvetica, sans-serif;
background: #FFF;
color: #3C4E5A;
display: block;
margin: 0;
padding: 0;
border: 1px solid #BBB;
border-bottom-width: 0;
min-width: 138px;
padding: 10px;
text-decoration: none;
}
#map-ui a:hover {
background: #ECF5FA;
}
#map-ui li:last-child a {
border-bottom-width: 1px;
-webkit-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
}
#map-ui li:first-child a {
-webkit-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
}
#map-ui a.active {
background: #3887BE;
border-color: #3887BE;
border-top-color: #FFF;
color: #FFF;
}
</style>
<ul id='map-ui'></ul>
<div id='map'></div>
<script type='text/javascript'>
var map = L.mapbox.map('map', 'maxmeles.map-a2km8b40', { zoomControl: false }).setView([56.54, 52.16], 4);
var ui = document.getElementById('map-ui');
addLayer(L.mapbox.tileLayer('maxmeles.Spb-Moscow'), L.mapbox.gridLayer('maxmeles.Spb-Moscow'),'Petersburg-Moscow', 1);
addLayer(L.mapbox.tileLayer('maxmeles.Astrakan-MoscowLegend'), L.mapbox.gridLayer('maxmeles.Astrakan-MoscowLegend'),'Moscow-Astrakhan', 2);
addLayer(L.mapbox.tileLayer('maxmeles.SPB-ASTRAKHANLEGENDRED'), L.mapbox.gridLayer('maxmeles.SPB-ASTRAKHANLEGENDRED'),'Petersburg-Astrakhan', 3);
addLayer(L.mapbox.tileLayer('maxmeles.Perm-MoscowLegend'), L.mapbox.gridLayer('maxmeles.Perm-MoscowLegend'),'Moscow-Perm', 4);
addLayer(L.mapbox.tileLayer('maxmeles.moskvakazan'), L.mapbox.gridLayer('maxmeles.moskvakazan'),'Moscow-Kazan', 5);
addLayer(L.mapbox.tileLayer('maxmeles.DonLegend'), L.mapbox.gridLayer('maxmeles.DonLegend'),'Rostov-Astrakhan', 6);
addLayer(L.mapbox.tileLayer('maxmeles.DneprRed'), L.mapbox.gridLayer('maxmeles.DneprRed'),'Kiev-Odessa', 7);
addLayer(L.mapbox.tileLayer('maxmeles.RedTulceaIstanbul'), L.mapbox.gridLayer('maxmeles.RedTulceaIstanbul'),'Tulcea-Istanbul', 8);
addLayer(L.mapbox.tileLayer('maxmeles.SPB-ROSTOVLEGENDRED'), L.mapbox.gridLayer('maxmeles.SPB-ROSTOVLEGENDRED'),'Rostov-Petersburg', 9);
addLayer(L.mapbox.tileLayer('maxmeles.Rostov-MoscowLegend'), L.mapbox.gridLayer('maxmeles.Rostov-MoscowLegend'),'Rostov-Moscow', 10);
addLayer(L.mapbox.tileLayer('maxmeles.Trans-Siberian'), L.mapbox.gridLayer('maxmeles.Trans-Siberian'),'Trans-Siberian', 11);
function addLayer(layer, gridlayer, name, zIndex) {
layer
.setZIndex(zIndex)
gridlayer
// add the gridControl the active gridlayer
var gridControl = L.mapbox.gridControl(gridlayer, {follow: false}).addTo(map);
// Create a simple layer switcher that toggles layers on and off.
var item = document.createElement('li');
var link = document.createElement('a');
link.href = '#';
link.className = '';
link.innerHTML = name;
link.onclick = function(e) {
e.preventDefault();
e.stopPropagation();
if (map.hasLayer(layer)) {
map.removeLayer(layer);
map.removeLayer(gridlayer);
map.legendControl.removeLegend(layer.getTileJSON().legend);
this.className = '';
} else {
map.addLayer(layer);
map.addLayer(gridlayer);
map.legendControl.addLegend(layer.getTileJSON().legend);
this.className = 'active';
}
};
item.appendChild(link);
ui.appendChild(item);
}
new L.Control.Zoom({ position: 'topright' }).addTo(map);
</script>
</body>
</html>

JavaScript induced style changes are not permanent

Okay, I change the appearance of links using JavaScript. When I change the content of a hard-coded link, it sticks in that the changed color and underlining remains when the cursor is not hovering above it. However, when the content of a DIV has been changed using JavaScript, the style changes do not stick.
Here is the HTML code:
<!doctype html>
<html>
<head>
<title>Bla bla</title>
<meta charset="UTF-8">
<link href="style/kim.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="scripts/Kim.js"></script>
</head>
<body>
<div class="wrapper">
<div class="main">
<div class="nav">
<div class="topNav">
<ul>
<li onClick="changeNav('design')">Design</li>
<li onClick="changeNav('code')">Programming</li>
<li onClick="changeNav('science')">Science</li>
<li onClick="changeNav('Kim')">Kim</li>
</ul>
</div>
<div id="subNav">
<script>changeNav("design");</script>
</div>
</div>
<div class="content">
<p id="mainText">Test</p>
</div>
</div>
</div>
</body>
</html>
Here is the JS code:
var topNavNames = ["design", "code", "science", "Kim"];
var subNavCode = ["<ul><li onClick=\"loadPHP('design/websites.php', 'sub0')\">Websites</li><li onClick=\"loadPHP('design/graphics.php', 'sub1')\">Graphics</li><li onClick=\"loadPHP('design/flash.php', 'sub2')\">Flash</li></ul>",
"<ul><li onClick=\"loadPHP('code/interactive.php', 'sub0')\">Interactive applets</li><li onClick=\"loadPHP('code/statistics.php', 'sub1')\">Statistics</li><li onClick=\"loadPHP('code/wings.php', 'sub2')\">Wings</li><li onClick=\"loadPHP('code/3D.php', 'sub3')\">3D</li></ul>",
"<ul><li onClick=\"loadPHP('science/3D.php', 'sub0')\">3D</li><li onClick=\"loadPHP('science/ssd.php', 'sub1')\">Sexual Size Dimorphism</li><li onClick=\"loadPHP('science/shape.php', 'sub2')\">Wing shape</li><li onClick=\"loadPHP('science/phylogenetics.php', 'sub3')\"><i>Drosophila</i> phylogenetics</li><li onClick=\"loadPHP('science/communitygenetics.php', 'sub4')\">Community Genetics</li><li onClick=\"loadPHP('science/biodiversity.php', 'sub5')\">Biodiversity</li></ul>",
"<ul><li onClick=\"loadPHP('Kim.php', 'sub0')\">Who is Kim?</li><li onClick=\"loadPHP('animals/horses.php', 'sub1')\">Horses</li><li onClick=\"loadPHP('animals/birds.php', 'sub2')\">Birds</li><li onClick=\"loadPHP('private/outdoors.php', 'sub3')\">Outdoors</li><li onClick=\"loadPHP('contact.php', 'sub4')\">Contact</li></ul>"];
function changeNav(target) {
for (var i = 0; i<topNavNames.length; i++) {
if (target == topNavNames[i]) {
document.getElementById("subNav").innerHTML=subNavCode[i];
document.getElementById(topNavNames[i]).style.color="#F7EDAA";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(topNavNames[i]).style.color="#EEE";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #111";
}
}
}
function loadPHP(url, target) {
for (var i = 0; i<10; i++) {
if(document.getElementById(target)!=null) {
if (("sub"+i) == target) {
document.getElementById(target).style.color="#F7EDAA";
document.getElementById(target).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
}
}
}
if I subsequently remove the:
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
from the loadPHP function, it changes the style, but does not reset it when the next link is clicked.
I observed this behavior in FireFox, Internet Exploder and Chrome.
Added: CSS code:
body {
background-color: #111111;
color: #DDD;
font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif;
}
.wrapper {
overflow: auto;
}
.banner {
float: left;
position: relative;
width: 100px;
}
.main {
position: relative;
width: 80%;
left: 25px;
font-size: 14px;
font-weight: normal;
}
a {
text-decoration: none;
color: #EEE;
}
a:hover {
border-bottom: thin solid #F7EDAA !important;
color: #F7EDAA !important;
}
.topNav {
height: 45px;
position: relative;
left: 100px;
font-size: large;
border: thin solid #111;
}
#subNav {
height: 45px;
position: relative;
left: 100px;
top: 2px;
border: thin solid #111;
}
.topNav li, #subNav li {
float: left;
margin: 10px 15px;
}
.topNav ul, #subNav ul {
list-style: none;
padding: 0px 0px;
margin: 0px 0px;
position: relative;
left: -100px;
}
.content {
position: relative;
left: 15px;
padding: 0px 0px;
margin: 0px 0px;
}
.content p {
padding: 5px 5px;
margin: 10px 15px;
left: -100px;
}
In my opinion you´re using the wrong technology to achieve your goal. What you need to do is to write your styles in a css stylesheet, and then add or remove classes to your elements using js if you want. (You can also do this through something called specificity, a little far ahead from the scope of your question)
Also think that if there is some bug in your script, or a third party script called in your page, JS may break and it won´t process your styling changes.
So, add the basic styling to your elements through css in the initial markup, so you will be sure that your elements will have always a basic styling, and then if you want use the equivalent to .addClass or removeClass jQuery methods.
In that way you will be always sure that your frontend will have always a safe styling, won´t break if js is not loaded, and separation of concerns will be properly implemented.
Regards.
I figured it out. The following code does not do the right thing:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]){
document.getElementById(target).className="selected";
} else {
document.getElementById(target).className="notSelected";
}
}
While this code does produce the right result:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]) {
document.getElementById(subNavNames[i]).className="selected";
} else {
document.getElementById(subNavNames[i]).className="notSelected";
}
}
The difference is that in the first example, and in the example of the original question, I use the variable passed on in the method (target), to find the element. In the second, I use the appropriate element from a array that I have added to the list. I am not sure WHY this behaves differently, but it does.

Optimize jQuery code

I've written this jQuery code that fades in a overlay with some links over an image. What i found out is that it is painfully slow when I add like 10 of these images. I would really appreciate some tips and tricks on how to make this code faster.
If you have some tips for my HTML and CSS that would be great too ;)
jQuery code
$(document).ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").hover(
function () {
$(this).children(".download").fadeTo("fast", 1);
$(this).children(".hud").fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
All the code
<style type="text/css">
a:active {
outline:none;
}
:focus {
-moz-outline-style:none;
}
img {
border: none;
}
#backgrounds {
font: 82.5% "Lucida Grande", Lucida, Verdana, sans-serif;
margin: 50px 0 0 0;
padding: 0;
width: 585px;
}
.thumb {
margin: 5px;
position: relative;
float: left;
}
.thumb img {
background: #fff;
border: solid 1px #ccc;
padding: 4px;
}
.thumb div {
display: none;
}
.thumb .download {
color: #fff;
position: absolute;
top: 0;
left: 0;
z-index: 999;
padding: 0 10px;
}
.thumb .download h3 {
font-size: 14px;
margin-bottom: 10px;
margin-top: 13px;
text-align: center;
}
.thumb .download a {
font-size: 11px;
color: #fff;
text-decoration: none;
font-weight: bold;
line-height: 16px;
}
.thumb .download a:hover {
text-decoration: underline;
}
.thumb .download .left, .thumb .download .right {
width: 44%;
margin: 0;
padding: 4px;
}
.thumb .download .left {
float: left;
text-align: right;
}
.thumb .download .right {
float: right;
text-align: left;
}
.thumb img, .thumb .hud {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.thumb .hud {
width: 100%;
height: 110px;
position: absolute;
top: 0;
left: 0;
background: #000;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").hover(
function () {
$(this).children(".download").fadeTo("fast", 1);
$(this).children(".hud").fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
</script>
<div id="backgrounds">
<div class="thumb">
<div class="download">
<h3>Download wallpaper</h3>
<p class="left">
1024x768
1280x800
1280x1024
</p>
<p class="right">
1440x900
1680x1050
1920x1200
</p>
</div>
<div class="hud"></div>
<img alt="image" src="thumb.jpg"/>
</div>
</div>
I got it to respond a little better by simply changing the following within the hover(..):
function () {
$(".download", this).fadeTo("fast", 1);
$(".hud", this).fadeTo("fast", 0.7);
},
function () {
$(".download, .hud", this).fadeTo("fast", 0);
}
The biggest difference comes from only applying the hoverout effect to the event target, no need to reapply to all your divs on the page.
I've put your code into a test page and to be perfectly honest, even with thirty or so .thumb divs it seemed ok - certainly responsive enough to use from my end. Sliding the mouse over a bunch of them means I have to wait for the rollover effect to go through them all which takes a while until it gets to the one I've actually stopped on, but surely that was what you wanted given that you're using 'hover' rather than 'click' (which would certainly remove any speed issues).
I'm not using actual images in my test page, just getting the alt text, so my best current guess would be to make sure all images you're loading are as small filesize as you can possibly make them.
Pre-Select MORE
Good job preselecting the div. Try this way so that it pre-selects the fade in elements as well instead of doing it on hover:
$().ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").each(function() {
var download = $(this).children(".download");
var hud = $(this).children(".hud");
$(this).hover(
function () {
download.fadeTo("fast", 1);
hud.fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
});
try removing the
:focus {
-moz-outline-style:none;
}
and see what happens

Categories