Jump to content
Search Community

TypeError: setting a property that has only a getter

Zuriel test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts


			$(".featured-image").each(function(index, element){
			var tl = new TimelineLite({paused:true});
			var bottomImages = $(this).find('.bottom');
			var topImage = $(this).find('.top');
			var myHeight = bottomImages.height();
			tl.to(topImage, .5, {zIndex:20,opacity:1, border:'none', scale: '1', transformPerspective:660,rotationX:0, transformOrigin:"bottom center"})
			.to(topImage, .5, {zIndex:20,opacity:1, scale: '1', transformPerspective:660,rotationX:40, transformOrigin:"bottom center"})
			.to(bottomImages, .25, {scale:.8, ease:Power2.easeInOut}, 0.5)
			.to(bottomImages, .25, {y:myHeight, ease:Power2.easeInOut}, 0.5)
			.to(topImage,0,{zIndex:20,delay:1})
			element.animation = tl;
			})

why does y: throw that error?   it worked fine in 1.8.2 but when I updated to tweenmax 1.8.3 I get a error on y:myHeight    setting a property that only has a getter.   am I missing something that has changed in the syntax from 1.8.2 to 1.8.3

 

 

 

edit:  i fix it with this

 

			.to(bottomImages, .25, {scale:.8, position: 'relative', ease:Power2.easeInOut}, 0.5)
			.to(bottomImages, .25, {top:myHeight, ease:Power2.easeInOut}, 1)

 

should I make Y:  now top:   and do i need to set the position to relative?  its the only way i could get top: to work in this situation?   still would like to know why in 1.8.2 things worked fine? 

Edited by Zuriel
Link to comment
Share on other sites

When you say that you're setting a property that "only has a getter", what do you mean?

 

Version 1.8.0 introduced a new feature that allows you to omit the css:{} wrapper that had previously been necessary in order to clarify css-related properties. For example, you'd need to do this: 

 

//prior to 1.8.0, you'd have to wrap things in a css:{} object:
TweenLite.to(element, 1, {css:{y:100, zIndex:5}});

However, since we found that it was SO common for people to animate css-related properties and the css:{} wrapper was a bit cumbersome and slightly more error-prone in terms of nesting (developers might, for example, accidentally put the onComplete or ease inside the css:{} object), we added some detection inside TweenLite that checks to see if the target is a DOM element and you didn't define a css:{} object and the CSSPlugin was loaded - if all those criteria were true, it would assume your intent was to animate css-related properties and it would create the wrapper for you, putting all but the reserved properties into the css:{} object. 

 

That worked great in the vast majority of cases, but we started hearing a few complaints because some developers liked putting their own custom properties on DOM elements and animating those. For example:

 

myElement.xpos = 0; //DOM element with custom property
TweenLite.to(myElement, 1, {xpos:100, onUpdate:function() {
    //do stuff with myElement.xpos...
}});

This wouldn't work in 1.8.0 through 1.8.2 because the auto-detection would put the "xpos" in a css:{} wrapper, but CSSPlugin works with the element's "style" object properties, thus xpos wouldn't get animated properly. So in 1.8.3, we added a conditional check so that TweenLite only adds properties to the css:{} object that aren't already defined directly on the target. So in the example above, it would first see if "xpos" is defined on myElement. If so, it'll just tween it directly and NOT send it to CSSPlugin. 

 

I wonder if you added something like this which would cause problems:

 

myElement.y = function() {
    return someValue; 
}

