I'm have an issue where I don't think the fitBounds call is setting the zoom level appropriately. I have managed to reproduce my test case here http://tom.haddons.net/map.html - basically the four outer points are the bounds I'm setting, and if you load the page, and then zoom in one level they're all still visible. So why isn't google maps setting the zoom level to that?
Thanks, Tom
I managed to work around this by doing the following:
var minlatminlong = new google.maps.LatLng({{ min_latitude }}, {{ min_longitude }});
var minlatmaxlong = new google.maps.LatLng({{ min_latitude }}, {{ max_longitude }});
var maxlatminlong = new google.maps.LatLng({{ max_latitude }}, {{ min_longitude }});
var maxlatmaxlong = new google.maps.LatLng({{ max_latitude }}, {{ max_longitude }});
zoomChangeBoundsListener = google.maps.event.addListener(map, 'bounds_changed', function(){
var bounds = this.getBounds();
if ((bounds.getSouthWest().lng() > {{ min_longitude }}) || (bounds.getNorthEast().lng() < {{ max_longitude }}) || (bounds.getSouthWest().lat() > {{ min_latitude }}) || (bounds.getNorthEast().lat() < {{ max_latitude }})) {
this.setZoom(this.getZoom() - 1);
} else {
google.maps.event.removeListener(zoomChangeBoundsListener);
}
});
Note that anything enclosed in '{{' and '}}' is a variable I'm passing into the html template.
Related
So I'm working with Symfony 4.4 and I'm facing an issue here.
I have the following script responsible for getting the value of an input tag and sending it back as json to the controller
{% if summoner is defined %}
let res = {{ summoner.summonerLevel }}
{% endif %}
$("#valid-summoner").click(function () {
let data = {'sumoner_name':$("#riot-summoner-input").val()}
let url = `/coach/`
let xhr = new XMLHttpRequest
xhr.open("GET", url)
xhr.send(JSON.stringify(data))
console.log(data)
function loadXMLDoc()
{
document.getElementById("display-summonerLevel").innerHTML = `Summoner Level: <h2>${res}</h2>`
}
loadXMLDoc();
});
I have a controller method responsible for rendering the index page that's receiving this json and extracting the content and using it to render the page again but with another option which is that value.
...
$data = json_decode($request->getContent());
if(isset($data->sumoner_name) && !empty($data->sumoner_name)){
// We return the code
return $this->render('coach/index.html.twig', [
'coaches' => $coaches, 'summoner'=> $this->showSummoner($data->sumoner_name),
'current_user'=>$currentUser, 'combined'=>$call->fetchCoachRating($coaches)
]);
}else{
return $this->render('coach/index.html.twig', [
'coaches' => $coaches,
'current_user'=>$currentUser, 'combined'=>$call->fetchCoachRating($coaches)
]);
}
I don't know if this is actually the way you're supposed to do it. But it certainly isn't working..
console.log(data) in the script give back the following output
(index):445 {sumoner_name: 'YàKûZa'}sumoner_name: "YàKûZa"[[Prototype]]: Object
I'm not sure what I can do here
So, I'm working on a Meteor project and I can't get this route to generate properly, or at all for that matter.
<template name="browseAll">
<h3>List of classes with books available!</h3>
<ul>
{{#each aggCount}}
<li>{{ _id }} ({{ count }})</li>
{{/each}}
</ul>
</template>
The data that is being iterated over is a result of aggregation using MongoInternals, and that is as follows:
(server/methods.js excerpt):
classCount: function() {
// Attempt aggregation of the books table to count by class, maybe.
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
var col = db.collection("books");
var aggregateSync = Meteor._wrapAsync(col.aggregate.bind(col));
var pipeline = [
{$group: {_id: "$class", count: {$sum: 1}}},
{$sort: {_id: 1}}
];
var theAnswer = aggregateSync(pipeline);
return theAnswer;
}
It seems that the data is coming through okay, and sample data from aggregation (coming into the template) looks like this:
[ { _id: 'ADNR1234', count: 2 }, { _id: 'ARTH1234', count: 1 } ]
That's the template code I've got, and this is the route that it's supposed to be working with:
this.route('browse-class', {
path: '/browse/:_class',
data: function() {
var booksCursor = Books.find({"class": this.params._class},{sort:{"createdAt": 1}});
return {
theClass: this.params._class,
numBooks: booksCursor.count(),
books: booksCursor
};
}
});
I don't understand it. The data is being SHOWN, and what I want to do is generate a URL for browse-class (route) that takes the value of {{ _id }} in the helper as a parameter, so as to generate something like this:
application.org/browse/CLSS
Be aware that {{pathFor}} must be called with a data context properly set :
{{#with class}}
{{pathFor "browse-class"}}
{{/with}}
Optionnaly it is possible to pass the data context as a parameter :
{{pathFor "browse-class" class}}
The data context provided to pathFor is used when generating the route path, if you defined a route path like this :
path: "/browse/:_id"
Then it will use the _id from the class to properly generate a URL.
For the text of the link, I doubt you want to display the _id, your class documents probably include a "label" so you could use this :
{{ label }}
When I try to use this.findAll on a template where the selector is in a sub-template, findAll returns nothing.
Here's the HTML:
<template name="products">
{{#each productList}}
{{> product }}
{{/each}}
</template>
<template name="product">
<div class="box">{{name}}</div>
</template>
Here's the JS:
Template.products.helpers({
productList: function() {
var all = Products.find({}).fetch();
return all;
}
});
Template.products.rendered = function(){
var boxes = this.findAll('.box');
console.log(boxes.length);
}
Output of boxes.length is 0. Any ideas how I could get the "box" elements?
According to the docs for findAll:
Only elements inside the template and its sub-templates can match parts of the selector.
So it should work for sub-templates. I tried this with a fixed array of products and it worked, which implies that you are just seeing a delay between the call to rendered and the products being fetched. For example if you do:
Template.products.events({
'click .box': function (e, t) {
var boxes = t.findAll('.box');
console.log(boxes.length);
}
});
Then if you click on one of the boxes, you should see the correct number logged to the console. In short, I think the test may just be invalid. If you are using iron-router, you could try adding a waitOn for the products - that may ensure they arrive before the rendered call.
Here's what I did to run a script after all products have been loaded.
I've added last_product property in all the products.
Template.products.helpers({
productList: function() {
var all = Products.find({}).fetch();
var total = all.length;
var ctr = 0;
all.forEach(function(doc){
doc.last_product = false;
ctr++;
if(ctr == total)
{
doc.last_product = true;
}
return doc;
});
return all;
}
});
Then instead of "Template.products", I used "Template.product" to detect if the last product is rendered. When the last product is rendered, run the script.
Template.product.rendered = function(){
if(this.data.last_product){
var boxes = $('.pbox');
console.log(boxes.length);
}
}
boxes.length now has the correct length.
Thanks to David for the idea!
Here's the correct answer. I've added this to my iron-router route:
action : function () {
if (this.ready()) {
this.render();
}
}
Found the answer from https://stackoverflow.com/a/23576039/130237 while I was trying to solve a different problem.
I am new to Handlebars.
I have created an ItemView which is used in CompositeView. Values for this template rendering correctly.
var singleMonth = Marionette.ItemView.extend({
tagName: 'tr',
template: {
type: 'handlebars',
template: monthTemplate
},
months: [ 'JAN','FEB','MAR','APR','JUN','JUL','AUG','SEP','OCT','NOV','DEC' ],
templateHelpers: function() {
var helpers = {};
helpers.months = this.months;
return helpers;
}
});
and this is my template
<td>{{ months.#index.[7] }}</td><td>{{ [12] }}</td>
I want to get respective month value based on value of [7] which will be index for months array.
for Ex. if [7] is 3 then I want to get expression value as 'MAR'.
I am not able to get how to do this.
Can you please tell me how can I do this ?
(NOTE: I don't want to use #each or any loop here )
Thanks
Despite the possible syntax error in your template, the template itself should not be so smart.
Keep it stupid like
<td>{{ thisMonth }}</td>
Then build thisMonth in templateHelpers
templateHelpers: function() {
// The reason for _this is: `this` means model in templateHelpers.
_this = this;
return {
thisMonth: _this.months[7]
}
};
I am successful to display multiple maps through a php loop. But at the end I am calling window.print. My problem is that the window.print is getting triggered before the map loads and blank space is shown on the print page.
Here is my example code:
{loop starts}
<div latitude="<?php echo $row['lat'];?>" longitude="<?php echo $row['lng'];?>" zoom="<?php echo $row['map_zoom_level'];?>" class="map_canvas"></div>
{loop ends}
Javascript:
$(document).ready(function(){
$('.map_canvas').each(function(index, Element) {
var lat = $(Element).attr('latitude');
var lng = $(Element).attr('longitude');
var latlng = lat+','+lng;
var zoomlevel = parseInt($(Element).attr('zoom'));
var origin = new google.maps.LatLng(lat,lng)
$(Element).gmap({'zoom': zoomlevel}).bind('init', function(ev, map) {
$(Element).gmap('get','map').setOptions({'center':origin});
$(Element).gmap('addMarker', {'position': latlng}).click();
});
});
window.print();
});
Can anyone help me fix this.