Improved Javascript Injection


#5

Hi mbc66

It seems that you might be able to help me. I hope so as I have spent days at this before I found your posts.

I have external JS files I have created and if I manually insert the following four lines into the html file generated by Axure, at the very end of the html file (ie just before the tags), it works.

I want Axure to embed these 4 lines at the end of the html code (just before the ) automatically so I don’t have to generate the html using Axure and then manually put in these four lines every time.

< script src=“testing/js/exporting.js”>
< link rel=“stylesheet” href=“testing/css/fonts.css”>
< script src=“testing/js/extra.js”>
< script src=“testing/js/a2.js”>

(Note that I had to put a space after the < in each of the lines above so that this forum message would display it.)

Also, I only want this for one of the pages in my Axure prototype.

Any ideas?? Anyone??


#6

Hello dav123456,

The method that Sam describes (first post in this thread) works for what you want to do. Have you tried that? It is a hack that adds javascript declarations to the HTML head section when Axure generates the HTML, so you don’t have to manually edit the HTML files. This allows you to make javascript calls in your Axure pages (and individual widgets, apparently.)

As I describe in my post above, you can insert declarations for external javascript by adding it to the end of the inserted code. Looks like the whole text and coloring did not port across from the old forums. The trick is to put your lines just before <meta name=

Thus, to add your calls above, the block of text to paste into the User Scalable field would be:

1"/><script type="text/javascript">window.open=window.open,window.open=function(){"use strict";"function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")});var _open=window.open;return function(url,a,b,c,d,e,f){if("javascript:"!==url.substring(0,11)||!$axure)return window.openReplace?(window.openReplace=!1,window.location.replace(url),!1):_open(url,a,b,c,d,e,f);if(!$axure.error){var ignoreError;$axure.error=function(a){return ignoreError||(ignoreError=!confirm(a)),!1},$axure.internal(function(a){$axure.debug=""!==a.globalVariableProvider.getVariableValue("Debug")}),$axure("@Axure.OnInitialize").moveBy(0,0,{})}var script=url.substring(11).trim();if("/"===script[0]&&"/"===script[1])return!1;if("@"==script[0]||"#"==script[0]){var args=script.split("<,>"),src=args[0].split(":");if(script=$axure(src[0].trim()).text(),!script)return $axure.error('Widget "'+src[0]+'" not found.');for(var i=1;i<args.length;i++){var l=args[i].split(":");script=script.replace("[["+l[0].trim()+"]]",JSON.stringify(l.slice(1).join(":")).slice(1,-1))}if(src.length>1){var frame=$axure(src[1].trim()).$().children("iframe")[0];return frame?(frame=(frame.contentWindow?frame.contentWindow:frame.contentDocument.document?frame.contentDocument.document:frame.contentDocument).document,frame.open("text/html","replace"),frame.write(script),frame.close(),!1):$axure.error('Widget InlineFrame "'+src[1]+'" not found.')}}if(""!==script){if($axure.debug)script=eval(script);else try{script=eval(script)}catch(a){return $axure.error("Exception:\n"+a+"\n\nTrace:\n"+a.stack+"\n\nScript:\n"+script.slice(0,1024))}if(script)return _open("javascript: "+JSON.stringify(script)+";",a,b,c,d,e,f)}return!1}}(),console.log("** Axure Javascript **");</script><script src="testing/js/exporting.js"><link rel="stylesheet" href="testing/css/fonts.css"><script src="testing/js/extra.js"><script src="testing/js/a2.js"><meta name="

This might make it easier to see what’s going on… Sam’s original code insertion block:

…and with your javascript lines added:

To make it happen, you paste all that into the User Scalable field in the Mobile/Device tab of the Generate HTML properties. I recommend creating a custom HTML Generator so you can reuse this for other prototypes, then just duplicate and modify the generator for other javascript/css you want to use. This will also allow you to add your javascript to only one page (kind of… see below.)

In Axure, select Publish > More Generators and Configurations…, select HTML 1 and duplicate it:

In your new generator, paste your code into User Scalable (no or blank):

Click Generate and test it out.


Now, for your other question…

I’m not entirely sure why you need this. I presume this is for the custom CSS? If you have external javascript declarations, but never make an actual javascript call, or call the CSS styles, it won’t matter.

If you publish to Axure Share and use the Plugins feature, you can assign the plugin (apply the external .js and .css) to only specific pages. This is your best choice.

