Yet Another Bug of V2 — ScrollPane doesn’t emit “scroll” event when the content being dragged

 

Remember to place super in the correct scope when programing!

 

Testing environment:

23:51 2005-7-28

Windows Server 2003 sp1

Macromedia Flash Player 7.0  r19

V2 Component ScrollPane 2.0.1.78

 

Class mx.containers.ScrollPane

 

The ScrollPane component has an event named "scroll" which is design to be triggered when when a user clicks the scroll bar buttons, scroll box (thumb), or scroll track.

However, there is another case in which scrolling occurs. That is, when the scrollDrag property is set to true and a user drags within the ScrollPane.

 

After scratching my head for as much as one hour, I realized that there’s a bug in the ScrollPane component. The "scroll" event does not trigger when the user drags within the pane!

 

try this:

import mx.containers.ScrollPane;

var sp:ScrollPane = createClassObject(ScrollPane, "sp", this.getNextHighestDepth, {contentPath:"test.jpg",scrollDrag:true});

sp.setSize(500, 300);

this.sp.addEventListener("scroll", function(){trace("scroll");});

 

But the trace is only done when you drag the drag thumb:(

 

We are tough guys of CIFIAS so we have to track down this problem:)

In ScrollPane.as:

function startDragLoop(Void):Void

{

// tabFocused=false; removed during port to AS2.0

spContentHolder.lastX = spContentHolder._xmouse;

spContentHolder.lastY = spContentHolder._ymouse;

spContentHolder.onMouseMove = function()

{

var scrollXMove:Number = lastX-_xmouse;

var scrollYMove:Number = lastY-_ymouse;

scrollXMove += _parent.hPosition;

scrollYMove += _parent.vPosition;

var vm = _parent.getViewMetrics();

var vs = _parent.__height – vm.top – vm.bottom;

var hs = _parent.__width – vm.left – vm.right;

_parent.__hPosition = Math.max(0, Math.min( scrollXMove, _width – hs));

_parent.__vPosition = Math.max(0, Math.min( scrollYMove, _height – vs));

_parent.hScroller.scrollPosition = _parent.__hPosition;

_x = -_parent.hPosition; // – bounds.xMin;

_parent.vScroller.scrollPosition = _parent.__vPosition;

_y = -_parent.vPosition; // – bounds.yMin;

 

// emit scroll event in case of Dragging as well

super.dispatchEvent({type:"scroll"});

}

}

 

We can see that the designer of this class intended to emit the "scroll" event in case dragging. But how he/she failed?

The error is that the super keyword occurs in a scope where "this" is spContentHolder instead of an instance of ScrollPane.

To make it clear, we have to know about the super keyword.

The super keyword can only be used in a class definition.

According to Macromedia:

super

Availability

Flash Player 6.

Usage

super.method([arg1, …, argN])
super([arg1, …, argN
])

Parameters

method The method to invoke in the superclass.

arg1 Optional parameters that are passed to the superclass version of the method (syntax 1) or to the constructor function of the superclass (syntax 2).

Returns

Both forms invoke a function. The function can return any value.

 

Description

Operator: the first syntax style can be used within the body of an object method to invoke the superclass version of a method and can optionally pass parameters (arg1argN) to the superclass method. This is useful for creating subclass methods that add behavior to superclass methods but also invoke the superclass methods to perform their original behavior.

The second syntax style can be used within the body of a constructor function to invoke the superclass version of the constructor function and can optionally pass parameters to it. This is useful for creating a subclass that performs additional initialization but also invokes the superclass constructor to perform superclass initialization.

 

Very interesting, according to the first syntax, I guess super is an [object Object]. But the second syntax implies that it should be a [type Function]. Trough a long and tedious test, I can conclude that super and this are interrelated which means that super is always the super of this.

 

Here’s the right way to implement function startDragLoop:

function startDragLoop(Void):Void

