Archive for January, 2007

parse CDATA as DOM (with html tags parsed)

January 30, 2007

I am trying to use google maps openInfoWindowHtml to display data from a CDATA section in a static xml file which has html tags in it, like so:

<description><![CDATA[
<b>Sandi Jackson</b>, the wife of U.S. Rep. <a href=”http://www.econym.demon.co.uk”>Jesse Jackson</a>, vs. Darcel Beavers, the daughter of former alderman and Cook County Commissioner William Beavers, in a battle of political heavyweights who have already been trash-talking.
]]></description>

The code looks like this:

var description = ward.getElementsByTagName(“description”)[0];
GEvent.addListener(marker, “click”, function() {
if(description){
if(description.childNodes[0]){ marker.openInfoWindow(description.childNodes[0].nodeValue);
}
}
});
map.addOverlay(marker);

BTW, I found out a discussion about using XSLT to parse XML using Ajaxslt 0.4 in google maps mashup.

responseXML not working in IE

January 27, 2007

I was attempting to use Ajax.Requst object in Prototype.js to parse a static xml file, which worked in Firefox 2 but not IE 6 on PC. It turns out that in IE, the request returns responseText instead of responseXML. And it's due to my web host doesn't set Content-Type HTTP header for static file as application/xml,etc. (when served through php, you can set document header dynamically.)

I found out one discussion about the same issue here. People were trying to figure out a client side solution and most of the them mentioned using a hidden iframe as an intermediate holder and writing custom function to parse the responseText into the iframe.

http://www.quirksmode.org/blog/archives/2005/09/xmlhttp_notes_r_1.html

and

http://forums.devshed.com/javascript-development-115/prototype-returning-xml-379021.html

Solutions:

Server-side:

We need to set the MIME type to ‘text/xml’ or ‘application/xml’, like so:

/**php*/

header("Content-type: text/xml");
or
header("Content-type: application/xml");

Then print out the xml nodes as strings. The whole sample code is provided as follows:

<?php
//header("Content-type: text/xml");
header("Content-type: application/xml");
$xml_output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
$xml_output .= "<donors>";
$xml_output .= "<donor>Steven Spielberg</donor>";
$xml_output .= "<donor/>";
$xml_output .= "<donor/>";
$xml_output .= "</donors>";
echo $xml_output;
?>

Client side

Since currently no main stream browsers are supporting E4X, and parsing XML<->native JavaScript object involve overheads both physically (processing) and mentally (learning curve for something too small to be worth it), we will just use the old school JavaScript + Prototype Ajax.Request object. Like so:

function initApp()
{
new Ajax.Request(url, {
method: 'get',
onSuccess: function(req){
onResults(req);
}
}
);
}

function onResults(req)
{
//Render data
var info = req.responseXML;
var infoIE = req.responseXML.documentElement;
alert('results returned>>>>>>> ' + infoIE.firstChild.childNodes[0].nodeValue);
}

initApp();

Note that req.responseXML only works at FF but not IE while req.responseXML.documentElement works fine both at IE and FF.

multiple targets in Fuse

January 22, 2007

import com.mosesSupposes.fuse.*;

ZigoEngine.register(Shortcuts, FuseFMP);

var f:Fuse = new Fuse([{
Glow_color: haloColor,
Glow_blurX: 5,
Glow_blurY: 5,
Glow_strength: 2,
Glow_quality: 3,
duration: 0,
target: [ball_mc,halo_mc]
},
{
Blur_quality: 2,
Blur_blurX: 2,
Blur_blurY: 2,
duration: 0,
target: halo_mc
}]
);
f.autoClear = true;
f.start();

javascript to swf Beyond 101

January 18, 2007

The communication between Flash and HTML is manipulated by Javascript/ActionScript.

The 101 #1:

Javascript->Flash: window.document.myMovie.SetVariable(variable_name, value);

Flash -> Javascript: getURL(‘javascript:function_name()’);

The 101 #2:

Flash DOM:

/* This utility function resolves the string movieName to a Flash object reference based on browser type. */
function getMovieName(movieName) {
if (navigator.appName.indexOf(“Microsoft”) != -1) {
return window[movieName]
}
else {
return document[movieName]
}
}

The 101 #3:

When using “SetVariable” to pass values to swf, swf object is “labeled” as “myMovie” in HTML by the following two tags. <object id=”myMovie”…><<embed name=”myMovie”…>.

In the following statement:
window.document.myMovie.SetVariable(variable_name, value)

variable_name is type of String and value could be anything but when actually passed into swf, this value is converted to type of String in Flash. So any Object would become “Object”. Practically I have been using JASON (a special type of Array), Array and String. Use AS “watch()” function to invoke the subsequent functions to handle the arrived data. The following example demonstrate value passed from JASON object in HTML to Flash and used by Flash as Model/data.