If you can’t use Axure Share, I don’t know of any way to select multiple generators for one prototype.

Here is what I’d do, though. I would create a second prototype for the “one page” and generate it with my custom JS-CSS generator. Then, back in my first prototype, that page would be blank with an OnPageLoad : Open < link to my second prototype > in Current Window so that it redirects to my special page. Then, when my special page needs to go to another page, use a link to the first prototype. Make sense?

Another approach would be to publish the second prototype with the one special page, but in the first prototype, put an Inline Frame widget on that page and call the second prototype to load in that inline frame.


Some general notes on this…

  • You will need network access to your external .js files or it won’t work. Seems obvious, but it can trip you up if you are testing outside a company firewall or that server is down, or you are testing remotely and your usability lab’s wi-fi is down… all the things that shouldn’t happen but do.

  • This works with the Preview (F5) as long as your custom generator is default, or you choose it from Publish > Preview Options (Ctrl-F5) > Select the HTML configuration…

  • You can see I’ve got a few custom generators in my screenshot above. If I want to publish locally (or upload to my company internal server) I choose a JS generator. If I want to publish to Axure Share with javascript support (and “User Scalable: no” which I need for my mobile app prototypes), I use a generator without this injection, and instead use Axure Share’s Plugin feature to do the same thing.

  • If in the future I need to create a prototype with custom javascript, I just import one of my custom generators from a previous project by: File > Import From .RP File > Next > Next > Next > Next > double-click the Import:No on a generator so it reads, “Yes” > Skip to End > Finish.

