How to set jQuery variable as a django template variable - javascript

I'm using a jQuery script inside of a Django template in order to render a Google Map. The goal is to plot multiple markers on the map. I've tried two things:
Set the jQuery var to a Django template variable, which I defined as a list in views.py. Was not able to produce any markers in this case. Just a blank map.
var markers = {{ marker_list }};
I printed marker_list on the page to confirm, which was this in my last test: marker_list = [['Chiang Mai Park', 21.0333, 21.0333], ['Ho Chi Minh Mausoleum', 21.036666667, 21.036666667]]
Make a for loop with template tags inside the jQuery script, and build the list with template variables. With this, only one marker will plot, even if there are multiple locations in the list (see marker_list above).
{% for instance in queryset %}
var markers = [
[{{ instance.place_id }}, {{ instance.place_lat }}, {{ instance.place_long }}]
];
{% endfor %}
Full code is below showing attempt #2. Note that "var markers" in the javascript requires a list of a lists. i.e. var markers = [[name1, latitude1, longitude1], [name2, latitude2, longitude2]].
Any help would be much appreciated. I'm both a Django and Javascript n00b.
views.py
def places_map(request):
if request.user.is_authenticated():
queryset = AddLink.objects.filter(user=request.user)
marker_list = []
for instance in queryset:
name = str(instance.location)
latitude = float(instance.place_lat)
longitude = float(instance.place_lat)
marker_list += [[name, latitude, longitude]]
context = {
"queryset": queryset,
"marker_list": marker_list
}
return render(request, "places_map.html", context)
else:
raise Http404("You must be logged in to view places.")
places_map.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load staticfiles %}
<style>
{% block style %}
#map_wrapper {
height: 400px;
}
#map_canvas {
width: 100%;
height: 100%;
}
{% endblock style %}
</style>
{% block content %}
<div class='row' align='center'>
<h1 id="places-title">Map</h1>
{% if queryset %}
<!-- removed -->
{% endif %}
</div>
<div id="map_wrapper">
<div id="map_canvas" class="mapping"></div>
</div>
<!-- For testing -->
{{ marker_list }}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
// Script from http://wrightshq.com/playground/placing-multiple-markers-on-a-google-map-using-api-3/
jQuery(function($) {
// Asynchronously Load the map API
var script = document.createElement('script');
script.src = "http://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize";
document.body.appendChild(script);
});
function initialize() {
var map;
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
mapTypeId: 'roadmap'
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
map.setTilt(45);
// Multiple Markers
{% for instance in queryset %}
var markers = [
// ['London Eye, London', 51.503454,-0.119562],
// ['Palace of Westminster, London', 51.499633,-0.124755],
// ['Ministry of Sound', 51.498231,-0.118468],
[{{ instance.place_id }}, {{ instance.place_lat }}, {{ instance.place_long }}]
];
{% endfor %}
// Info Window Content
var infoWindowContent = [
['<div class="info_content">' +
'<h3>London Eye</h3>' +
'<p>The London Eye is a giant...</p>' + '</div>'],
['<div class="info_content">' +
'<h3>Palace of Westminster</h3>' +
'<p>The Palace of Westminster is the...</p>' +
'</div>'],
['<div class="info_content">' +
'<h3>Ministry of Sound</h3>' +
'<p>Nice place.</p>' +
'</div>']
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow(), marker, i;
// Loop through our array of markers & place each one on the map
for( i = 0; i < markers.length; i++ ) {
var position = new google.maps.LatLng(markers[i][1], markers[i][2], markers[i][3]);
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0]
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infoWindow.setContent(infoWindowContent[i][0]);
infoWindow.open(map, marker);
}
})(marker, i));
// Automatically center the map fitting all markers on the screen
map.fitBounds(bounds);
}
// Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
this.setZoom(14);
google.maps.event.removeListener(boundsListener);
});
}
</script>
{% endblock content %}

You should use JSON for this.
context = {
"queryset": queryset,
"marker_list": json.dumps(marker_list)
}
and in your template, use the safe filter so Django doesn't escape the symbols:
var markers = {{ marker_list|safe }}

By doing {{ marker_list }} you just end up with a string which is obviously no good, the solution I normally go with is to define a blank array and then append to it
var markers = [];
{% for instance in queryset %}
markers.append([{{ instance.place_id }}, {{ instance.place_lat }}, {{ instance.place_long }}]);
{% endfor %}
Of course you could just close the array after the for loop, this can produce a jslint error although it should work just as well.
var markers = [
{% for instance in queryset %}
[{{ instance.place_id }}, {{ instance.place_lat }}, {{ instance.place_long }}],
{% endfor %}
];

