18 Replies Latest reply on Apr 11, 2009 1:27 AM by thejam82

    Start Drag button and get url

      Hi,

      Can someone please help re the below.

      I have a timeline with a movie clip with the instance 'first'. this is a series of logo with buttons that move from left to right. you can click and drag them right or left, and when you roll over them, it pauses the movie.

       

      The problem is now I need to make each logo link to a url.

      When I add for eg:

       

      on (release) {
          getURL("http://www.google.co.uk");
      }

       

      to the button within the movie, it does not work, it doesn't open up the url?

      Any ideas what actionscript or changes I need to make to allow each button to link to a url??

       

       

       

       

       

      goRight = true;

       

      _root.first.onRollOut = function() {
          goRight = true;
      };

       

      _root.first.onRollOver = function() {
          goRight = false;
      };

       

      _root.first.onPress = function () {
          startDrag(this, false, -7648, 0, 70, 0);
      };

       

      _root.first.onRelease = function () {
          stopDrag();
          goRight = true;
      };

       

      onEnterFrame = function () {
          if (goRight) {
              _root.first._x += 5;
          }
      };

        • 1. Re: Start Drag button and get url
          David Stiller Level 2

          thejam82,

           

               By the looks of it, your on(release) handler isn't working because it conflicts with the onRelease handler you already have in place.

           

               The on() and onClipEvent() functions are the earliest forms of event handling in Flash.  They're still supported in AS2, even though dot notation versions appeared in Flash MX (Flash Player 6).  It's even okay to mix them, but in this case you're setting two handler functions for the same event (release), so I recommend you stick with the dot notation approach and amend your code like this:

           

          _root.first.onRelease = function () {
            stopDrag();
            goRight = true;

            getURL("http://www.google.co.uk");
          };

           

               That means drop the directly attached on(release) code altogether.  See how the revised version accomplishes the same endeavor?

           

               Let me know if you have any questions.  Here's a bit more on the on()/onClipEvent() functions:

           

               http://www.quip.net/blog/2006/flash/museum-pieces-on-and-onclipevent

           

           

          David Stiller
          Co-author, ActionScript 3.0 Quick Reference Guide
          http://tinyurl.com/dpsAS3QuickReferenceGuide
          "Luck is the residue of good design."

          • 2. Re: Start Drag button and get url
            Level 1

            Hello David

            Many thanks for that and the kind reply.

            I have done as you said, and the reported error appeared:

             

            **Error** Symbol=Airlink logo, layer=Layer 1, frame=1:Line 1: Statement must appear within on handler
                 _root.first.onRelease = function () {

             

            Total ActionScript Errors: 1      Reported Errors: 1

             

            Where do I need to go from here please?

            Many thanks, much appreciated, Hope you can help here.

            Mark

            • 3. Re: Start Drag button and get url
              David Stiller Level 2

              thejam82,

               

                   Sounds like you're trying to attach timeline code to an object.  Make sure you've selected a keyframe first, then type or paste your code.  When code is attached directly to an object, it needs to appear within an on() or onClipEvent() function, which isn't what you're aiming for in this case.  Make sure my suggested code goes into the same keyframe that contains your other dot notation event handlers.  Make sense?

               

               

              David Stiller
              Adobe Community Expert
              Dev blog, http://www.quip.net/blog/
              "Luck is the residue of good design."

              • 4. Re: Start Drag button and get url
                Level 1

                David

                 

                Yes that makes sense, I took your code off the button and onto the main keyframe with all the other code.

                However what is happening now, is that, when exporting the movie, when you release the mouse on rolling over any logo, they all go to google. I have about 30 logos, that need individual urls. Hope that makes sense, are you able to suggest anything else? Would it be better to attach the fla as I see that is an option on here if you have time to have a quick look?

                Thank You

                • 5. Re: Start Drag button and get url
                  Level 1

                  I think what I require then now David, is a piece of code that tells a particular logo (button) to when 'on release' go to a certain url. Any ideas what this code is?

                  Thank you

                  • 6. Re: Start Drag button and get url
                    David Stiller Level 2

                    thejam82,

                     

                    > I think what I require then ... is a piece of code that tells a particular

                    > logo (button) to when 'on release' go to a certain url

                     

                         That's what I suggested in my first reply , but if you have 30 of these and want them to each to go to 30 different URLs, you'll have to supply individualized onRelease handlers for each button.  Or ... you could use a switch() statement to have each button check which button it is.  In that way, you can re-use your event handler functions.

                     

                         Assuming your instance names are first, second, third, and so on, I suggest something like this:

                     

                    first.goRight = true;

                    first.onRollOut = rollOutHandler;

                    first.onRollOver = rollOverHandler;

                    first.onPress = pressHandler;

                    first.onRelease = releaseHandler;

                    first.onEnterFrame = objectMover;

                     

                    second.goRight = true;

                    second.onRollOut = rollOutHandler;

                    second.onRollOver = rollOverHandler;

                    second.onPress = pressHandler;

                    second.onRelease = releaseHandler;

                    second.onEnterFrame = objectMover;

                     

                    // same for third, etc.

                     

                         So far, this associates each of your buttons -- by way of their instance names -- with the same set of functions.  Again, this assumes each button/movie clip is supposed to behave the same way.  The same, that is, except for which URL to visit.  For that, you'll see a switch() statement that checks the _name property of the button/clip in question and behaves accordingly.  Check it out:

                     

                    function rollOutHandler():Void {
                      this.goRight = true;
                    };

                    function rollOverHandler():Void {
                      this.goRight = false;
                    };

                    function pressHandler():Void {
                      this.startDrag(false, -7648, 0, 70, 0);
                    };

                    function releaseHandler() {
                      this.stopDrag();
                      this.goRight = true;

                      switch(this._name) {

                        case "first":

                          getURL("http://www.firstURL.co.uk/");

                          break;

                        case "second":

                          getURL("http://www.secondURL.co.uk/");

                          break;

                        case "first":

                          getURL("http://www.thirdURL.co.uk/");

                          break;

                        // etc.

                      }
                    };

                    function objectMover():Void {
                      if (this.goRight) {
                        this._x += 5;
                      }
                    };

                     

                         Again, all of this code would go into whatever frame contains these buttons/movie clips.  The only thing that has changed here is that you're using named functions instead of function literals (also known as anonymous functions).  This is a way to consolidate your code, which makes it easier to type (less typing!) and easier to maintain.

                     

                         Let me know if you have additional questions. 

                     

                     

                    David Stiller
                    Adobe Community Expert
                    Dev blog, http://www.quip.net/blog/
                    "Luck is the residue of good design."

                    • 7. Re: Start Drag button and get url
                      Level 1

                      Hi David

                      Thank you for the above, I'll be honest, I am slightly confused now, so I am hoping you will have a spare 5mins to  open the attached file in question. It will soon become apparent I hope to you where the problem lies. And of course when you drag and release it opens up a url you may not want to go to!

                      Hoping you can help!

                      http://spark.dessol.com/animation.zip

                      • 8. Re: Start Drag button and get url
                        David Stiller Level 2

                        thejam82,

                         

                             Aha.  Well, now I can see why you're confused by my previous reply.  It all comes down to communication.    You said you had numerous URLs for numerous buttons/clips, but you didn't mention that all of those were collected inside a single movie clip (the one you gave the instance name first).  This isn't a problem -- and in fact, you can still use the named functions I suggested -- but you'll only be assocating the first movie clip with the functions (there is no second, third, and so on; I thought those might be the instance names of each of the symbols inside first).

                         

                             I'm guessing now that you were attaching your on(release) code to the inside symbols, which makes a bit more sense over all.  The problem is, the code on those inner symbols was getting blocked, because the parent of those symbols -- first -- was "catching" all your mouse-related code.  Flash didn't "see" the your inner on(release) code, because the outer onRelease code was effectively blocking it.  In ActionScript 3.0, there's something called bubbling that allows you to listen for the events of nested assets, but that's a different story.

                         

                             In this case, you'll need instance names on each of your inner symbols (the logos), and you can keep the same instance name (first) on the movie clip that contains all of those inner symbols.  Instead of assigning an onRelease function to each of the inner symbols -- because they'd be blocked, remember -- you can use the MovieClip.hitTest() method to see if the mouse is within the bounds of each given logo when the mouse releases its click on the outer movie clip.

                         

                             My code suggestion is very nearly the same.  Here's the code (for the benefit if anyone else reading this post), and I'll intersperse with a bit of explanation.

                         

                        first.goRight = true;
                        first.onRollOut = rollOutHandler;
                        first.onRollOver = rollOverHandler;
                        first.onPress = pressHandler;
                        first.onRelease = releaseHandler;
                        first.onEnterFrame = objectMover;

                         

                             So far, nothing has changed.  You're simply referencing the first movie clip by its instance name and associating functions with various MovieClip events.

                         

                        function rollOutHandler():Void {
                          this.goRight = true;
                        };
                        function rollOverHandler():Void {
                          this.goRight = false;
                        };
                        function pressHandler():Void {
                          this.startDrag(false, -7648, 0, 70, 0);
                        };

                         

                             These are the first three functions.  Nothing has changed.  The releaseHandler() function, however, will drop its switch() statement and, instead, see if the mouse is within the bounds of any of first's nested movie clip symbols, each of which has its own intance name, such as airlift, airparks, aph, and so on.


                        function releaseHandler() {
                          this.stopDrag();
                          this.goRight = true;
                          if (this.airlift.hitTest(_xmouse, _ymouse)) {
                              getURL("http://www.airlift.co.uk/");
                          }
                          if (this.airparks.hitTest(_xmouse, _ymouse)) {
                              getURL("http://www.airparks.co.uk/");
                          }
                          if (this.aph.hitTest(_xmouse, _ymouse)) {
                              getURL("http://www.aph.co.uk/");
                          }
                          // etc. with remaining instance names
                        };

                         

                             See the difference?  You're using an if() statement for each logo, and each statement does the same thing.  If the mouse is within this logo, you've as good as clicked on it, so when the mouse releases over first, the appropriate URL is opened.  I'm including a revision of your FLA file, but I only added instance names to the first few (that is, the right-side) inner symbols.  You'll have to add relevant instance names to the remainder.

                         

                        function objectMover():Void {
                          if (this.goRight) {
                            this._x += 5;
                          }
                          if (this._x > 0) {
                            this._x = -1952;
                          }
                        };

                         

                             Here in objectMover(), I figured you'll want the scrolling logos to eventually loop.  Without the new lines at the end, your scrolling logos would eventually move off the right side of the banner, never to return.  They _x value of first starts way to the left (approx -1952), so you'll want to play with that number a bit for better accuracy, or if you add (or remove) logos from the first movie clip.  You may also want to change the values in the startDrag() method to better reflect the draggable boundaries of the movie clip.

                         

                         

                        David Stiller
                        Adobe Community Expert
                        Dev blog, http://www.quip.net/blog/
                        "Luck is the residue of good design."

                        • 9. Re: Start Drag button and get url
                          David Stiller Level 2

                               Hrm.  Amazingly, these forums don't support FLA or ZIP attachments (at least, not yet).  Wow.

                           

                               Here's your file:  http://www.quip.net/cb-sponsors_animation_rev.zip (I'll keep it there for a few weeks, but it'll eventually disappear).

                           

                           

                          David Stiller
                          Adobe Community Expert
                          Dev blog, http://www.quip.net/blog/
                          "Luck is the residue of good design."

                          • 10. Re: Start Drag button and get url
                            Level 1

                            David - many thanks for your expert help and work on the file. Impressive.

                            I downloaded file last night and had a look. The only trouble is that, when you click and drag the logos left to right to move to further along the list, everytime you do this, it opens up the url, which you probably will not want to do until you get to the one you want to. Maybe this way of building it is not possible, in terms of logistics, maybe it is better to have a scrollbar horizontal that control the movement going from left to right in terms of dragging, yet the logos cannot drag themselves. The main reason for this idea is so that the logos are always moving until you hover on one, then click to load the particular url to that logo. Any further ideas grateful!!

                            • 11. Re: Start Drag button and get url
                              David Stiller Level 2

                              thejam82,

                               

                              > David - many thanks for your expert help and work on the

                              > file. Impressive.

                               

                                   Glad to help!

                               

                              > The only trouble is that, when you click and drag the logos

                              > left to right to move to further along the list, everytime you

                              > do this, it opens up the url, which you probably will not want

                              > to do until you get to the one you want to

                               

                                   I was wondering about that, but didn't say anything because I wasn't sure if that's the behavior you wanted.  From a logic perspective, it makes sense that the dragging/URL behavior happens, because the getURL() function is triggered any time the mouse releases over the first movie clip (the clip that contains all those logos).  From a hypothetical standpoint, if AS2 had allowed what you were originally hoping for (that is, the on(release) code attached to each logo), then you would have run into the same issue:  one of the logos' URLs would have been launched, because -- as is the case here -- you would have been releasing the mouse over a given logo.

                               

                                   So at this point, it becomes a logic problem.  How can you detect if the mouse has been moving just prior to being released?  If it was moving before the release, the user was probably dragging the first movie clip.  If it was not moving, the user was probably just clicking.  It's this latter case only when you want the appropriate URL to launch.

                               

                                   Off the top of my head, the MovieClip.onMouseMove event seems like a good tool for the job.  This is an event that is triggered whenever the mouse moves over the object in question.  Let's associate this event with a function in response to an onPress event.  This function will set an arbitrary isDragging variable to true.  This will only happen when the user presses and moves the mouse (that is, drags).  If the user presses and simply releases without moving, the isDragging variable will remain in its default value, false.  In the onRelease event handler, we'll check if isDragging is true.  If it's true, we'll ignore the instructions to launch a URL.  If it's false, it means the user wasn't just dragging -- the user simply pressed and released -- so we'll launch the appropriate URL.  In any case, the onRelease handler will set isDragging back to false and remove the onMouseMove handler.

                               

                                   Here's the revised code, and I've highlighted the changes in bold:

                               

                               

                              var isDragging:Boolean = false;

                               

                              first.goRight = true;
                              first.onRollOut = rollOutHandler;
                              first.onRollOver = rollOverHandler;
                              first.onPress = pressHandler;
                              first.onRelease = releaseHandler;
                              first.onEnterFrame = objectMover;

                               

                              function rollOutHandler():Void {
                                this.goRight = true;
                              };
                              function rollOverHandler():Void {
                                this.goRight = false;
                              };
                              function pressHandler():Void {
                                this.startDrag(false, -7648, 0, 70, 0);
                                this.onMouseMove = moveHandler;
                              };
                              function moveHandler():Void {
                                isDragging = true;
                              };

                              function releaseHandler() {
                                this.stopDrag();
                                this.goRight = true;
                                if (!isDragging) {
                                  if (this.airlift.hitTest(_xmouse, _ymouse)) {
                                      getURL("http://www.airlift.co.uk/");
                                  }
                                  if (this.airparks.hitTest(_xmouse, _ymouse)) {
                                      getURL("http://www.airparks.co.uk/");
                                  }
                                  if (this.aph.hitTest(_xmouse, _ymouse)) {
                                      getURL("http://www.aph.co.uk/");
                                  }
                                  // etc. with remaining instance names
                                }
                                this.onMouseMove = null;
                                isDragging = false;

                              };
                              function objectMover():Void {
                                if (this.goRight) {
                                  this._x += 5;
                                }
                                if (this._x > 0) {
                                  this._x = -1952;
                                }
                              };

                               

                                   Keep your chin up.    There's usually a way to accomplish whatever you like in Flash, provided Flash Player supports the functionality.

                               

                               

                              David Stiller
                              Co-author, Foundation Flash CS4 for Designers
                              http://tinyurl.com/dpsFoundationFlashCS4
                              "Luck is the residue of good design."

                              • 12. Re: Start Drag button and get url
                                Level 1

                                David

                                Firstly, fantastic, great work. Nice one. Brilliant.

                                I have used your code and understood your explanation.

                                I have uploaded to: http://spark.dessol.com/kt/

                                 

                                The airparks and aph logos click through fine, but for some reason the airlink (the verfirst logo) does not open up a url? I have doubled checked the instance names matches with the actionscript, which it does. Bizarre? See if it clicks through for you?

                                • 13. Re: Start Drag button and get url
                                  David Stiller Level 2

                                  thejam82,

                                   

                                       Looks like I referenced the wrong instance name myself.  Heh, the devil is in the details!  The logo says Airlink, and that was the instance name I gave it (airlink), but I typed "airlift" in the code sample.

                                   

                                   

                                  David Stiller
                                  Adobe Community Expert
                                  Dev blog, http://www.quip.net/blog/
                                  "Luck is the residue of good design."

                                  • 14. Re: Start Drag button and get url
                                    Level 1

                                    Many thanks David, working great now. Thank you very much, appreciate it.

                                     

                                    One last query if I may - If I wanted the logos to be on a loop, ie, once the last one has disappeared from the screen, the first logo (airlink) comes in from the left so it is always on a permanent loop?

                                     

                                    Thanks for all your excellent help.

                                    • 15. Re: Start Drag button and get url
                                      David Stiller Level 2

                                      thejam82,

                                       

                                           That's taken care of inside the second if() statement in the objectMover() function.  The _x property is usually changing, because of the nearly constant addition of 2 to its value, right?  Because the first clip starts way to the left, its value is lower than zero.  That second if() statement checks when the value of _x gets higher than zero, then sends it back to where it started.  You'll probably want to play with the numbers a bit to get as smooth a loop as possible.  (For example, you might when to check when the value is higher than 10, 20, or some other number -- or maybe higher than -10, -20, or some other negative number.)

                                       

                                       

                                      David Stiller
                                      Adobe Community Expert
                                      Dev blog, http://www.quip.net/blog/
                                      "Luck is the residue of good design."

                                      • 16. Re: Start Drag button and get url
                                        Level 1

                                        Thanks. I had a go with that and it turned out that the actionscript to get this working was:

                                         

                                          if (this._x > 550) {
                                            this._x = -7148;
                                          }

                                         

                                        Having learnt from this, I have put together another version, this time with a scroll bar on the base of the stage. This control the left and right movements and dragging. One last issue I am having is that I have told buttons 1 and 2 to go to a url but they are not working. Nothing happens when you click.

                                        Actionscipt is below, any idea what I am missing here? Yet funnily enough if I remove:

                                         

                                        main.onRollOver = function(){
                                           
                                        grabbed = true
                                        ;
                                        }
                                        main.onRollOut
                                        = function(){
                                           
                                        grabbed = false
                                        ;
                                        }

                                         

                                        it then works? Must be something to do with this?

                                        Cheers David, this is the last issue!

                                         

                                         

                                         

                                         

                                         

                                        goRight = true;
                                        goLeft = false;
                                        Direction = 1;
                                        grabbed = false;
                                        scrollFace.onPress = function() {
                                            goLeft = false;
                                            goRight = false;
                                            currPos = this._y;
                                            grabbed = true;
                                            startDrag(this, false, 10, scrollTrack._y, 520, scrollTrack._y);
                                        };
                                        scrollFace.onRelease = function(){
                                            stopDrag();
                                            grabbed = false;
                                        }
                                        main._x = (scrollFace._x+20)-(main._width)
                                        onEnterFrame = function(){
                                            main._x = ((scrollFace._x)*(6900.1/530)-(main._width))+400
                                            if((goLeft == true) && (grabbed == false)){
                                                if(scrollFace._x>=10){
                                                    scrollFace._x-=.3;
                                                }
                                            }
                                            if((goRight == true) && (grabbed == false)){
                                                if(scrollFace._x<=520){
                                                    scrollFace._x+=.3;
                                                }
                                            }
                                            if((Direction == 1) && (grabbed == false)){
                                                goRight = true;
                                            }
                                            if((Direction == 2) && (grabbed == false)){
                                                goLeft = true;
                                            }
                                        }
                                        main.onRollOver = function(){
                                            grabbed = true;
                                        }
                                        main.onRollOut = function(){
                                            grabbed = false;
                                        }

                                        btnDown.onPress = function(){
                                            goRight = true;
                                            goLeft = false;
                                            Direction = 1;
                                        }
                                        btnUp.onPress = function(){
                                            goRight = false;
                                            goLeft = true;
                                            Direction = 2;
                                        }
                                        main.button1.onPress = function() {
                                            getURL("http://www.google.com", "_blank");
                                            goRight = false;
                                            goLeft = false;
                                        }
                                        main.button2.onPress = function() {
                                            getURL("http://www.bbc.co.uk", "_blank");
                                            goRight = false;
                                            goLeft = false;
                                        }

                                        • 17. Re: Start Drag button and get url
                                          David Stiller Level 2

                                          thejam82,

                                           

                                               Well ... you've made a complete overhaul of the functionality here, so that potentially changes everything I'd said until now.    So much has been altered, I'm not really sure which code pertains what object anymore.

                                           

                                               It looks to me like main is now what used to be called first.  If that's so (and I'm really not sure!) then I'm assuming your URL-related buttons (the logos) now have instance names button1, button2, and so on.  If that's true, then the mouse-related event handlers you've assigned to those inner symbols (their onPress handlers) are being obscured, or "blocked" by the mouse-related handlers associated with the main movie clip.

                                           

                                               We encountered this phenomenon earlier -- both with dot notation and the original on() function -- and it was for this reason that I suggested using the MovieClip.hitTest() method to determine which logo had the mouse positioned over it.  In ActionScript 2.0, mouse-related events didn't "pass through" parent symbols that also have mouse-related event handlers.  The technical term for this is bubbling, and it isn't formally supported in ActionScript until 3.0.  So you'll probably have to use the same hitTest() workaround.  That means you'll use an onPress or onRelease event handler associated with main that uses hitTest() in a series of if() statements to determine which logo currently "owns" the mouse.

                                           

                                               The reason this works again -- at least partly -- when you remove main's onRollOver and onRollOut handlers is because, once those are gone, main no longer has any mouse-related event handlers, so the inner mouse-related event handlers are allowed through.

                                           

                                               Off the top of my head, I'm thinking it may be possible to re-write this so that it omits the goRight and goLeft variables (grabbed might still be necessary), but from a pragmatic standpoint, the fact that it works is the most important part.  I'm not sure why you reverted to unnamed functions; that is ...

                                           

                                          // this

                                          main.onRollOver = function() {
                                            grabbed = true;
                                          }

                                           

                                          // instead of this

                                          main.onRollOver = rollOverHandler;

                                          function rollOverHandler() {
                                              grabbed = true;
                                          }

                                           

                                          ... but no harm done, either way.  There are definitely times when named functions are the better way to go.  For example, when you want to assign the same event handler with more than one object, you can simply define your function once, then refer to it as often as you like by name.  It also comes in handy when you want to programmatically assign and unassign event handlers, such as my earlier example where one function did this:

                                           

                                          this.onMouseMove = moveHandler;

                                           

                                          and another function did this ...

                                           

                                          this.onMouseMove = null;

                                           

                                          ... but again, the mechanics are ultimately up to you.

                                           

                                               Your series of if() statements, with hitTest(), should probably look something like this:

                                           

                                          main.onRelease = function() {
                                            if (this.button1.hitTest(_xmouse, _ymouse)) {
                                              getURL("http://www.google.com", "_blank");
                                            }
                                            if (this.button2.hitTest(_xmouse, _ymouse)) {
                                              getURL("http://www.bbc.co.uk", "_blank");
                                            }
                                            // etc.
                                          }

                                           

                                           

                                          David Stiller
                                          Adobe Community Expert
                                          Dev blog, http://www.quip.net/blog/
                                          "Luck is the residue of good design."

                                          • 18. Re: Start Drag button and get url
                                            Level 1

                                            Thanks very much, all buttons working fine now. Many thanks David.

                                             

                                            All the best