I am using django 1.10.5, booststrap 4.0 and LeafletJs 1.0.3 with routing machine plugin and geocoder.
Now I have the following problem, the collapse button of the control pannel for routing machine is not loading (its not showing up in the html code) when the map is bigger than 640 x 640px when the page is loaded the first time.
there are no problems when I make the map bigger with chrome dev tools after the page is fully loaded with the map size set in css to 640x640px or smaller.
I have a version of that works the way it should, but this is without django and bootstrap and I need it to work with both.
css code
.map-add-size{
position: relative;
width: 500px;
height:500px;
}
.html
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block css %}
<link href="{% static 'routes/css/add.css' %}" rel="stylesheet">
{{block.super}}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css">
<link href="{% static 'routes/css/leaflet-routing-machine.css' %}" rel="stylesheet" >
<link href="{% static 'routes/css/Control.Geocoder.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<h3>Add a new route</h3>
<div class="row">
<div class="route-edit">
<div class="col-xs-6">
<p>Route page information</p>
<form id="mainForm" method="post" class="form">
{% csrf_token %}
{{ routeAddForm|crispy }}
<div class="row route-edit">
<button type="submit" name="save_route" class="btn btn-primary">Save and continue</button>
</div>
</form>
</div>
</div>
</div>
<div class ="row">
<div class="cols-xs-8 map-container-div">
<p>Add start and end markers by left clicking on the map. <br>
Add markers by clicking on the lines inbetween the start and end markers<br>
Remove markers by clicking on the cross next to the address of the marker.
</p>
</div>
</div>
<div id="map-add" class="map-add-size"></div>
{% endblock %}
{%block javascript %}
{{block.super}}
<script src="{% static 'routes/js/cookie.js' %}"></script>
<script>
var csrftoken = Cookies.get('csrftoken');
</script>
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet.js"></script>
<script src="{% static 'routes/js/leaflet-routing-machine.js' %}"></script>
<script src="{% static 'routes/js/Control.Geocoder.js' %}"></script>
<script src="{% static 'routes/js/map-add.js' %}"></script>
{%endblock%}
javascript
window.lrmConfig = {
// serviceUrl: 'https://api.mapbox.com/directions/v5',
// profile: 'mapbox/driving',
};
var map = L.map('map-add').setView([51.505, -0.09], 3);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}{r}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var geocoder = L.Control.Geocoder.mapzen('search-DopSHJw'),
control2 = L.Control.geocoder({
geocoder: geocoder,
defaultMarkGeocode: false
}).on('markgeocode', function(e){
var bbox = e.geocode.bbox;
var poly = L.polygon([
bbox.getSouthEast(),
bbox.getNorthEast(),
bbox.getNorthWest(),
bbox.getSouthWest()
]).addTo(map);
map.fitBounds(poly.getBounds());
}).addTo(map);
control = L.Routing.control(L.extend(window.lrmConfig, {
geocoder: L.Control.Geocoder.nominatim(),
routeWhileDragging: true,
reverseWaypoints: true,
showAlternatives: true,
altLineOptions: {
styles: [
{color: 'black', opacity: 0.15, weight: 9},
{color: 'white', opacity: 0.8, weight: 6},
{color: 'blue', opacity: 0.5, weight: 2}
]
},
})).addTo(map);
L.Routing.errorControl(control).addTo(map);
function createButton(label, container) {
var btn = L.DomUtil.create('button', '', container);
btn.setAttribute('type', 'button');
btn.innerHTML = label;
return btn;
}
map.on('click', function(e) {
var container = L.DomUtil.create('div'),
startBtn = createButton('Start from this location', container),
destBtn = createButton('Go to this location', container);
var removeContainer = L.DomUtil.create('div'),
removeBtn = createButton('Remove waypoint',removeContainer);
L.popup()
.setContent(container)
.setLatLng(e.latlng)
.openOn(map);
L.DomEvent.on(startBtn, 'click', function() {
control.spliceWaypoints(0, 1, e.latlng);
map.closePopup();
});
L.DomEvent.on(destBtn, 'click', function() {
control.spliceWaypoints(control.getWaypoints().length - 1, 1, e.latlng);
map.closePopup();
});
});
// Submit post on submit
$('#mainForm').on('submit', function(event){
event.preventDefault();
console.log("form submitted!"); // sanity check
postData();
});
var successText;
function postData(){
console.log("postData is working!");// sanity check
var formData = $("#mainForm").serializeArray();
var routeArray =Array(),
routeArray = control.getWaypoints();
var json_obj = JSON.stringify(routeArray);
formData.push({name:'json_data',value:json_obj});
console.log("form data that is send")
console.log(formData);
$.post({
type: 'POST',
url: '/routes/add/',
data: formData,
});
}
I found a way to make it work for sizes bigger than 640px. I am unsure if this is the correct way to fix it, but it works for now.
in leaflet-routing-machine.js changed 640 to 1200 in this line and now the button works for maps that are bigger than 640px.
collapsible = collapsible || (collapsible === undefined && map.getSize().x <= 1200);
Related
In my web site I want to show the user ratings - for that I used the infinite scroll but I am facing one problem.
When it first loads the data before calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is showing the star with the count of vote,but when after calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is not showing the star.
my views.py
#login_required
def ratings_user(request,pk):
ratings = VoteUser.objects.filter(the_user_id=pk).order_by('-pk')
paginator = Paginator(ratings, 1)
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request,request.session['is_mobile']+'profile/ratings.html',{'ratings':posts})
html
{% extends 'mobile/profile/base.html' %}
{% block title %}
Ratings
{% endblock %}
{% block leftcontent %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet">
{% endblock %}
{% block middlecontent %}
<div class="infinite-container">
{% for i in ratings %}
<div class="infinite-item">
<div class="w3-container w3-card w3-white w3-round w3-margin">
<img src="{{ i.the_user.profile.avatar.url }}" alt="Avatar" class="w3-left w3-circle w3-margin-right" style="width:40px;height:40px;border-radius:50%;">
{% with user=i.the_user.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}
<br>
<span class="stars" data-rating="{{ i.vote.vote }}" data-num-stars="5" ></span>
<hr class="w3-clear">
<p>
{{ i.commentaire|linebreaksbr }}
</p>
<span class="glyphicon glyphicon-user"></span> {% with user=i.the_sender.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}
</div>
</div>
{% endfor %}
</div>
{% if ratings.has_next %}
<a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a>
{% endif %}
{% endblock %}
{% block rightcontent %}
{% endblock %}
{% block js %}
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0]
});
</script>
<script>
//ES5
$.fn.stars = function() {
return $(this).each(function() {
var rating = $(this).data("rating");
var fullStar = new Array(Math.floor(rating + 1)).join('<i class="fas fa-star"></i>');
var halfStar = ((rating%1) !== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
var noStar = new Array(Math.floor($(this).data("numStars") + 1 - rating)).join('<i class="far fa-star"></i>');
$(this).html(fullStar + halfStar + noStar);
});
}
//ES6
$.fn.stars = function() {
return $(this).each(function() {
const rating = $(this).data("rating");
const numStars = $(this).data("numStars");
const fullStar = '<i class="fas fa-star"></i>'.repeat(Math.floor(rating));
const halfStar = (rating%1!== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
const noStar = '<i class="far fa-star"></i>'.repeat(Math.floor(numStars-rating));
$(this).html(`${fullStar}${halfStar}${noStar}`);
});
}
</script>
<script>
$(function(){
$('.stars').stars();
});
</script>
{% endblock %}
I have tried to put the <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet"> inside the class="infinite-item" but it does not help.what might be the reason for that ? Thanks.
Since yesterday I am on this question I tried everything.
This is another user that has tried to help me here https://stackoverflow.com/a/69930878/15042684 but I did not really understand could you please help me to understand it with some code.
this is his answer:
It doesn't look like .stars() will look for new elements being added to the DOM. You should look for a callback function configuration option within Waypoint.Infinite that you can call .stars() on the new elements.
Assuming you are using waypoint's Infinite Scroll, you can use the onAfterPageLoad callback
onAfterPageLoad
Default: $.noop.
Parameters: $items.
This is a callback that will fire at the end of the request cycle, after new items have been appended to the container. It is passed one parameter, which is a jQuery object of all the items that were appended during the page load.
Note that despite using the jquery convention of $name indicates a jquery object and stating is a jquery object, in this case, trial and error shows that $items are the DOM elements, not a jquery object.
No example provided in the docs, so it will probably look something like:
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
onAfterPageLoad: function(items) {
$(items).find(".stars").stars();
}
});
</script>
I just made a carousel using splide and I just made it in the way I want. There is only one detail left and it doesn't work. I don't want to show the main slider at the beginning and begin to show it only when the user click on any thumbnail. I implemented it this way:
#main-slider{
display:none;
}
and then
thumbnails.on('click', function(){
document.getElementById('main-slider').style.display = "block";
})
But the main slider only get partially visible. That is, only pagination and arrows will display. No way to show everything, especially the image.
Here's the entire code:
{% load static %}
{% comment %} If you want to fully customize the slider appearance, pick the splide-core.min.css file that does not include arrows, pagination and progress bar styles, which reduces unnecessary "override" works. {% endcomment %}
<link href="{% static 'js/splide-3.2.1/dist/css/splide.min.css' %}" rel="stylesheet">
<style>
.splide__slide {
/* opacity of the thumbnails */
opacity: .6;
}
.splide__slide.is-active {
/* opacity of the selected thumbnail */
opacity: 1;
}
#main-slider{
display:none;
}
</style>
<div class="splide">
<div id="main-slider" class="splide">
<div class="splide__track">
<ul class="splide__list">
{% for image in images %}
<li class="splide__slide">
<img src="{{ image.image.url }}" />
</li>
{% endfor %}
</ul>
</div>
</div>
<div id="thumbnail-slider" class="splide">
<div class="splide__track">
<ul class="splide__list">
{% for image in images %}
<li class="splide__slide">
{% comment %} data-splide-lazy must be enabled for lazy load {% endcomment %}
<img src="{{ image.image.url }}" data-splide-lazy="{{ image.image.url }}">
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
<script>
document.addEventListener( 'DOMContentLoaded', function () {
var main = new Splide( '#main-slider', {
type : 'slide',
heightRatio: 0.5,
speed :500,
pagination : true,
arrows : true,
cover : true,
} );
var thumbnails = new Splide( '#thumbnail-slider', {
fixedWidth : 100,
fixedHeight : 60,
gap : 10,
perMove : 1,
perPage : 1,
rewind : true,
pagination : false,
cover : true,
isNavigation: true,
lazyLoad : false,
keyboard : true,
wheel : true,
focus : 'center',
dragMinThreshold: {
mouse: 4,
touch: 10,
},
breakpoints : {
600: {
fixedWidth : 60,
fixedHeight: 44,
},
},
} );
main.sync( thumbnails );
main.mount();
thumbnails.mount();
thumbnails.on('click', function(){
document.getElementById('main-slider').style.display = "block";
})
} );
</script>
<script src="{% static 'js/splide-3.2.1/dist/js/splide.min.js' %}"></script>
I am trying to print the contents of a specific div with a class called "container" which has a number of divs having their individual classes. The problem I am facing is that when I click the print button the print preview shows the contents to be printed in completely plain format, no css styles applied. But I want the contents to be exactly the way it is being displayed in the browser. I have tried a number of ways and solutions from here but nothing seems to work. Please suggest me some way to do it. I was trying to do it with javascript. The javascript code given below is cpied as I said I was trying out all the possible ways.
javascript
$(function () {
$("#btnPrint").click(function () {
var contents = $("#content").html();
var frame1 = $('<iframe />');
frame1[0].name = "frame1";
frame1.css({ "position": "absolute", "top": "-1000000px" });
$("body").append(frame1);
var frameDoc = frame1[0].contentWindow ? frame1[0].contentWindow : frame1[0].contentDocument.document ? frame1[0].contentDocument.document : frame1[0].contentDocument;
frameDoc.document.open();
//Create a new HTML document.
frameDoc.document.write('<html><head><title>DIV Contents</title>');
frameDoc.document.write('</head><body>');
//Append the external CSS file.
frameDoc.document.write('<link href="C:\Users\Intel\Envs\test\project\static\doc.css" rel="stylesheet" type="text/css" />');
//Append the DIV contents.
frameDoc.document.write(contents);
frameDoc.document.write('</body></html>');
frameDoc.document.close();
setTimeout(function () {
window.frames["frame1"].focus();
window.frames["frame1"].print();
frame1.remove();
}, 500);
});
});
The below images are the way it is being displayed in the browser and the way it is displayed in the preview
This is how i want it to get it printed
and this is how it getting printed]2
html file
<link rel="stylesheet" href="{% static 'doc.css' %}" media="all"/>
<div class="main-container">
<div class="container" id="content">
{% if object.reportable %}
<div class="report">
<p>Reportable </p>
</div>
{% endif %}
{% if object.non_reportable %}
<div class="report">
<p>Non-Reportable </p>
</div>
{% endif %}
{% if object.over_ruled %}
<div class="over">
<p>Over Ruled </p>
</div>
{% endif %}
{% if object.equivalent_citations %}
<div class="cit">
<p><b>Equivalent Citations:</b> {{object.equivalent_citations}}</p>
</div>
{% endif %}
<div class="crt">
<p><b>In The {{object.court_type}}</b></p>
</div>
<div class="appeal">
<p><b>{{object.apelLate_type}}</b></p>
</div>
<div class="jdge">
<p> <b>Before:</b> {{object.judge_name}}</p>
</div>
<div class="party-name">
<p> <b> {{object.party_name}} </b> </p>
</div>
<div class="case-no">
<p><b>Case No.:</b> {{object.case_no}} </p>
</div>
...
<div class="container-2">
<input type="button" id="btnPrint" value="Print" />
</div>
</div>
Consider the following example: https://jsfiddle.net/Twisty/aspehr0m/7/
JavaScript
$(function() {
$("#btnPrint").click(function() {
var contents = $("#content").html();
var frame1 = $('<iframe>', {
id: "frame1",
name: "frame1"
})
.css({
"position": "absolute",
"top": "-1000000px"
})
.appendTo($("body"));
var myHTML = $("<html>");
$("<head>").appendTo(myHTML);
$("<title>").html("DIV Contents").appendTo($("head", myHTML));
$("<body>").appendTo(myHTML);
$("body > link").clone().appendTo($("body", myHTML));
$("body", myHTML).append(contents);
console.log("Content", myHTML.prop("outerHTML"));
var frameDoc = window.frames.frame1;
frameDoc.document.open();
//Create a new HTML document.
frameDoc.document.write(myHTML.prop("outerHTML"));
frameDoc.document.close();
setTimeout(function() {
frame1.focus();
window.frames.frame1.print();
frame1.remove();
}, 500);
});
});
Here you can use .clone() to make a copy of the existing Stylesheet Link. this will ensure it uses the same as the primary page.
It is consider a better practice not to mix JavaScript and jQuery, to stick to one or the other. In this case, it's a bit easier to to manage the iFrame element with native JavaScript.
Update
You might consider making a new Function: https://jsfiddle.net/Twisty/aspehr0m/38/
JavaScript
$(function() {
$.fn.printContent = function() {
var target = $(this);
var title;
if (target.attr("title") != undefined) {
title = target.attr("title");
} else {
title = "Element Contents"
}
var uid = Date.now();
var printFrame = $("<iframe>", {
id: "printFrame_" + uid,
name: "printFrame_" + uid
}).css({
position: "absolute",
top: "-1000000px"
}).appendTo($("body"));
var frameHTML = $("<html>");
$("<head>").appendTo(frameHTML);
$("<title>").html(title).appendTo($("head", frameHTML));
$("<body>").appendTo(frameHTML);
if ($("body > link").length == 1) {
$("body > link").clone().appendTo($("body", frameHTML));
}
$("body", frameHTML).append(target.html());
var winFrame = window.frames['printFrame_' + uid];
winFrame.document.open();
winFrame.document.write(frameHTML.prop("outerHTML"));
winFrame.document.close();
setTimeout(function() {
printFrame.focus();
winFrame.print();
printFrame.remove();
}, 100);
};
$("#btnPrint").click(function() {
$("#content").printContent();
});
});
Use an URL or accessible path instead of:
C:\Users\Intel\Envs\test\project\static\doc.css" rel="stylesheet" type="text/css" />
By the way, The javascript seems to be ok, your page wouldn't show content if it were misspelled
I created a project in Django. I need charts in my project.
I use chart.js library and Json.
I use an API for take values. In the API page there are 5 objects.Every object has title, value1 and value2.
When I create a table it works. I can get values but I cannot display values in charts. How can I create several charts with a loop?
views.py
def Jdeneme(request):
response = requests.get('https://api....t')
data = response.json()
return render(request, 'charts.html', {'data': data})
charts.html
{% extends "layouts/base.html" %}
{% load static %}
{% block content %}
<div class="content">
<div class="page-inner">
<h4 class="page-title">Chart.js</h4>
<div class="page-category"></div>
{% for dt in data %}
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<div class="card-title">{{ dt.title }} Doughnut Chart</div>
</div>
<div class="card-body">
<div class="chart-container">
<canvas id="doughnutChart" style="width: 50%; height: 50%"></canvas>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock content %}
{% block javascripts %}
<script>
doughnutChart = document.getElementById('doughnutChart').getContext('2d');
var myDoughnutChart = new Chart(doughnutChart, {
type: 'doughnut',
data: {
datasets: [
{
data: [ {{ dt.value1 }}, {{ dt.value2 }} ],
backgroundColor: ['#e95bda','#4bbffd']
}
],
labels: [
'value 1',
'value 2'
]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend : {
position: 'bottom'
},
layout: {
padding: {
left: 20,
right: 20,
top: 20,
bottom: 20
}
}
}
});
// Chart with HTML Legends
var gradientStroke = htmlLegendsChart.createLinearGradient(500, 0, 100, 0);
gradientStroke.addColorStop(0, '#177dff');
gradientStroke.addColorStop(...
var myHtmlLegendsChart = new Chart(htmlLegendsChart, {
...
var myLegendContainer = document.getElementById("myChartLegend");
// generate HTML legend
myLegendContainer.innerHTML = myHtmlLegendsChart.generateLegend();
...
}
</script>
{% endblock javascripts %}
You are referencing the (template) for-loop variable dt outside of the for loop.
You are also giving all the created canvases the same fixed id.
You are only building one Chart in your javascript code.
Try changing your code like this:
{% extends "layouts/base.html" %}
{% load static %}
{% block content %}
<div class="content">
<div class="page-inner">
<h4 class="page-title">Chart.js</h4>
<div class="page-category"></div>
{% for dt in data %}
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<div class="card-title">{{ dt.title }} Doughnut Chart</div>
</div>
<div class="card-body">
<div class="chart-container">
<canvas id="doughnutChart{{ forloop.counter }}" style="width: 50%; height: 50%"></canvas> {# CHANGE THIS #}
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock content %}
{% block javascripts %}
<script>
{% for dt in data %} {# ADD THIS #}
doughnutChart = document.getElementById('doughnutChart{{ forloop.counter }}').getContext('2d'); {# CHANGE THIS #}
var myDoughnutChart{{ forloop.counter }} = new Chart(doughnutChart, { {# CHANGE THIS #}
type: 'doughnut',
data: {
datasets: [
{
data: [ {{ dt.value1 }}, {{ dt.value2 }} ],
backgroundColor: ['#e95bda','#4bbffd']
}
],
labels: [
'value 1',
'value 2'
]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend : {
position: 'bottom'
},
layout: {
padding: {
left: 20,
right: 20,
top: 20,
bottom: 20
}
}
}
});
{% endfor %} {# ADD THIS #}
// Chart with HTML Legends
var gradientStroke = htmlLegendsChart.createLinearGradient(500, 0, 100, 0);
gradientStroke.addColorStop(0, '#177dff');
gradientStroke.addColorStop(...
var myHtmlLegendsChart = new Chart(htmlLegendsChart, {
...
var myLegendContainer = document.getElementById("myChartLegend");
// generate HTML legend
myLegendContainer.innerHTML = myHtmlLegendsChart.generateLegend();
...
}
</script>
{% endblock javascripts %}
By the way, this is just to make your code work the way you are writing it, but it is debatable whether it's a good idea to dynamically generate Javascript code via Django templates.
I am using jqvmap to show a map series (ifthq.com scroll low left). On the USA map, I have two states with values: LA and OH, both equal to 1.
The JSON used to feed jqvmap is: {"OH":1,"LA":1}.
The map shows, but does not fill correctly. My assumption is that linear normalizeFunction would result in two states at max, and the rest at min. This is not the case.
Since the US Map is over 50 elements, and the data is only two, how do I set "default" data to zero in the jqvmap? In other words, undefined states would be equal to zero?
Thanks.
UPDATE #1: Code for question:
View definition. mbrmap is the result of the data pull:
#login_required
def index_view(request):
enlisted = models.Subscription.objects.rankset("E").active().count()
officer = models.Subscription.objects.rankset("O").active().count()
civilian = models.Subscription.objects.rankset("C").active().count()
lifer = models.Subscription.objects.lifer().active().count()
subscriptions = models.Subscription.objects.all().order_by("-Modified")
mbrcnt = models.Member.objects.values('State').annotate(c=Count('State')).exclude(State='')
mbrcnt2 = models.Member.objects.values('Country').annotate(c=Count('Country')).exclude(Country='')
mbrmap = dict([(type_and_count['State'], type_and_count['c']) for type_and_count in mbrcnt])
mbrmap2 = dict([(type_and_count['Country'], type_and_count['c']) for type_and_count in mbrcnt2])
mbrmap.update(mbrmap2)
units = models.Unit.objects.values('Unit_name', 'Hull_type', 'Hull_number').annotate(c=Count('memberunit__Member'))
context = {'mbrmap': mbrmap, 'enlisted': enlisted, 'officer': officer, 'civilian': civilian, 'lifer': lifer, 'units': units, 'Subscriptions': subscriptions}
return render(request, 'index.html', context)
html:
<div class="portlet-body">
<div id="region_statistics_loading">
<img src="{% static "img/loading.gif" %}" alt="loading"/>
</div>
<div id="region_statistics_content" class="display-none">
<div class="btn-toolbar margin-bottom-10">
<div class="btn-group btn-group-circle" data-toggle="buttons">
<a href="" class="btn grey-salsa btn-sm active">
Members </a>
<a href="" class="btn grey-salsa btn-sm">
Units </a>
</div>
<div class="btn-group pull-right">
<a href="" class="btn btn-circle grey-salsa btn-sm dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
Select Region <span class="fa fa-angle-down">
</span>
</a>
<ul class="dropdown-menu pull-right">
<li>
<a href="javascript:;" id="regional_stat_world">
World </a>
</li>
<li>
<a href="javascript:;" id="regional_stat_usa">
USA </a>
</li>
{% comment %}<li>
<a href="javascript:;" id="regional_stat_europe">
Europe </a>
</li>
<li>
<a href="javascript:;" id="regional_stat_russia">
Russia </a>
</li>
<li>
<a href="javascript:;" id="regional_stat_germany">
Germany </a>
</li>{% endcomment %}
</ul>
</div>
</div>
<div id="vmap_world" class="vmaps display-none">
</div>
<div id="vmap_usa" class="vmaps display-none">
</div>
{% comment %}<div id="vmap_europe" class="vmaps display-none">
</div>
<div id="vmap_russia" class="vmaps display-none">
</div>
<div id="vmap_germany" class="vmaps display-none">
</div>{% endcomment %}
</div>
</div>
<!-- PAGE LEVEL SPELLS -->
{% block PageSpells %}
<!-- PLUGINS -->
<script src="{% static "plugins/jqvmap/jqvmap/jquery.vmap.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.russia.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.world.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.europe.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.germany.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.usa.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/jqvmap/jqvmap/data/jquery.vmap.sampledata.js" %}" type="text/javascript"></script>
<!-- SPELLS -->
<script src="{% static "js/index.js" %}" type="text/javascript"></script>
<script src="{% static "plugins/uniform/jquery.uniform.min.js" %}" type="text/javascript"></script>
{% endblock %}
<!-- PAGE JQUERY -->
{% block Jquery %}
var mapdata = {{ mbrmap|safe }};
Index.init();
Index.initCmdSelect();
Index.initJQVMAP(mapdata); // init index page's custom scripts
{% endblock %}
javascript code:
initJQVMAP: function (mapdata) {
if (!jQuery().vectorMap) {
return;
}
var showMap = function (name) {
jQuery('.vmaps').hide();
jQuery('#vmap_' + name).show();
}
var setMap = function (name) {
var data = {
map: 'world_en',
backgroundColor: null,
borderColor: '#333333',
borderOpacity: 0.5,
borderWidth: 1,
color: '#c6c6c6',
enableZoom: true,
hoverColor: '#c9dfaf',
hoverOpacity: null,
values: mapdata,
normalizeFunction: 'linear',
scaleColors: ['#C8EEFF', '#0071A4'],
selectedColor: '#c9dfaf',
selectedRegion: null,
showTooltip: true,
onLabelShow: function (event, label, code) {
},
onRegionOver: function (event, code) {
if (code == 'ca') {
event.preventDefault();
}
},
onRegionClick: function (element, code, region) {
if (typeof mapdata[code.toUpperCase()] === 'undefined') {
var sval = 0;
} else {
var sval = mapdata[code.toUpperCase()]
}
var message = 'You clicked "' + region + '" which has the code: ' + code.toUpperCase() + ' and value: ' + sval;
alert(message);
}
};
data.map = name + '_en';
var map = jQuery('#vmap_' + name);
if (!map) {
return;
}
map.width(map.parent().parent().width());
map.show();
map.vectorMap(data);
map.hide();
}
setMap("world");
setMap("usa");
//setMap("europe");
//setMap("russia");
//setMap("germany");
showMap("world");
jQuery('#regional_stat_world').click(function () {
showMap("world");
});
jQuery('#regional_stat_usa').click(function () {
showMap("usa");
});
jQuery('#regional_stat_europe').click(function () {
showMap("europe");
});
jQuery('#regional_stat_russia').click(function () {
showMap("russia");
});
jQuery('#regional_stat_germany').click(function () {
showMap("germany");
});
$('#region_statistics_loading').hide();
$('#region_statistics_content').show();
},
Of note, the initJQVMAP function is a method in the index object:
var Index = function() {....
It is initialized by the Index.initJQVMAP(mapdata); function call. Thanks.
You could try changing the colors after creating the map:
var newData = {};
for (var key in mapdata)
newData[key.toLowerCase()] = '#0071A4';
map.vectorMap('set', 'colors', newData);
Here there is a working sample.
Edit
I've also found this different solution:
var arrStates = [];
for (var key in mapdata)
arrStates.push(key);
map.vectorMap('set', 'colors', arrStates, '#0071A4');
You can use $.extend() to combine two objects, overwriting the values of one if they exist in the other (documentation here). For example:
var mySmallData = {
"OH": 1,
"LA": 1
};
var DEFAULTS = {
"OH": 0,
"LA": 0,
"WA": 0,
"ID": 0,
// etc.
};
var fullData = $.extend({}, DEFAULTS, mySmallData);
fullData would now contain:
{
"OH": 1,
"LA": 1,
"WA": 0,
"ID": 0
}
This way, you have one object that has all of your defaults and you never have to mess with it. Your sparse object can have as few data points as you want, and it will always get expanded to the full set of states.