Related

How can I assign a JS function to a list of tag that are generate with a loop?

I have a loop in my twig file :
{% for item in listItem %}
<h2 class="title" id="name-id"> ID {{ item.getRobotName() }}</h2>
<p id="latbot" data-lat="lat">{{ item.geteLat() }}</p>
<p id="lonbot" data-lon="lon">{{ item.getLon() }}</p>
{% endfor %}
In my Javascript file I have:
let h2 = document.getElementById("name-id");
h2.addEventListener("click", link);
function link() {
document.getElementById("name-id");
let thisLat = document.getElementById('latbot').getAttribute('data-lat');
console.log(thisLat);
let thisLon = document.getElementById('lonbot').getAttribute('data-lon')
console.log(thisLon);
let notifyIcon = L.divIcon({
className: 'notify-icon',
iconSize: [25, 25],
html: '<span></span>'
});
map.panTo([thisLat, thisLon]);
L.marker([thisLat,thisLon], {icon: notifyIcon}).addTo(map);
}
linkToMarker();
I would like to assign a JS function to all the h2 that are generate with this for loop. How can I do that ?
Only the first item is connected to the JS function but not the others
Thank you.

how to get values from views.py and use it in Javascript tag

This is my views.py
def list_note(request):
note_info = Note.objects.filter(id_teacher__exact=request.user.id).select_related()
actual_date = date.today()
for notes in note_info:
note_date = notes.remind.date()
tmp = actual_date + timedelta(days=3)
note_expired_list = []
if tmp == note_date:
print()
else:
note_expired_list.append(notes)
print(note_expired_list)
note_data = {
"note_details": note_info,
"note_expired_list_details": note_expired_list,
}
return render_to_response('list_note.html', note_data, context_instance=RequestContext(request))
I want use value note_expired_list_details in <scrpit> tag to display this in alert. How do this?
I try use {{ note_expired_list_details}} but in <script> tag not work.
This is a part of my templates (I try finding HTML element by Id in JS)
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
<div >
{% for details in note_expired_list_details %}
<p>{{ details }}</p>
{% endfor %}
<script>
var x = document.getElementsByTagName("p");
alert("Test\n" + x[1].childNodes.nodeValue + "\n");
</script>
</div>
{% endblock %}
Why not store value of {{ note_expired_list_details }} in a JS variable and then use it however you want?
<script>
var expiredList = '{{ note_expired_list_details }}';
alert(expiredList);
</script>

How do I correctly load a specific jQuery script

