I'm working on a project at the moment which will incorporate multiple animations created with Adobe Edge Animate into an single AngularJS application. The idea is that these animations will act as the visuals for a game and I will control the composition based on input from the player. It's taken some experimenting to get to this stage but all of that is working perfectly.
My problems start whenever the player chooses to exit the current view and access it for a second time. For some reason this causes an issue with the Adobe Edge Animate Javascript API and the composition fails to load.
Essentially, I can load a composition once but no more. Whenever I attempt to load the composition for a second time I get 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
I'm currently loading the composition directly from within the controller as follows...
.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've also disabled caching for this state...
.state('game-test', {
cache: false,
url: "/games/test",
controller: 'GameTest',
templateUrl: 'templates/games/test.html'
})
All suggestions welcome and appreciate any help!
Thanks
Update: I've worked out a solution! Hopefully...
The issue seems to be resolved if the browser handles the contents of the relevant *_edge.js again. Since these are injected into the <head>
whenever AdobeEdge.loadComposition(...)
is called (via yepnope), and there doesn't appear to be any method of asking yepnope to reload injected Javascript, I have written a small service for Angular that I can use to handle this in place of the standard AdobeEdge.loadComposition(...)
function. It's essentially a wrapper that will do the relevant checks beforehand.
.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]);
// Let's 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];
}
});
// Ultimately we always need to call loadComposition() no matter what
AdobeEdge.loadComposition(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM);
}
}
})
Using this method I can simply invoke this service in the relevant controllers and load a composition in a similar manner to normal. In this particular case...
.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: [ ]});
});
So far it's been working great! I'll use it to build out the rest of the games in our project and post any issues I run into.
Hopefully this saves someone else a lot of heartache!
<script>
node and then re-add it right after – shouldn't the call toAdobeEdge.loadComposition()
do that for you? – Gamybody
element over here. Thanks! – Leisurely