Using output Hype 3 in a Cordova/PhoneGap project


(Rob Willett) #1

Hi,

We have an existing Cordova project thats in both the Apple UK App Store and the Google Play store (Jambuster). This is only available in the UK as it provides personalised traffic information for London drivers.

We currently have a help screen which is a simple (and lame) PNG page. However this simple page technically works.

We are exploring using Hype 3 to generate far more interesting and useful help pages. Our current Hype 3 test page consists of a simple scene with three lines of text that fades in over a few seconds. We don’t think we’ll have any issues generating the actual Hype 3 document, but how we use it in Cordova is more complicated and hence this email.

We’ve generated and exported the Hype 3 html folder to our application. We can open the index.html file created in Chrome to verify that it works correctly outside Hype and in a browser.

What we are struggling to do is to get the Hype 3 displayed in our app.

What have we done so far?

We’ve opened up the index.html file and located the three lines that we think are relevant

<div id="testintro1_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
	<script type="text/javascript" charset="utf-8" src="TestIntro1.hyperesources/testintro1_hype_generated_script.js?36551"></script>
</div>

We have moved the Hype 3 script resources to our head section in the document.

<script type="text/javascript" charset="utf-8" src="TestIntro1.hyperesources/testintro1_hype_generated_script.js?36551"></script>

We have 40-50 script resources in our head section so this is nothing new.

We have left

<div id="testintro1_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
</div>

in the section where we used to load the simple .png file. This used to be

<script id="image-modal.html" type="text/ng-template">
  <div class="modal image-modal transparent" ng-click="closeModal()">
    <ion-pane class="transparent">
      <img ng-src="{{imageSrc}}" class="fullscreen-image"/>
    </ion-pane>
  </div>
</script>

and is now

<script id="image-modal.html" type="text/ng-template">
  <div class="modal image-modal transparent" ng-click="closeModal()">
    <ion-pane class="transparent">
      <div id="testintro1_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
      </div>
    </ion-pane>
  </div>
</script>

So far this is nothing more than simple refactoring (though probably wrong).

If we recompile our app and push it down to an iPhone we can see that the script is loaded correctly as no error is reported in the Safari console.

However if we then fire off the action to load the Hype 3 script in the image-modal.html section defined above we get an error. As there are graphics in safari we can’t simply cut and paste the text, we have to insert an image

This is where we start to struggle. We can’t see how to resolve this or indeed what the problem is at all.

Looking at the code shows the minified versions and we probably couldn’t work it out anyway.

Any suggestions or help gratefully received.

Our other option was to look at exporting and importing an animated GIF. We can easily display the GIF, but the animations only run once and its very difficult to reset it from JavaScript. To be honest we’d much rather have an HTML 5 solution if possible.

Thanks for reading this far, any ideas let us know.

Rob


(Jonathan Deutsch) #2

The error you are seeing is what happens when Hype cannot find the container div to place its contents.

Looking at your code:

<script id="image-modal.html" type="text/ng-template">
  <div class="modal image-modal transparent" ng-click="closeModal()">
    <ion-pane class="transparent">
      <div id="testintro1_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
      </div>
    </ion-pane>
  </div>
</script>

The hype container div is inside a script tag. In a normal .html file, the script tag is for javascript, not for HTML tags. Since the type is an ng-template, I assume it is doing something special there, and somehow could get the div to show up. However what’s likely happening is that the div is showing up after Hype is trying to load, so it isn’t finding the div at the time it needs.

I’m not too familiar with angular/ionic, but are there any calls that can let you run/load javascript after the template has been shown/loaded?


(Rob Willett) #3

Jonathon,

We’re working on this at the moment and in the last two mins have come to a similar conclusion. We think the div isn’t loaded at the right time.

We’re also just looking through the minimised code to try and work out what it was trying to do and we think that it has to have the script tag inside the div tag. The code is somewhat opaque to read :slight_smile:

We’ve pulled the code out of the image-modal.html block and are now experimenting with it in another part of the html code.