If you did that, it would indeed break things because TweenLite's autoCSS detection would see that "y" is defined on your element and try tweening it directly. Since that function only serves as a getter and not a setter too, the new values that get applied during the tween wouldn't get applied (the function isn't doing anything with values it receives). See the issue? 

 

Even if you did the custom getter as above, there's an easy solution: define your css-related stuff inside a css:{} wrapper so that TweenLite doesn't have to guess which properties belong where.

 

Also, if you want a particular tween to skip any kind of auto css:{} creation internally, you can set autoCSS:false on the tween (inside the vars object). I don't think you'd want to do that here, though, because you are tweening css-related properties and you didn't create a css:{} wrapper of your own. 

 

Does that clear things up? Was I correct about you adding a "y" property directly to your element? 

  • Like 1
Link to comment
Share on other sites

well i mean i took the element and did the height  var myHeight = bottomImages.height();   but then I just did y: myHeight

 

i always though y was a default property, like x: y:  but maybe there is no x and y and thats really top and left?      but this exact code worked in 1.8.2 and in 1.8.3 it throws a javascript error and the error is "TypeError: setting a property that has only a getter"  

 

if i add css:{y:myHeight} it works.   so i guess the next question is..  if css is optional, when is it NOT optional.. i like not having to write css because its shorter, but i do not like having to write it randomly because i get a error..  that just makes me want to write it always because errors scare me.

Link to comment
Share on other sites

What kind of element are you animating? 

 

And no, x and y are NOT the same as left and top. "x" and "y" affect the transform: translate() values. 

 

As far as when css:{} is optional, I'd say always unless your element has an existing property directly on itself with the same name that you don't want to animate (that's EXTREMELY rare). I tried to explain the conditions above so that you understand what's happening under the hood and there's no confusion. Let me try in a more succinct way:

 

If (and only if) the target is a DOM element AND you have CSSPlugin loaded AND you didn't define a css:{} object AND you didn't set autoCSS:false, it will create a css:{} wrapper for you and add all non-reserved properties to that css object EXCEPT properties that already exist directly on the element itself. I honestly can't think of a time where this logic would fail, but obviously you must have found a scenario which makes me pretty curious - can you post a super simple HTML file that demonstrates the issue? Or a codepen link or jsfiddle? 

Link to comment
Share on other sites

I wonder if this has to do with the fact that you're using YUI and it's adding various getters to your elements without you realizing it. I see that the element has "x" and "y" properties directly on it. Instead of digging through all your code and YUI and trying to diagnose it in a much larger context, can you just create a very simple, isolated example file and either zip/post it here or put it on codepen or jsfiddle? Again, the goal is to create the simplest possible example that generates an error or funky behavior. Nobody else has reported a similar problem and when I try to tween "x" or "y" even using jQuery objects as the target, everything is working perfectly. 

 

As for the image artifacts around the edges, that definitely has nothing to do with GSAP, but I've seen it before in some webkit browsers and what helped was setting a zIndex (and maybe even add -webkit-backface-visibility:hidden" in your css, but that doesn't always make a difference). 

Link to comment
Share on other sites

http://jsfiddle.net/Zuriel/6BgHr/

 

Simplified it down into a backbone.js view with the mouse event being binded by a button, which is similar to how i am doing it on my site. 

 

you can easily fork this and experiement.  you will see that if you set the y to {css: { y    it instantly works.. just like you said...  but with no YUI logger and other stuff attached, so its pretty bare bones simple..   i hope this helps us solve things or maybe helps identify a mistake I am making.

 

 

also.  in safari this is the error:

 

TweenMax.min.js:17TypeError: Attempted to assign to readonly property.

 

 

and in firefox:

 

Edited by Zuriel
Link to comment
Share on other sites

Good news, I've figured it out ;-)
 
It seems that <img> elements come with a read-only DOM property y, while other elements do not. HTMLImageElement:
 

x: Read only long, like Netscape 4.
y: Read only long, like Netscape 4.

Note: The x and y properties were removed in Gecko 7.0 (Firefox 7.0 / Thunderbird 7.0 / SeaMonkey 2.4) but restored in Gecko 14.0 (Firefox 14.0 / Thunderbird 14.0 / SeaMonkey 2.11) for compatibility reasons.

 
Here's a very basic example showing if the y property exists.
 
In 1.8.3, when you skip the css wrapper, GSAP detects that y is a property of the image element and assumes that it's not meant for CSSPlugin. Jack has been correct that it was caused by the existing read-only y property, and now we know where it's coming from. Since it seems different versions of browsers will have different results for the existence of y, I'll leave it in Jack's hands to propose a solution. For now, you could revert to 1.8.2, change y to top, or use a css:{} wrapper for tweening <img>.y.

  • Like 4
Link to comment
Share on other sites

cool.  I will use the css wrapper for now.  I could also just wrap the image in a div and then the div won't have a y prop either.  but I am sure eventually someone may try to animate an image. 

 

Thank you Jack and Jamie for  the help ;)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...