How can google.maps.geometry be undefined? - javascript

I'm writing a JavaScript application using the Google Maps Javascript API v3 and RequireJS. I wrote a little wrapper for gmaps in order to get the dependencies right:
define('gmaps', ['goog!maps,3.9,packages:[geometry],language:de,other_params:sensor=false&channel=...&client=...'],
function(){
return window.google.maps;
});
This works perfectly fine in most of the cases, even after minifying the code using the optimizer. However, sometimes I get an error saying gmaps.geometry is undefined in a module that has gmaps as a dependency and tries to calculate a distance:
define(['gmaps'], function(gmaps) {
return {
...
calcDistance: function(target) {
var position = this.getPosition();
var distance = gmaps.geometry.spherical.computeDistanceBetween(
new gmaps.LatLng(position.latitude, position.longitude),
new gmaps.LatLng(target.latitude, target.longitude)
);
return (distance / 1000).toFixed(2);
}
}
});
This only happens if I try to execute calcDistance right after the page and the required data has loaded and only sometimes. I guess this is some problem with the async loading of gmaps, but I don't fully understand it. How can gmaps be defined but gmaps.geometry be undefined? Is there any way to fix this?

It seems you are not loading the correct library. Just append &libraries=geometry in the library url.
Check this
google.maps.geometry.spherical error

packages:[geometry] doesn't seem to work like I thought it would, so geometry wasn't loaded at all. Google seems to internally load geometry at some point, so my code for distance calculation worked in most cases. I fixed the problem by changing the define call of my gmaps module to:
define('gmaps', ['goog!maps,3.9,language:de,other_params:libraries=geometry&sensor=false&channel=...&client=...'],
function(){
return window.google.maps;
});

I know this is an old question, but in my situation I see that geometry libraries is not available at the initialization. I don't know why. But it became defined after some time. So I resolve the problem using a wait function.
setTimeout(waitForGeometryLibraries, 250);
function waitForGeometryLibraries(){
if(typeof google.maps.geometry !== "undefined"){
// code using geometry library
}
else{
setTimeout(waitForGeometryLibraries, 250);
}
}

Related

unable to load and eval javascript code in postman pre-request

I am trying to load external javascript in the pre-request tab of postman request by following the steps mentioned in https://blog.postman.com/adding-external-libraries-in-postman/ but seems like it is not working. Below is the code I am trying and it is not loading. I am not sure what is wrong and what is not working
pm.sendRequest("https://cdnjs.cloudflare.com/ajax/libs/chance/1.1.8/chance.min.js", (err, res) => {
//convert the response to text and save it as an environment variable
pm.collectionVariables.set("chancejs_library", res.text());
eval(pm.collectionVariables.get("chancejs_library"));
console.log(this.chance().string()) // --> not working
console.log(this.chance()) // --> not working
console.log(this.Chance()) // --> not working
console.log(this.Chance().string()) // --> not working
})
In all the above cases, I get the same error
ReferenceError: chance is not defined
It is indeed chancejs's "fault". I don't know what kind of "environment"/"runtime" Postman is providing for running js in general, but it seems that Chance() instance is never created in it - no matter if using eval() or IIFE... Last lines of chance.js are to blame (starting with the comment "// CommonJS module" where - to my understanding - instantiation happens).
So I figured a dirty "hack" which makes chancejs usable in Postman:)
I took version 1.1.9 of chancejs from github, then I simply added "else" statement to one of those "ifs" from instantiation section:
// if there is a importsScrips object define chance for worker
// allows worker to use full Chance functionality with seed
if (typeof importScripts !== 'undefined') {
chance = new Chance();
self.Chance = Chance;
}
else {
chance = new Chance();
}
Then I followed Load a library from a variable section from https://blog.postman.com/adding-external-libraries-in-postman/ (when setting chancejs collection variable I obviously had to use the "hacked" version of the chancejs)
var chancejs = pm.collectionVariables.get('chancejs');
(new Function(chancejs))();
// testing if this works by calling sentence() method :)
console.log(chance.sentence());
Seems to work :)

Rendering React.js clientside webapp with PhantomJS

