Scope question... I think...

  • Thread starter Daniel Smedegaard Buus
  • Start date
D

Daniel Smedegaard Buus

Consider this piece of code:

eval(" function f0825022001228918765(args)
{$.get('/xhr/video_player_comments_box.php',merge_objects({},
{\"category_id\":\"1\",\"clip_id\":\"371\"}, args),function(response){var
old =
$('#video_player_meta_box');old.hide().after(response);old.remove();});};
function f0825246001228918765(){ajaxify_form({
form_element_id:'commenting_form',
submit_url:'/json/core_create_clip_comment.php', track_input_states:true,
clear_texts_on_first_focus:true, post_data:{\"category_id\":\"1\"
\"clip_id\":\"371\"}, on_failure: function(response){
$(\"#info\").removeClass(\"thanksWriteComment_hide\").addClass(\"thanksWriteComment_show\"); }} );};
setTimeout('f0825246001228918765();', 100); ");

Why would this error out with "f0825246001228918765 is not defined"? Is this
a scope issue?

Thanks,
Daniel :)
 
D

Daniel Smedegaard Buus

Btw, I should probably say that the code is okay, if I simply eval what's
inside the function directly, instead of wrapping it in a randomly named
function and do a setTimeout on it, the code is properly executed.

However, I need to be able to declare functions in this way and call them
later, but it also fails with "not defined" issues.

I should probably be more specific: The script that you see there is loaded
via XHR (jQuery, to be exact) and put into a Shadowbox as HTML. Shadowbox,
however, seems to strip out/disregard script code within <script> tags,
e.g. if I were to retrieve via jQuery,

<script type="text/javascript">alert('I am loaded via XHR');</script>
<div onclick="alert('hi');">This is the Shadowbox contents</div>

, and open it in a Shadowbox, I get what's inside the div, and I can click
on it to get a "hi", but I don't get the alert box from the <script> tag.

So, I basically tried to extract all <script> embedded code from the loaded
content into a variable and eval() it on Shadowbox.onFinish, which works, I
can executed all the code, and I'd see the "I am loaded via XHR" message.

However, if I declare a function instead of doing the alert() message, this
function is somehow not within scope of the Shadowbox... At least, I can't
use it in onclick or elsewhere within the HTML in the Shadowboxed contents.
Neither by doing javascript:func_name(); in the address bar for that
matter, but more times than not this is the case anyway, so I don't think
that has much to do with my issue.

Any ideas where my code resides after this eval()? Is it destroyed again
after the eval? Is it possible to do a different type of eval() that
ensures my scope is intact?

Thanks :)
 
D

Daniel Smedegaard Buus

Daniel said:
[ramblings]

Aha! It's funny how writing about a problem gets your mind untangled
sometimes.

window.eval(<stuff>);

instead of

eval(<stuff>);

certainly makes the eval'ed code available in global scope!

However, can I be certain this works for all browsers?

Cheers.
 
H

Henry

Daniel said:
[ramblings]

Aha! It's funny how writing about a problem gets your mind
untangled sometimes.

window.eval(<stuff>);

instead of

eval(<stuff>);

certainly makes the eval'ed code available in global scope!

However, can I be certain this works for all browsers?

No, the correct thinking would be to expect it to fail in all browsers
and then consider yourself lucky if you observe a browser where it
works. The specification for - eval - (from ECMA 262 3rd Ed.Section
15.1.2.1) includes:-

| If value of the eval property is used in any way other than a
| direct call (that is, other than by the explicit use of its
| name as an Identifier which is the MemberExpression in a
| CallExpression), or if the eval property is assigned to,
| an EvalError exception may be thrown.

You handle statements like the above by assuming the worst (that the
exception will be thrown) unless you are writing for known
environments that you also know will not change from under you. Web
browse related environments don't tend to satisfy those conditions.
 
H

Henry

Consider this piece of code:

eval(" function f0825022001228918765(args)
setTimeout('f0825246001228918765();', 100); ");

Why would this error out with "f0825246001228918765 is not defined"?
Is this a scope issue?

Yes, eval execution contexts adopt the scope from the execution
context in which the - eval - call occurs, which is usually the scope
of a function, making functions declarations that get - eval- ed local
to those containing functions.
 
E

Erwin Moller

Daniel Smedegaard Buus schreef:
Consider this piece of code:

eval(" function f0825022001228918765(args)
{$.get('/xhr/video_player_comments_box.php',merge_objects({},
{\"category_id\":\"1\",\"clip_id\":\"371\"}, args),function(response){var
old =
$('#video_player_meta_box');old.hide().after(response);old.remove();});};
function f0825246001228918765(){ajaxify_form({
form_element_id:'commenting_form',
submit_url:'/json/core_create_clip_comment.php', track_input_states:true,
clear_texts_on_first_focus:true, post_data:{\"category_id\":\"1\"
\"clip_id\":\"371\"}, on_failure: function(response){
$(\"#info\").removeClass(\"thanksWriteComment_hide\").addClass(\"thanksWriteComment_show\"); }} );};
setTimeout('f0825246001228918765();', 100); ");

Why would this error out with "f0825246001228918765 is not defined"? Is this
a scope issue?

Thanks,
Daniel :)

Hi Daniel,

I cannot help at all with your issue.

But if you allow me to make an observation:
I see a short piece of code that contains strangely named functions, $,
eval, json, setTimeout, etc.
All on one line I expect.

I don't want to lecture you, but why do you program so messy?

Can't you approach your problem in a cleaner, more maintainable way?

Regards,
Erwin Moller

--
"There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult."
-- C.A.R. Hoare
 
L

Lasse Reichstein Nielsen

Daniel Smedegaard Buus said:
Consider this piece of code:

eval(" function f0825022001228918765(args)
{$.get('/xhr/video_player_comments_box.php',merge_objects({},
{\"category_id\":\"1\",\"clip_id\":\"371\"}, args),function(response){var
old =
$('#video_player_meta_box');old.hide().after(response);old.remove();});};
function f0825246001228918765(){ajaxify_form({
form_element_id:'commenting_form',
submit_url:'/json/core_create_clip_comment.php', track_input_states:true,
clear_texts_on_first_focus:true, post_data:{\"category_id\":\"1\"

(Missing comma here!)
\"clip_id\":\"371\"}, on_failure: function(response){
$(\"#info\").removeClass(\"thanksWriteComment_hide\").addClass(\"thanksWriteComment_show\"); }} );};
setTimeout('f0825246001228918765();', 100); ");

Why would this error out with "f0825246001228918765 is not defined"? Is this
a scope issue?

First of all: Why use eval for a fixed string at all? Just remove the
eval and unquote the string and execute it directly. Eval is evil.
And it makes the formatting completely impossible to read. I tried to
reformat it, but it didn't parse because of a missing comma before
\"clip_id\":\"371\"

Second: Don't use a string as first argument to setTimeout (that's
going to be eval'ed in the global scope at a later point, and ...
eval is evil :)
Instead just give the function itself as first argument to setTimeout.
There were once some browsers that didn't understand a function as
argument, but they should be all dead by now.

This is probably also your problem: Eval evaluates in the current scope,
which might not be the global scope, but the string passed to setTimeout
is evaluated in the global scope. If you use a function argument to
setTimeout, it should work.

Using window.eval instead of just eval will probably be safe eventually,
since many browsers are converging on making that evaluate the string
in the global context (whereas it has so far worked either as real eval,
or thrown an exception).

/L
 
J

Jorge

Consider this piece of code:

eval(" function f0825022001228918765(args)
{$.get('/xhr/video_player_comments_box.php',merge_objects({},
{\"category_id\":\"1\",\"clip_id\":\"371\"}, args),function(response){var
old =
$('#video_player_meta_box');old.hide().after(response);old.remove();});};
function f0825246001228918765(){ajaxify_form({
form_element_id:'commenting_form',
submit_url:'/json/core_create_clip_comment.php', track_input_states:true,
clear_texts_on_first_focus:true, post_data:{\"category_id\":\"1\"
\"clip_id\":\"371\"}, on_failure: function(response){
$(\"#info\").removeClass(\"thanksWriteComment_hide\").addClass(\"thanksWrit eComment_show\"); }} );};
setTimeout('f0825246001228918765();', 100); ");

Why would this error out with "f0825246001228918765 is not defined"? Is this
a scope issue?

Most likely. ISTM that you'd either modify the setTimeout:

setTimeout(function () { f0825246001228918765(); }, 100);

Or modify the eval :

eval("window.f0825022001228918765= function () { etc etc };")
 
D

Daniel Smedegaard Buus

Thanks to all for the feedback, It was a messy crap of piss-hack in the
first place.

FYI, the problem with javascript not being evaluated inside Shadowboxed HTML
can be worked around like this (if you use the jQuery adapter):

Shadowbox.init({
onFinish: function(element) {
// Shadowbox destroys javascript, so we extract and reinsert:
$('#shadowbox').after('<script
type="text/javascript">'+extract_js($('#shadowbox').html())+'</script>');
}
});

And, the function I've created for extracting the js looks like this:

/**
* Strips anything outside <script> tags, including the tags themselves,
* from input html and returns just the script code within these tags.
*
* @param html The text containing script tags.
* @return The javscript found inside html.
*/
function extract_js(html)
{
// Strip whitespace:
html = html.replace(/[ \n\f\r\v\t]+/g, ' ');

// Collect script sections:
var matches = html.match(/<script\b[^>]*>(.*?)<\/script>/gi);

// Got nothing? Return empty string:
if (is_empty(matches)) return '';

// Strip script tags from matches:
var code = '';
for (i=0; i<matches.length; ++i)
code += matches.replace(/(<script\b[^>]*>[ ]*(<\!--)*)
((\/\/[ ]*--\>)<\/script>)/gi, '');

// Return the extracted, raw code:
return code;
}
 
D

Daniel Smedegaard Buus

Daniel Smedegaard Buus wrote:

// Got nothing? Return empty string:
if (is_empty(matches)) return '';

Oups, sorry, that's one of my other funcs, you should of course just use
(matches.length == 0)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,123
Messages
2,570,740
Members
47,296
Latest member
EarnestSme

Latest Threads

Top