...

View Full Version : IE "Object Expected" Error



binaryWeapon
06-20-2008, 01:45 AM
I'm developing a UI using the <canvas> element and google's IE hack. Here comes the familiar line: The code works beautiful in FF but doesn't work in IE. I'm 90% sure that its not a problem with the canvas or google's hack. The error is "Object Expected" and the line number always is the line with my <body> tag. Here are the codes, but what I really need is some info on the error. What causes it? How to fix it? I could debug the code but I don't really have a ton of info.


<html>
<head>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
<script type="application/x-javascript">
function getInterval(start, end, num)
{
var difference;
var interval;
difference=end-start;
interval=difference/(num-1);
return interval;
}

function gradient(r1,g1,b1,r2,g2,b2,px)
{
var colors=new Array();
rInt=getInterval(r1,r2,px);
gInt=getInterval(g1,g2,px);
bInt=getInterval(b1,b2,px);
rC=r1;
gC=g1;
bC=b1;
for(i=0;i<px;i++)
{
colors[i]=new Array(rC,gC,bC);
rC+=Math.round(rInt);
gC+=Math.round(gInt);
bC+=Math.round(bInt);
}
colors[colors.length-1][0]=r2;colors[colors.length-1][1]=g2;colors[colors.length-1][2]=b2;
return colors;
}

function left(gr1,gg1,gb1,gr2,gg2,gb2,gl,go1,go2,sr,sg,sb,so1,so2,sl,innerw,outerw,innero,outero,h,innerr,inn erg,innerb,outerr,outerg,outerb)
{
var canvas = document.createElement("canvas");
canvas.id="left";
canvas.width=innerw+outerw+gl+sl;
canvas.height=h;
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");

grInt=getInterval(gr1,gr2,gl);
ggInt=getInterval(gg1,gg2,gl);
gbInt=getInterval(gb1,gb2,gl);
goInt=getInterval(go1,go2,gl);
soInt=getInterval(so1,so2,sl);
grC=gr1;
ggC=gg1;
gbC=gb1;
goC=go1;
soC=so1;

ctx.fillStyle = "rgba("+innerr+","+innerg+","+innerb+","+innero+")";
ctx.fillRect (canvas.width-innerw, 0, innerw, canvas.height);

for(i=1;i<=gl;i++)
{
ctx.fillStyle = "rgba("+grC+","+ggC+","+gbC+","+goC+")";
ctx.fillRect (canvas.width-(i+innerw), 0, 1, canvas.height);
grC+=Math.round(grInt);
ggC+=Math.round(ggInt);
gbC+=Math.round(gbInt);
goC+=goInt;
}

ctx.fillStyle = "rgba("+outerr+","+outerg+","+outerb+","+outero+")";
ctx.fillRect (canvas.width-(innerw+gl+outerw), 0, outerw, canvas.height);

for(i=1;i<=sl;i++)
{
ctx.fillStyle = "rgba("+sr+","+sg+","+sb+","+Math.round(soC*100)/100+")";
ctx.fillRect (canvas.width-(innerw+gl+outerw+i), 0, 1, canvas.height);
soC+=soInt;
}

}
</script>
</head>
<body onload="left(202,206,212,233,236,239,15,0.75,0.75,0,0,0,0.75,0,12,2,2,0.75,0.75,300,132,135,138,172,175,180) ;">
</body>
</html>

Yes, the HTML doesn't validate, but I haven't gotten to that step in the design process.

I googled the forum and the internet, I came up with that it could be caused by referencing an item in the document before it exists. Is there a problem in IE with using createElement+appendchild?

Trinithis
06-20-2008, 06:04 AM
I kind of got it to work. The colors in IE are not crisp like when loaded in firefox.

The canvas code I used is here http://me.eae.net/projects/iecanvas/



<html>
<head>
<script type="text/javascript" src="iecanvas.js"></script>
<script type="text/javascript">

function Color(r, g, b, a) {
if(arguments[0] instanceof Color) {
this.r = arguments[0].r;
this.g = arguments[0].g;
this.b = arguments[0].b;
this.a = arguments[0].a;
}
else {
this.r = r;
this.g = g;
this.b = b;
this.a = a !== undefined
? a
: 1
}
}
Color.prototype = {
toString: function() {
return [this.r, this.g, this.b, this.a].join(',');
}
};

function getInterval(start, end, num) {
var difference;
var interval;
difference = end - start;
interval = difference / (num - 1);
return interval;
}