Ionic and ng-templates are a complete nightmare at times, but we think you are right and that the div isn’t loaded. We need to think carefully about this as we have a working app with 20,000 lines of code :smile:

We’ll come back later with our conclusions (if we can arrive at any) today. We really want to get this working as it would make a nice addition to our app.

Rob


(Rob Willett) #4

We’ve had a good look at this and have found a way to get it working. It does appear that we have to defer calling the script

test1intro.hyperesources/test1intro_hype_generated_script.js

until after the DOM is completely created.

What we did

Our test Hype 3 document is called test1intro. It has a single scene with two lines of text that gradually appear.

We created the document and saved it to a folder test1intro.

This created a series of files, the important ones of which are:

index.html,
HYPE-552.thin.min.js and
test1intro_hype_generated_script.js

Looking in index.html we pulled out these lines

<div id="test1intro_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
	<script type="text/javascript" charset="utf-8" src="test1intro.hyperesources/test1intro_hype_generated_script.js?54709"></script>
</div>

We updated the view that used to show the .png file to now hold the Hype 3 div. Note that the script tag is NOT in here.

<script id="image-modal.html" type="text/ng-template">
  <div class="modal image-modal transparent" ng-click="closeModal()">
    <ion-pane class="transparent">
      <div id="test1intro_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
      </div>
    </ion-pane>
  </div>
</script>

We opened up the file test1intro_hype_generated_script and pulled out all the Javascript and added it to a function that we control when we call it. This function sits in one of Ionic controllers. The Hype 3 script seems to modify the DOM quite a lot and worries us a little :slight_smile:

We then explicitly added HYPE-552.thin.min.js to our index.html file.

<script src="test1intro.hyperesources/HYPE-552.thin.min.js"></script>

We assume this is a framework type file and the JavaScript in test1intro_hype_generated_script.js calls it.

We then call our new function that simply contains the contents of test1intro_hype_generated_script.js, CallHype() when we load up the help page on top of our main screen. As we don’t call the Hype 3 script until we have setup the DOM (or rather Ionic has) this works and we get a simple yellow screen appear with two lines of text and no errors.

If we rerun the CallHype() function we have created, we don’t get the nice animations running again, we simply get the end screen.

So we have managed to get this working, we have tried quite a lot of ways to get this working but none of the other techniques such as late binding using ng-bind-html worked. This was literally the last thing we tried and we had more or less given up by this stage.

So this leads is to whether this is feasible to continue this approach. We could automate it by wrapping the workflow in various Unix shell/Perl scripts which is not that difficult but is just one more thing to go wrong. We also created an animated GIF and that works but the quality of the animations is inferior to the HTML5. e.g. the fade in of text looks poor in comparison to the CSS (?) fade in. There is also the issue of the animations only running once.

One option is for Tumult to change the way they generate the scripts, perhaps have a callable function which we can call from JavaScript rather than assuming that things run when loaded through the index.html file. This function should be reentrant so it can be called multiple times as needed. Our function wrapper does this but its hard and the TypeScript compiler nearly barged compiling it :wink:

These are all options to consider. I’d be interested in Tumults views. We all need to see if its worth the effort and at this stage we need a large coffee more than anything.

Thanks for the help,

Rob


(Jonathan Deutsch) #5

While we don’t support any modifications, you can export unminified versions if you enter this command into the Terminal:

defaults write com.tumult.Hype2 UseFullHypeJSTemplate -bool YES 

I highly recommend setting it to the default NO for any production output.

There’s nothing explicitly wrong in doing this; in fact I believe an advance export option to inline will do the same. do note that this is including the “thin” version; Hype has a smaller file size one (“thin”) and one that includes support for IE6-9 and Physics. The loader file determines at runtime which to use; I never recommend using thin in a static context, especially because we may change the feature set of thin vs. full later.

If you have a callback for the right time to run the Hype javascript, then instead I would recommend using head injection for the script tag. This means you would not need to hack the hype javascript or make any changes to the Hype export. You also would not need to include the HYPE-552.thin.min.js manually.

Head injection literally just adds the <script> tag to the head; when this happens the browser will load this.

So the code would look something like:

function CallHype() {
	var headElement = document.getElementsByTagName('head')[0];
	var scriptElement = document.createElement('script');
	scriptElement.type = 'text/javascript';
	scriptElement.src = "test1intro.hyperesources/test1intro_hype_generated_script.js";
	headElement.appendChild(scriptElement);
}

Hype uses this method itself to inject the HYPE-552.thin.min.js :slight_smile:. Does this work for you?


(Rob Willett) #6

Jonathan,

Thank you very much for the detailed and helpful reply.

Your CallHype () function does work. We can see how to use this now without getting into complex wrappers :slight_smile:

We’ve tested it on our simple page and it looks OK, the only thing we now have to do is make it work twice in a row. The first time we run it, it looks great, when we invoke the page again, the ‘video’ is at the end rather than the start.

We’re going to play with unloading the script and reloading it to see if that works, but it would good to know if there is an easier way of simply reseting the HTML5 doc to the start. We’re looking at

http://tumult.com/hype/documentation/3.0/#javascript

and can see some stuff in there but not sure if we can use it as this is all new to us :slight_smile:

The next problem is actually doing the onboarding animation, thats ‘design’ stuff which we’re not very good at :wink:

Thanks again,

Rob


(Jonathan Deutsch) #7

To clarify, do you mean a video or the animation itself?

If it is the animation, you could always try using the HYPE.documents["documentName"].showSceneNamed("firstSceneName") API to go back to the scene.

If it is a video element, that’s a little more complicated; I’d expect it should be reset automatically though. If not, you may need to give it a unique element ID and then set its currentTime property.


(Rob Willett) #8

Jonathan,

Thanks for the update.

We are creating an animation NOT a movie. Sorry for the confusion. We have experimented with movies before and it’s not a fantastic user experience in Cordova. Everything is a mess :slight_smile:

We want to create simple HTML5 animations for help screens and for onboarding.

To summarise what we have done as this might be useful to other people.

  1. We have created a simple HTML5 animation using Hype 3.

  2. We export the JS and add them to our cordova project.

  3. We use your function call CallHype() to load the animation up when we press a help button in our app.

  4. The animation appears, two lines of text gently fade in as designed. Looks great.

  5. We close the window and it goes away.

  6. If we click on the help button again, the window appears and the end point of the animation is shown. There is no fading in of the text.

  7. We tried to add in HYPE.documents["documentName"].showSceneNamed("firstSceneName") but were getting HYPE is undefined. Clearly we haven’t got access to HYPE.

  8. Searching through the docs and the javascript forums shows this http://forums.tumult.com/t/hype-is-not-defined-calling-hype-from-external-html/5278/3 which looks interesting.

  9. We added the callback and bingo, we have a working callback. Doesn’t do anything but early days. We added in a JSON.stringify(hypeDocument) and we can see ‘hype stuff’ so we have some sort of confidence that something is working.

  10. We looked through more sections and doc and found http://tumult.com/hype/documentation/3.0/#invoking-api-from-outside-oftumult-hype. So we created a new callback for when the event HypeTimelineComplete is complete with a call to actually do something practical, ie.e goto a scene, in our case the first scene, so it loops.


window.HYPE_eventListeners.push({"type":"HypeTimelineComplete", "callback":HypeTimelineComplete});