A friend has asked me to capture a client-side rendered website built with React.js, preferably using PhantomJS. I'm using a simple rendering script as follows:
var system = require('system'),
fs = require('fs'),
page = new WebPage(),
url = system.args[1],
output = system.args[2],
result;
page.open(url, function (status) {
if (status !== 'success') {
console.log('FAILED to load the url');
phantom.exit();
} else {
result = page.evaluate(function(){
var html, doc;
html = document.querySelector('html');
return html.outerHTML;
});
if(output){
var rendered = fs.open(output,'w');
rendered.write(result);
rendered.flush();
rendered.close();
}else{
console.log(result);
}
}
phantom.exit();
});
The url is http://azertyjobs.tk
I consistently get an error
ReferenceError: Can't find variable: Promise
http://azertyjobs.tk/build/bundle.js:34
http://azertyjobs.tk/build/bundle.js:1 in t
...
Ok so I figured out that ES6 Promises aren't natively supported by PhantomJS yet, so I tried various extra packages like the following https://www.npmjs.com/package/es6-promise and initiated the variable as such:
var Promise = require('es6-promise').Promise
However this still produces the same error, although Promise is now a function. The output of the webpage is also still as good as empty (obviously..)
Now I'm pretty oldschool, so this whole client-side rendering stuff is kind of beyond me (in every aspect), but maybe someone has a solution. I've tried using a waiting script too, but that brought absolutely nothing. Am I going about this completely wrong? Is this even possible to do?
Much appreciated!
Ludwig
I've tried the polyfill you linked and it didn't work, changed for core.js and was able to make a screenshot. You need to inject the polyfill before the page is opened:
page.onInitialized = function() {
if(page.injectJs('core.js')){
console.log("Polyfill loaded");
}
}
page.open(url, function (status) {
setTimeout(function(){
page.render('output.jpg');
phantom.exit();
}, 3000);
});
What you need to understand is that there are several parts of a page loading. First there is the HTML - the same thing you see when you "view source" on a web page. Next there are images and scripts and other resources loaded. Then the scripts are executed, which may or may not result in more content being loaded and possible modifications to the HTML.
What you must do then is figure out a way to determine when the page is actually "loaded" as the user sees it. PhantomJS provides a paradigm for you to waitFor content to load. Read through their example and see if you can figure out a method which works for you. Take special note of where they put phantom.exit(); as you want to make sure that happens at the very end. Good luck.
Where (how) are you trying to initialise Promise? You'll need to create it as a property of window, or use es6-promise as a global polyfill, like this require('es6-promise').polyfill(); or this require('es6-promise/auto'); (from the readme).
Also, what do you mean by "capture"? How If you're trying to scrape data, you may have better luck using X-ray. It supports Phantom, Nightmare and other drivers.
Keep in mind also that React can also be server rendered. React is like templating, but with live data bindings. It's not as complicated as you're making it out to be.

RequireJS and IE9

