I'm having trouble with the following piece of code. The error occurs in the last line:
return p_Function.constructor.name + "(" + v_args + ")";
When I run it on Internet Explorer 8, the function returns undefined(). Howerver, it works perfectly for Google Chrome (returning FunctionName()). I think it's a problem with the "constructor" property, but I can't figure out how to solve it. I'm new to JavaScript, and I'd be glad if I could get some help with this.
Thanks in advance.
getFunctionExecutionString: function(p_Function){
var v_args = "";
if(p_Function.arg) {
for(var k=0; k < p_Function.args.length; k++) {
if(typeof p_Function.args[k] == "string"){
v_args += "\"" + p_Function.args[k].replace(/'/g, "") + "\",";
}
else{
v_args += p_Function.args[k] + ",";
}
}
v_args = trim(v_args,",");
}
return p_Function.constructor.name + "(" + v_args + ")";
}
};
Per How do I get the name of an object's type in JavaScript?
return p_Function.constructor.toString().match(/function (.{1,})\(/)[1] + "(" + v_args + ")";
Example:
var A = function A(){};
var a = new A();
console.log(a.constructor.toString().match(/function (.{1,})\(/)[1]);
Related
I have a recusive function that is supposed to loop through a json object and output the expression. However, my recusion seems to be off because it's outputting field1 != '' AND field3 == '' when it should be outputting field1 != '' AND field2 == '' AND field3 == ''
I've tried a couple different things and the only way I can get it to work is by creating a global variable outstring instead of passing it to the function. Where am I off? When I step through it, i see a correct result but once the stack reverses, it start resetting outstring and then stack it back up again but leaves out the middle (field2).
JSFiddle
function buildString(json, outstring) {
var andor = json.condition;
for (var rule in json.rules) {
if (json.rules[rule].hasOwnProperty("condition")) {
buildString(json.rules[rule], outstring);
} else {
var field = json.rules[rule].id;
var operator = json.rules[rule].operator;
var value = json.rules[rule].value == null ? '' : json.rules[rule].value;
outstring += field + ' ' + operator + ' ' + value;
if (rule < json.rules.length - 1) {
outstring += ' ' + andor + ' ';
}
}
}
return outstring;
}
var jsonObj = {"condition":"AND","rules":[{"id":"field1","operator":"!= ''","value":null},{"condition":"AND","rules":[{"id":"field2","operator":"== ''","value":null}]},{"id":"field3","operator":"== ''","value":null}]};
$('#mydiv').text(buildString(jsonObj, ""));
The function has a return of a string.
When you call the function recursively from within itself, you aren't doing anything with the returned string from that instance, just calling the function which has nowhere to return to
Change:
if (json.rules[rule].hasOwnProperty("condition")) {
buildString(json.rules[rule], outstring);
}
To
if (json.rules[rule].hasOwnProperty("condition")) {
// include the returned value in concatenated string
outstring += buildString(json.rules[rule], outstring);
}
DEMO
Why so complicated?
function buildString(obj) {
return "condition" in obj?
obj.rules.map(buildString).join(" " + obj.condition + " "):
obj.id + " " + obj.operator + " " + string(obj.value);
}
//this problem occurs quite often, write a utility-function.
function string(v){ return v == null? "": String(v) }
Okay, that title will sound a bit crazy. I have an object, which I build from a bunch of inputs (from the user). I set them according to their value received, but sometimes they are not set at all, which makes them null. What I really want to do, it make an item generator for WoW. The items can have multiple attributes, which all look the same to the user. Here is my example:
+3 Agility
+5 Stamina
+10 Dodge
In theory, that should just grab my object's property name and key value, then output it in the same fashion. However, how do I setup that if-statement?
Here is what my current if-statement MADNESS looks like:
if(property == "agility") {
text = "+" + text + " Agility";
}
if(property == "stamina") {
text = "+" + text + " Stamina";
}
if(property == "dodge") {
text = "+" + text + " Dodge";
}
You get that point right? In WoW there are A TON of attributes, so it would suck that I would have to create an if-statement for each, because there are simply too many. It's basically repeating itself, but still using the property name all the way. Here is what my JSFiddle looks like: http://jsfiddle.net/pm2328hx/ so you can play with it yourself. Thanks!
EDIT: Oh by the way, what I want to do is something like this:
if(property == "agility" || property == "stamina" || ....) {
text = "+" + text + " " + THE_ABOVE_VARIABLE_WHICH_IS_TRUE;
}
Which is hacky as well. I definitely don't want that.
if(['agility','stamina','dodge'].indexOf(property) !== -1){
text = "+" + text + " " + property;
}
If you need the first letter capitalized :
if(['agility','stamina','dodge'].indexOf(property) !== -1){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
UPDATE per comment:
If you already have an array of all the attributes somewhere, use that instead
var myatts = [
'agility',
'stamina',
'dodge'
];
if(myatts.indexOf(property) !== -1){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
UPDATE per next comment:
If you already have an object with the attributes as keys, you can use Object.keys(), but be sure to also employ hasOwnProperty
var item = {};
item.attribute = {
agility:100,
stamina:200,
dodge:300
};
var property = "agility";
var text = "";
if(Object.keys(item.attribute).indexOf(property) !== -1){
if(item.attribute.hasOwnProperty(property)){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
}
Fiddle: http://jsfiddle.net/trex005/rk9j10bx/
UPDATE to answer intended question instead of asked question
How do I expand the following object into following string? Note: the attributes are dynamic.
Object:
var item = {};
item.attribute = {
agility:100,
stamina:200,
dodge:300
};
String:
+ 100 Agility + 200 Stamina + 300 Dodge
Answer:
var text = "";
for(var property in item.attribute){
if(item.attribute.hasOwnProperty(property)){
if(text.length > 0) text += " ";
text += "+ " + item.attribute[property] + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
}
It's unclear how you're getting these values an storing them internally - but assuming you store them in a hash table:
properties = { stamina: 10,
agility: 45,
...
}
Then you could display it something like this:
var text = '';
for (var key in properties) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (h.hasOwnProperty(k)) {
text = text + ' ' h[k] + ' ' + k + '<br/>';
}
}
After chat, code came out as follows:
var item = {};
item.name = "Thunderfury";
item.rarity = "legendary";
item.itemLevel = 80;
item.equip = "Binds when picked up";
item.unique = "Unique";
item.itemType = "Sword";
item.speed = 1.90;
item.slot = "One-handed";
item.damage = "36 - 68";
item.dps = 27.59;
item.attributes = {
agility:100,
stamina:200,
dodge:300
};
item.durability = 130;
item.chanceOnHit = "Blasts your enemy with lightning, dealing 209 Nature damage and then jumping to additional nearby enemies. Each jump reduces that victim's Nature resistance by 17. Affects 5 targets. Your primary target is also consumed by a cyclone, slowing its attack speed by 20% for 12 sec.";
item.levelRequirement = 60;
function build() {
box = $('<div id="box">'); //builds in memory
for (var key in item) {
if (item.hasOwnProperty(key)) {
if (key === 'attributes') {
for (var k in item.attributes) {
if (item.attributes.hasOwnProperty(k)) {
box.append('<span class="' + k + '">+' + item.attributes[k] + ' ' + k + '</span>');
}
}
} else {
box.append('<span id="' + key + '" class="' + item[key] + '">' + item[key] + '</span>');
}
}
}
$("#box").replaceWith(box);
}
build();
http://jsfiddle.net/gp0qfwfr/5/
See my code
for (var i = 0; i < allTextLines.length; i++) {
var row_data = allTextLines[i];
console.log(row_data);
row_data = row_data.replace(/ /g,'');
try {
ir(row_data == "")
{
continue;
}
if (document.getElementById("devicesList").value.length > 0) {
document.getElementById("devicesList").value += ",";
}
document.getElementById("devicesList").value += row_data;
}
catch (oErr) {
not_read += 1;
console.log(oErr.message);
str_error_detail_rows += "<tr><td colspan='2'>Error :" + oErr.message + " could not read line# " + i + " while reading from file.</td></tr>";
}
}
when i run the code, in the console i got "ir is not defind" please someone help me. the code goes smooth when i remove str.replace. thanks.
ir(row_data == "")
should be
if(row_data == "")
The ir should be an if, I reckon - it's a typo.
To be perfectly frank, you really could have read through and practically immediately noticed the problem while paying attention.
I figured it out, thank you. I need to move the body to the html. Changed some tags in the body section.
}
else
{
window.alert ("You entered an invalid character (" + enterLetter + ") please re-enter");
secondPrompt();
}
}
</script>
<body onload = "firstPrompt();">
<h2>
Word Checker
</h2>
</body>
</html>
You can increment indexOf each time you find a match-
function indexFind(string, charac){
var i= 0, found= [];
while((i= string.indexOf(charac, i))!= -1) found.push(i++);
return found;
}
indexFind('It\'s more like it is today, than it ever was before','o');
/* returned value: (Array)
6,22,48
*/
Using indexOf recursively:
function findMatches(str, char) {
var i = 0,
ret = [];
while ((i = str.indexOf(char, i)) !== -1) {
ret.push(i);
i += char.length; //can use i++ too if char is always 1 character
};
return ret;
}
Usage in your code:
var matches = findMatches(enterWord, enterLetter);
if (!matches.length) { //no matches
document.write ("String '" + enterWord + "' does not contain the letter '" + enterLetter + ".<br />");
} else {
for (var i = 0; i < matches.length; i++) {
document.write ("String '" + enterWord + "' contains the letter '" + enterLetter + "' at position " + matches[i] + ".<br />");
}
}
Live Demo
Full source (with some tweaks from your last question)
Is there some way to render all the literal objects and the literal objects within them using mustache? Being a neophyte at this I wondered if the following would work...
var data2 = {};
data2["collector"]={"sname":"Collector", "lname":"Collector", "V":[11,12,13,14,15]};
data2["storage"] ={"sname":"Storage", "lname":"Storage", "V":[21,22,23,24,25]};
data2["aux1"] ={"sname":"Aux1", "lname":"Loop High", "V":[31,32,33,34,35]};
data2["aux2"] ={"sname":"Aux2", "lname":"Loop Low", "V":[41,42,43,44,45]};
data2["aux3"] ={"sname":"Aux3", "lname":"Aux3", "V":[51,52,53,54,55]};
data2["aux4"] ={"sname":"Aux4", "lname":"Aux4", "V":[61,62,63,64,65]};
var T2 = "<table border='1'>" +
"{{#.}}<tr>" +
"{{#.}}" +
"<td>{{.}}</td>" +
"{{/.}}" +
"</tr>" +
"{{/.}}" +
"</table>"
html = Mustache.to_html(T2, data2);
but of course it doesn't. I get
{{/.}}
Since the goal was to use mustache, here's the final deal using mustache to expand the array.
I don't know if Jesse meant to put embedded literal objects in tables within table or not but that was not my goal. I deleted wrap and all from the function in this version as I either didn't need them or understand why they were there. I remain indebted to Jesse for this hint; I doubt I would have come up with anything so clever.
var getMustache = function(data, depth)
{
var r = "";
if (depth == 0)
{
r=r+"<tr>";
}
for(var d in data)
{
if(data.hasOwnProperty(d))
{
if(typeof data[d] =="object")
{
if (data[d].length) // is it an array?
{
var T = "{{#" + d + "}}<td>{{.}}</td>{{/" + d + "}}";
r += Mustache.to_html(T, data);
}
else
{
r += getMustache(data[d], depth+1);
}
}
else
{
r += "<td>" + data[d] + "</td>";
}
}
if (depth == 0)
{
r=r+"</tr>";
}
}
return r;
}
var T2 = "<table border='1'>" + getMustache(data2,0) + "</table>";
html = Mustache.to_html(T2, data2);
document.write(html);
Seems like you could just make a recursive function for this - mustache is pretty static, but recursion is perfect for looking up all the nodes in a deep object.
Untested hypothetical code:
var data2 = {};
data2["collector"]={"sname":"Collector", "lname":"Collector", "V":[11,12,13,14,15]};
data2["storage"] ={"sname":"Storage", "lname":"Storage", "V":[21,22,23,24,25]};
data2["aux1"] ={"sname":"Aux1", "lname":"Loop High", "V":[31,32,33,34,35]};
data2["aux2"] ={"sname":"Aux2", "lname":"Loop Low", "V":[41,42,43,44,45]};
data2["aux3"] ={"sname":"Aux3", "lname":"Aux3", "V":[51,52,53,54,55]};
data2["aux4"] ={"sname":"Aux4", "lname":"Aux4", "V":[61,62,63,64,65]};
var getMustache = function(data, wrap, all, depth){
var r = "";
var depth = depth || 0;
for(var d in data){
if(data.hasOwnProperty(d)){
r += "<" + wrap[depth] || all + ">";
if(data[d].length){
r += "{{#" + d + "}}";
r += getMustache(data[d], wrap, all, depth ++);
r += "{{/" + d + "}}";
} else {
r += "{{" + data[d] + "}}";
}
r += "</" + wrap[depth] || all + ">";
}
}
return r;
}
var T2 = "<table border='1'>" + getMustache(data2,['tr','td'],'span');
html = Mustache.to_html(T2, data2);
The following works. It doesn't use mustache facilities at all. I plan to change it so that it uses mustache's iteration on the array.
var getMustache = function(data, wrap, all, depth)
{
var r = "";
if (depth == 0)
{
r=r+"<tr>";
}
for(var d in data)
{
if(data.hasOwnProperty(d))
{
if(typeof data[d] =="object")
{
r += getMustache(data[d], wrap, all, depth+1);
}
else
{
r += "<td>" + data[d] + "</td>";
}
}
if (depth == 0)
{
r=r+"</tr>";
}
}
//alert("r=" + r);
return r;
}