Javascript Error: Cannot Convert Object to Primitive Value - javascript

I'm receiving this error using the following javascript code:
function tempTest(evt) {
alert(evt.currentTarget.id);
ct = document.getElementById(evt.currentTarget.id);
rslt = document.getElementById('rslt');
var props;
for (var prop in ct) {
if (ct.hasOwnProperty(prop)) {
propVal = ct[prop];
var propDat = prop + ' = ' + propVal;
props += propDat + '<br/>';
}
}
rslt.innerHTML = props;
}
This one has me puzzled. Any ideas?

Not all the properties of a HTML element are primitives. for example, parent, childs etc are also HTML elements. You can't just use them as strings or numbers.
You need to add there a condition and use that property accordingly.

If the object in question is json, you can call JSON.stringify(thingThatIsJson) which will return a String. .toString() does not work on json.
This is a message to those of you dealing with something like req.body which will work in console.log() which is rather confusing since it may not otherwise behave like a String (like when you're trying to add it to another String).

(The OP:)
Just wanted to post the updated snippet for anyone who stumbles onto this post...
function tempTest(evt) {
alert(evt.currentTarget.id);
ct = document.getElementById(evt.currentTarget.id);
rslt = document.getElementById('rslt');
var props;
for (var prop in ct) {
if (ct.hasOwnProperty(prop)) {
var propVal = ct[prop];
props += prop + ' (' + typeof(prop) + ')' + ' = ';
if (typeof(ct[prop]) == 'string') {
propVal += ct[prop];
} else {
if (propVal != null && propVal.toString) {
props += propVal.toString();
} else {}
}
props += '<br/>';
}
}
rslt.innerHTML = props;
}

The problem lies with the propVal part of your code. Since that may not be converted into a string.

Related

Is it possible to change default fallback message i18n-js?

I want to change fallback message on missing translation for i18n-js ([missing translation "en....."]) Is it possible and how to?
Thanks #Vasfed, but now i know easier way to do this.
Just add:
I18n.t("some.missing.scope", {defaults: [{message: "Some message"}]});
Instead of [missing translation "bla.bla.bla" ] you will get "Some message".
In library itself it is defined this way:
I18n.missingTranslation = function() {
var message = '[missing "' + this.currentLocale()
, count = arguments.length
;
for (var i = 0; i < count; i++) {
message += "." + arguments[i];
}
message += '" translation]';
return message;
};
you can replace this with your own implementation by reassigning I18n.missingTranslation after library is already evaluated.

Removing nulls from html popup

I would like to format the content of my popup so that null values are completely removed. At this point, my popup is filled with the features.properties array. There are 20 elements in properties, and depending on the queried feature, many of those values will be null.
var feature = features[0];
// Populate the popup and set its coordinates
// based on the feature found.
popup.setLngLat(feature.geometry.coordinates)
.setHTML('<div><b>' + feature.properties.city + '</div></b>' + '<div>'
+ feature.properties.course1 + '</div>' + '<div>'+
feature.properties.course2 + '<div>' + feature.properties.course3 + '</div>')
.addTo(map);
At this point, an example popup with some null values looks like this:
My aim is to eliminate null values and not to display them in the popup.
So far I've tried the JSON.stringify option instead of listing each element in separate <div> element.
function replacer(key, value) {
// Filtering out properties
if (value === "null" || value === null) {
return undefined;
}
return value;
}
JSON.stringify(feature.properties, replacer, "\t").replace(/\"/g, "").replace(/,/g, "")
This produces the desired result but then formatting is the problem.
The JSON object does not display well in a popup even when encasing it in <pre> tags, which produces:
I would like to know if there is a solution to format my popup so that it looks like the first image - but excludes null values. How can one do this is html by listing all of the property elements (course1, course2, course3, etc...) without producing a bunch of empty <div> s?
Here's one way using classic Javascript:
var features = {
properties: {
city: "Salzburg",
course1: "DCLead",
course2: "null",
course3: null,
field_1: "Hello"
}
};
function htmlFromProps(props, exclude) {
var html = "";
var i = 0;
for (p in props) {
if (props[p] && props[p] != "null" && exclude.indexOf(p) === -1) {
html += "<div>" + (i === 0 ? "<strong>" : "");
html += props[p];
html += (i++ === 0 ? "</strong>" : "") + "</div>\n";
}
}
return html;
}
popup.innerHTML = htmlFromProps(features.properties, ["field_1"]);
#popup {
width: 80%
}
<textarea id="popup"></textarea>
Use it by calling .setHTML(htmlFromProps(features.properties, [])) where the second argument is an array of fields you want to exclude.
You could try filtering your properties, see the example below:
var feature = {
properties: {
city: 'Salzburg',
course1: 'test',
course3: 'test3'
}
};
var html = Object
.keys(feature.properties)
.map(key => feature.properties[key])
.filter(value => value)
.map((value, i) => i === 0
? `<div><strong>${value}</strong></div>`
: `<div>${value}</div>`
)
console.log(html);
The crucial part is .filter(value => value) where filter makes sure that only truthy (non-null) values remain in the array.

ReactJS is it possible to render a string?

I have a code that returns a string, but since it's on render it needs to be accompanied by an HTML tag, in this case span.
I want to use this code in multiple places including placeholders and labels, but with span, I believe that's impossible.
Here's the code in question, would appreciate some ideas on how to fix.
let LocalizedString = React.createClass({
render: function() {
if (!this.getKey(loadLang, this.props.xlKey)) {
return <span>{this.props.xlKey + ' untranslated in ' + userLang + ' JSON'}</span>;
} else {
return <span>{this.getKey(loadLang, this.props.xlKey)}</span>;
}
},
getKey: function(obj, str) {
str = str.replace(/\[(\w+)\]/g, '.$1'); // let's convert indexes to properties
str = str.replace(/^\./, ''); // gets rid of leading dot
let a = str.split('.');
for (let i = 0, n = a.length; i < n; i++) {
let key = a[i];
if (key in obj) {
obj = obj[key];
} else {
return null;
}
}
return obj;
},
});
module.exports = LocalizedString;
In another file that calls LocalizedString, I have this, but makes placeholder return undefined...
<TextField alert={alerts.username} onChange={this._onChangeUsername} placeholder={<LocalizedString xlKey='pages.signin.general.username'/>} ref="username" value={this.props.username}/>
Bottom line is pretty much, can I make render return just a string without any tags or make placeholder accept and discard the span tag?
Regards.
You must have to use a function instead of a React Component as per the requirement.
React Component's render method must be bound to return single wrapped markup or essentially a Virtual DOM.

Detecting if input has been entered before

Lately I've been having trouble checking whether an input (player name) has been input more than once. This is not in-database, but just based on arrays contained within JavaScript. What I've been using after a couple of google searches was the indexOf() function. However this does not seem to work. My code is as follows:
var numberPlayers = 1;
var players = [];
var AddPlayer = function() {
if(!(players.indexOf($(".name")).val() > -1)) {
players.push($(".name").val());
$(".players").append("<p>Player number " + numberPlayers + " is " + $(".name").val() + "</p>");
numberPlayers++;
}
};
What method of detection would you recommend? I've tried looping, but wouldn't work either.
EDIT: Updated code. Still doesn't work!
Try this - note where the ) is placed:
if(!(players.indexOf($(".name").val()) > -1)) {
instead of:
if(!(players.indexOf($(".name")).val() > -1)) {
and actually, for readability this would be better:
var name = $('.name').val();
if ( players.indexOf(name) == -1)) {
In general, try adding console.log and breakpoints to find your bugs...
You can use an object (read Set / Hash) instead of an array; it should be faster anyway.
Note that I'm also using .text() which will escape text.
var numberPlayers = 1;
var players = {};
var AddPlayer = function() {
var newPlayer = $(".name").val();
if(!(newPlayer in players)) {
players[newPlayer] = true;
$(".players").append($("<p>").text("Player number " + numberPlayers + " is " + newPlayer));
numberPlayers++;
}
};
jQuery has a utility function for this:
$.inArray(value, array)
It returns the index of a value in an array. It returns -1 if the array does not contain the value.

Way to check a bunch of parameters if they are set or not in JavaScript

So, this happens to me quite frequently, but here's my latest one:
var generic_error = function(title,msg){
if(!title){ title= 'Oops!'; }
if(!msg) { msg = 'Something must have gone wrong, but no worries we\'re working on it!'; }
$.fancybox(
{
content:'\
<div class="error_alert">\
<h2>'+title+'</h2>\
<p>'+msg+'\
</div>'
});
}
Is there a cleaner way to check all params like title and msg above and OR set them as optional OR define defaults in the function like how PHP does it for example? Sometimes i could have 10 options and if(!var){var='defaults'} x 10 is icky...
Slightly shorter but equivalent to what you're doing now is to use "||" AKA "or" AKA "the default operator".
title = title || 'Oops!';
msg = msg || 'Something must have gone wrong, but no worries we\'re working on it!';
I doubt you'll find anything considerably shorter and simpler than if(!title)title='DefaultTitle' for function arguments.
However, I'd even use the longer form to make it more explicit: if (title===null) title='DefaultTitle'.
Here is a related question with an answer, but I think it would just makes your code more complicated. How can I access local scope dynamically in javascript?
You could use ternary notation as recommended by this article but in a simpler form:
var n = null;
!title ? title = 'Oops' : n;
You've also got the arguments[] array which holds the arguments and could be used in a loop, something like this:
function test(one,two,three) {
i=0;
while(typeof(arguments[i]) != 'undefined') {
alert(arguments[i++]);
}
}
test(40,27,399);
switch (arguments.length) {
case 0: title = 'Oops';
case 1: message = 'Something must have gone wrong...';
}
Here's another approach. The argsOK function is a little complex, but calling it is easy.
//-----------------------------------------------------
/*
PURPOSE Ensures a function received all required arguments, no extra
arguments & (if so specified) no arguments are empty.
RETURNS True if the arguments validate, else false.
*/
function argsOk(
functionCallee , // Caller's callee object
allArgsRequired , // True = All arguments are required
emptyArgsAllowed // True = Empty arguments are allowed
){
var ok = true;
for (var i = 0; i < 1; ++i) {
var functionName = functionCallee.toString().split(' ')[1].split('(')[0];
var args = functionCallee.arguments;
var expectedArgCount = functionCallee.length;
var actualArgCount = args.length;
if ((allArgsRequired && actualArgCount < expectedArgCount) ||
(actualArgCount > expectedArgCount)) {
error("Function " + functionName + " expected " + expectedArgCount + " arguments, but received " + actualArgCount + ".");
ok = false;
break;
}
if (emptyArgsAllowed) {
break;
}
for (var j = 0; j < args.length; ++j) {
if (args[j] != null && args[j].length == 0) {
error("Function " + functionName + "() received an empty argument.");
ok = false;
break;
}
}
}
return ok;
}
Example of calling it (a one-liner, as you can see):
//------------------------------------------------
function image(item, name, better)
// PURPOSE Write a request for picture or photo
// ENTRY Init() has been called
{
if (!showingShortVersion()) {
var betterString = '';
if (better != null && better == true)
betterString = 'better ';
if (argsOk(arguments.callee, true, false))
write('<p class="request maintain">If you have ac­cess to a ' + betterString + item + ' of ' + name + ' that we could put on­line, please click here.</p>');
}
}
In general, especially in Javascript, clean != short.
Do not use if(!title){ title= 'Oops!'; } as a general solution, because e.g. 0 and empty string are falsy, too. Arguments that are not set, are undefined, so I prefer using
if (title === undefined) {
title= 'Oops!';
}
It may be more wordy to do so, but It will prevent unwanted side effects, and in my experience, Javascript generates a lot of unwanted side effects, if you try to use shortcuts.

Categories

Resources