I have for loop which goes through the array with arguments. When next argument is "?", "&" or "||", it shouldn't add comma, however, it always adds. I couldn't understand why, here is the code:
var args = ["arg1","arg2","?","arg3"];
var query = "";
for (var i = 0; i < args.length; i++) {
switch (args[i]) {
case "?":
query += " where ";
break;
case "&":
query += " and ";
break;
case "||":
query += " or ";
break;
default:
if (args[i+1] != "?");
{
query += args[i] + ", ";
break;
}
query += args[i] + " ";
break;
}
}
document.write(query);
When I type this (this is splitted by " " and sent to array args):
arg1 arg2 ? arg3
It prints it like this:
arg1, arg2, where arg3, // while it should be arg1, arg2 where arg3,
Thanks for helping people, problem was caused by an extern script. And yes, I removed semicolon ;)
Your if statement is broken:
if (args[i+1] != "?"); // <---- remove that semicolon
{
query += args[i] + ", ";
break;
}
You've got a stray semicolon. It is not a syntax error, but it means the if doesn't do anything. The code that adds the comma always runs, and exits the switch before the code that doesn't add the comma.
You have a semicolon between your if and your block:
if (args[i+1] != "?");
Should be
if (args[i+1] != "?")
There may be completely different ways to solve this problem which would make your code easier to extend without deepening trees of if or switch
A quick example,
// define some dictionaries
let logicDict = Object.assign(Object.create(null), {
'?': 'where',
'&': 'and',
'||': 'or'
});
// define some flags
let noComma = false;
// reduce your array
['arg1', 'arg2', '?', 'arg3'].reduceRight((str, e) => {
if (e in logicDict) {
noComma = true;
return logicDict[e] + ' ' + str;
}
if (!noComma) e += ',';
noComma = false;
return e + ' ' + str;
}, '').slice(0, -1);
// "arg1, arg2 where arg3,"
Thanks for noticing semicolon guys, problem was caused by an extern script.
Related
I am trying to get a code for a webpage using javascript. But I only want to return lines that include the word "array"
How can I remove all lines that do not include "array?"
I can't find anything online and my skills are very basic.
"I type this sentence because it says the post is mostly a code, and it still says the same so I'm just extending this."
function DOMtoString(document_root) {
var sourcecode = '',
node = document_root.firstChild;
while (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
sourcecode += node.outerHTML;
break;
case Node.TEXT_NODE:
sourcecode += node.nodeValue;
break;
case Node.CDATA_SECTION_NODE:
sourcecode += '<![CDATA[' + node.nodeValue + ']]>';
break;
case Node.COMMENT_NODE:
sourcecode += '<!--' + node.nodeValue + '-->';
break;
case Node.DOCUMENT_TYPE_NODE:
// (X)HTML documents are identified by public identifiers
sourcecode += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
break;
}
node = node.nextSibling;
}
var public = sourcecode.substring(
sourcecode.lastIndexOf("'[[") + 1,
sourcecode.lastIndexOf("]]';")
);
var matematika = sourcecode.substring(
sourcecode.lastIndexOf("var arraypaginascopia;") + 1,
sourcecode.lastIndexOf("var rellenado;")
);
var test = ("testovaci zprava");
var test2 = ("testovaci zprava druha");
var fail = ("Internal Error");
//arrayrespuestas
var currenturl = document.URL;
var url = currenturl.includes("www.liveworksheets.com/workbooks")
//return url;
if (url == true){
return matematika;
} else {
return public;
}
For example:
This is an example
This is an example
This is an example
This is a banana
This is an example
This is an example
This is a banana
The result should be:
This is a banana
This is a banana
In your question, you asked for the word array, but I'll use your example banana for the code.
const regex = /.*banana.*/gm;
// (.*) matches any character before and after the search string 'banana';
// The g flag is to match all occurrences and;
// The m flag is for a multi-line string
const str = `This is an example
This is an example
This is an example
This is a banana
This is an example
This is an example
This is a banana`;
console.log(str.match(regex));
In the end, I managed to do this.
const regex = /.*array.*/gm;
// (.*) matches any character before and after the search string 'banana';
// The g flag is to match all occurrences and;
// The m flag is for a multi-line string
const matematika2 = matematika;
// console.log(matematika2.match(regex));
return matematika2.match(regex);
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) }
Update
I've come up with a concise solution to this problem, that behaves similar to node's vm module.
var VM = function(o) {
eval((function() {
var src = '';
for (var prop in o) {
if (o.hasOwnProperty(prop)) {
src += 'var ' + prop + '=o[\'' + prop + '\'];';
}
}
return src;
})());
return function() {
return eval(arguments[0]);
}
}
This can then be used as such:
var vm = new VM({ prop1: { prop2: 3 } });
console.assert(3 === vm('prop1.prop2'), 'Property access');
This solution overrides the namespace with only the identifier arguments taken.
Thanks to Ryan Wheale for his idea.
Short version
What is the best way to evaluate custom javascript expression using javascript object as a context?
var context = { prop1: { prop2: 3 } }
console.assert(3 === evaluate('prop1.prop2', context), 'Simple expression')
console.assert(3 === evaluate('(function() {' +
' console.log(prop1.prop2);' +
' return prop1.prop2;' +
'})()', context), 'Complex expression')
It should run on the latest version of node (0.12) and all evergreen browsers at the time of writing (3/6/2015).
Note: Most templating engines support this functionality. For example, Jade.
Long version
I'm currently working on an application engine, and one of its features is that it takes a piece of code and evaluates it with a provided object and returns the result.
For example, engine.evaluate('prop1.prop2', {prop1: {prop2: 3}}) should return 3.
This can be easily accomplished by using:
function(code, obj) {
with (obj) {
return eval(code);
}
};
However, the usage of with is known to be bad practice and will not run in ES5 strict mode.
Before looking at with, I had already written up an alternative solution:
function(code, obj) {
return (function() {
return eval(code);
}).call(obj, code);
}
However, this method requires the usage of this.
As in: engine.evaluate('this.prop1.prop2', {prop1: {prop2: 3}})
The end user should not use any "prefix".
The engine must also be able to evaluate strings like
'prop1.prop2 + 5'
and
'(function() {' +
' console.log(prop1.prop2);' +
' return prop1.prop2;' +
'})()'
and those containing calls to functions from the provided object.
Thus, it cannot rely on splitting the code string into property names alone.
What is the best solution to this problem?
I don't know all of your scenarios, but this should give you a head start:
http://jsfiddle.net/ryanwheale/e8aaa8ny/
var engine = {
evaluate: function(strInput, obj) {
var fnBody = '';
for(var prop in obj) {
fnBody += "var " + prop + "=" + JSON.stringify(obj[prop]) + ";";
}
return (new Function(fnBody + 'return ' + strInput))();
}
};
UPDATE - I got bored: http://jsfiddle.net/ryanwheale/e8aaa8ny/3/
var engine = {
toSourceString: function(obj, recursion) {
var strout = "";
recursion = recursion || 0;
for(var prop in obj) {
if (obj.hasOwnProperty(prop)) {
strout += recursion ? " " + prop + ": " : "var " + prop + " = ";
switch (typeof obj[prop]) {
case "string":
case "number":
case "boolean":
case "undefined":
strout += JSON.stringify(obj[prop]);
break;
case "function":
// won't work in older browsers
strout += obj[prop].toString();
break;
case "object":
if (!obj[prop])
strout += JSON.stringify(obj[prop]);
else if (obj[prop] instanceof RegExp)
strout += obj[prop].toString();
else if (obj[prop] instanceof Date)
strout += "new Date(" + JSON.stringify(obj[prop]) + ")";
else if (obj[prop] instanceof Array)
strout += "Array.prototype.slice.call({\n "
+ this.toSourceString(obj[prop], recursion + 1)
+ " length: " + obj[prop].length
+ "\n })";
else
strout += "{\n "
+ this.toSourceString(obj[prop], recursion + 1).replace(/\,\s*$/, '')
+ "\n }";
break;
}
strout += recursion ? ",\n " : ";\n ";
}
}
return strout;
},
evaluate: function(strInput, obj) {
var str = this.toSourceString(obj);
return (new Function(str + 'return ' + strInput))();
}
};
UPDATE 3: Once we figured out what you are really asking, the question is clear: you do not do that. Especially in the strict mode.
As an viable alternative to your approach please refer to the documentation on require.js, common.js and other libraries allowing you to load modules in the browser. basically the main difference is that you do not do prop1.prop2 and you do context.prop1.prop2 instead.
If using context.prop1.prop2 is acceptable, see jsfiddle: http://jsfiddle.net/vittore/5rse4jto/
"use strict";
var obj = { prop1 : { prop2: 'a' } }
function evaluate(code, context) {
var f = new Function('ctx', 'return ' + code);
return f(context)
}
alert(evaluate('ctx.prop1.prop2', obj))
alert(evaluate(
'(function() {' +
' console.log(ctx.prop1.prop2);' +
' return ctx.prop1.prop2;' +
'}) ()', obj))
UPDATE: Answer to original question on how to access properties with prop1.prop2
First of all, you can access your variable using dictionary notation, ie:
obj['prop1']['prop2'] === obj.prop1.prop2
Give me several minutes to come up with example of how to do it recursively
UPDATED:This should work (here is gist):
function jpath_(o, props) {
if (props.length == 1)
return o[props[0]];
return jpath_(o[props.shift()], props)
}
function jpath(o, path) {
return jpath_(o, path.split('.'))
}
console.log(jpath(obj, 'prop1.prop2'))
I want to change
every single quote to double quote
and
every double quote to single quote
in jquery or js.
var myString = " tes't tes\"t tes\"t te'st ";
console.log(myString);
for (i = 0; i < myString.length; i++) {
console.log(myString[i]);
if (myString[i] == "'") {
myString[i] == "\"";
continue;
}
if (myString[i] == "\"") {
myString[i] == "'";
continue;
}
}
console.log(myString);
But my function is not working well.
Please correct me.
Inside the ifs you're not doing an assignment (myString[i] == "\"";) but a comparsion. This should probably be a single =. Only problem is, strings are immutable and thus this would not work as expected. Solution, build a new string:
function flipQuotes(str) {
var result = [], i = 0, lim = str.length, c;
for (; i < lim; i += 1) {
c = str.charAt(i);
switch(c) {
case '"':
result.push("'");
break;
case "'":
result.push('"');
break;
default:
result.push(c);
}
}
return result.join('');
}
var myString = " tes't tes\"t tes\"t te'st ";
console.log(
flipQuotes(myString) // => ' tes"t tes't tes't te"st '
);
You are doing comparations, not assingments. Also, you can't change a string that way, you need to create a new one:
var myString = " tes't tes\"t tes\"t te'st ";
console.log(myString);
var str = [];
for (i = 0; i < myString.length; i++) {
console.log(myString[i]);
if (myString[i] == "'") {
str.push("\"");
}
else if (myString[i] == "\"") {
str.push("'");
continue;
}
else
{
str.push(myString[i]);
}
}
str.join("");
console.log(str);
Check it in this live demo
Here is one more solution using different approach:
var myString = " tes't t%es\"t tes\"t te'st ",
result = myString.replace(/%/g, '\\%')
.replace(/'/g, '%')
.replace(/"/g, "'")
.replace(/[^\\]%/g, function (m) {
return m[0] + '"';
})
.replace('\\%', '%');
First, strings are immutable, any operation on strings like .replace() actually returns a new string. You can NOT do the following:
myString[ i ] = "x";
Your other mistake was using a comparison operator as assignment operator.
myString[ i ] == "x";
Knowing this, you need to construct a new string and replace the value of myString with the new value. One way of constructing a string is using the .split('') method to create an array representation of the string, perform mutations on the array and then revert back to string using the .join('') method of the array.
var myString = " tes't tes\"t tes\"t te'st ";
var tokens = myString.split('');
for (i = 0; i < tokens.length; i++) {
if (tokens[i] == "'") {
tokens[i] = "\"";
continue;
}
if (tokens[i] == "\"") {
tokens[i] = "'";
continue;
}
}
myString = tokens.join('');
console.log(myString);
Besides the incorrect use of == operator, you have another problem in your code:
myString[i] can be used to get the ith character of the string (in most browsers); but it cannot be used to "change" that character. This will work:
var a = myString[i];
This won't:
myString[i] = a;
Here is your code, re-written with minor changes plus the use of charAt and substring to read and change characters of string:
var myString = " tes't tes\"t tes\"t te'st ";
console.log(myString);
for (i = 0; i < myString.length; i++) {
if (myString.charAt(i) == "'") {
myString = myString.substring(0, i) + '"' + myString.substring(i + 1);
} else if (myString.charAt(i) == '"') {
myString = myString.substring(0, i) + "'" + myString.substring(i + 1);
}
}
console.log(myString);
Is there a quick function to convert JSON objects received via jQuery getJSON to a string variable dump (for tracing/debugging purposes)?
Yes, JSON.stringify, can be found here, it's included in Firefox 3.5.4 and above.
A JSON stringifier goes in the opposite direction, converting JavaScript data structures into JSON text. JSON does not support cyclic data structures, so be careful to not give cyclical structures to the JSON stringifier. https://web.archive.org/web/20100611210643/http://www.json.org/js.html
var myJSONText = JSON.stringify(myObject, replacer);
You can use console.log() in Firebug or Chrome to get a good object view here, like this:
$.getJSON('my.json', function(data) {
console.log(data);
});
If you just want to view the string, look at the Resource view in Chrome or the Net view in Firebug to see the actual string response from the server (no need to convert it...you received it this way).
If you want to take that string and break it down for easy viewing, there's an excellent tool here: http://json.parser.online.fr/
i personally use the jquery dump plugin alot to dump objects, its a bit similar to php's print_r() function
Basic usage:
var obj = {
hubba: "Some string...",
bubba: 12.5,
dubba: ["One", "Two", "Three"]
}
$("#dump").append($.dump(obj));
/* will return:
Object {
hubba: "Some string..."
bubba: 12.5
dubba: Array (
0 => "One"
1 => "Two"
2 => "Three"
)
}
*/
Its very human readable, i also recommend this site http://json.parser.online.fr/ for creating/parsing/reading json, because it has nice colors
Here is the code I use. You should be able to adapt it to your needs.
function process_test_json() {
var jsonDataArr = { "Errors":[],"Success":true,"Data":{"step0":{"collectionNameStr":"dei_ideas_org_Private","url_root":"http:\/\/192.168.1.128:8500\/dei-ideas_org\/","collectionPathStr":"C:\\ColdFusion8\\wwwroot\\dei-ideas_org\\wwwrootchapter0-2\\verity_collections\\","writeVerityLastFileNameStr":"C:\\ColdFusion8\\wwwroot\\dei-ideas_org\\wwwroot\\chapter0-2\\VerityLastFileName.txt","doneFlag":false,"state_dbrec":{},"errorMsgStr":"","fileroot":"C:\\ColdFusion8\\wwwroot\\dei-ideas_org\\wwwroot"}}};
var htmlStr= "<h3 class='recurse_title'>[jsonDataArr] struct is</h3> " + recurse( jsonDataArr );
alert( htmlStr );
$( document.createElement('div') ).attr( "class", "main_div").html( htmlStr ).appendTo('div#out');
$("div#outAsHtml").text( $("div#out").html() );
}
function recurse( data ) {
var htmlRetStr = "<ul class='recurseObj' >";
for (var key in data) {
if (typeof(data[key])== 'object' && data[key] != null) {
htmlRetStr += "<li class='keyObj' ><strong>" + key + ":</strong><ul class='recurseSubObj' >";
htmlRetStr += recurse( data[key] );
htmlRetStr += '</ul ></li >';
} else {
htmlRetStr += ("<li class='keyStr' ><strong>" + key + ': </strong>"' + data[key] + '"</li >' );
}
};
htmlRetStr += '</ul >';
return( htmlRetStr );
}
</script>
</head><body>
<button onclick="process_test_json()" >Run process_test_json()</button>
<div id="out"></div>
<div id="outAsHtml"></div>
</body>
something along this?
function dump(x, indent) {
var indent = indent || '';
var s = '';
if (Array.isArray(x)) {
s += '[';
for (var i=0; i<x.length; i++) {
s += dump(x[i], indent)
if (i < x.length-1) s += ', ';
}
s +=']';
} else if (x === null) {
s = 'NULL';
} else switch(typeof x) {
case 'undefined':
s += 'UNDEFINED';
break;
case 'object':
s += "{ ";
var first = true;
for (var p in x) {
if (!first) s += indent + ' ';
s += p + ': ';
s += dump(x[p], indent + ' ');
s += "\n"
first = false;
}
s += '}';
break;
case 'boolean':
s += (x) ? 'TRUE' : 'FALSE';
break;
case 'number':
s += x;
break;
case 'string':
s += '"' + x + '"';
break;
case 'function':
s += '<FUNCTION>';
break;
default:
s += x;
break;
}
return s;
}