function HypeTimelineComplete(hypeDocument, element, event) {
  // do something with hypeDocument...
  // HYPE.documents["documentName"] which is the same thing is also ready now

  ConsoleLog("HypeTimelineComplete");

  ConsoleLog("hypeDocument " + JSON.stringify(hypeDocument));

  ConsoleLog("hypeDocument.sceneNames() = " + hypeDocument.sceneNames());

  hypeDocument.showSceneNamed("Untitled Scene")

  return true;
}
  1. We now have a looping animation. We think we can work out bits to start and stop the animation using ```pauseTimelineNamed`` and similar. We want to make sure animations don’t constantly run in the background in our app as this consumes battery power.

  2. This page is also very useful http://tumult.com/hype/documentation/3.0/#api-functions

I think we have got something we can work with. Lets leave this open for a bit so if anything useful pops up I’ll add it here. We may be the first people to embed Hype 3 in Cordova :blush:

Sorry for how long this is, I thought it useful for other people to see what we did and the steps we went through.

Rob


#9

Hi Rob (@rwillett)

Unfortunatley … no :slight_smile:

I’m not totally sure of your setup and I see ionic / angularjs being thrown around together with cordova. Makes it a little confusing :wink: They are all separate things :smiley: even though they are quite often used together.

That being said, and it’s totally beside the point … a straight forward (ish) way to use a hype project in an angular App is to load the generated script once the view has loaded and you can do this by placing the script’s contents in the controller for that view. A few screenshots to hopefully help with familiarity.

For the following, I am assuming an ionic app (the structure is based on the starter-tabs template)

notice that the .hypresources folder is placed at the root of this www folder.

Now, all you have to do to get this hype document to appear is …

  • place the contents of the hype_generated_script in the associated controller for the view file and wrap it in a $scope.$on("$ionicView.loaded") … call.
$scope.$on("$ionicView.loaded", function(){
//	HYPE.documents["DOCUMENT-NAME"]

(function(){(function k() 
.... 
(this.body)})();})();
}) // end function
  • inside the view template place the following code - note that you must substitute your document name

<ion-view view-title="Help"> <div padding="true" id="DOCUMENT-NAME_hype_container" style="margin:auto;position:relative;width:100%;height:100%;overflow:hidden;" aria-live="polite"></div> </ion-view>

  • the important thing is to make sure there is nothing else other than an ion-view tag (or model tag) you may have to play around as ion-content causes the hype document to disappear. With this in mind, you must account for any padding in your Hype document for headers and tabs if you have them.

This is a basic setup and may not work out of the box for your situation. But the logic is there so you may find the solution. If you need any pointers, give me a shout :wink:


(Rob Willett) #10

Rats, we wanted to be the first :slight_smile: Oh well…

You are correct, we are throwing things around and treating them as one, when we should be more careful with our words.

We have an Ionic V1 app which provides personalised traffic updates to London drivers. We are just putting two more apps into alpha testing which are variants of the first app.

The reason for using Hype 3 is to try and put some simple (but decent quality) help and onboarding screens together.

We have come to similar conclusions and yours though we have differences…

  • We have the hypresources folder in the root directory,
  • We originally put the contents of the hype_generated script in a function call, though we didn’t put it in the $scope.$on("$ionicView.loaded") function. Our function call is triggered by user action.
  • We pulled the hype_generated script out of the function as we were having issues (I cannot remember what they were now) and used the CallHype function
function CallHype() {
	var headElement = document.getElementsByTagName('head')[0];
	var scriptElement = document.createElement('script');
	scriptElement.type = 'text/javascript';
	scriptElement.src = "test1intro.hyperesources/test1intro_hype_generated_script.js";
	headElement.appendChild(scriptElement);
}

We currently call CallHype() when we load up a modal window that sits on top of the current view. This modal window acts as a help screen. Clicking on it makes the window disappear. This modal window was used just to test the proof of concept of getting a Hype 3 animation to work, we may well change it as we explore more how to use Hype 3 and understand more about how to integrate it with our app. The major issue for us is that opening up the help screen again does NOT rerun the Hype 3 animation. It stays at the end of the animation.

We currently have the Hype 3 JavaScript callback system working along with a trivial call to a Hype 3 JavaScript function. This proves we can make things happen from our code back to the Hype system. Time permitting this week we may, get a simple help system setup which implements NextScene(), PreviousScene(), StopScene() and StartScene() on the Hype 3 document. This allows us to ‘play’ HTML 5 animations in any order and how we want to.

Now we have not implemented the Ionic section of our code in quite the same way as you have done, we use ion-pane as that was how we set up the help system. This was some time ago and in hindsight may not be optimal! e.g.

    <script id="image-modal.html" type="text/ng-template">
      <div class="modal image-modal transparent" ng-click="closeModal()">
        <ion-pane class="transparent">
          <div id="test1intro_hype_container" style="margin:auto;position:relative;width:320px;height:568px;overflow:hidden;" aria-live="polite">
          </div>
        </ion-pane>
      </div>
    </script>

Does your use of ionicView.loaded mean that the Hype 3 function within it gets called and reloaded each time? Would this be another way of restarting the HTML 5 animation? In our system we get it running once and thats it :slight_smile:

Hope this clarifies things a little more.

Rob


#11

Sorry :frowning:

it doesn’t … no, but if you add cache-view="false" to your ion-view it should restart (as if opened from new) when you view it after changing tabs.

Again, this is based on my implementation but should work. If not I can explore further using a similar setup to yours.

EDIT: Tomorrow I will add a new post documenting my work on embedding a Hype document in an app using the ionic framework and angular.js and using PhoneGap to create a build. Essentially a how to … on using Hype to create a “hypbrid” :slight_smile: app for use on an Android, iOS and Windows phone.


#12

@DBear – thanks for the Info. I was working a while ago on something similar (and now again). I came up with a very primitive “solution” that is not tested yet with larger Hype documents (or many Hype documents). See here what I am doing:

http://forums.tumult.com/t/embedding-hype-document-in-ionic-framework?source_topic_id=8909

A few questions if you don’t mind:

  1. So you are pasting the complete Hype script in the controller? Is there not a way to somehow “inject” the source file there src="example.hyperesources/example_hype_generated_script.js?39004" … not sure if this is possible in Angular…

  2. Not an experieced developer, so what is this part of the function doing?

    [quote=“DBear, post:9, topic:8909”]
    (function(){(function k()

    (this.body)})();})();
    [/quote]

  3. As a side question – would you have an Idea how to call something like this from inside of Hype (I mean the ng-click) - lets say with a standard Hype Button:

    [quote=“sandor, post:1, topic:9102”]
    <button class=“button button-block button-positive” ng-click=“login()”>
    Open PopUp
    </button>
    [/quote]

And of course it would be awesome to see your new post you have anounced regarding Ionic/Hype!

Thanks an Cheers!


(Rob Willett) #13

We forgot about cache-view=“false”. We know about it and some of our views need it.

It would be good to see the writeup.

Thanks


#14

Sorry guys! been super busy.

I’m still planning on adding a “How to” if it will help?

I’ll share the files with you soon so you can see what I did to get a Hype project (with AngularJS) up and running and ready for Phonegap building


#15

Three thumbs up!


(Rob Willett) #16

We’d also like to see the write up.

We have managed to get Hype 3 working well within our project. We have written two sets of onboarding scenes, each with 5-8 scenes and a few timelines within them.

Seems to work well enough for us. We’re just about to start another one set of scenes which we will use for Tip of the Day.

Thoughts so far are that it works well but there are certain things that make life better.

  1. The ability to NOT put out the Hype 3 framework script for each export. The reason for this is that we might be incorporating 3-4 different Hype 3 projects and its a little bit of a faff to remove them.

  2. Specify the name of the HYPE3 container in our code. At the moment it use the filename but does some slight changes on the container name.

  3. We’d like to see an event thats called when ALL the time timelines in a scene have finished. At the moment if we chain a few timelines together we have to work out which is the last one. It would be nice to see an event thats triggered for this.

  4. Better integration with Angular so we don’t have to do nasty calls to get access to controller functions (and vice versa). We recognise that this may never be done.

  5. Slightly better handling of text fields when trying to edit them. If we have two text fields on top of each other, it can be tricky working out which one we are editing.

  6. For some reason we always seem to catch the vertical resize bar when trying to add new actions. Highly annoying but that could be us.

  7. It would be great to see CSS call outs implemented. At the moment if we want to highlight something, we end up doing it in Affinity Designer using a shaded item with a transparent cut out. It would be nice to have this directly as a capability in Hype 3. ScreenFlow does this very well indeed.

  8. It would also be good to have the home/end etc keys do things like move backward and forward along the timeline.

Some of these are trivial, some are niggles, some are enhancements.

Rob


#17

six thumbs up!