{

// tabFocused=false; removed during port to AS2.0

spContentHolder.lastX = spContentHolder._xmouse;

spContentHolder.lastY = spContentHolder._ymouse;

spContentHolder.onMouseMove = mx.utils.Delegate.create(this, function()

{

var scrollXMove:Number = spContentHolder.lastX-spContentHolder.l_xmouse;

var scrollYMove:Number = spContentHolder.llastY-spContentHolder.l_ymouse;

scrollXMove += hPosition;

scrollYMove += vPosition;

var vm = getViewMetrics();

var vs = __height – vm.top – vm.bottom;

var hs = __width – vm.left – vm.right;

__hPosition = Math.max(0, Math.min( scrollXMove, _width – hs));

__vPosition = Math.max(0, Math.min( scrollYMove, _height – vs));

hScroller.scrollPosition = __hPosition;

spContentHolder.l_x = -hPosition; // – bounds.xMin;

vScroller.scrollPosition = __vPosition;

spContentHolder.l_y = -vPosition; // – bounds.yMin;

 

// emit scroll event in case of Dragging as well

super.dispatchEvent({type:"scroll"});

});

}

 

Unfortunately I cannot correct and recompile the ScrollPane component:(

Developers of V2, please come and have a look at this post 🙂

 

 

P.S.

My long and tedious test:

In the fla file, a MovieClip symbol is linked to AS2 class A.

It has a MovieClip instance name button inside.

//——–A.as——–

class A //extends MovieClip

{

function A() {

trace("—–In constructor A—–");

trace("super.sayHello(): " + super.sayHello());

trace("super: " + (super));

trace("super instanceof Object: " + (super instanceof Object));

trace("super instanceof MovieClip: " + (super instanceof MovieClip));

trace("super instanceof A: " + (super instanceof A));

trace("super instanceof B: " + (super instanceof B));

trace("this instanceof B: " + (this instanceof B));

trace("this == super: " + (this == super));

trace("super.__proto__: " + (super.__proto__));

trace("super.__proto__ == this.__proto__: " + (super.__proto__ == this.__proto__));

trace("super[\"constructor\"]: " + (super["constructor"]));

trace("super[\"constructor\"] == this[\"constructor\"]: " + (super["constructor"] == this["constructor"]));

trace("super[\"constructor\"] == B: " + (super["constructor"] == B));

trace("super[\"constructor\"] == A: " + (super["constructor"] == A));

trace("super[\"constructor\"] == MovieClip: " + (super["constructor"] == MovieClip));

trace("super[\"constructor\"] == Object: " + (super["constructor"] == Object));

trace("super[\"__constructor__\"]: " + (super["__constructor__"]));

trace("this[\"__constructor__\"]: " + (this["__constructor__"]));

trace("—–End of constructor A—–");

}

function sayHello() {

trace("Hello, I’m A");

}

}

 

//——–end of A.as——–

 

//——–B.as——–

import mx.utils.Delegate;

class B extends A {

var button:MovieClip;

function B() {

super();

trace("—–In constructor B—–");

trace("call super.sayHello(): ");

super.sayHello()

trace("super: " + (super));

trace("super instanceof Object: " + (super instanceof Object));

trace("super instanceof MovieClip: " + (super instanceof MovieClip));

trace("super instanceof A: " + (super instanceof A));

trace("super instanceof B: " + (super instanceof B));

trace("this instanceof B: " + (this instanceof B));

trace("this == super: " + (this == super));

trace("super.__proto__: " + (super.__proto__));

trace("super.__proto__ == this.__proto__: " + (super.__proto__ == this.__proto__));

trace("super[\"constructor\"]: " + (super["constructor"]));

trace("super[\"constructor\"] == this[\"constructor\"]: " + (super["constructor"] == this["constructor"]));

trace("super[\"constructor\"] == B: " + (super["constructor"] == B));

trace("super[\"constructor\"] == A: " + (super["constructor"] == A));

trace("super[\"constructor\"] == MovieClip: " + (super["constructor"] == MovieClip));

trace("super[\"constructor\"] == Object: " + (super["constructor"] == Object));

trace("super[\"__constructor__\"]: " + (super["__constructor__"]));

trace("this[\"__constructor__\"]: " + (this["__constructor__"]));

 

// button.onRelease = Delegate.create(this, function() {

 

//

 

trace(this);

 

//

 

super.sayHello();

 

//

 

});

 

button.onRelease = function() {

trace("—–In button.onRelease—–");

trace("super.sayHello(): " + super.sayHello());

trace("super: " + (super));

trace("super instanceof Object: " + (super instanceof Object));

trace("super instanceof MovieClip: " + (super instanceof MovieClip));

trace("super instanceof A: " + (super instanceof A));

trace("super instanceof B: " + (super instanceof B));

trace("this instanceof B: " + (this instanceof B));

trace("this == super: " + (this == super));

trace("super.__proto__: " + (super.__proto__));

trace("super.__proto__ == this.__proto__: " + (super.__proto__ == this.__proto__));

trace("super[\"constructor\"]: " + (super["constructor"]));

trace("super[\"constructor\"] == this[\"constructor\"]: " + (super["constructor"] == this["constructor"]));

trace("super[\"constructor\"] == B: " + (super["constructor"] == B));

trace("super[\"constructor\"] == A: " + (super["constructor"] == A));

trace("super[\"constructor\"] == MovieClip: " + (super["constructor"] == MovieClip));

trace("super[\"constructor\"] == Object: " + (super["constructor"] == Object));

trace("super[\"__constructor__\"]: " + (super["__constructor__"]));

trace("this[\"__constructor__\"]: " + (this["__constructor__"]));

trace("—–End of button.onRelease—–");

}

trace("—–End of constructor B—–");

}

}

 

