Javascript: Array.from() not working as expected | XM Community
Skip to main content

Hey all,
I noticed that a bit of my code was not working properly when I put it into Qualtrics whereas when testing it with NodeJS it seemed to work fine. I narrowed it down to an array that I constructed as follows:
Array.from({length: 20}, (e, i) => i);
This should just produce an array of increasing number [0, 1, 2, ... , 19]. It works as expected in NodeJS, but when calling it in Qualtrics it creates an Array of length 20 but each element is undefined. Does anyone know why this is?

Support of Array.from() depends on your browser, not on Qualtrics. Browser compatibility is listed here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#browser_compatibility


https://community.qualtrics.com/XMcommunity/discussion/comment/48854#Comment_48854Hey TomG I didn't realize it depended on browser. Thanks for pointing that out. However, I tried both Chrome (ver. 104) and Safari (ver. 15). Neither seem to work. Maybe I'm confused on how browser compatibility works...


https://community.qualtrics.com/XMcommunity/discussion/comment/48860#Comment_48860Very strange. It is Qualtrics after all because it works in Chrome outside of Qualtrics. They must have their own Array.from that doesn't support sequencing correctly. Not sure why they would replace Array.from unless it is meant to be a polyfill and isn't implemented correctly.
Anyway, you can do it using spread syntax instead:
[...Array(20).keys()].slice();


I think this is affecting my google maps on one of our surveys. Is there a work around for this?

Error:
This site overrides Array.from() with an implementation that doesn't support iterables, which could cause Google Maps JavaScript API v3 to not work correctly.


I think this is affecting my google maps on one of our surveys. Is there a work around for this?

Error:
This site overrides Array.from() with an implementation that doesn't support iterables, which could cause Google Maps JavaScript API v3 to not work correctly.

You can try replacing the Qualtrics Array.from with your own Array.from polyfill from here. For example:

Qualtrics.SurveyEngine.addOnload(function() {
console.log(Array.from({length: 20}, (e, i) => i));
});

// Production steps of ECMA-262, Edition 6, 22.1.2.1
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError('Array.from requires an array-like object - not null or undefined');
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = itemsmk];
if (mapFn) {
A k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());

 


This does fix the array.from() but it is not loaded until after the call to Google Maps API even when adding to Qualtrics.SurveyEngine.addOnload(); still getting same error.

Below is how it is being implemented.

Qualtrics.SurveyEngine.addOnload(function(){

    Array.from = ...see above...

    var script = document.createElement('script');
    script.setAttribute("async","true");
    script.setAttribute("after","true");
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?v=3&key=amy-key]&callback=MakeMyMap';
    document.body.appendChild(script);

});

Qualtrics.SurveyEngine.addOnReady(function(){
    function MakeMyMap(){...makes map...};
});

This looks and feels correct.  Debugging locally it works but not in survey.

 


@KrisGourd,

Did you try putting the Array.from polyfill code as-is in the survey header (not in the addOnload function)?


@KrisGourd

Did the suggestion from @TomG work for you? I’m running into the same issue. Also tried placing the polyfill code into the header but nothing seems to work.

Happy to hear any further ideas on how to solve this issue!


Surely this is a bug that should be fixed? Leaving a comment to bump. It stops many js libraries and packages being used within the Qualtrics system.


Leave a Reply