(Oh, by the way, you can include code samples in your posts by using the Preformatted Text button in the editor header (used to be called “Insert Code” in old forums. That’s what I did above.


#7

Wow, thanks so much mbc66. There is a lot to get through and for me to test… but I wanted to get back to you asap to thank you. I was stuck and now I have a way forward. I will post my progress later.

FYI I wanted to try the method that Sam describes (first post in this thread), but I don’t understand how to do it. Is there a detailed example someone could send me or really spell it out for a novice like me? For instance I don’t understand your comments in the second paragraphs where you say, “The trick is to put your lines just before <meta name=”. I can’t find where <meta name=" is? It is probably straight forward, but I can’t find it.

Also to answer your question; the reason I wanted to be able to control different javascript injections on each page is because I have written a different JS script to populate tables, graphs, etc and they are specific for the page they refer to.


#8

I understand—this is some tricky stuff to get around some of Axure’s shortcomings. I’ve had to play around with it quite a bit to get stuff to work.

If you have an .rp file you could attach here or send me, and your real javascript references, I could try to get it to work for you.

The <meta name= " is in the block of code to be inserted… Look in my long code examples above, it is right at the end… the last 10 characters. Do you see where I highlighted your javascript declarations in yellow? It comes right after that.

So, just highlight all of the text in the gray box (in my previous post starting with 1"/><script and ending with meta name=" --Then paste it into your favorite editor, paste your external javascript references just before meta name=" , copy it all and paste it into the “User Scalable” text field in the Axure generator, as shown above.

Here is an example .rp file which calls an external javascript file from https://responsivevoice.org/

It adds text-to-speech to your website/prototype. To enable it, just add this:
<script src='https://code.responsivevoice.org/responsivevoice.js'></script>

To use it, open this hyperlink:
javascript:responsiveVoice.speak('Hello javascript!');

As in:

Responsive_Voice v3.rp (90.8 KB)

Look at the HTML generators in this file. There are “HTML 1”, “HTML JS (default)” and “HTML JS 2”. The “HTML” generator is the basic built-in one you get in every .rp file. “HTML JS” has code in the User Scalable field, which includes the reference to the responsivevoice.js script. If you preview or publish with this generator, and turn your speakers/headphones on, the prototype should work correctly and speak things out loud. If you publish with the plain “HTML” generator, the pages will load and work, but no voice will come out (unless the js is still cached in your browser.)

Now, the “HTML JS 2” generator has your dummy javascript references in it. Look at the end of the long line in the User Scalable field and you’ll find it.

Hope all this helps you out!


If you get this working, you could try declaring all your external js for all pages, then only making the calls you need for a specific page. Might have to rename some of your functions so they are all different, but seems doable.


#9

Hi mbc66 & dav123456,

Thank you for your shared interrest in extending Axure prototypes with custom javascript. As mbc66 describes the official method to do this is to use “AxShare” plug-ins. The limitation of this method is that it only works on prototypes hosted on AxShare. If the javascript must work when a prototype is previwed from Axure or hosted elsewhere then the “hack” is an option. Remeber that the hack is a hack, and may not work in new versions of Axure.

Thanks,
Sam


#10

Another method to add custom javascript and CSS to prototypes is to “misuse” webfonts.

To add javascript use:

}</style><script type="text/javascript">
/* Insert Javascript Here */
</script><style type="text/css">{

To add css use:

}
/* Insert CSS Here */
{

/sam


#11

Nice. Really wish plugins were a part of the file instead of the AxShare project, just like this method works.


#12

Yes. It would be nice to get custom javascript into the Axure IDE.


#13

A great example of Javascript injection is the awesome CSS animations library created by DeeKey.


#14

More information about custom Javascript and CSS available here:
https://b2grli.axshare.com/#g=0&p=javascript_improved


#15

Hi mbc66,
May I ask you if you could please post an option with a ‘male’ voice?
Also, is it possible to control the voice’s pitch, rate and volume, by using code from this page ResponsiveVoice.JS?

Thank you,
Natalie


#16

Thanks bermanatalie,

Say, do you know if it is possible to replace the “Hello world” part with a variable from Axure? For instance, how would I get this to read back anything I type in a text field in an Axure prototype?

Well I found the answer. Use the following line where LVAR1 equals the text in the text field using the fx button.
javascript:responsiveVoice.speak(’[[LVAR1]]’, “UK English Male”);


#17

Hi dav123456
It’s really work as a :dizzy:charm!:dizzy:

VOICE-SPEAKING.rp (609.0 KB)
This file include:

  • 2 Female voices
  • 3 Male voices

Thank you so much!
Natalie


#18

If the text field contains a ’ or \ or newline then there will be an error. If the text field contains the text:
iam’error

then the javascript becomes (after the text field value is inserted):
javascript:responsiveVoice.speak(‘iam’error’, “UK English Male”);

you can fix this by escaping some characters. Here is an updated version of the javascript:
javascript:responsiveVoice.speak(’[[LVAR1.replace("\\", “\\\\”).replace("’", “\\’”).replace("\n", “\\n”)]]’, “UK English Male”);

(note that i have updated the javascript. the forum display \\ as , so i had do add a lot of extra \ to get the javascript correct)

/sam


#19

Thanks Sam, but I can’t get this working.
My javascript that works is: javascript:responsiveVoice.speak(’[[LVAR1]]’, “UK English Male”);
but when I replace it with your line I get no sound at all. So I tested the original javascript and tried to get it to say “Don’t” and it failed to respond, then I change the javascript to yours which didn’t respond, and then I put in this one:
javascript:responsiveVoice.speak(’[[LVAR1.replace("’", “’”)]]’, “UK English Male”);
but that didn’t respond either.

Any suggestions as to what I am doing wrong?


#20

Oh. I can see that this forum is messing with \ in the text. I have updated my post so that it now display the correct javascript.


#21

Hey Sam, try wrapping your script examples in backticks to bypass the Markdown/HTML parser:

some code here with as many \ backslashes \ as you want

You can also access this formatting by highlighting your text and clicking the Preformatted text icon, </>, at the top of the message editor.


#22

Excellent. It works. Thanks!


#23

I implemented voice in my prototype: https://9vtssu.axshare.com/#g=1&p=chatbot
I discovered that changing the “I’m” to “I am” in the widget allows Watson to speak.


#24

Hi sam.hepworth,

May I ask you if you could please share your expertise on how to fix errors that show up in MSIE and Firefox when trying to run javascript calls. I have 2 events OnShow and OnLoad code.
Here link to page with error: [Error in Firefox and MS Edge]
(https://sjlif6.axshare.com/#g=1&p=ask_watson_chatbot&c=1)

I tried to resolve this but couldn’t figure out.

Voice-Js -browser error.rp (97.8 KB)

Preview for attached file.
Please click to
Here I use javascript code:

javascript:var jsurl_one = document.createElement('script');
jsurl_one.setAttribute("type", "text/javascript");
jsurl_one.setAttribute("src", "https://code.responsivevoice.org/responsivevoice.js");
var head = document.getElementsByTagName('head')[0];
head.appendChild(jsurl_one);


javascript:responsiveVoice.speak('[[LVAR1]]', "US English Male");

Would appreciate your any help and advice!
Natalie