18 Replies Latest reply on Dec 6, 2007 1:22 PM by Greg Dove

    LMSSetValue function called in Flash 8

    KevT Level 1
      I know there's allot of requests for calling javascript functions from within Flash. I'm also aware of the externalinterface.

      Does anyone have experience with Flash quizes, SCORM, and passing variables to and from an LMS?

      I have a SCO (Sharable Content Object) course. The course contains several lessons layed out in a linear progression - page1, page2, page3, etc. When a user gets to the quiz/assessment page, a Flash quiz object is embedded. In my ActionScript, I calculate the attempts, score, pass, fail, and a other data.

      What I'm wanting to do is call functions to pass the final 'score' and a status of 'complete' back to the LMS.

      Ex:
      if (amtcorrect == 3) {
      getURL("javascript:LMSSetValue('cmi.core.score.raw','100')");
      getURL("javascript:LMSSetValue('cmi.core.lesson_status','completed')");
      }
      getURL("javascript:LMSCommit()");

      Where 'amtcorrect' calcualtes the passing score.
      - the first call sets the score to '100'
      - the second call sets the status to 'completed'
      Upon exiting the that frame/page a call to Commit that score and status to the LMS.

      It doesn't work.

      It works if I put all this in the html pages, however if a user exits prior to or during the quiz, these functions are called and they get a status of complete whether they took the assessment or not.

      Any suggestions would be super!
        • 2. Re: LMSSetValue function called in Flash 8
          Greg Dove Level 4
          Its unclear what the problem is.

          You say "It works if I put all this in the html pages"

          -that's good. So presumably your javascript communications are working as is. Flash 8 introduced a new way of talking to javascript, that is considered more reliable using the ExternalInterace class, which you say you're aware of. But it seems that your problem is unrelated to a failure of talking to javascript.

          "if a user exits prior to or during the quiz, these functions are called and they get a status of complete whether they took the assessment or not."

          How does a user exit? Is there an exit button in flash? If so, then whatever actions are related to that button press must be executing the calls to the external javascript functions. Can you show that code.


          • 3. Re: LMSSetValue function called in Flash 8
            KevT Level 1
            It works in html pages meaning I put a onload=onLoadPage(); in the body tag. This function calls the LMSGetValue(); - get raw passing value, and LMSInitialize(); - establish communication with LMS. Also, the onunload=onunLoadPage(); which sets the value (score) in LMSSetValue();- set the users score compared against the passing score. If the user's score is =< raw score, send a "completed" status to LMSCommit(); If not, a 'not competed' status is set. The single html page has the quiz embeded which has it's own naviagtion.

            The [EXIT] button is not part of the course/quiz SCO - it is part of the LMS window or 'wrapper' that communicates between the SCO and the LMS. Once that button is pressed, it sends whatever related data to your transcript and updates your record.

            That being said, the Flash course/quiz is 11 frames/pages with minimal interaction. So presumably a user can...say, get to frame 4, click the [EXIT] button and the functions will be called sending a 'completed' status to the LMS prior to the user ever getting to frame 8 where the actual quiz begins.

            Thinking through that logic, my thinking was to compare the user's score against the raw passing score in the last frame of the quiz - Results. If not passing, give user option to quit and try again later, or return to beginning to review. If passing, go to next frame where my problem lies.

            I thought if I put the LMSSetValue(); and LMSCommit(); in that last frame, those funcitons would not be called unless and only a user got a passing score. They would not be able to get to this frame/page if not.

            I'm aware of ExternalInterface, but I have not used it and not sure where to begin.

            The only code calling javascript is what I've already shown. All other ActionScript is related to the actions within the flash movie.

            There are two .js files related to a SCO in this instance. APIWrapper.js which is a standard .js written by ADL and used by all SCORM 1.2 courses. The other is SCOfuncitons.js which specific parameters can be set - raw passing score, status, etc. The functions I'm calling are in the latter. Within those functions calls others in the first.

            Does the ExternalInterface need to be associated with a button or movie clip? Can it be exectuted by simply leaving the frame on which it is associated?

            Thanks for the feedback and allowing me to confuse you more!
            • 4. Re: LMSSetValue function called in Flash 8
              Greg Dove Level 4
              Oh I think I understand now. You don't already have it working in html pages with flash..You want to make a flash version of something that was previously html based... is that it?

              EI works like this:

              if (ExternalInterface.available){
              ExternalInterface.call("LMSSetValue",'cmi.core.score.raw','100');
              } else {
              //no javascript interface, panic code here.
              }
              • 5. Re: LMSSetValue function called in Flash 8
                KevT Level 1
                Yes. All our on-line training content has been html based only. Essentially "page flippers" with no assessment. All assessments were conducted in a separate system.

                Now that we're implementing an LMS, we need to incorporate the assessment within the training package. There are hundreds of rapid delivery tools that can do this on the fly, but that requires total re-working of all our content. I just need to get these up and running for the launch. I have a plan next year normal cyclic updating of content to merge into a new development environment. In the meantime, I'm simply building small assessments and embedding them into the already existing html course content.

                Apologies for not being more clear initially.

                I'll try this, but I have another question.
                Can I call more than one function in the 'if' statement - nested?
                ex:
                if (amtcorrect == 3) {
                if (ExternalInterface.available) {
                ExternalInterface.call("LMSSetValue",'cmi.core.score.raw','100');
                ExternalInterface.call("LMSSetValue",'cmi.core.lesson_status','completed');
                }
                }
                ExteranalInterface.call("javascript:LMSCommit()");
                • 6. Re: LMSSetValue function called in Flash 8
                  Greg Dove Level 4
                  Sure you can do it like that.

                  It would probably be more like this:
                  if (ExternalInterface.available) {
                  if (amtcorrect == 3) {

                  ExternalInterface.call("LMSSetValue",'cmi.core.score.raw','100');
                  ExternalInterface.call("LMSSetValue",'cmi.core.lesson_status','completed');

                  }
                  ExternalInterface.call("LMSCommit");
                  } else {

                  //what should I do here... I can't talk to javsacript.
                  //gotoErrorFrame or something
                  }
                  • 7. Re: LMSSetValue function called in Flash 8
                    Greg Dove Level 4
                    BTW, ExternalInterface, unlike getURL("javascript:someFunc()"), can receive a return value from your javascript function calls. So if LMSSetValue returns (for example) a true or false value you can access that inside flash.
                    e.g.

                    var lmsresponse= ExternalInterface.call("LMSSetValue",'cmi.core.score.raw','100');


                    • 8. Re: LMSSetValue function called in Flash 8
                      KevT Level 1
                      Thanks GWD. I'll give this a try. Looks relatively simple and should work.

                      In your second post if I understand correct.y, with ExteranalInterface I can receive a value from javascript and assign it to a variable?
                      e.g.
                      Say the passing score is 80% or 80. In your example the 'Imsresponse' would hold that value. I could then compare that var against whatever a user earned as a score followed by an IF statement of pass or fail. Is that about right?

                      I see 'ExteranInterface' being very useful in projects to come! I'll post my resulsts soon.
                      • 9. Re: LMSSetValue function called in Flash 8
                        Greg Dove Level 4
                        "with ExteranalInterface I can receive a value from javascript and assign it to a variable? "

                        yes, that's exactly what I meant. You can call a javascript function in the page and have it return boolean, string, number, object, or array type values which can be assigned to a variable inside flash.

                        One thing you'll need to do before you use ExternalInterface is import it.

                        So if your code is on a frame, at the top of the code you would usually put:

                        import flash.external.ExternalInterface;

                        or maybe
                        import flash.external.*;

                        at the top.
                        • 10. Re: LMSSetValue function called in Flash 8
                          KevT Level 1
                          Ahh...maybe that's why. Just did a quick test with a trace and something wasn't working. Must have been the missing 'import' :)

                          Let me try again...
                          • 11. Re: LMSSetValue function called in Flash 8
                            KevT Level 1
                            Ok, it works...almost. I'm getting the 'completed' status. However, I get an alert saying "Not Initialized." I think I know where that is and its not associated with Flash.

                            Another question on ExternalInterface....here's the code I'm using based on your suggestions:
                            var lmsrawscore = ExternalInterface.call("LMSSetValue", 'cmi.core.score.raw', '100');
                            if (ExternalInterface.available) {
                            if (amtcorrect == 3) {
                            // where amtcorrect compares the var lmsrawscore for passing.
                            ExternalInterface.call("LMSSetValue", 'cmi.core.lesson_status', 'completed');
                            }
                            ExternalInterface.call("LMSCommit");
                            } else {
                            ExteranlInterface.call("LMSSetValue",'cmi.core.lesson_status','incomplete');
                            gotoAndStop("errorPage");
                            }

                            1. How do I know here when I'm 'sending' ? ExternalInterface.send ?
                            2. In the getUrl(javascript:myfunc(); the use of the open and closed parens are used along with semicolon. From your examples, again I presume we don't use them here?
                            3. The above functions reside in two different .js files. Does ExternalInterface simply look for the name of the function across all available .js files?
                            4. If I move the .js files into their own folder (currently at the root of the swf), I'm assuming to also include the pathing?
                            • 12. LMSSetValue function called in Flash 8
                              Greg Dove Level 4
                              1. You don't 'send'. ExernalInterface is just a way to bridge to javascript. Its synchronous, which means actionscript waits for the external javascript function to execute before it continues inside flash. This is not the case with getURL.
                              The first parameter is the name of the function in javascript to call as a string. the other parameters are teh arguments you send to that function. The check
                              if (ExternalInterface.available) {
                              //do stuff here
                              }

                              is just because flash doesn't have control over whether it can talk to javascript. That's a) part of the embedding parameters ("allowscriptaccess","sameDomain" is the default, and basically means its OK) and b) whether javascript is switched on or off in the browser (thankfully most people have it switched on. In your case its OK, because none of your SCORM stuff will work without it anyway I'm guessing).

                              So you don't have to do that check... but its useful maybe to do it once at the start and if it fails then basically you can't do anything.... because you can't talk to javascript.

                              2. No, you don't use the parentheses here. You can check the livedocs for more detail.

                              3. No it doesn't matter. ExternalInterface doesn't care about the javascript files themselves... so long as they're loaded and the functions are defined.

                              4. That shouldn't be relevant. Javascript is loaded by the browser and flash doesn't get involved directly. You just need to make sure the script tags have the correct path to whereever you put the js files.
                              • 13. Re: LMSSetValue function called in Flash 8
                                KevT Level 1
                                I am so close! I put a trace on several of the functions that communicate with the LMS. It was good to see exactly when and where they are being called. I'm liking this ExternalInterface thing!

                                However, I'm still getting a popup alert error "Not Intilaized." I've sent some of our conversation to a buddy of mine who's more familiar with SCORM than I am to see if he can make sense of it.

                                Here's what I think is going on. Once the call to compare the raw score to the users score, the status is set to 'complete' if it's a passing score. Good - it's supposed to do that. But what's happening is the code we've been discussing is exectuted immediately upon arriving at that frame (the congratulatory results page). Then the popup which I have to click the OK button several times before it closes. Then the page in question flickers for an instance and goes to the LMS course window (frame where a course launches from). When I exit the course window the transcript updates to a 'completed' status.

                                All good except for that pesky popup. I've looked through all of the .js files and I can't find any reference to a text string "Not Initialized." Hopefully my buddy has an answer.

                                That all being said, is it possible to use ExternalInterface with some sort of 'unload frame' function in ActionScript? The unloadMove won't work becuase this code is at the root of the main timeline. Basically, this code would only exectute if I close the whole movie itself - the main .swf file.
                                • 14. Re: LMSSetValue function called in Flash 8
                                  Greg Dove Level 4
                                  Great to hear that its within reach. Its difficult for me to understand a lot of what's going on there as I'm guessing much of it is happening outside flash. Hopefully your friend can help pinpoint whats going on.


                                  If you want to retrieve something from flash when the containing html page unloads then I can't answer that one with certainty because I've never tried it. ExternalInterface works both ways, although you need to specify what javascript can access as internal actionscript functions using ExternalInterface.addCallback. So you could perhaps call something inside flash from a javascript window.onUnLoad type event (I think that's the one). Whether it works during that phase I do not know as, like I said, I've never tried it.
                                  I *think* (didn't check it) that in as3 you can catch the page unload event from inside flash, but as2 has no native event for that.
                                  • 15. Re: LMSSetValue function called in Flash 8
                                    KevT Level 1
                                    Good news. Found the error. I'm in Memphis and flew out to Washington D.C. to look at this with some LMS gurus first hand. They found the culprit this afternoon. It was in the SCOfuncions.js file. When the user gets a passing score, the ExternalInterface.call sets the status to complete. When the user is done and ready to exit the cource a function is called - doQuit(); In short, this function calls a nested function LMSFinish(); The problem was in the doQuit(); in that it also calls a LMSCommit(); In that function it calls the LMSFinish(); Basically, it was trying to reset the time started and reinitialize the instance. The alert was inherant to the LMS.

                                    Now...I've added a button to the last page so users will execute the final function to pass all the variables accordingly. That's one more click of a button I'd rather not have. If I remove the button, as soon as a user gets to that frame the function executes and the .swf closes...only a blink of an eye sees the final screen. Had to put a stop(); action, add a button, and tell users "to update your transcript click this button" so they'd have a chance to 'see' their final results page before it closes when they click the button.

                                    That main objective of this thread has been solved thanks to you. I'll study more on AS3 on how to execute a function ONLY when closing an .swf. instead of executing as soon as a frame loads or by user button input. That would make everything all nice and neat.

                                    Finally! Thanks for all you help GWD. You really helped me through this by introducing me to ExternalInterface. Mucho Kudos!!!

                                    • 16. Re: LMSSetValue function called in Flash 8
                                      Greg Dove Level 4
                                      Great to hear! I haven't checked out the as3 thing... but I think I read that somewhere...anyhow:

                                      Another option would have been to put a delayed execution on the last frame, using

                                      setTimeout

                                      (for example) and then making your externalinterface call when the timer runs out. That means people have time to see their results and don't have to press the button, but it would perhaps should some sort of reverse progress bar for a countdown so people knew it was "doing something". You could even make the button available for people to exit early if they got bored looking at their results.

                                      • 17. Re: LMSSetValue function called in Flash 8
                                        KevT Level 1
                                        Great minds think alike! I am actually working on timed movie clip that would load and count down a number of seconds...then execute the externalinterface at the end of that timeline. Using setTimeout would be more efficient for sure along with your suggestion of adding a button for those who want to exit sooner.

                                        I'm going to start a new thread about the other topic on onlly executing an externalinterface call on closing of the main .swf, not just a movieclip.
                                        • 18. Re: LMSSetValue function called in Flash 8
                                          Greg Dove Level 4
                                          I'm not super confident about that possibility in as3... but I thought I'd read of something like it. I just took a quick look at the docs to see if I could find something relevant... but I couldn't... perhaps I got my thoughts confused with the deactivate event, which is more to do with focus on the player.