//——–end of B.as——–

 

//——–output——–

—–In constructor A—–

super.sayHello(): undefined

super: _level0.test_mc

super instanceof Object: false

super instanceof MovieClip: false

super instanceof A: false

super instanceof B: false

this instanceof B: true

this == super: true

super.__proto__: undefined

super.__proto__ == this.__proto__: false

super["constructor"]: [type Function]

super["constructor"] == this["constructor"]: false

super["constructor"] == B: false

super["constructor"] == A: false

super["constructor"] == MovieClip: false

super["constructor"] == Object: true

super["__constructor__"]: undefined

this["__constructor__"]: [type Function]

—–End of constructor A—–

—–In constructor B—–

call super.sayHello():

Hello, I’m A

super: _level0.test_mc

super instanceof Object: false

super instanceof MovieClip: false

super instanceof A: false

super instanceof B: false

this instanceof B: true

this == super: true

super.__proto__: [object Object]

super.__proto__ == this.__proto__: false

super["constructor"]: [type Function]

super["constructor"] == this["constructor"]: true

super["constructor"] == B: false

super["constructor"] == A: true

super["constructor"] == MovieClip: false

super["constructor"] == Object: false

super["__constructor__"]: undefined

this["__constructor__"]: [type Function]

—–End of constructor B—–

—–In button.onRelease—–

super.sayHello(): undefined

super: _level0.test_mc.button

super instanceof Object: false

super instanceof MovieClip: false

super instanceof A: false

super instanceof B: false

this instanceof B: false

this == super: true

super.__proto__: undefined

super.__proto__ == this.__proto__: false

super["constructor"]: [type Function]

super["constructor"] == this["constructor"]: false

super["constructor"] == B: false

super["constructor"] == A: false

super["constructor"] == MovieClip: false

super["constructor"] == Object: true

super["__constructor__"]: undefined

this["__constructor__"]: undefined

—–End of button.onRelease—–

 

//——–end of output——–

 

Notice in the version of A.as above "extends MovieClip" is commented. If we uncomment itwe get:

//——–output——–

—–In constructor A—–

super.sayHello(): undefined

super: _level0.test_mc

super instanceof Object: false

super instanceof MovieClip: false

super instanceof A: false

super instanceof B: false

this instanceof B: true

this == super: true

super.__proto__: [object Object]

super.__proto__ == this.__proto__: false

super["constructor"]: [type Function]

super["constructor"] == this["constructor"]: true

super["constructor"] == B: false

super["constructor"] == A: false

super["constructor"] == MovieClip: true

super["constructor"] == Object: false

super["__constructor__"]: undefined

this["__constructor__"]: [type Function]

—–End of constructor A—–

—–In constructor B—–

call super.sayHello():

Hello, I’m A

super: _level0.test_mc

super instanceof Object: false

super instanceof MovieClip: false

super instanceof A: false

super instanceof B: false

this instanceof B: true

this == super: true

super.__proto__: [object Object]

super.__proto__ == this.__proto__: false

super["constructor"]: [type Function]

super["constructor"] == this["constructor"]: true

super["constructor"] == B: false

super["constructor"] == A: false

super["constructor"] == MovieClip: true

super["constructor"] == Object: false

super["__constructor__"]: [type Function]

this["__constructor__"]: [type Function]

—–End of constructor B—–

—–In button.onRelease—–

super.sayHello(): undefined

super: _level0.test_mc.button

super instanceof Object: false

super instanceof MovieClip: false

