SVGAnimatedLength instead of method argument, why?

21 views
Skip to first unread message

VK

unread,
Sep 26, 2006, 2:13:32 PM9/26/06
to
I was cleaning some old libraries and want to ask:
why some selected arguments in method calls are disregarded
(if supplied in the conventional way) and SVGAnimatedLength
object is used instead?

See comments in the script.


<html>
<head>
<title>Demo</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<script type="text/javascript">

var ns = 'http://www.w3.org/2000/svg';
var canvas = null;

function demo() {
canvas = document.createElementNS(ns, 'svg');
with (canvas) {
setAttribute('xmlns', ns);
setAttribute('width', 550);
setAttribute('height', 400);
setAttribute('viewBox', '0 0 '+550+' '+400);
setAttribute('preserveAspectRatio','none');
}
document.body.appendChild(canvas);

// The below doesn't work: instead of provided
// r value (50) Firefox creates some
// SVGAnimatedLength object and inserts it
// instead. Respectively the shape gets nuked

//drawCircle(100, 100, 50);


// *this* works - with arguments sent
// over function object properties:
drawCircleBar.x = 100;
drawCircleBar.y = 100;
drawCircleBar.r = 50;
drawCircleBar();


// Also you can try
//drawCircleFoo();
// no problem with literals

// what a hey?
}

function drawCircle(x, y, r) {
var circle = document.createElementNS(ns, 'circle');
with (circle) {
setAttribute('cx', x);
setAttribute('cy', y);
setAttribute('r', r);
}
canvas.appendChild(circle);
}


function drawCircleFoo() {
var circle = document.createElementNS(ns, 'circle');
with (circle) {
setAttribute('cx', 100);
setAttribute('cy', 100);
setAttribute('r', 50);
}
canvas.appendChild(circle);
}

function drawCircleBar() {
var circle = document.createElementNS(ns, 'circle');
with (circle) {
setAttribute('cx', drawCircleBar.x);
setAttribute('cy', drawCircleBar.y);
setAttribute('r', drawCircleBar.r);
}
canvas.appendChild(circle);
}

window.onload = demo;
</script>
</head>

<body>

</body>
</html>

Ken Stacey

unread,
Sep 26, 2006, 9:59:53 PM9/26/06
to dev-te...@lists.mozilla.org
VK,

I can't comment on the SVGAnimatedLength behaviour but drawCircle()
appears to work if you change the value argument name in
setAttribute() to something other than r :

function drawCircle(x, y, r) {
var circle = document.createElementNS(ns, 'circle');

var rad = r;


with (circle) {
setAttribute('cx', x);
setAttribute('cy', y);

setAttribute('r', rad);
}
canvas.appendChild(circle);
}

Ken Stacey
Software Mechanics

Boris Zbarsky

unread,
Sep 26, 2006, 10:08:58 PM9/26/06
to
VK wrote:
> function drawCircle(x, y, r) {
> var circle = document.createElementNS(ns, 'circle');
> with (circle) {
> setAttribute('cx', x);
> setAttribute('cy', y);
> setAttribute('r', r);

Inside the |with|, "r" means circle.r, which is defined by the SVG specification
to be an object of type SVGAnimatedLength representing the circle's current radius.

Had you used "cx" and "cy" instead of "x" and "y", those would have failed in
the same way.

Moral: Don't use |with|. It's a performance nightmare, and causes
hard-to-diagnose bugs like this.

-Boris

VK

unread,
Sep 27, 2006, 10:42:25 AM9/27/06
to
Boris Zbarsky wrote:
> Inside the |with|, "r" means circle.r, which is defined by the SVG specification
> to be an object of type SVGAnimatedLength representing the circle's current radius.

Wow! That's indeed an unexpected side effect, thank you for pointing
out. I will talk with my partner, he may be spending too much of time
with VBA :-)


P.S. Are you using some stricter chain resolution for SVG shapes or I'm
missing again something important here? Other blocks with the
conventional DOM elements seem do not have this problem:

<html>
<head>
<title>Doc</title>


<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

function test() {
f('200px');
}

function f(width) {
var obj = document.getElementById('foo');
with(obj) {
setAttribute('width', width);
}
alert(obj.getAttribute('width')); // '200'
}

window.onload = test;
</script>
</head>

<body>
<div id="foo" width="100px"></div>
</body>
</html>

Martin Honnen

unread,
Sep 27, 2006, 10:49:59 AM9/27/06
to
VK wrote:


> P.S. Are you using some stricter chain resolution for SVG shapes or I'm
> missing again something important here? Other blocks with the
> conventional DOM elements seem do not have this problem:

> function f(width) {
> var obj = document.getElementById('foo');
> with(obj) {
> setAttribute('width', width);
> }
> alert(obj.getAttribute('width')); // '200'
> }

> <div id="foo" width="100px"></div>

HTMLDivElement objects do not have a width property so the problem you
are looking for can't happen with width. Try align for instance
<http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-22445964>
and then you should see the same problem as in that SVG example.

--

Martin Honnen
http://JavaScript.FAQTs.com/

Boris Zbarsky

unread,
Sep 27, 2006, 11:05:59 AM9/27/06
to
VK wrote:
> P.S. Are you using some stricter chain resolution for SVG shapes or I'm
> missing again something important here?

The latter. ;)

