Javascript and HTMLNames

Because i want to make my scripts and awts as reusable as possible, i always been struggling with the fact that Lectora recreates htmlnames when copying and pasting elements. Even when you make library objects of them htmlnames get recreated and are unique.

Thus making easy reusable snippets and awts tough when javascript is used to target elements on the page.

Previously i either scanned the complete page...got all assets into arrays and then with the use of indexnumbers targeted whatever i needed. A way to tackle it, but surely not ideal.

Another solution i used is setting unique classes to elements, then you can target any element you need/want ..but still this isnt ideally, because either you have to name each element uniquely or you need to get a specific element from the array or list of classes in Javascript.

Well on LUC16 in the 'Extending Lectora with Scripting' course, John showed a method that opens new possibilities to target specific elements.

Token Replacement!

Inside Lectora you can use %HTMLNAME% to get the htmlname of a specific object.

- Add a Run Javascript action to any object

- code in the JS is: alert(%HTMLNAME%)

When you run it now you get a message saying: [object Object]

This is because this is a Javascript Object with a lot of properties like name, x, y and many many more... if you want to know all properties available change your code into:

obj=%HTMLNAME%

for (var key in obj){

if(obj.hasOwnProperty(key)){

alert(key);

}

}

With this code you see all properties available within this object. A lot... :-)

Offcourse you allready noticed name when running the code above.

So to see the htmlname of your element ( i used images ) you run this code:

alert(%HTMLNAME%.name);

Ok thats fine when you code inside Lectora. I however prefer to have most of my Javascript in an external Javascript file. Untill today i ran into trouble trying to access the htmlname with token replacement in my external javascript. Found a solution to that however.

- add a variable to your title. Mine is CurrentHTMLObj

- make sure its used on the page. I do by adding an action OnPageShow -undefined

So now i can add this to any element in Lectora..Pass my actual htmlName to my Javascript... dont have to be afraid for copying/pasting and no need to change the code afterwards. Great bonus for creating reusable elements !!!!

Discussion (14)

All you need to do is assign a unique class name to a given object and then use the following:

function findObjectByClassName(objClassName){

var ocName = objClassName.toLowerCase();

var divs = document.getElementsByTagName(undefined

for(var i=0;iundefined

if(cName!=';';){

var cNames = cName.split('; ';);

for(var j=0;jundefined

}

}

}

}

return ';';;

}

HTH

Regards, Peter

undefined

@ Darrel...will upload a sample tomorrow or so...

@ Peter... yep, that is one of the methods i used before..and it works...only downside is as i allready mentioned in my post, you have to give an element a class in Lectora. And getting elements by classname returns a list or array... so you have to parse those too. When i post a sample..benefits will be clearer.

What exactly are you trying to accomplish? Please upload an example.

And getElementsByClassName returns a list/array... Even with just a single specific classed element in Lectora... Thus needing the [0] Thats why %HTMLNAME% can be usefull...

@mnotermans5114 It returns a HTMLCollection, not an array. It is an array-like type but it is much better. For example, it gets updated live when DOM changes.

Thanks for sharing, I did not know about %HTMLNAME% shorthand. Very useful.

@pjackson2462, with all due respect, this is a convoluted way of replicating JavaScript's native getElementsByClassName() function. Instead of basically all this code, you could just write literally one line of code:

var domObj = getElementsByClassName(objClassName)[0]

Basically what im trying to achieve.... apart from Meta tags vs Header and name attr. is an easy way for non-javascript developers to achieve javascript/gsap effects in Lectora by simply inserting/copying pasting elements.

Should not be needed to check/change htmlnames or do anything in javascript besides some simple functioncalls.

There comes the Token Replacement in function..if i can manage to get it working on other elements too..trying with onShow ... then Javascript enabled elements and parts can be fully self-sufficient without any need for changing code for someone who reuses it.

Didnot know about HTMLCollection and live updates Sergey :) Like this we learn something new each day. One thing i do love about this forum! Thx :D

Added a sample of Token Replacement and Non-centered scaling here:

http://community.trivantis.com/shared-content/scaling-tricks-and-token-replacement/

@klaatu

Couldnot resist making this a sample of both scaling and token replacement ;-)

@pjackson2462

Token replacement helps with selecting elements clicked, but you cannot target elements not clicked.(or at least i didnot find how yet)

So for that you need other selectors. getElementById or getElementsByClassName are options for that.

I'm still not seeing where this is necessary. By 'necessary' I mean it does something you can't do otherwise. I've looked over Math's firstpage script. I'm sure it's me and I'm probably missing out on something good that's right in front of my face. Please, I'm hoping one of you will take the time to explain it in simpler terms so that it is clearer to me.

In case you are not aware, using the "name" attribute on img tags was deprecated in HTML4.01 and is obsolete in HTML5. While it may still work for a while, it is not recommended to use. W3C, MDN.

Math, why do you use the 'Meta tags' html extension for script linking over "Header Scripting" or "Bottom of file scripting"? In production, I do not suggest it because, among other reasons, it puts them before the CSS in the head.

As Tim mentions, it is indeed related to the object %HTMLNAME% is added too. Couldnot target it in any way from outside Lectora ( external Javascript ) ..only from within Lectora.. ( http://trivantis.com/help/Lectora/16/ENG/Lectora_Help/Content/5565.html )

Option to get access from outside is setting a variable and accessing that from outside, like in my sample.

Experiment im doing now ( well yesterday evening ) is adding a OnShow action with %HTMLNAME% to several objects on a page, and then in the external JS dynamically create a variable for the passed HTMLNAMES so that i can access any object without ever need to know its HTMLNAME, thus making things really good reusable.

Thanks for sharing. I've played around with it a little:

%HTMLNAME% seems to always refer to the object an action is added to, no matter which trigger this action uses. It can be used to get several properties of the object:

%HTMLNAME%.name = html name of the object = id of the div

%HTMLNAME%.w = %WIDTH% = width of the div

%HTMLNAME%.h = %HEIGHT% = height of the div

%HTMLNAME%.x = x-position of the div

%HTMLNAME%.y = y-position of the div

There's more information available.

You can get the same information for any object:

text123.w = width of the div with the html name / id "text123".

Tim

Coming in very late, but this is highly relevant to what I'm trying to do now.

I asked a question recently about questions: Multiple choice/select questions: scripted access to CURRENT order on page? Apparently there's no direct support in Lectora for this. I therefore need to script around the gap.

Could I put a Token Substitution snippet on each of the Choice nn text objects adding some unique string to their HTMLnames, say "choice", and then in JavaScript parse the list of DOM objects on the page to get an array (or better structure?) of pointers to the labels for each question choice? Or would it be simpler to just manually name each choice label from the Lectora developer interface, for every question in every quiz?

My final goal is to then sort the choice labels by Y position and be able to play audio clips reading each one aloud, in order by vertical position. The audio clips would be linked to each question choice and also would play if the item is clicked. (I would thus override the default behavior of selecting the appropriate radio button/checkbox when the label is clicked.)

Thoughts?

@CarlFink ... i am not quite sure what you want to achieve...but any element in a Lectora.awt is accessible by Javascript externally. The order of elements is decided by the order a developer places them in a view. Actually the title explorer has the exact same order. At some point i made a setup ( Lectora 16 ) that reads any element on screen and adds them into arrays for animation.

http://community.trivantis.com/shared-content/reusable-oop-setup-in-lectora/

I do think the order in the array is the order of the element.

If you add a sample of what your planning to achieve, i gladly jump onto it.

Kind regards,

Math

PS. this sample is old... keep that in mind ;-)

Discussions have been disabled for this post