function gradient(c1, c2, px) {
var colors = [];
var cInt = new Color(
Math.round( getInterval(c1.r, c2.r, px) )
, Math.round( getInterval(c1.g, c2.g, px) )
, Math.round( getInterval(c1.b, c2.b, px) )
)
var currC = new Color(c1);
for(var i = 0; i < px; i++) {
colors[i] = new Color(currC);
currC.r += cInt.r;
currC.g += cInt.g;
currC.b += cInt.b;
}
currC = colors[colors.length - 1];
currC.r = r2;
currC.g = grad2;
currC.b = b2;
return colors;
}

function left(
grad1
, grad2
, shadow
, inner
, outer
, gradLen, shadowLen, shadowAlphaEnd, innerW, outerW, height
) {
var canvas = document.createElement("canvas");
canvas.width = innerW + outerW + gradLen + shadowLen;
canvas.height = height;
canvas.id = "left";
document.body.appendChild(canvas);
ieCanvasInit("iecanvas.htc");
setTimeout(function() {
canvas = document.getElementById("left");
canvas.width = innerW + outerW + gradLen + shadowLen;
canvas.height = height;
var ctx = canvas.getContext("2d");
var gradInt = new Color(
Math.round( getInterval(grad1.r, grad2.r, gradLen) )
, Math.round( getInterval(grad1.g, grad2.g, gradLen) )
, Math.round( getInterval(grad1.b, grad2.b, gradLen) )
, getInterval(grad1.a, grad2.a, gradLen)
);
var gradC = new Color(grad1);
for(var i = 1; i <= gradLen; i++) {
ctx.fillStyle = "rgba(" + gradC + ")";
ctx.fillRect(
canvas.width - (i + innerW)
, 0
, 1
, canvas.height
);
gradC.r += gradInt.r;
gradC.g += gradInt.g;
gradC.b += gradInt.b;
gradC.a += gradInt.a;
}

shadow = new Color(shadow);
var shadowAlphaInt = getInterval(shadow.a, shadowAlphaEnd, shadowLen);
for(var i = 1; i <= shadowLen; i++) {
ctx.fillStyle = "rgba(" + shadow +")";
ctx.fillRect(
canvas.width - (innerW + gradLen + outerW + i)
, 0
, 1
, canvas.height
);
shadow.a += shadowAlphaInt;
}

ctx.fillStyle = "rgba(" + inner + ")";
ctx.fillRect(
canvas.width - innerW
, 0
, innerW
, canvas.height
);

ctx.fillStyle = "rgba(" + outer + ")";
ctx.fillRect(
canvas.width - (innerW + gradLen + outerW)
, 0
, outerW
, canvas.height
);
}, 1);
}

window.onload = function() {
left(
new Color(202, 206, 212, .75)
, new Color(233, 236, 239, .75)
, new Color(0, 0, 0, 0.75)
, new Color(132, 135, 138, 0.75)
, new Color(172, 175, 180, 0.75)
, 15, 12, 0, 2, 2, 300
);
}
</script>
</head>
<body>
</body>
</html>