> var obj = document.getElementById('foo');
> with(obj) {
> setAttribute('width', width);

...


> <div id="foo" width="100px"></div>

HTMLDivElement does not have a "width" property defined in the HTML DOM spec.
So "width" is not resolved on |obj| and we look further up the scope chain, to
the function.

-Boris

VK

unread,
Sep 27, 2006, 11:16:06 AM9/27/06
to

Martin Honnen wrote:
> HTMLDivElement objects do not have a width property so the problem you
> are looking for can't happen with width.

Thank you, I see now a more than serious reason to request some blocks
re-writting. It appears we were going by a minefield. The only reason
it did not exploded sooner is because of proprietary attributes
assigning/reading.


<OT>
I feel to save Mr. Zbarsky's statement about [with] (which is totally
correct) in my selected quotes file. I know one newsgroup and one man
in it who will just love it :-)
</OT>

Daniel Amelang

unread,
Sep 27, 2006, 11:44:33 PM9/27/06
to VK, dev-te...@lists.mozilla.org
> <OT>
> I feel to save Mr. Zbarsky's statement about [with] (which is totally
> correct) in my selected quotes file. I know one newsgroup and one man
> in it who will just love it :-)
> </OT>

<More OT>

In case that's a VB newsgroup that you're referring to, keep in mind
that the Visual Basic |with| (which you alluded to previously) doesn't
suffer as much from the same problems that the javascript |with| does.
This is because VB requires a period before the properties/methods of
the implied object. So this confusing javascript code:

var length = 10;
with ("string") {
alert(length);
}

would be (slightly) more clear if written in the VB |with| style
(which is invalid syntax in javascript), as follows:

var length = 10;
with ("string") {
alert(.length); // refers to the string's length (notice the '.')
alert(length); // refers to the var length
}

The '.' also allows for increased performance as the language
implementation doesn't have to search around nearly as much. Doesn't
mean that I really like VB |with|, either, but it's good to know
before you go raiding the castle :)

</More OT>

Dan

VK

unread,
Sep 28, 2006, 8:46:30 AM9/28/06
to
followup-to set: comp.lang.javascript


Daniel Amelang wrote:
> In case that's a VB newsgroup that you're referring to, keep in mind
> that the Visual Basic |with| (which you alluded to previously) doesn't
> suffer as much from the same problems that the javascript |with| does.

<OOT>
No I had in my mind comp.lang.javascript (where I already referenced
this thread).
But it is indeed a VB influence in the posted code as I originally
mentioned, I explained the stuff to the guy so we are changing the
relevant fragments.
That is a rather common issue though with web-development: especially
in small companies. There are not separate VBScript/ASP Department,
JavaScript Department, C# Department etc. There are one or two John
Doe's doing all stuff at once and all together. On some 3rd party
projects ordered to be extended - or incorporated into something else -
you may have to "switch the language" in your mind N times/minute. It
is like to have to speak at once with a British, a New Englander, a
Chinese and a Russian :-) There is always a risk to insert some word
from another language or use an expression literally taken from another
language: especially when you are feeling the cold breathing of
Deadline on your neck :-)

JavaScript/JScript doesn't have default object shortcut like the VB
family does, and this makes with() statements dangerous (ambiguous) in
many situations.
It also may make with(){...} resolution a run-time challenge for an
engine with a productivity impact. With default object shortcut that
would be nothing but a pre-processor tack easily done on the tokens'
parsing stage:
// this is a wishfull thinking,
// this code is wrong
with(foo.bar) { .property = x;}
that becomes first internally
foo.bar.property = x;
and only then goes into production. That would hardly work for
Crockford-Cornford scope management stuff with anonymous
FunctionExpression in with(). From other side we would not need it with
the conventional scope modifiers. Eh, you just start thinking about
it... :-)

Actually it seems that many programmers learned to emulate this feature
by javascript means: by using intermediary variables (alias):
var obj = foobar.foo.bar
obj.property1 = x;
obj.property2 = y;
is effectively an attempt to get "with() a la VB" (but lesser effective
as still run-time operations are involved).

I guess more on the matter (if more to come) would be more
appropriately discussed at comp.lang.javascript
</OOT>

VK

unread,
Sep 28, 2006, 11:50:58 AM9/28/06
to

Daniel Amelang wrote:
> In case that's a VB newsgroup that you're referring to, keep in mind
> that the Visual Basic |with| (which you alluded to previously) doesn't
> suffer as much from the same problems that the javascript |with| does.

<OOT>

Reply all
Reply to author
Forward
0 new messages