"Incorporating Adobe Edge Animate alongside AngularJS and AngularUI Router for dynamic web design

Currently, I'm in the process of integrating multiple animations created using Adobe Edge Animate into a single AngularJS application for a project. These animations will serve as the visual elements for a game, with player input controlling the composition. After some trial and error, I've successfully reached this stage.

However, my challenges arise when a player exits the current view and tries to access it again. This seems to trigger an issue with the Adobe Edge Animate Javascript API, causing the composition to fail loading.

In essence, I can load the composition once, but subsequent attempts result in the following Javascript errors...

Uncaught TypeError: Cannot read property 'stage' of undefined    edge.5.0.1.js:4872
Uncaught TypeError: Cannot read property 'stage' of undefined    edge.5.0.1.js:4519

The composition is currently loaded directly within the controller like so...

.controller('GameTest', function($scope, $state) {
    AdobeEdge.loadComposition('edge-animate/GameTest', 'GameTest', {
      scaleToFit: "width",
      centerStage: "none",
      minW: "0",
      maxW: "undefined",
      width: "2048px",
      height: "1134px"
    }, {dom: [ ]}, {dom: [ ]});
})

I have also disabled caching for this state...

.state('game-test', {
  cache: false,
  url: "/games/test",
  controller: 'GameTest',
  templateUrl: 'templates/games/test.html'
})

Any suggestions or assistance are greatly appreciated!

Thank you

Update: I may have found a solution!

The issue appears to be resolved when the browser reprocesses the contents of the relevant *_edge.js file. Since these files are injected into the <head> whenever AdobeEdge.loadComposition(...) is called (via yepnope), and there is no way to force yepnope to reload injected Javascript, I have developed a small Angular service that handles this instead of the standard AdobeEdge.loadComposition(...) function. It serves as a wrapper that performs necessary checks before execution.

.service('$AdobeEdge', function() {
  var head = document.getElementsByTagName('head')[0],
    scripts = head.getElementsByTagName('script');

  return { 
    loadComposition: function(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM) {
      // Determine the filename for our project
      var projectFile = projectPrefix + '_edge.js';
      var newScript = null;

      // Iterate through each script tag in the header to search for our file
      angular.forEach(scripts, function(script, index, scripts) {

        // Does the script src tag end with our project filename?
        if (script.src.substr(script.src.length - projectFile.length) == projectFile) {

          // It's already loaded! Let's go about removing it and injecting a fresh script tag...
          script.remove();
          newScript = document.createElement('script');
          newScript.setAttribute('type', 'text/javascript');
          newScript.setAttribute('src', script.src);
          head.insertBefore(newScript, scripts[0]);

          // Also delete the composition within the Adobe Edge API to ensure events like 'compositionReady' fire again when we call loadComposition()
          delete AdobeEdge.compositions[compId];
        }
      });

      // Regardless, always call loadComposition()
      AdobeEdge.loadComposition(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM);
    }
  }
})

With this approach, I can simply use this service in the respective controllers to load a composition similarly to before. For instance...

.controller('GameTest', function($scope, $state, $AdobeEdge) {
  $AdobeEdge.loadComposition('edge-animate/GameTest', 'GameTest', {
    scaleToFit: "width",
    centerStage: "none",
    minW: "0",
    maxW: "undefined",
    width: "2048px",
    height: "1134px"
  }, {dom: [ ]}, {dom: [ ]});
});

Thus far, this method has been successful! I intend to utilize it for other games in our project and will share any issues encountered along the way.

Hopes this spares others from similar frustrations!

Answer №1

Answer by Rob Sinton:

A resolution to the problem is found when the browser reprocesses the contents of the relevant *_edge.js file. These files are injected into the <head> section whenever AdobeEdge.loadComposition(...) is called (via yepnope). As there is no direct way to force yepnope to reload injected JavaScript, I have devised a small Angular service to handle this situation as an alternative to the standard AdobeEdge.loadComposition(...) function. It acts as a wrapper that performs necessary checks before loading.

.service('$AdobeEdge', function() {
  var head = document.getElementsByTagName('head')[0],
    scripts = head.getElementsByTagName('script');

  return { 
    loadComposition: function(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM) {
      // Determine the filename for our project
      var projectFile = projectPrefix + '_edge.js';
      var newScript = null;

      // Iterate through each script tag in the header to search for our file
      angular.forEach(scripts, function(script, index, scripts) {

        // Does the script src tag end with our project filename?
        if (script.src.substr(script.src.length - projectFile.length) == projectFile) {

          // It's already loaded! Let's go about removing it and injecting a fresh script tag...
          script.remove();
          newScript = document.createElement('script');
          newScript.setAttribute('type', 'text/javascript');
          newScript.setAttribute('src', script.src);
          head.insertBefore(newScript, scripts[0]);

          // Also delete the composition within the Adobe Edge API so that events like 'compositionReady' are fired again when we call loadComposition()
          delete AdobeEdge.compositions[compId];
        }
      });

      // Always call loadComposition() regardless
      AdobeEdge.loadComposition(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM);
    }
  }
})

By using this method, I can easily utilize this service in the appropriate controllers to load a composition in a similar fashion to usual. In this specific instance...

.controller('GameTest', function($scope, $state, $AdobeEdge) {
  $AdobeEdge.loadComposition('edge-animate/GameTest', 'GameTest', {
    scaleToFit: "width",
    centerStage: "none",
    minW: "0",
    maxW: "undefined",
    width: "2048px",
    height: "1134px"
  }, {dom: [ ]}, {dom: [ ]});
});

