ear-fung.us I’m a programmer. I’m also pro-grammar.

24Jul/082

script.aculo.us effects in AIR

I'm starting a new Adobe AIR project and was trying to add some snazzy script.aculo.us effects to my application. It worked fine in the preview mode, but when I actually ran the application, I got a sandbox error since AIR is very restrictive on "eval()" statements.

Error: Adobe AIR runtime security violation for JavaScript code
in the application security sandbox (eval)

Turns out that others have had this problem too. script.aculo.us apparently isn't planning on releasing an AIR-compatible version, but I found this great page where a developer re-wrote the code in question.

the offending code in in effects.js at line 254:

    eval('this.render = function(pos){ '+
      'if (this.state=="idle"){this.state="running";'+
      codeForEvent(this.options,'beforeSetup')+
      (this.setup ? 'this.setup();':'')+
      codeForEvent(this.options,'afterSetup')+
      '};if (this.state=="running"){'+
      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
      'this.position=pos;'+
      codeForEvent(this.options,'beforeUpdate')+
      (this.update ? 'this.update(pos);':'')+
      codeForEvent(this.options,'afterUpdate')+
      '}}');

In order to run this code in an AIR application, it can't be in an eval() statement.
To fix this problem, change that entire code block to:

	/*
	eval('this.render = function(pos){ '+
	'if (this.state=="idle"){this.state="running";'+
	codeForEvent(this.options,'beforeSetup')+
	(this.setup ? 'this.setup();':'')+
	codeForEvent(this.options,'afterSetup')+
	'};if (this.state=="running"){'+
	'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
	'this.position=pos;'+
	codeForEvent(this.options,'beforeUpdate')+
	(this.update ? 'this.update(pos);':'')+
	codeForEvent(this.options,'afterUpdate')+
	'}}');*/
	this.render = function(pos){

		if (this.state=="idle"){
			this.state="running";
			if(this.options["beforeSetupInternal"]) {
			this.options.beforeSetupInternal(this);
			}
			if(this.options["beforeSetup"]) {
				this.options.beforeSetup(this);
		}
		if(this.setup) {
			this.setup();
			}
		if(this.options["afterSetupInternal"]) {
			this.options.afterSetupInternal(this);
			}
		if(this.options["afterSetup"]) {
			this.options.afterSetup(this);
			}
		}
		if (this.state=="running"){
			pos=this.options.transition(pos)*this.fromToDelta+this.options.from;
			this.position=pos;
			if(this.options["beforeUpdateInternal"]) {
				this.options.beforeUpdateInternal(this);
			}
			if(this.options["beforeUpdate"]) {
				this.options.beforeUpdate(this);
			}
			if(this.update) {
				this.update(pos);
			}
			if(this.options["afterUpdateInternal"]) {
				this.options.beforeUpdateInternal(this);
			}
			if(this.options["afterUpdate"]) {
				this.options.beforeUpdate(this);
			}
		}
	}

Thanks King Maxemilian!

Comments (2) Trackbacks (0)
  1. I think there is an error. Near the end of the code snippet you are checking for this.options['afterUpdate'] and executing this.options.beforeUpdate(this) instead.

    This might be a smaller solution
    (I have not tested this)

    [code]
    this.render = (function() {
    function dispatch(effect, eventName) {
    if (effect.options[eventName+'Internal'])
    effect.options[eventName+'Internal'](effect);
    if (effect.options[eventName])
    effect.options[eventName](effect);
    }

    return function(pos) {
    if (this.state === "idle") {
    this.state = "running";
    dispatch(this, 'beforeSetup');
    if (this.setup) this.setup();
    dispatch(this, 'afterSetup');
    }
    if (this.state === "running") {
    pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
    this.position = pos;
    dispatch(this, 'beforeUpdate');
    if (this.update) this.update(pos);
    dispatch(this, 'afterUpdate');
    }
    }
    })();

    [/code]

    The indenting may not show up :)
    - JDD


Leave a comment


No trackbacks yet.