Related
I'm trying to include a threejs visual in a documentation page generated via Julia's Documenter.jl package. Unfortunately, the way Documenter currently handles javascript components is via require.js and it appears to break three.js (or its modules) with the error
Uncaught ReferenceError: THREE is not defined
My self-contained example is like this
var container = document.getElementById("three_container");
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xeeeeee );
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 200;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
const frontSpot = new THREE.SpotLight(0xeeeece);
frontSpot.position.set(1000, 1000, 1000);
scene.add(frontSpot);
const frontSpot2 = new THREE.SpotLight(0xddddce);
frontSpot2.position.set(-500, -500, -500);
scene.add(frontSpot2);
scene.add(new THREE.AmbientLight(0xffffff, 1));
function createSphere(radius, segments) {
const material = new THREE.MeshStandardMaterial({
color: 0xfcc742,
emissive: 0x111111,
specular: 0xffffff,
metalness: 0.8,
roughness: 0.6,
});
return new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, segments),
material
);
}
// sphere params
var radius = 1,
segments = 36,
rotation = 6;
// spheres
var sphere1 = createSphere(radius, segments);
sphere1.position.x = 35.35533905932738;
sphere1.position.y = 35.35533905932737;
sphere1.position.z = 99.99999999999999;
sphere1.scale.set(10,10,20);
sphere1.rotation.z = 3.9269908169872414;
sphere1.rotation.x = 2.137707831735906;
sphere1.rotation.y = 0.0;
sphere1.rotation.order = 'ZXY';
scene.add(sphere1);
var sphere2 = createSphere(radius, segments);
sphere2.position.x = 3.061616997868383e-15;
sphere2.position.y = 50.0;
sphere2.position.z = 74.99999999999999;
sphere2.scale.set(10,10,20);
sphere2.rotation.z = 4.71238898038469;
sphere2.rotation.x = 2.137707831735906;
sphere2.rotation.y = 0.0;
sphere2.rotation.order = 'ZXY';
scene.add(sphere2);
var sphere3 = createSphere(radius, segments);
sphere3.position.x = -35.35533905932737;
sphere3.position.y = 35.35533905932738;
sphere3.position.z = 49.999999999999986;
sphere3.scale.set(10,10,20);
sphere3.rotation.z = -0.7853981633974483;
sphere3.rotation.x = 2.137707831735906;
sphere3.rotation.y = 0.0;
sphere3.rotation.order = 'ZXY';
scene.add(sphere3);
var sphere4 = createSphere(radius, segments);
sphere4.position.x = -50.0;
sphere4.position.y = 6.123233995736766e-15;
sphere4.position.z = 24.999999999999986;
sphere4.scale.set(10,10,20);
sphere4.rotation.z = -2.220446049250313e-16;
sphere4.rotation.x = 2.137707831735906;
sphere4.rotation.y = 0.0;
sphere4.rotation.order = 'ZXY';
scene.add(sphere4);
var sphere5 = createSphere(radius, segments);
sphere5.position.x = -35.355339059327385;
sphere5.position.y = -35.35533905932737;
sphere5.position.z = 0.0;
sphere5.scale.set(10,10,20);
sphere5.rotation.z = 0.7853981633974481;
sphere5.rotation.x = 2.137707831735906;
sphere5.rotation.y = 0.0;
sphere5.rotation.order = 'ZXY';
scene.add(sphere5);
var sphere6 = createSphere(radius, segments);
sphere6.position.x = -9.184850993605149e-15;
sphere6.position.y = -50.0;
sphere6.position.z = -25.000000000000014;
sphere6.scale.set(10,10,20);
sphere6.rotation.z = 1.5707963267948963;
sphere6.rotation.x = 2.137707831735906;
sphere6.rotation.y = 0.0;
sphere6.rotation.order = 'ZXY';
scene.add(sphere6);
var sphere7 = createSphere(radius, segments);
sphere7.position.x = 35.35533905932737;
sphere7.position.y = -35.355339059327385;
sphere7.position.z = -49.999999999999986;
sphere7.scale.set(10,10,20);
sphere7.rotation.z = 2.356194490192345;
sphere7.rotation.x = 2.137707831735906;
sphere7.rotation.y = 0.0;
sphere7.rotation.order = 'ZXY';
scene.add(sphere7);
var sphere8 = createSphere(radius, segments);
sphere8.position.x = 50.0;
sphere8.position.y = -1.2246467991473532e-14;
sphere8.position.z = -75.00000000000001;
sphere8.scale.set(10,10,20);
sphere8.rotation.z = 3.141592653589793;
sphere8.rotation.x = 2.137707831735906;
sphere8.rotation.y = 0.0;
sphere8.rotation.order = 'ZXY';
scene.add(sphere8);
var sphere9 = createSphere(radius, segments);
sphere9.position.x = 35.355339059327385;
sphere9.position.y = 35.35533905932737;
sphere9.position.z = -100.00000000000001;
sphere9.scale.set(10,10,20);
sphere9.rotation.z = 3.9269908169872414;
sphere9.rotation.x = 2.137707831735906;
sphere9.rotation.y = 0.0;
sphere9.rotation.order = 'ZXY';
scene.add(sphere9);
var sphere10 = createSphere(radius, segments);
sphere10.position.x = 1.5308084989341916e-14;
sphere10.position.y = 50.0;
sphere10.position.z = -124.99999999999999;
sphere10.scale.set(10,10,20);
sphere10.rotation.z = 4.71238898038469;
sphere10.rotation.x = 2.137707831735906;
sphere10.rotation.y = 0.0;
sphere10.rotation.order = 'ZXY';
scene.add(sphere10);
// end spheres
document.body.appendChild(renderer.domElement);
//renderer.render(scene, camera);
var controls = new THREE.TrackballControls(camera);
function render() {
controls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
I've read and tried various suggestions to make the THREE namespace available or something, but haven't had any luck. If I manually insert
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://unpkg.com/three#0.85.0/examples/js/controls/TrackballControls.js"></script>
<script src="https://unpkg.com/three#0.85.0/examples/js/Detector.js"></script>
at the top of the page <head>, everything works fine, but I cannot change the order when it's generated by Documenter. Any thoughts on how to work around this?
Edit: The requirejs configuration generated by Documenter looks like this:
// Generated by Documenter.jl
requirejs.config({
paths: {
'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/julia.min',
'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.10.3/headroom.min',
'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min',
'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/contrib/auto-render.min',
'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min',
'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.10.3/jQuery.headroom.min',
'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min',
'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min',
'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/julia-repl.min',
},
shim: {
"highlight-julia": {
"deps": [
"highlight"
]
},
"katex-auto-render": {
"deps": [
"katex"
]
},
"headroom-jquery": {
"deps": [
"jquery",
"headroom"
]
},
"highlight-julia-repl": {
"deps": [
"highlight"
]
}
}
});
////////////////////////////////////////////////////////////////////////////////
require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) {
$(document).ready(function() {
renderMathInElement(
document.body,
{
"delimiters": [
{
"left": "$",
"right": "$",
"display": false
},
{
"left": "$$",
"right": "$$",
"display": true
},
{
"left": "\\[",
"right": "\\]",
"display": true
}
]
}
);
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($, hljs) {
$(document).ready(function() {
hljs.initHighlighting();
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) {
// Manages the top navigation bar (hides it when the user starts scrolling down on the
// mobile).
window.Headroom = Headroom; // work around buggy module loading?
$(document).ready(function() {
$('#documenter .docs-navbar').headroom({
"tolerance": {"up": 10, "down": 10},
});
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
// Modal settings dialog
$(document).ready(function() {
var settings = $('#documenter-settings');
$('#documenter-settings-button').click(function(){
settings.toggleClass('is-active');
});
// Close the dialog if X is clicked
$('#documenter-settings button.delete').click(function(){
settings.removeClass('is-active');
});
// Close dialog if ESC is pressed
$(document).keyup(function(e) {
if (e.keyCode == 27) settings.removeClass('is-active');
});
});
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
// Manages the showing and hiding of the sidebar.
$(document).ready(function() {
var sidebar = $("#documenter > .docs-sidebar");
var sidebar_button = $("#documenter-sidebar-button")
sidebar_button.click(function(ev) {
ev.preventDefault();
sidebar.toggleClass('visible');
if (sidebar.hasClass('visible')) {
// Makes sure that the current menu item is visible in the sidebar.
$("#documenter .docs-menu a.is-active").focus();
}
});
$("#documenter > .docs-main").bind('click', function(ev) {
if ($(ev.target).is(sidebar_button)) {
return;
}
if (sidebar.hasClass('visible')) {
sidebar.removeClass('visible');
}
});
})
// Resizes the package name / sitename in the sidebar if it is too wide.
// Inspired by: https://github.com/davatron5000/FitText.js
$(document).ready(function() {
e = $("#documenter .docs-autofit");
function resize() {
var L = parseInt(e.css('max-width'), 10);
var L0 = e.width();
if(L0 > L) {
var h0 = parseInt(e.css('font-size'), 10);
e.css('font-size', L * h0 / L0);
// TODO: make sure it survives resizes?
}
}
// call once and then register events
resize();
$(window).resize(resize);
$(window).on('orientationchange', resize);
});
// Scroll the navigation bar to the currently selected menu item
$(document).ready(function() {
var sidebar = $("#documenter .docs-menu").get(0);
var active = $("#documenter .docs-menu .is-active").get(0);
if(typeof active !== 'undefined') {
sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15;
}
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
function set_theme(theme) {
var active = null;
var disabled = [];
for (var i = 0; i < document.styleSheets.length; i++) {
var ss = document.styleSheets[i];
var themename = ss.ownerNode.getAttribute("data-theme-name");
if(themename === null) continue; // ignore non-theme stylesheets
// Find the active theme
if(themename === theme) active = ss;
else disabled.push(ss);
}
if(active !== null) {
active.disabled = false;
if(active.ownerNode.getAttribute("data-theme-primary") === null) {
document.getElementsByTagName('html')[0].className = "theme--" + theme;
} else {
document.getElementsByTagName('html')[0].className = "";
}
disabled.forEach(function(ss){
ss.disabled = true;
});
}
// Store the theme in localStorage
if(typeof(window.localStorage) !== "undefined") {
window.localStorage.setItem("documenter-theme", theme);
} else {
console.error("Browser does not support window.localStorage");
}
}
// Theme picker setup
$(document).ready(function() {
// onchange callback
$('#documenter-themepicker').change(function themepick_callback(ev){
var themename = $('#documenter-themepicker option:selected').attr('value');
set_theme(themename);
});
// Make sure that the themepicker displays the correct theme when the theme is retrieved
// from localStorage
if(typeof(window.localStorage) !== "undefined") {
var theme = window.localStorage.getItem("documenter-theme");
if(theme !== null) {
$('#documenter-themepicker option').each(function(i,e) {
e.selected = (e.value === theme);
})
} else {
$('#documenter-themepicker option').each(function(i,e) {
e.selected = $("html").hasClass(`theme--${e.value}`);
})
}
}
})
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
// update the version selector with info from the siteinfo.js and ../versions.js files
$(document).ready(function() {
var version_selector = $("#documenter .docs-version-selector");
var version_selector_select = $("#documenter .docs-version-selector select");
version_selector_select.change(function(x) {
target_href = version_selector_select.children("option:selected").get(0).value;
window.location.href = target_href;
});
// add the current version to the selector based on siteinfo.js, but only if the selector is empty
if (typeof DOCUMENTER_CURRENT_VERSION !== 'undefined' && $('#version-selector > option').length == 0) {
var option = $("<option value='#' selected='selected'>" + DOCUMENTER_CURRENT_VERSION + "</option>");
version_selector_select.append(option);
}
if (typeof DOC_VERSIONS !== 'undefined') {
var existing_versions = version_selector_select.children("option");
var existing_versions_texts = existing_versions.map(function(i,x){return x.text});
DOC_VERSIONS.forEach(function(each) {
var version_url = documenterBaseURL + "/../" + each;
var existing_id = $.inArray(each, existing_versions_texts);
// if not already in the version selector, add it as a new option,
// otherwise update the old option with the URL and enable it
if (existing_id == -1) {
var option = $("<option value='" + version_url + "'>" + each + "</option>");
version_selector_select.append(option);
} else {
var option = existing_versions[existing_id];
option.value = version_url;
option.disabled = false;
}
});
}
// only show the version selector if the selector has been populated
if (version_selector_select.children("option").length > 0) {
version_selector.toggleClass("visible");
}
})
})
In my application i have to show the path covered by an user in particulat date working fine for first response,from second response from ajax i am getting data which is diffrent from first one but still map showing 1st response result
I included google map javascript api like below in header section of html
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
I am using following code in my jsp file
<script>
$(document).ready(function(){
window.setInterval(positionCheck, 20000);
});
</script>
<script>
$(document).ready(function(){
document.getElementById("directions_panel").innerHTML = "";
document.getElementById("map").innerHTML = "";
$("#searchSubmit").onclick(){
positionCheck();
}
});
</script>
<script type="text/javascript">
function positionCheck(){
var username=$("#xmlLabel").val();
var searchDate=$("#searchDate").val();
if(username!=""&& searchDate!=''){
This part where i used ajax call working fine for first response
from second response onwards problem arises it is showing content of first response from server
$.ajax({
type : "POST",
url : "searchLocation.mnt",
data :"xmlLabel="+username+"&searchDate="+searchDate,
dataType : "json",
mimeType : 'application/json',
success : function(data) {
if(data!=""){
mapLoaded(data);
function mapLoaded(data){
var size=0;
var counts=0;
var stops = data;
alert(stops);
size =stops.length;
if(stops.length>0){
var mapid=document.getElementById("map");
var map = new window.google.maps.Map(mapid);
// new up complex objects before passing them around
var directionsDisplay = new window.google.maps.DirectionsRenderer({suppressMarkers: true,polylineOptions: {
strokeColor: "black"
}});
var directionsService = new window.google.maps.DirectionsService();
Tour_startUp(stops);
window.tour.loadMap(map, directionsDisplay);
window.tour.fitBounds(map);
alert(stops.length);
if (stops.length > 1)
window.tour.calcRoute(directionsService, directionsDisplay);
}
alert(stops.length);
function Tour_startUp(stops) {
if (!window.tour) window.tour = {
updateStops: function (newStops) {
stops = newStops;
},
// map: google map object
// directionsDisplay: google directionsDisplay object (comes in empty)
loadMap: function (map, directionsDisplay) {
var myOptions = {
zoom:4,
center: new window.google.maps.LatLng(17.379818, 78.478542), // default to Hyderabad
mapTypeId: window.google.maps.MapTypeId.ROADMAP
};
map.setOptions(myOptions);
directionsDisplay.setMap(map);
},
fitBounds: function (map) {
var bounds = new window.google.maps.LatLngBounds();
// extend bounds for each record
jQuery.each(stops, function (key, val) {
var myLatlng = new window.google.maps.LatLng(val.latitude, val.longitude);
bounds.extend(myLatlng);
});
map.fitBounds(bounds);
},
calcRoute: function (directionsService, directionsDisplay) {
var batches = [];
var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
var itemsCounter = 0;
var wayptsExist = stops.length > 0;
while (wayptsExist) {
var subBatch = [];
var subitemsCounter = 0;
for (var j = itemsCounter; j < stops.length; j++) {
subitemsCounter++;
subBatch.push({
location: new window.google.maps.LatLng(stops[j].latitude, stops[j].longitude),
stopover: true
});
if (subitemsCounter == itemsPerBatch)
break;
}
itemsCounter += subitemsCounter;
batches.push(subBatch);
wayptsExist = itemsCounter < stops.length;
// If it runs again there are still points. Minus 1 before continuing to
// start up with end of previous tour leg
itemsCounter--;
}
// now we should have a 2 dimensional array with a list of a list of waypoints
var combinedResults;
var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
var directionsResultsReturned = 0;
for (var k = 0; k < batches.length; k++) {
var lastIndex = batches[k].length - 1;
var start = batches[k][0].location;
var end = batches[k][lastIndex].location;
// trim first and last entry from array
var waypts = [];
waypts = batches[k];
waypts.splice(0, 1);
waypts.splice(waypts.length - 1, 1);
var request = {
origin: start,
destination: end,
waypoints: waypts,
travelMode: window.google.maps.TravelMode.WALKING
};
(function (kk) {
directionsService.route(request, function (result, status) {
if (status == window.google.maps.DirectionsStatus.OK) {
var unsortedResult = { order: kk, result: result };
unsortedResults.push(unsortedResult);
directionsResultsReturned++;
if (directionsResultsReturned == batches.length) // we've received all the results. put to map
{
// sort the returned values into their correct order
unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
var count = 0;
for (var key in unsortedResults) {
if (unsortedResults[key].result != null) {
if (unsortedResults.hasOwnProperty(key)) {
if (count == 0) // first results. new up the combinedResults object
combinedResults = unsortedResults[key].result;
else {
// only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
// directionResults object, but enough to draw a path on the map, which is all I need
combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
}
count++;
}
}
}
directionsDisplay.setDirections(combinedResults);
var legs = combinedResults.routes[0].legs;
var summaryPanel = document.getElementById('directions_panel');
summaryPanel.innerHTML = '';
var totdist=0;
// alert(legs.length);
for (var i=0; i < legs.length;i++){
var markerletter = "A".charCodeAt(0);
var markerletter2= "B".charCodeAt(0)
markerletter += i;
markerletter2 += i;
markerletter = String.fromCharCode(markerletter);
markerletter2 = String.fromCharCode(markerletter2);
createMarker(directionsDisplay.getMap(),legs[i].start_location,legs[i].start_address,markerletter);//To display location address on the marker
var routeSegment = i + 1;
var point=+routeSegment+1;
summaryPanel.innerHTML += '<b>Route Segment: ' + routeSegment + '</b><br>';
summaryPanel.innerHTML += '<b>Point '+ routeSegment +' :</b>'+ ' ' +legs[i].start_address + ' <br> ';
summaryPanel.innerHTML += '<b>Point '+ point +' :</b>'+ ' '+legs[i].end_address + '<br>';
summaryPanel.innerHTML += '<b>Distance Covered '+' :</b>'+legs[i].distance.text + '<br><br>';
var test=legs[i].distance.text.split(' ');
var one=parseFloat(test[0]);
if(test[1]=="m"){
var one=parseFloat(test[0]/1000);
}
totdist=parseFloat(totdist)+parseFloat(one);
}
summaryPanel.innerHTML += '<b> Total Distance :'+totdist + 'km'+ '</b><br><br>';
var i=legs.length;
var markerletter = "A".charCodeAt(0);
markerletter += i;
markerletter = String.fromCharCode(markerletter);
createMarker(directionsDisplay.getMap(),legs[legs.length-1].end_location,legs[legs.length-1].end_address,markerletter);
}
}
});
})(k);
}
}
};
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
function getMarkerImage(iconStr) {
counts++;
if(counts==size){
var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/blue.png";
}else{
if (iconStr=="undefined") {
iconStr = "red";
var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/red.png";
}
else{
var markerimageLoc="http://www.google.com/mapfiles/marker"+ iconStr +".png";
// var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/red.png";
}
}
icons[iconStr] = new google.maps.MarkerImage(markerimageLoc,
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(25, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 6,20.
new google.maps.Point(9, 34));
return icons[iconStr];
}
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
// The shadow image is larger in the horizontal dimension
// while the position and offset are the same as for the main image.
new google.maps.Size(37, 34),
new google.maps.Point(0,0),
new google.maps.Point(9, 34));
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var iconShape = {
coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
type: 'poly'
};
function createMarker(map, latlng, label, character) {
var markerletter=character;
if( /[^a-zA-Z]/.test( character ) ) {
var markerletter="undefined";
}
var contentString = '<b>'+label+'</b><br>';
var marker = new google.maps.Marker({
position: latlng,
map: map,
shadow: iconShadow,
icon: getMarkerImage(markerletter),
shape: iconShape,
title: label,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
marker.myname = label;
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
return marker;
}
}
}else{
}
},
error : function(e) {
alert('Error: ' + e,"Alert Box");
}
});
}
}
</script>
and i included div tag like this in body section
<div id="map" style="border: 2px solid #3872ac; height: 500px;"
class="col-sm-6"></div>
above code working fine if i am not using ajax,problem exist only for ajax
sorry to trouble all of you,i feel very silly that i declared variable of stops globally and i need to call methods like below
function initialize(data) {
size = 0;
counts = 0;
var map=0;
var stops = data;
size = stops.length;
if (stops.length > 0) {
var map = new window.google.maps.Map(document
.getElementById("map"));
// new up complex objects before passing them around
var directionsDisplay = new window.google.maps.DirectionsRenderer(
{
suppressMarkers : true,
polylineOptions : {
strokeColor : "black"
}
});
var directionsService = new window.google.maps.DirectionsService();
Tour_startUp(stops);
window.tour.loadMap(map, directionsDisplay);
i changed the below methods from window.tour.fitBounds(map); window.tour.calcRoute(stops,directionsService,
directionsDisplay); to
window.tour.fitBounds(map,stops);
if (stops.length > 1)
window.tour.calcRoute(stops,directionsService,
directionsDisplay);
}
}
In OpenLayers 2, in the OverviewMapControl, you can drag the "box" to move the map.
You can not do this in OpenLayers 3.
I've tried to implement a custom control based on https://github.com/openlayers/ol3/blob/master/src/ol/control/overviewmapcontrol.js, but you can not use goog.xxx or other fancy stuff like ol.extent.scaleFromCenter when you are not in debug !
How should I proceed ?
basically, implementing drag'n drop is fairly "simple" :
var dragging = null;
var getMap = this.getMap.bind(this); //during ctor of a control, we have no access to the map !
$(document.body).on("mousemove", function (e) {
if (dragging) {
dragging.el.offset({
top: e.pageY,
left: e.pageX
});
}
});
$(box).on("mousedown", function (e) {
dragging = {
el: $(e.target)
};
});
$(document.body).on("mouseup", function (e) {
if (dragging) {
debugger;
var coords = ovmap.getEventCoordinate(e.originalEvent);
//TODO: taking event coordinates is not good, we must use center of the box coordinates
//the problem is that ovmap.getCoordinateFromPixel(dragging.el.offset()) is not working at all because we need to adjust ovmap viewport
getMap().getView().setCenter(coords);
dragging = null;
}
});
For those interested (which does not seem to be the case at the moment :)), here is the way I solved
/**
* Mostly a big copy/paste from https://raw.githubusercontent.com/openlayers/ol3/master/src/ol/control/overviewmapcontrol.js
* without rotation and zoom/dezoom plus some adapations from http://ol3.qtibia.ro/build/examples/overviewmap-custom-drag.html
* to add the possibility to drag the box on the minimap to move the main map
*/
ol.control.CustomOverviewMap = function (opt_options) {
var options = typeof opt_options !== 'undefined' ? opt_options : {};
this.collapsed_ = typeof options.collapsed !== 'undefined' ? options.collapsed : true;
this.onCollapseOrExpand = options.onCollapseOrExpand || function () { };
this.needFirstRenderUpdate_ = this.collapsed_; //prepare the hack to render the map when uncollapsed the first time
var tipLabel = typeof options.tipLabel !== 'undefined' ? options.tipLabel : 'Overview map';
this.collapseLabel_ = $('<span>\u00BB</span>').get(0);
this.label_ = $('<span>\u00AB</span>').get(0);
var activeLabel = (!this.collapsed_) ? this.collapseLabel_ : this.label_;
var button = $('<button type="button" title="{0}"></button>'.replace('{0}', tipLabel)).append(activeLabel);
button.on('click', this.handleClick_.bind(this));
//ol.control.Control.bindMouseOutFocusOutBlur(button);
button.on('mouseout', function () { this.blur(); });
button.on('focusout', function () { this.blur(); });
var ovmapDiv = $('<div class="ol-overviewmap-map"></div>').get(0);
this.ovmap_ = new ol.Map({
controls: new ol.Collection(),
interactions: new ol.Collection(),
layers: [options.tileLayer],
target: ovmapDiv,
view: new ol.View(opt_options.view)
});
var box = $('<div class="ol-overviewmap-box"></div>');
this.boxOverlay_ = new ol.Overlay({
position: [0, 0],
positioning: 'bottom-left',
element: box.get(0)
});
this.ovmap_.addOverlay(this.boxOverlay_);
var cssClasses = 'ol-overviewmap ol-unselectable ol-control' +
(this.collapsed_ ? ' ol-collapsed' : '');
var element = $('<div class="{0}"></div>'.replace('{0}', cssClasses)).append(ovmapDiv).append(button).get(0);
ol.control.Control.call(this, {
element: element,
render: ol.control.CustomOverviewMap.render
});
// deal with dragable minimap
this.dragging = null;
box.on("mousedown", this.onStartDrag.bind(this));
$(document.body).on("mousemove", this.onDrag.bind(this));
$(document.body).on("mouseup", this.onEndDrag.bind(this));
};
ol.inherits(ol.control.CustomOverviewMap, ol.control.Control);
ol.control.CustomOverviewMap.prototype.onStartDrag = function (e) {
// remember some data to use during onDrag or onDragEnd
var box = $(e.target);
this.dragging = {
el: box,
evPos: { top: e.pageY, left: e.pageX },
elPos: box.offset()
};
}
ol.control.CustomOverviewMap.prototype.onDrag = function (e) {
if (this.dragging) {
//set the position of the box to be oldPos+translation(ev)
var curOffset = this.dragging.el.offset();
var newOffset = {
top: curOffset.top + (e.pageY - this.dragging.evPos.top),
left: curOffset.left + (e.pageX - this.dragging.evPos.left)
};
this.dragging.evPos = { top: e.pageY, left: e.pageX };
this.dragging.el.offset(newOffset);
}
}
ol.control.CustomOverviewMap.prototype.onEndDrag = function (e) {
if (this.dragging) {
//see ol3.qtibia.ro href at the top of the class to understand this
var map = this.getMap();
var offset = this.dragging.el.position();
var divSize = [this.dragging.el.width(), this.dragging.el.height()];
var mapSize = map.getSize();
var c = map.getView().getResolution();
var xMove = offset.left * (Math.abs(mapSize[0] / divSize[0]));
var yMove = offset.top * (Math.abs(mapSize[1] / divSize[1]));
var bottomLeft = [0 + xMove, mapSize[1] + yMove];
var topRight = [mapSize[0] + xMove, 0 + yMove];
var left = map.getCoordinateFromPixel(bottomLeft);
var top = map.getCoordinateFromPixel(topRight);
var extent = [left[0], left[1], top[0], top[1]];
map.getView().fitExtent(extent, map.getSize());
map.getView().setResolution(c);
//reset the element at the original position so that when the main map will trigger
//the moveend event, this event will be replayed on the box of the minimap
this.dragging.el.offset(this.dragging.elPos);
this.dragging = null;
}
}
ol.control.CustomOverviewMap.render = function (mapEvent) {
//see original OverviewMap href at the top of the class to understand this
var map = this.getMap();
var ovmap = this.ovmap_;
var mapSize = map.getSize();
var view = map.getView();
var ovview = ovmap.getView();
var overlay = this.boxOverlay_;
var box = this.boxOverlay_.getElement();
var extent = view.calculateExtent(mapSize);
var ovresolution = ovview.getResolution();
var bottomLeft = ol.extent.getBottomLeft(extent);
var topRight = ol.extent.getTopRight(extent);
overlay.setPosition(bottomLeft);
// set box size calculated from map extent size and overview map resolution
if (box) {
var boxWidth = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution);
var boxHeight = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution);
$(box).width(boxWidth).height(boxHeight);
}
};
ol.control.CustomOverviewMap.prototype.handleClick_ = function (event) {
event.preventDefault();
this.collapsed_ = !this.collapsed_;
$(this.element).toggleClass('ol-collapsed');
// change label
if (this.collapsed_) {
this.collapseLabel_.parentNode.replaceChild(this.label_, this.collapseLabel_);
} else {
this.label_.parentNode.replaceChild(this.collapseLabel_, this.label_);
}
// manage overview map if it had not been rendered before and control is expanded
if (!this.collapsed_ && this.needFirstRenderUpdate_) {
this.needFirstRenderUpdate_ = false;
this.ovmap_.updateSize();
this.ovmap_.once("postrender", function () {
this.render();
}.bind(this));
}
//trigger event
this.onCollapseOrExpand(this.collapsed_);
};
Inside my ion-content I have a list which when scrolled to the bottom more items are loaded (provided by ion-infinite-scroll which calls 'LoadMore()').
The problem is that if I set direction = xy to ion-content, ion-infinite-scroll calls 'LoadMore()' if I scroll vertically and horizontally.
It is possible to my ion-infinite-scroll only call 'LoadMore()' when scrolled vertically?
Currently ionic version beta.13 does not support this feature.
I already have posted my suggested solution on ionic repository ( https://github.com/driftyco/ionic/issues/1073 )
I've created 'ion-infinite-scroll-fixed' directive wich differs only in last if block:
.directive('ionInfiniteScrollFixed', ['$timeout', function($timeout) {
function calculateMaxValue(distance, maximum, isPercent) {
return isPercent ?
maximum * (1 - parseFloat(distance,10) / 100) :
maximum - parseFloat(distance, 10);
}
return {
restrict: 'E',
require: ['^$ionicScroll', 'ionInfiniteScrollFixed'],
template: '<i class="icon {{icon()}} icon-refreshing"></i>',
scope: true,
controller: ['$scope', '$attrs', function($scope, $attrs) {
this.isLoading = false;
this.scrollView = null; //given by link function
this.getMaxScroll = function() {
var distance = ($attrs.distance || '2.5%').trim();
var isPercent = distance.indexOf('%') !== -1;
var maxValues = this.scrollView.getScrollMax();
return {
left: this.scrollView.options.scrollingX ?
calculateMaxValue(distance, maxValues.left, isPercent) :
-1,
top: this.scrollView.options.scrollingY ?
calculateMaxValue(distance, maxValues.top, isPercent) :
-1
};
};
}],
link: function($scope, $element, $attrs, ctrls) {
var scrollCtrl = ctrls[0];
var infiniteScrollCtrl = ctrls[1];
var scrollView = infiniteScrollCtrl.scrollView = scrollCtrl.scrollView;
$scope.icon = function() {
return angular.isDefined($attrs.icon) ? $attrs.icon : 'ion-loading-d';
};
var onInfinite = function() {
$element[0].classList.add('active');
infiniteScrollCtrl.isLoading = true;
$scope.$parent && $scope.$parent.$apply($attrs.onInfinite || '');
};
var finishInfiniteScroll = function() {
$element[0].classList.remove('active');
$timeout(function() {
scrollView.resize();
checkBounds();
}, 0, false);
infiniteScrollCtrl.isLoading = false;
};
$scope.$on('scroll.infiniteScrollComplete', function() {
finishInfiniteScroll();
});
$scope.$on('$destroy', function() {
void 0;
if(scrollCtrl && scrollCtrl.$element)scrollCtrl.$element.off('scroll', checkBounds);
});
var checkBounds = ionic.animationFrameThrottle(checkInfiniteBounds);
//Check bounds on start, after scrollView is fully rendered
setTimeout(checkBounds);
scrollCtrl.$element.on('scroll', checkBounds);
function checkInfiniteBounds() {
if (infiniteScrollCtrl.isLoading) return;
var scrollValues = scrollView.getValues();
var maxScroll = infiniteScrollCtrl.getMaxScroll();
if ((maxScroll.left !== -1 && scrollValues.left >= maxScroll.left && $attrs.notOnHorizontal !=="true") ||
(maxScroll.top !== -1 && scrollValues.top >= maxScroll.top && $attrs.notOnVertical !=="true")) {
onInfinite();
}
}
}
};
}]);
and in my HTML:
<ion-infinite-scroll-fixed
not-on-horizontal="true"
ng-if="infiniteScroll.canLoad"
on-infinite="infiniteScroll.loadMore();"
distance="1%">
</ion-infinite-scroll-fixed>
I hope this can help somebody :)
I have a problem with my script. I want to remove the load more button and instead do an infinite scroll when I get to bottom of the page.
I'm using a WordPress template and without support I'm stuck on this nonsense.
What should I change to do to this script?
jQuery(document).ready(function($){
var $container = $('#hentry-wrapper');
// Isotope
// modified Isotope methods for gutters in masonry
$.Isotope.prototype._getMasonryGutterColumns = function() {
var gutter = this.options.masonry && this.options.masonry.gutterWidth || 0;
containerWidth = this.element.width();
this.masonry.columnWidth = this.options.masonry && this.options.masonry.columnWidth ||
// or use the size of the first item
this.$filteredAtoms.outerWidth(true) ||
// if there's no items, use size of container
containerWidth;
this.masonry.columnWidth += gutter;
this.masonry.cols = Math.floor( ( containerWidth + gutter ) / this.masonry.columnWidth );
this.masonry.cols = Math.max( this.masonry.cols, 1 );
};
$.Isotope.prototype._masonryReset = function() {
// layout-specific props
this.masonry = {};
// FIXME shouldn't have to call this again
this._getMasonryGutterColumns();
var i = this.masonry.cols;
this.masonry.colYs = [];
while (i--) {
this.masonry.colYs.push( 0 );
}
};
$.Isotope.prototype._masonryResizeChanged = function() {
var prevSegments = this.masonry.cols;
// update cols/rows
this._getMasonryGutterColumns();
// return if updated cols/rows is not equal to previous
return ( this.masonry.cols !== prevSegments );
};
var loadMore = $('#load-more');
var posts_per_page = parseInt(loadMore.attr('data-perpage'));
var offset = posts_per_page;
var totalPosts = parseInt(loadMore.attr('data-total-posts'));
var author = parseInt(loadMore.attr('data-author'));
var category = parseInt(loadMore.attr('data-category'));
var tag = loadMore.attr('data-tag');
var datemonth = loadMore.attr('data-month');
var dateyear = loadMore.attr('data-year');
var search = loadMore.attr('data-search');
var loader = $('#posts-count').attr('data-loader');
if (!author) author = 0;
if (!category) category = 0;
if (!tag) tag = '';
if (!datemonth) datemonth = 0;
if (!dateyear) dateyear = 0;
if (!search) search = '';
// cache jQuery window
var $window = $(window);
// start up isotope with default settings
$(window).load(function(){
reLayout();
$window.smartresize( reLayout );
if (offset < totalPosts) {
$('#nav-pagination-load-more').fadeIn(200);
mega_initLoadMore();
}
});
function reLayout() {
var mediaQueryId = getComputedStyle( document.body, ':after' ).getPropertyValue('content');
// fix for firefox, remove double quotes "
//mediaQueryId = mediaQueryId.replace( /"/g, '' );
//console.log( mediaQueryId );
var windowSize = $window.width();
var masonryOpts;
// update sizing options
switch ( mediaQueryId ) {
case 'large' :
masonryOpts = {
gutterWidth: 0
};
break;
case 'big' :
masonryOpts = {
//columnWidth: 297,
gutterWidth: 0
};
break;
case 'medium' :
masonryOpts = {
//columnWidth: 269,
gutterWidth: 0
};
break;
case 'small' :
masonryOpts = {
//columnWidth: $container.width() / 4,
gutterWidth: 0
};
break;
case 'tiny' :
masonryOpts = {
//columnWidth: $container.width() / 1,
gutterWidth: 0
};
break;
}
$container.isotope({
resizable: false, // disable resizing by default, we'll trigger it manually
itemSelector : '.type-post',
transformsEnabled: false, // Firefox Vimeo issue
masonry: masonryOpts
}).isotope( 'reLayout' );
}
function mega_initLoadMore(){
loadMore.click(function(e) {
$(this).unbind("click").addClass('active');
$('#posts-count').html('<img src="'+ loader +'"/>');
e.preventDefault();
mega_loadMorePosts();
});
}
function mega_reLayout(){
$container.isotope( 'reLayout' );
}
function mega_loadMorePosts(){
jQuery.ajax({
url: megaAjax.ajaxurl,
type: 'POST',
data: {
action : 'mega_ajax_blog',
nonce : megaAjax.nonce,
category: category,
author: author,
tag: tag,
datemonth: datemonth,
dateyear: dateyear,
search: search,
offset: offset
},
success: function( data ) {
var $newElems = $(data);
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded( function(){
// FitVids
$('.fluid-video, .entry-content', $newElems).fitVids();
$container.append($newElems).isotope( 'appended', $newElems );
// Flex Slider
$('.flexslider', $newElems).flexslider({
animation: "fade",
slideshow: false,
keyboard: false,
directionNav: true,
touch: true,
prevText: "",
nextText: ""
});
setTimeout(function(){
mega_reLayout();
}, 1000);
offset = offset + posts_per_page;
loadMore.removeClass('active');
if (offset < totalPosts){
$('#posts-count').text('');
loadMore.bind("click", mega_initLoadMore());
}
else {
setTimeout(function(){
loadMore.parent().remove();
}, 1000 );
}
});
}
});
return false;
}
});
I think this script is taken from "HEAT WORDPRESS THEME" directly which is located in js folder of the theme. Its simple to modify,you just need to remove Ajax post loading function and keep Isotop initializing function only. For help see this link
http://www.shambix.com/en/isotope-twitter-bootstrap-infinite-scroll-fluid-responsive-layout/