function expand(element) {
var target = document.getElementById(element);
var h = target.offsetHeight;
var sh = target.scrollHeight;
var loopTimer = setTimeout('expand(\'' + element + '\')', 10);
if (h < sh) {
h += 1;
} else {
clearTimeout(loopTimer);
alert("伸縮完成");
}
target.style.height = h + "px"
}
\' is an escape character for ', so what this is doing is building a string that can be consumed as a function, which contains a parameter, which is wrapped in single quotes...
'expand(\''
The above portion "opens" the string, applies expand( as a literal, then an escaped ', followed by one more ' to close that portion of the string. So, the return on that is:
expand('
Next, they concatenate the value of element variable:
'expand(\'' + element
The string now contains:
expand('elementVariableValue
Next up is to open another literal string, add in another single quote (escaped), followed by the closing parenthese:
'\')'
this is evaluated to:
')
put it all together and you get:
expand('elementVariableValue')
(which is finally interpreted as a function for the timeout).
Now, with JavaScript, you can use both " and ' for string delimiters, so much easier might have been:
setTimeout("expand('" + element + "')", 10);
Code in your example is a recursive call. It's a timer and the callback is expand(element). Understand this, you can easy understand that var loopTimer = setTimeout('expand(\'' + element + '\')', 10); means another call to expand(element). However, function expand need a string parameter, so \'' + element + '\' it is. Finally, if element here equals to scaleid, we finally get expand('scaleid'), it is obviously another call to expand(). Cause it is in string, so \' is needed to escape it.
In Javascript you can pass as the first parameter of the function a string, this string is evaluated as if you use eval(). That code is like if you call the function expand("something") every 10 milliseconds.
Related
I’m loading the contents of a JS file using FileReader and dumping the results into a textarea container. I then want to run some checks on the actual JS file.
I know there are probably tools out there for this already (or better ways), but this is for a closed-environment project.
After the textarea contains the content of the JS file as one large string, I need to loop the string and find all instances of parseInt() to check if they have been supplied with a radix.
I would provide code, but I have nothing working at this point. Any ideas?
The following snippet will search the string value of your <textarea> element for parseInt() and output the occurences, with radix where applicable:
var textareaValue = 'var func = function(){' +
'var i = parseInt(1,1);' +
'var j = parseInt(10, 10);' +
'var k = parseInt(3) + j;' +
'};';
occurences = textareaValue.match(/parseInt\(.+?(, ?\d+)?\)/g);
occurences.forEach(function(occurence){
var hasRadix = /, ?\d+\)$/.test(occurence);
document.body.innerHTML += '<p>"' + occurence + '" has ' +
(hasRadix ? 'a' : 'no') + ' radix' +
(hasRadix ? ' (' + occurence.match(/, ?(\d+)\)$/)[1] + ')' : '') +
'.</p>';
});
Note that this is no actual syntax interpretation, it’s merely text analysis. You will have to go from the result, which comprises all the occurences of parseInt() as strings. Also, JavaScript allows whitespace, comments, expressions and other witchcraft at the text passage in question. You might to have to check for anything.
The actual regex /parseInt\(.+?(, ?\d+)?\)/g will demand…
parseInt( at the beginning of the match
any characters (might need to be expanded to include brackets, etc. by :punct:)
as optional group, determining whether a radix is supplied or not:
a comma, an optional space (might need to respond to any number of whitespace using *)
at least one digit (might need to limit to {1,2}, because only 2 to 36 are valid)
a trailing closing bracket.
The following function should be able to tell the difference between usages of parseInt with radix versus its usages without radix by simplistic regex matching:
function have_radix(str){
parseIntRegex = /parseInt\(.+?\)/g;
parseIntRegexWithRadix = /parseInt\(.+?(,.+?\))/g;
indices = [];
while ( (result = parseIntRegex.exec(str)) ) {
indices.push(result.index);
}
count = indices.length;
indices = [];
while ( (result = parseIntRegexWithRadix.exec(str)) ) {
indices.push(result.index);
}
diff = count - indices.length;
return diff;
}
As part of a homework I am trying to implement a JavaScript console similar to the one available in Firebug in a browser environment. From what I've picked up, eval() seems to be the easiest way to do this. However, my code runs into some problems on even very basic user input. For example:
var number = 5;
Causes a syntax error rather than just evaluating to undefined like it would in Firebug. Because of this I can't seem to declare variables at all inside the eval string. If I do something more simple like:
3 + 4 * Math.PI
It works correctly. I have tried to find an example of someone using eval() on a string containing a variable declaration, and I just can't seem to find anyone doing this.
Do I need to parse the user input completely using regular expressions before compiling it into a new string for eval()?
Can eval() understand semicolons as line breaks? I can't find people using these either.
function runMiniFirebug() {
var userInput = document.getElementById("user-input").value;
try {
var userOutput = eval('(' + userInput + ')');
document.getElementById("js-output").innerHTML += '<p class="input">>>>' + userInput + '<p>';
document.getElementById("js-output").innerHTML += '<p class="ouput">' + userOutput + '<p>';
}
catch(error) {
document.getElementById("js-output").innerHTML += '<p class="input">>>>' + userInput + '<p>';
document.getElementById("js-output").innerHTML += '<p class="error">' + error.message + '<p>';
}
}
EDIT:
So it seems the added parens are causing the error. This is a section from my instructors slides. Is the information incorrect, or am I just interpreting it incorrectly?
Strings that are delimited with { ... }
– You have to add extra parens so that JavaScript will know that the
braces are for object literals, not for delimiting statements.
• It never hurts to do this, so add parens routinely
– var test2 = "{ firstName: 'Jay', lastName: 'Sahn' }";
– var person = eval("(" + test2 + ")");
var userOutput = eval('(' + userInput + ')');
Why are you wrapping with parentheses? This creates the statement
(var number = 5;)
which is invalid syntax.
Simply remove the '(' + and + ')'.
As for your edit, that is referring to only evaluating single expressions. var number = 5; is not an expression, nor is alert(1 + 1); alert(2 + 2);. Wrapping either in parentheses will cause an error.
My input is many lines of text that looks like this:
a.b.c.d.e (f:g)
I need to turn this into
a.b.c.d.e (a/b/c/d/e/f?g)
Note that the dotted part (a.b.c.d.e) can have varying numbers of elements, so sometimes it'll be q.r.s.t, sometimes u.v.w.x.y.z and so on. I have a replace() that will give me (a.b.c.d.e.f?g), but what I need is then to turn all those .s into /s in the result.
Is there a way to do a replace inside a replace? Or should I just call replace() on the string twice?
Sorry if this question is poorly worded, I'm not awfully well versed at regular expressions in javascript.
A very crazy way of doing it:
var str = "a.b.c.d.e (f:g)";
var re = /([^\s]+)\s\(([^:]+):([^\)]+)\)/;
var newStr = str.replace(re, function(a,b,c,d){ return b + " (" + b.replace(/\./g,"/") + "/" + c + "?" + d + ")"; });
jsfiddle
You need to chain the calls to replace() one after the other.
var result = source.replace("foo", "bar").replace("oof", "rab");
A saner way :) http://jsfiddle.net/smfPU/
input = "a.b.c.d.e.w.x.y.z (f:g:h)";
output = input.replace(/:/g, "?");
outputparts = output.split("(");
left = outputparts[0];
middle = left.replace(/\./g, "/").trim();
right = outputparts[1];
output = left + "(" + middle + "/" + right;
document.write(output);
Is there a library for replacing using functions as argument
when I call this function
"foo[10]bar[20]baz".replacef(/\[([0-9]*)\]/g, function(a) {
return '[' + (ParseInt(a)*10) + ']';
});
it should return
"foo[20]bar[30]baz";
and when I call with this
"foo[10;5]bar[15;5]baz".replacef(/\[([0-9]*);([0-9]*)\]/g, function(a, b) {
return '_' + (ParseInt(a)+ParseInt(b)) + '_';
});
it should return
"foo_15_bar_20_baz"
Is there existing Cross-Browser library that have function like this or similar in JavaScript?
That's how the "replace()" function already works. If the second parameter is a function, it's passed a list of arguments that are pretty much the same as the array returned from the RegExp "exec()" function. The function returns what it wants the matched region to be replaced with.
The first argument to the called function is the whole matched string. The second and subsequent arguments are the captured groups from the regex (like your second example). Your second example, however, would need a function with one more parameter to hold the entire matched string.
Example:
var s = "hello world".replace(/(\w+)\s*(\w+)/, function(wholeMatch, firstWord, secondWord) {
return "first: " + firstWord + " second: " + secondWord;
});
alert(s); // "first: hello second: world"
As far as I know you can readily do something like this in javascript :
"foo[10]bar[20]baz".replace(/\[([0-9]+)\]/g, function() {
return '[' + (parseInt(arguments[1])*10) + ']';
});
This is afaik cross browser (notice that parseInt got no leading uppercase p), arguments contains the match, index 0 is the whole thing, 1 and so on are the captured groups.
How can I use javascript to add a number (any number between 0-100) followed by a underscore, before the variable value?
Example:
2000 becomes 12_2000 //a number of my choice is added followed by an underscore
hello becomes 12_hello
The number (12 in this case) is a constant chosen by me!
Thanks
i + '_' + x where i is the number and x is an arbitrary value.
Just use string concatenation:
var res = '12_' + myNum;
Or with a variable prefix:
var res = prefix + '_' + myNum;
This is just basic string concatenation, which can be done with the + operator:
var num = 2000;
"12_" + num;
// "12_2000"
var_name = "2000";
output = "12_" + var_name;
function prefixWithNumber(value, number) {
return number + "_" + value;
}
This expression is evaluated as (number + "_") + value. Since one of the operants in the first addition is a string literal, the second argument number is converted (coerced) to a string. The result is a string, which causes the third argument to be converted to a string as well.
This is what the JS engine does behind the scenes:
(number.toString() + "_") + value.toString();
Maybe you're looking for something like this:
Object.prototype.addPrefix = function(pre){
return pre + '_' + this;
};
This allows code like:
var a = 5;
alert(a.addPrefix(7));
or even:
"a string".addPrefix(7);
Joining an array can be faster in some cases and more interesting to program than "+"
[i, '_', myNum].join('')