I've been given a script by my e-commerce provider that will allow me to dynamically change the stock levels based on the product option selected by the user from a simple select element.
While the code seems strait forward, it will not run properly. As I am fairly new to jQuery, I'm assuming this is due to me not properly initializing the script within my html. The code itself is a default code that my e-commerce provider hands out, but does not support it in any way.
Here is the script
<script>
// <![CDATA[
var selectCallback = function(variant, selector) {
if (variant) {
if (variant.available) {
// Selected a valid variant that is available.
$('#add-to-cart').removeClass('disabled').removeAttr('disabled').val('Add to Cart').fadeTo(200,1);
} else {
// Variant is sold out.
$('#add-to-cart').val('Sold Out').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
}
// Whether the variant is in stock or not, we can update the price and compare at price.
if ( variant.compare_at_price > variant.price ) {
$('#product_price').html('<span class="product-price on-sale">'+ Shopify.formatMoney(variant.price, "") +'</span>'+' <s class="product-compare-price">'+Shopify.formatMoney(variant.compare_at_price, "")+ '</s>');
} else {
$('#product_price').html('<span class="product-price">'+ Shopify.formatMoney(variant.price, "") + '</span>' );
}
} else {
// variant doesn't exist.
$('#add-to-cart').val('Unavailable').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
}
}
// initialize multi selector for product
jQuery(function($) {
new Shopify.OptionSelectors("product-select", { product: , onVariantSelected: selectCallback });
});
// ]]>
</script>
Any ideas on why this might not be working? You can see this script live on my site:
http://www.yandasmusic.com/products/fender-american-standard-stratocaster?variant=1178632565
EDIT:
Upon further inspection, I have found a second piece of code that also calls up the product option selection box. I can tell that this code also serves the function of changing the currently shown product image based on the current option selected:
<script>
var selectCallback = function(variant, selector) {
if (variant && variant.available) {
jQuery('#add-to-cart').removeAttr('disabled').removeClass('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
if(variant.price < variant.compare_at_price){
jQuery('#product_price .price').html('<span class="money">' + Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span><span class="money compare-at-price">' + Shopify.formatMoney(variant.compare_at_price, "{{ shop.money_format }}") + '</span>');
} else {
jQuery('#product_price .price').html('<span class="money">' + Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span>');
}
} else {
jQuery('#add-to-cart').addClass('disabled').attr('disabled', 'disabled'); // set add-to-cart button to unavailable class and disable button
var message = variant ? "Sold Out" : "Unavailable";
jQuery('#product_price .price').text(message);
}
// if (variant && variant.featured_image) {
// var originalImage = $(".zoomWrapper img");
// var newImage = variant.featured_image;
// var element = originalImage[0];
// Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
// $(element).parents('a').attr('href', newImageSizedSrc);
// $(element).attr('src', newImageSizedSrc);
// });
// };
if (variant && variant.featured_image) {
var originalImage = $("#elevatezoom_big");
var newImage = variant.featured_image;
var element = originalImage[0];
Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
$(element).attr('src', newImageSizedSrc);
$("#elevatezoom_gallery a").each(function(){
if ( $(this).attr('data-zoom-image') == newImageSizedSrc ) {
$(this).trigger('click')
};
});
});
};
};
jQuery(document).ready(function($){
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true });
// Add label if only one product option and it isn't 'Title'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.selector-wrapper:eq(0)').prepend('<label>{{ product.options.first }}</label>');
{% endif %}
// Auto-select first available variant on page load.
{% assign found_one_in_stock = false %}
{% for variant in product.variants %}
{% if variant.available and found_one_in_stock == false %}
{% assign found_one_in_stock = true %}
{% for option in product.options %}
$('.single-option-selector:eq({{ forloop.index0 }})').val({{ variant.options[forloop.index0] | json }}).trigger('change');
{% endfor %}
{% endif %}
{% endfor %}
});
</script>
If I run both scripts, the page shows two select boxes for the product options. Is it possible to combine them?
You have a JavaScript error on your page because of this line of code:
new Shopify.OptionSelectors("product-select", { product: , onVariantSelected: selectCallback });
According to this reference document: https://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/linked-product-options, that line of code should actually look like this:
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });

Javascript not reading the keys and values of a dictionary in django template

I have a dictionary like:
dest = {2: [u'canada', u'A', 'Ottawa'], 5: [u'Malaysia', u'A', 'KualaLumpur'],...}
Then I tried to retrieve the keys and values from dest in django template using javascript:
function categorizeReports()
{
var a = [];
var b = [];
{% for i,v in dest %}
id = '{{i}}';
console.log('id', id)
values = '{{v}}';
console.log('values',values)
{% for name, type, cat in values %}
if(type=='A' && cat=='Ottawa')
{
a.push(id,name,type,cat)
}
if(type=='A' && cat=='KualaLumpur')
{
b.push(id,name,type,cat)
}
{% endfor %}
{% endfor %}
console.log(a)
console.log(b)
}
But both the Arrays are shown as 'an empty string' as well as id and values are too shown as 'an empty string', Please help!
Missing .items
Change
{% for i,v in dest %}
to
{% for i,v in dest.items %}

polygon color changes automatically when zooming map

I have implemented a google map using V3 js API. I am drawing about 500 zip code polygons inside the map. The colouring of the zip code polygons depends upon certain conditions which is working fine. Like I am assigning distinct colours to a set of zipcodes. But the problem is when I am zooming in the map some of the zipcode polygon colours getc changed. How can we fix it.
Here is the code
{% ifequal zip.rank 1 %}
var fillColor = '#FF0000';
{% endifequal %}
{% ifequal zip.rank 2 %}
var fillColor = '#FF00D3';
{% endifequal %}
{% ifequal zip.rank 3 %}
var fillColor = '#BE4BAA';
{% endifequal %}
{% ifequal zip.rank 4 %}
var fillColor = '#BE88B5';
{% endifequal %}
{% ifequal zip.rank 5 %}
var fillColor = '#857081';
{% endifequal %}
var path = [
{% for polycoord in zip.zip_info.zip_polygon %}
new google.maps.LatLng({{polycoord.1}}, {{polycoord.0}}),
{% endfor %}
];
var polygon = new google.maps.Polygon(
{
path:path,
clickable:true,
strokeColor: '#000000',
strokeOpacity: 0.75,
strokeWeight: 1,
fillColor: fillColor,
fillOpacity: 1,
}
);
polygon.setMap(map);

Categories