I've tried to find the solution in previous questions but i couldn't.
I have a web project developed in jquery using requireJS. Everything seems to work fine (in all modern browsers) until i tested in IE9 where there isn't a script working. I tried to find the cause but all i can get is the feedback from dev tool console:
SCRIPT1002: Syntax error libCommon.js, line 10 character 3
SCRIPT445: Object doesn't support this action libEvents.js, line 5
character 2
This is the beginning code of libCommon.js:
//generic JS for all views
define(['jquery'], function ($) {
var LibCommon = function () {};
LibCommon.prototype.hideSubmenu = function() {
$submenu.removeClass('show');
}
LibCommon.prototype.toggleSubmenu = function(tipo) {
const $tipoSubmenu = $('#'+tipo);
this.hideSubmenu();
if (!$tipoSubmenu.hasClass('show')) {
$tipoSubmenu.addClass('show');
} else {
$tipoSubmenu.removeClass('show');
}
};
//and other functions...
And this is the beginning code of libEvents.js:
//generic JS for all views
define(['jquery', 'bootstrap', './libCommon', 'modernizr'], function ($, Bootstrap, LibCommon, Modernizr) {
var common = new LibCommon();
/**
* =================
* TO EXECUTE WHEN INIT
* =================
*/
$( document ).ready(function() {
console.log('initialized all common events');
var common = new LibCommon();
// Fixed header
var stickyNavTop = $('.topmenu').offset().top;
common.fixedNav(stickyNavTop);
$(window).scroll(function() {
common.fixedNav(stickyNavTop);
});
// and other functions or events...
In both errors it's first character of creating a variable/instance of an object after defining all objects/dependencies in requireJS, so it shouldn't be an error. I tried by changing for var common = 0; but error continues appearing in console. It seems that IE9 doesn't like any script. Otherwise, require's instances are working because bootstrap is working properly. Any idea?
Shilly already pointed out in a comment that you should not pass ES6 constructs to IE9. Either write ES5 or use a tool to transpile it.
Now, the error you are getting in libEvents is bizarre because libCommon should not have loaded at all, and consequently the factory of libEvents should not run because one of the dependencies did not load. It is possible to have a module load and later give errors. But I don't recall ever seeing a syntax error in the immediately-interpreted code of a module that did not just cause the load to fail. (The code you are showing is interpreted immediately, even if it is executed later. If you had an eval(string_of_code) in there or a Function(string_of_code) then string_of_code would be interpreted later but this is not something that happens in your code.) I suspect the reason RequireJS goes ahead with executing the factory for libEvents has to do with a problem catching load failures in IE9 and lower. The documentation suggests turning on enforceDefine. I would do this for your code. This won't solve everything but it may help RequireJS detect problems better.
console.log will also probably give you troubles, as explained by this question and answer.

Asynchronous Mathjax SVG

I am using mpld3 to convert Matplotlib plots into D3 web embedable graphics. I am then using a JS library written on top of MathJax called svg_mathjax2.js (https://github.com/ichuang/svg_mathjax2) to apply Tex conversions.
The error I get is at this line of svg_mathjax2.js:
var svgmath = mathjaxdiv.getElementsByClassName('MathJax_SVG')
[0].getElementsByTagName('svg')[0];
It gives the error:
Uncaught TypeError: Cannot read property 'getElementsByTagName' of undefined
Everything works fine the first time I load Mathjax, it converts the text appropriately. However, any additional calls (via AJAX) don't work.
I've posted an issue on the github page, but have not heard back. I'm not sure if this is an issue with svg_mathjax2 or mpld3. Perhaps someone familiar with MathJax can help out?
Never mind, I figured this out. It was specific to the svg_mathjax2.js.
I solved it by activating this block of code:
if (1) {
MathJax.Hub.Register.StartupHook("End Typeset", function () {
forEach(items, function (x) {
});
// remove the temporary items
var mathbucket = document.getElementById('mathjax_svg_bucket');
mathbucket.parentNode.removeChild(mathbucket);
});
}
}

Retrieving jQuery.data() values from within setInterval

I've been stuck on this problem for a while now. I'm using jQuery's .data() method to store state in a plugin I'm writing. Everything works fine, except for when I try to retrieve these data values from within a setInterval block. I am able to see the jQuery object inside the setInterval block, but I'm not able to see values stored by the data() method.
tminusStart: function() {
return this.each(function() {
var $tminus = $(this).data("tminus.state", "running");
var intervalId = setInterval(function(tm) {
if ($tminus.tminusIsRunning()) {
$tminus.tminusDecrementCounter();
$tminus.data("tminus.settings").tick_event();
if ($tminus.tminusTimeRemaining() <= 0) {
$tminus.data("tminus.settings").expiration_event();
}
$tminus.text(tminus.tminusTimeRemaining);
}
else {
clearInterval(intervalId);
}
}, 1000, $tminus);
});
}
In the above code, the $tminus does return the jQuery object alright, but the calls to the functions - which are calling the .data() method - return undefined; so does the .data("tminus.settings") call.
Any help in understanding why .data() isn't working here would be greatly appreciated.
Rewrite of function removing cruft:
tminusStart: function() {
var tminus = this;
tminus.data("tminus.state", "running");
return this.each(function() {
console.log(tminus.data("tminus.state")); // "running"
var intervalId = setInterval(function() {
console.log(tminus.data("tminus.state")); // undefined
}, 1000);
});
}
I need to know why it's undefined in the setInterval block
What are tminusIsRunning and tminusDecrementCounter? Did you mean to call that under $tminus? Unless you're extending jQuery, those calls are going to error out. If you're using Chrome, check the Javascript Console, you should see something like: "Uncaught TypeError: Object [object Object] has no method 'tminusIsRunning'"
.data() doesn't work with xhtml + IE (see note in docs).
Alternatively, This looks like a jQ extension, so watch out for that. jQuery has a (IMO) bad habit of aliasing this all over the place. Make sure you don't have a dependency on this being something different than what it is. I suggest installing firebug and using console.log to log this in both the place where you set the value, and where you access it. If it's not the IE issue, I suspect this would locate it.
Finally figured it out. I'm using jasmine to test drive this and the jasmine-jquery library has a fixtures piece which I'm apparently not using correctly. I tested the code in a webpage and everything is now working according to plan. Now I just have to make sure all my tests are passing.
I won't accept my own answer since I didn't provide the necessary information to begin with. I appreciate everyone's time on this. I really wish I could have accepted someone's answer.

Categories