Reveal Hidden element onclick while hiding other elements

He means the actual helper is in the head ( or within a hype function, amended accordingly) But calling it for help is meant to be done from within a hype elements innerHtml

Hypeelement on the stage is chosen -> menu -> edit -> edit innerHTML
you can store any regular js, css, html here ...

So IF you need a function to be global, you need create a persistent symbol, hidden or off stage, and assign the function to that using innerHTML?

Seems like a an opportunity as a feature in Hype to encapsulate Head HTML scripts as global with the selection of a checkbox? Or maybe this case is not common...

Still think you misunderstand.

The function in the head is effectively global already.

This is why you can call to it from within the rectangle.

Is your problem that you are not using the exported html file but it instead using your own.
If so you may just want to copy the function to your own html head.

Or do as @MaxZieb says and put it in an Hype function

This is exactly what I am doing. In my Hype doc I use Head HTML so the function is global. Then on publish (->html5 folder) I copy the functions to the end file that used to display the Hype doc. This usually works well but in this last case it created a condition where the script was still looking for hypeDocument. Jonathans suggestion to add the Object value of [0] worked just fine. But I am trying to fully understand both the proper methods that should be used and if this was a bug.

So now I think I should explore using a Hype function to better isolate within the Hype container/environment (rather than Head HTML).

Ok. Well it is not a bug just procedure.

I think is if you do not need to use the head then don't.

I see you doing this

__MigrationHistory (empty)<br>
<a href="#" onclick="showElement('MigrationLog')">__MigrationLog</a><br>
__MigrationLogCurrent<br>
__RefactorLog<br>
__SchemaSnapshot<br>

SM_AutoActionsLog<br>
<a href="#" onclick="showElement('SM_BillingAddress')">SM_BillingAddress</a><br>
SM_BlastSettings<br>

SM_DontSolicitList<br>
SM_DynamicWIP<br>
SM_EmailTemplates<br>
SM_EmployeeDepartment<br>
<a href="#" onclick="showElement('SM_EventsStatistics')">SM_EventsStatistics</a><br>
SM_Feedbacks<br>
SM_Invoice<br>
SM_Invoice_Archive<br>

in the innerHTML which would need the functions in the head but not sure why you need the structure above ?

What you are seeing is a list of items that get assigned the showElement function that then targets a hidden layer. This layer contains information presented on the same page and also hides any other similar layers/elements that might have been displayed using the same function.

The end goal is to have this list (truncated in the example) linked to information on each Database Table Name (which is what these actually are). In some cases I move onClick to a different scene if more visuals are needed. The showElement function is global also because another Scene uses this function to show Stored Procedures from a similar list.

So maybe structure it like so

<span class="datbasname" name="MigrationLog">__MigrationLog</span><br>
<span class="datbasname" name="SM_BillingAddress">SM_BillingAddress</span><br>
<span class="datbasname" name="SM_EventsStatistics">SM_EventsStatistics</span><br>

And have a hype function that adds an addEventListener to each list item using the class name datbasname ( meant it to be databasname but misspelled it, lol )

and get the value from the name attribute.

var datbasnames = document.querySelectorAll('.datbasname')
 
for (let i = 0; i < datbasnames.length; i++) {
  datbasnames[i].addEventListener('click', listener);
}



function  listener(){
 
 var val = this.getAttribute('name')
 
   var blockEl_ = document.querySelectorAll('.blockEl')
		
		for (let i = 0; i < blockEl_.length; i++) { 
  					hypeDocument.getElementById(blockEl_[i].id).style.display='none';
			}
  
		hypeDocument.getElementById(val).style.display='block';
		 
 
 }

And do away with all the head code.

SLM_DB_R2_v2.hype.zip (131.3 KB)

Yes, that works well. Thanks. I did update the text list to be proper anchors so we know which are linked to some resource or not.

But, now I lost my ability to link to the other scenes which was a secondary function in showElement()

function goScene(val2){
	var sceneName = (val2);
	hypeDocument.showSceneNamed(sceneName, hypeDocument.kSceneTransitionCrossfade, 1.1)
	};

I created a new separate goScene() function, loaded it with On Scene Load but that throws a "Uncaught ReferenceError: goScene is not defined" error.

Since the function is fired using an onclick event I tried removing it from the On Scene Load but getting the same error. :tired_face:

SLM_DB_R2_v3.hype.zip (128.3 KB)

A couple things to note:

This is because the function would be made within the scope of that function, and not globally visible.

If you want to make it as a global, you can instead define it as:

window.goScene = function (val2){

Functions made in the Hype editor are not assigned to the global scope. Therefore if you call it like in your code:

<a href="#" onclick="goScene('Notes')">Notes</a><br>

It will not find it, since you are trying to call a global.

Instead, it is assigned in the .functions() array of a hypeDocument object.

The getHypeDocument() call is really something that was supposed to help out for calling it in these situations by either using it at that time or assigning as a global hypeDocument object so you could call it like hypeDocument.functions().goScene(...).

However, it appears you have removed getHypeDocument() from the head. It does seem like from a console error you have an element with inner HTML that's trying to use it though.

As another point on this, you are passing a string into the goScene() function, but this is not really good programming practice since hype functions should be taking (hypeDocument, element, event) arguments.

Note that On Scene Load action will run the function at that time. So this is probably also inappropriate. It is created when your document loads.

showElement does appear to be a setup function, so this would be okay to use at this time. (That said, I think showElement may not be the best name, since it implies it will show an element when invoked).

It is a hidden Symbol that was initiating the Global Hype Document.
hypeDocument-presistent
Now removed in the project below.


The point of changing the text links to include a name attribute and class so you could add a listener to each was so you could avoid putting a function calls directly in the innerHTML.

I missed that you had also had another one in there to change scene.
But you just needed to take the idea of adding your listeners and use a similar one for changing scene.

<a href="#" class="datbasname" name="MigrationLog">__MigrationLog</a><br>
<a href="#" class="datbasname" name="SM_BillingAddress">SM_BillingAddress</a><br>
<a href="#" class="datbasname" name="SM_EventsStatistics">SM_EventsStatistics</a><br>
<a href="#" class="showscene" name="Notes" > Notes</a><br>

In the Hype Function now named initLinks
We can put all of the link inits that add listeners and the functions that do the work.

/// init listiner for show / hide element links	
var datbasnames = document.querySelectorAll('.datbasname' )
 
for (let i = 0; i < datbasnames.length; i++) {
  datbasnames[i].addEventListener('click', showeHidelements);
}

/// init listiner for show scene links
var showscenes = document.querySelectorAll( '.showscene')
 
for (let i = 0; i < showscenes.length; i++) {
  showscenes[i].addEventListener('click', goScene);
}


/// Go to Scene 
function  goScene(){

var sceneName  = this.getAttribute('name');

		hypeDocument.showSceneNamed(sceneName, hypeDocument.kSceneTransitionCrossfade, 1.1);

}


/// Show hide elements

function  showeHidelements(){
 
 var val = this.getAttribute('name')
 
    var blockEl_ = document.querySelectorAll('.blockEl')
		for (let i = 0; i < blockEl_.length; i++) { 
  					hypeDocument.getElementById(blockEl_[i].id).style.display='none';
			}
  		hypeDocument.getElementById(val).style.display='block';
 }

SLM_DB_R2_v4.hype.zip (133.4 KB)

I have no idea of your real setup but all of this is to help keep hype functions within hype and not have to go to global/head ( if you do not need to ?)

If you do need global then for your case @jonathan 's original solution I think works best with your original setup.
var hypeDocument = Object.values(HYPE.documents)[0];

Also if you wanted to not use any innerHTML


Single function for all links

     var val = element.dataset.name 
	 
	 if (element.classList.contains('dataBase')){
	 		var blockEl_ = document.querySelectorAll('.blockEl')
			
			for (let i = 0; i < blockEl_.length; i++) { 
  					hypeDocument.getElementById(blockEl_[i].id).style.display='none';
			}
			
  		hypeDocument.getElementById(val).style.display='block';
 
	 }
	 
	 if (element.classList.contains('changeScene')){
  

			hypeDocument.showSceneNamed(val, hypeDocument.kSceneTransitionCrossfade, 1.1);
 		}

SLM_DB_R2_v5.hype.zip (137.4 KB)

1 Like

Thinking of variables and scopes like a folder structures with files is sometimes helpful. Additionally there are hidden folders that are inaccessible (like on a encrypted drive). Hypes runtime is such a hidden folder. It exposes an API for each and every Hype widget running on a website. The “folder” Hype mounts it API in is global (window object) and is called HYPE.documents (In full window.HYPE.documents but we can omit the window part). Inside there each Hype widget is listed by name. The confusion starts with Hype as the name differs between previews and exported files. In previews it is always “index” and on exports it depends on the file name you export to.

In a preview the “folder” containing the API would be HYPE.documents.index, but if you export to custom name like “Test” you would need to address it as HYPE.documents.Test

This is called the dot notation and doesn’t work for all names, so I prefer writing it like this HYPE.documents['Test']

Either way the main topic of this thread is “execution scopes”. This brings us to second insight in this thread. Hype executes any script tags it finds in innerHTML on a global (window) level. So, the scripts are completely agnostic to the context they are running in. The function and mention that spawned me into this thread was about getHypeDocument that solves receiving the appropriate API by either determining the element it is executed on or by passing in an element and then walking up the DOM tree until it finds a Hype document element it can resolve to the corresponding API. Hence, use it outside of loops and inside a innerHTML inside an Hype document or pass on an element that is part of a hype document (like this when used on onclick etc).

The easier way is to avoid innerHTML and do it like @MarkHunte suggested only in the Hype Interfaxe with local Hype functions as he runtime takes care of scoping in that case.another approach I was tinkering with is petite Vue as it actually exposes the API to the innerHTML.

This will probably be my last contribution to this thread because the poor OP is getting so much advise and mixed messages that probably are more confusing and overwhelming then helpful. There is a saying in German “zu viele Köche verderben die Suppe“.

2 Likes