// swf files
var swfs:String = “”;
//url requested when a banner was clicked
var links:String = “”;
//target of links, either “_self” or “_blank”
var targets:String = “”;

var slidesTotal;
//
function main() {
slidesTotal = swfs.length;
//a number from 0 to slidesTotal-1
rdmStart = Math.round(Math.random()*(slidesTotal-1));
genSlide(rdmStart);
}

function onData(){
main();
}

watchCallback = function (id, oldval, newval):Array {
var newvalArr = newval.split(“,”);
onData();
return newvalArr;
};
this.watch(“swfs”, watchCallback);
this.watch(“links”, watchCallback);
this.watch(“targets”, watchCallback);

swfs/links/targets originally resided in a JASON object in Javascript and were pared as 3 separate arrays before passed into Flash.

Beyond 101:

The adobe/macromedia site demonstrates how to pass variables by a user event (a button click) on the HTML. In most of my projects, I want instead to use JASON data to initialize the whole application. So I need the data in Flash as soon as swf is available.

To invoke the function call that passes the data, use something like:
window.onload = function(){parseJSONToFlash();};

Unfortunately it only works for IE (v6 on PC), not Firefox (v2 on PC).

The reason was probably the swf was not totally “initialized” when the “onload” get’s called. The trick was to use the following. So instead, we call the javascript in Flash. That guarantees that swf object is already available when the data arrives.

var callJas:String = ‘javascript:parseJSONToFlash()’;

getURL(callJas);

Also note that using this trick eliminates the need to invoke the javascript function in window.onload.

References:

Scripting with Flash 5(old school but most effective)
Using JavaScript with Flash Player(sept, 2005)
External API documentation
The quite popular tutorial on debut of External API at adobe.com
Flash Developer Center: Javascript API

call() function

January 11, 2007

The call() function is a generic method of any Function object. This function can be used in the following two scenarios:

1. Used as invokation to a callback function within another function;

2. if a function must be invoked as a method of an object, but is not actually stored as a method of that object ( I still don’t know how that could happen and I am interested in knowing)…

ActionScript:
public call(thisObject:Object, [parameter1:Object]) : Object

Usage:
function dosomeCallback(onReady:Function, scope, params):Void{
var x = 7;
var y = 5;
onReady.call(scope, params);
}
function saySomething(SomethingToSay:String):Void{
trace(SomethingToSay);
}
dosomeCallback(saySomething, null, “good morning!”);

About “thisObject”/first parameter in the function:

“In some situations, you might want thisObject to point somewhere else; for example, if a function must be invoked as a method of an object, but is not actually stored as a method of that object:

 

myObject.myMethod.call(myOtherObject, 1, 2, 3);

“You can pass the value null for the thisObject parameter to invoke a function as a regular function and not as a method of an object. For example, the following function invocations are equivalent:

 

Math.sin(Math.PI / 4)
Math.sin.call(null, Math.PI / 4)"

									

Grouping and nesting Fuses and triggering advance

January 6, 2007

Grouping, nesting and triggering advances all can be used to emulate overlapping layers in timeline tween.

Fuses can be blocked by using “simple generic Array square braces”(“[]”.) Grouped Fuses can be used to animate multiple objects simultaneously, or play all the animations at once.

import com.mosesSupposes.fuse.*;
ZigoEngine.register(Shortcuts);

var cir_mc:MovieClip;
var rec_mc:MovieClip;

var f:Fuse = new Fuse([{
x: 100,
y: 200,
duration: 1,
// trigger : .1,
target:cir_mc},
{
x: 100,
y: 200,
duration: 1,
trigger : .1,
target:rec_mc}
],
{
trigger: .1,
x: -10,
y: 200,
duration: 1,
target:rec_mc},
{
x: -10,
y: 100,
duration: 1,
target:cir_mc}
);
f.start();

Note that in the grouped Fuse, both durations of the animations need to be set, otherwise the second one would be treated as “zero-second tween”.

“Trigger:Advances the sequence prior to action completion”

“You may include other Fuse instances within a Fuse.

var f1:Fuse = new Fuse(action1, action2, action3);
var f2:Fuse = new Fuse(action4, f1, action5);
f2.start();”

Don’t rely on the order!

January 4, 2007

When using data in a format of array/JASON, don’t pull out the data based on the index of the object in the array/JASON. The reason is very obvious but wa always ignored: data would be disarrayed when items are inserted, deleted, or the order of the items are changed.

Instead, something (JASON) like this can be used:

var data:Object = {d0:”hello”, d1:new Array(), d2:new SimpleButton(), d7:123456};

trace(data.d1===undefined);

One drawback is now it takes a second line to really access the real data you need:

for (var j in data){if(j.indexOf(“d”, 1)) var info:Object = data[j]; }