super instanceof A: false

super instanceof B: false

this instanceof B: false

this == super: true

super.__proto__: undefined

super.__proto__ == this.__proto__: false

super["constructor"]: [type Function]

super["constructor"] == this["constructor"]: false

super["constructor"] == B: false

super["constructor"] == A: false

super["constructor"] == MovieClip: false

super["constructor"] == Object: true

super["__constructor__"]: undefined

this["__constructor__"]: undefined

—–End of button.onRelease—–

 

//——–end of output——–

 

See the differences? I’m not going to point them out and do a thorough analysis here because… you know it’s really a long story of the object model of AS and I’ve already spent too much time on it… If you are particularly fond of this, it can’t be wrong to consult the ECMA 262, the prototype pattern, the book O’Reilly – Actionscript For Flash Mx The Definitive Guide, 2Nd Edition by Colin Moock and the Flash File Format Specification.

Remember to place super in the correct scope when programing!

Advertisements
This entry was posted in Flash and ActionScript. Bookmark the permalink.

9 Responses to Yet Another Bug of V2 — ScrollPane doesn’t emit “scroll” event when the content being dragged

  1. hazart says:

    Even though I can\’t understand much, this looks like one of the best bug reports I\’ve ever seen! Well done, Arrix; CIFIAS rocks!

  2. Arrix says:

    Thank you! It takes a village to be one CIFIAS member.Your msn space is really nice. Now I don\’t go to neowin nor winbeta, but msn space codename Hazart: )

  3. babe says:

    Arrix is a serious guy for life, I foresee///\’//…..

  4. Arrix says:

    原来你就是的成都的啊~~a sersious guy for life? Hope so…

  5. Unknown says:

    wow gold!All wow gold US Server 24.99$/1000G on sell! Cheap wow gold,wow gold,wow gold,Buy Cheapest/Safe/Fast WoW US EU wow gold Power leveling wow gold from the time you wWorld of Warcraft gold ordered!

    wow power leveling wow power leveling power leveling wow power leveling wow powerleveling wow power levelingcheap wow power leveling wow power leveling buy wow power leveling wow power leveling buy power leveling wow power leveling cheap power leveling wow power leveling wow power leveling wow power leveling wow powerleveling wow power leveling power leveling wow power leveling wow powerleveling wow power leveling buy rolex cheap rolex wow gold wow gold wow gold wow gold -29628135617210

  6. Unknown says:

    wow gold!All wow gold US Server 24.99$/1000G on sell! Cheap wow gold,wow gold,wow gold,Buy Cheapest/Safe/Fast WoW US EU wow gold Power leveling wow gold from the time you wWorld of Warcraft gold ordered!

    wow power leveling wow power leveling power leveling wow power leveling wow powerleveling wow power levelingcheap wow power leveling wow power leveling buy wow power leveling wow power leveling buy power leveling wow power leveling cheap power leveling wow power leveling wow power leveling wow power leveling wow powerleveling wow power leveling power leveling wow power leveling wow powerleveling wow power leveling buy rolex cheap rolex wow gold wow gold wow gold wow gold -34617107938088

  7. Unknown says:

    wow gold!All wow gold US Server 24.99$/1000G on sell! Cheap wow gold,wow gold,wow gold,Buy Cheapest/Safe/Fast WoW US EU wow gold Power leveling wow gold from the time you wWorld of Warcraft gold ordered!

    wow power leveling wow power leveling power leveling wow power leveling wow powerleveling wow power levelingcheap wow power leveling wow power leveling buy wow power leveling wow power leveling buy power leveling wow power leveling cheap power leveling wow power leveling wow power leveling wow power leveling wow powerleveling wow power leveling power leveling wow power leveling wow powerleveling wow power leveling buy rolex cheap rolex wow gold wow gold wow gold wow gold -209948357139696

  8. Unknown says:

    Hi,Do you have used LCDs, used flat screens and secondhand LCDs? Please go here:www.sstar-hk.com(Southern Stars).We are constantly buying re-usable LCD panels and working for LCD recycling.The re-usable panels go through strictly designed process of categorizing, checking, testing, repairing and refurbishing before they are re-used to make remanufactured LCD displays and TV sets.Due to our recent breakthrough in testing and repairing technology of LCD, we can improve the value for your LCD panels.
    Contact Us
    E-mail:sstar@netvigator.com
    website:www.sstar-hk.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s