Thus far, this approach has proved to be effective! I will continue using it to develop the remaining games in our project and will share any challenges encountered along the way.

Hopefully, this solution prevents others from experiencing similar issues!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The jquery script tag threw an unexpected ILLEGAL token

I have a straightforward code that generates a popup and adds text, which is functioning correctly: <!DOCTYPE html><html><body><script src='./js/jquery.min.js'></script><script>var blade = window.open("", "BLA ...

Angular offers a range of search filters for optimizing search results

The system currently has 3 search fields: 1. Name.... 2. Subject.... 3.Price.... Each of these filters works independently - when searching by name, only results matching that name are displayed; similarly for subject and price. However, the challeng ...

Error message: The recursive function is unable to return a value when operating

My current task involves solving this problem recursively: Clean the room function: given an input of [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20], create a function that organizes these into individual arrays that are ordered. For example, answer(ArrayFromAb ...

What is the best way to convert a JSON object back into an object with its own set of methods?

Currently, I have a JavaScript object with multiple methods attached via prototype. When I serialize the object to JSON, only the property values are saved, which is expected. It wouldn't make sense to save the methods as well. Upon deserialization ...

What is the best way to eliminate query parameters in NextJS?

My URL is too long with multiple queries, such as /projects/1/&category=Branding&title=Mobile+App&about=Lorem+ipsum+Lorem+. I just want to simplify it to /projects/1/mobile-app. I've been struggling to fix this for a week. While I found so ...

What is the purpose of using a hash in a WebSocket handshake?

When establishing a Websocket connection, the client initiates by connecting to a tcp socket on a server and then performs a handshake. In the client's handshake, there is a base64 encoded key (Sec-WebScoket-Key). The expected response from the serv ...

The JavaScript date picker is malfunctioning in the HTML editor, but it functions properly in Fiddle

I have a working format available in a JS fiddle. Here is the code I have used on my demo site: I created a new folder named "js" and placed datepicker.js inside it, then linked it in my HTML like this: <script type="text/javascript" src="js/datepicke ...

tips on customizing buttons within form groups

I have set up two separate form-groups: My goal is to click on each button within each group and toggle its style from grey to green, and vice versa. However, when I click on a button, all buttons within the group turn grey except for the one that was cli ...

React: Managing various browsers and browser tabs to prevent duplicate operations

On my webpage, I have a button labeled Submit that, when clicked, triggers an operation by calling an API. After the button is clicked, it should be disabled or changed to reflect that the operation has started. I am facing an issue where multiple browser ...

NPM Messer - the innovative chat tool for Facebook Messenger. Ready to see it in action?

Previously, I had the idea of creating my own Messenger client. However, when I reviewed the documentation, it only provided instructions on how to write a chatbot. Despite this obstacle, I stumbled upon something intriguing - a Messer command line client. ...

Error: The reduce function cannot be applied to $scope.array as it is not a

I am currently facing an issue with a section of my code that involves loading attributes related to a page using drop-down lists. These attributes, namely instruments, style, and scoring, are fetched through a service call. For instance, when retrieving ...

Unable to modify existing attributes in a sails.js model

I'm new to sails.js and I have a question about adding fields to an existing model in Sails.js. Here is the current model: module.exports = { attributes: { id: { columnName: 'id', type: 'integer&apos ...

Can someone please help me figure out how to detect active users within my Next.js application while utilizing Supabase authentication?

I'm looking for a way to recognize users on my app in order to display green badges as visual cues. After logging into my app using Google OAuth, the session remains active even though I logged out days ago. I am unsure of the most effective algorith ...

Tips for making sure AngularJS runs a function and its subfunction sequentially

How do I run the code below to display the details of each flavor and its corresponding ITEM ID in a specific order. Execution Format: Flavor1, Flavor2 -- Getflavors() Flavor1 ITEM1, ITEM2... -- GetItemIDs_ofeachFlavor(MapFlvID) GET ITEM1 DETAILS and ad ...

Achieving a function call within a Backbone view in Backbone.js

Is it possible to call the plotPort function from the plotLoc function using this.plotPort() instead of self.plotPort()? It seems to not work for Internet Explorer when using self.plotPort(). As a workaround, I added an event to lLoca upon reset to call ...

Add the div id to the script

Currently, I have a script set up where by clicking on a specific div (for example id=packtoa), it will add a class 'show' to listview items that have a matching class with the clicked div's id. While this system works well, I find myself n ...

Are there more efficient methods than having to include require('mongoose') in each models file?

Is it possible to only require mongoose once in the main app.js file and then pass it to other files without loading it again? Will the script do extra work every time the same module is required? var mongoose = require('mongoose'); I'm wo ...

Tips for refining a list to only include items that contain every element from a specified array

Is there a way to search for all elements in an array and display them if they are all present? For instance, consider the following: const data = [ { "languages": ["JavaScript"], "tools": ["React", "Sass"] }, { "languages": ["Python" ...

What is the best way to eliminate a trailing backslash from a string?

Currently, I am iterating through a list of Discord server names in node.js. The goal is to create a php file that contains an array structured like this: <?php $guildLookup = array( "164930842483761" => "guildName1", "56334 ...

Is it impossible to extend a Typescript class with an overriding method that uses a different parameter?

I am currently working on a Typescript MVC app and encountering an issue. When I try to extend my BaseController and override the ajaxMethod with different parameters, my transpiler throws an error. Any help would be appreciated. Below is the code snippet ...