binaryWeapon
06-20-2008, 06:56 PM
I tried your canvas library, didn't work for me. I also checked out the canvas demo on the iecanvas site. Didn't work in either case. Also in both cases, I could highlight a shape that was the exact shape that the canvas should be. Nothing was rendered on the canvas however. Also, the object expected error was gone, but now I was getting an error with the ctx.getContext("2d") line. I did some research and found this comment on a blog post (http://me.eae.net/archive/2005/12/29/canvas-in-ie/):


Has anyone tried using this with dynamically created canvases? I am creating a canvas using document.createElement on demand, which works in Safari and Firefox, but in IE the canvas doesn’t work … it seems canvas.context is defined and something like canvas.context.fillStyle has the correct inital value, but neither the canvas nor the context have methods so canvas.getContext() doesn’t work (for instance). After doing document.createElement(’canvas’), the behaviour is not applied for some non-trivial amount of time so called getContext is invalid until the behaviour has been applied. Not sure if the thread of execution blocks this until control is returned to the browser or not. In any case, by redesigning so my canvas is created early on, and the context is retrieved at some later time, it works.


After that I found another blog post (http://erik.eae.net/archives/2006/03/28/12.05.59/), which said this:


Normally, the canvas elements are initialized when the page is loaded but if you want to create canvas elements on the fly (or use them before the page has loaded) the following code should work:


var c = document.createElement("canvas");
document.body.appendChild(c);
// we need to init this for IE
if (typeof G_vmlCanvasManager != "undefined") {
G_vmlCanvasManager.initElement(c);
}

There is one more quirk. The canvas elements are recreated when initialized so do not store a reference to them before they are actually used.


I implemented this along with the excanvas.js file from their site, and everything worked beautifully.

Thank you so much for redesigning my codes (and putting up with my terrible naming conventions :p), I wouldn't have been able to get this far without that. Everything worked exactly right, except for one bug I had run into previously in which the opacity value had too many decimal places, which was stopping the borders from being rendered. I just added a line to round it to 5 decimal places, which should be far more than enough.

Here were my final codes:

<html>
<head>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
<script type="text/javascript">

function Color(r, g, b, a) {
if(arguments[0] instanceof Color) {
this.r = arguments[0].r;
this.g = arguments[0].g;
this.b = arguments[0].b;
this.a = arguments[0].a;
}
else {
this.r = r;
this.g = g;
this.b = b;
this.a = a !== undefined
? a
: 1
}
}
Color.prototype = {
toString: function() {
return [this.r, this.g, this.b, this.a].join(',');
}
};

function getInterval(start, end, num) {
var difference;
var interval;
difference = end - start;
interval = difference / (num - 1);
return interval;
}

function gradient(c1, c2, px) {
var colors = [];
var cInt = new Color(
Math.round( getInterval(c1.r, c2.r, px) )
, Math.round( getInterval(c1.g, c2.g, px) )
, Math.round( getInterval(c1.b, c2.b, px) )
)
var currC = new Color(c1);
for(var i = 0; i < px; i++) {
colors[i] = new Color(currC);
currC.r += cInt.r;
currC.g += cInt.g;
currC.b += cInt.b;
}
currC = colors[colors.length - 1];
currC.r = r2;
currC.g = grad2;
currC.b = b2;
return colors;
}

function left(
grad1
, grad2
, shadow
, inner
, outer
, gradLen, shadowLen, shadowAlphaEnd, innerW, outerW, height
) {
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width = innerW + outerW + gradLen + shadowLen;
canvas.height = height;
canvas.id = "left";
if (typeof G_vmlCanvasManager != "undefined") {
G_vmlCanvasManager.initElement(canvas);
}
if(navigator.appname=="Microsoft Internet Explorer"){ieCanvasInit("iecanvas.htc");}
setTimeout(function() {
canvas = document.getElementById("left");
canvas.width = innerW + outerW + gradLen + shadowLen;
canvas.height = height;
var ctx = canvas.getContext("2d");
var gradInt = new Color(
Math.round( getInterval(grad1.r, grad2.r, gradLen) )
, Math.round( getInterval(grad1.g, grad2.g, gradLen) )
, Math.round( getInterval(grad1.b, grad2.b, gradLen) )
, getInterval(grad1.a, grad2.a, gradLen)
);
var gradC = new Color(grad1);
for(var i = 1; i <= gradLen; i++) {
ctx.fillStyle = "rgba(" + gradC + ")";
ctx.fillRect(
canvas.width - (i + innerW)
, 0
, 1
, canvas.height
);
gradC.r += gradInt.r;
gradC.g += gradInt.g;
gradC.b += gradInt.b;
gradC.a += gradInt.a;
}
shadow = new Color(shadow);
var shadowAlphaInt = getInterval(shadow.a, shadowAlphaEnd, shadowLen);
for(var i = 1; i <= shadowLen; i++) {
ctx.fillStyle = "rgba("+ shadow +")";
ctx.fillRect(
canvas.width - (innerW + gradLen + outerW + i)
, 0
, 1
, canvas.height
);
shadow.a += shadowAlphaInt;shadow.a = Math.round(shadow.a*100000)/100000;
}

ctx.fillStyle = "rgba(" + inner + ")";
ctx.fillRect(
canvas.width - innerW
, 0
, innerW
, canvas.height
);

ctx.fillStyle = "rgba(" + outer + ")";
ctx.fillRect(
canvas.width - (innerW + gradLen + outerW)
, 0
, outerW
, canvas.height
);
}, 1);
}

window.onload = function() {
left(
new Color(202, 206, 212, .75)
, new Color(233, 236, 239, .75)
, new Color(0, 0, 0, 0.75)
, new Color(132, 135, 138, 0.75)
, new Color(172, 175, 180, 0.75)
, 15, 12, 0, 2, 2, 300
);
}
</script>
</head>
<body>
</body>
</html>

Tested in IE7, Opera 9.5, FF2.0.14, NS9, and Safari 3.1.2, all works like a charm.

Thanks again!

~bW

Trinithis
06-20-2008, 08:16 PM
I bet you can take out the setTimeout I placed the code in. I kinda suspected the
behaviour is not applied for some non-trivial amount of time so that's why I put in the timeout. Perhaps with the
if (typeof G_vmlCanvasManager != "undefined") {
G_vmlCanvasManager.initElement(c);
} you won't need it anymore.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum