Reveal Hidden element onclick while hiding other elements

This sounds similar to what was discussed here... Rogue Button Behaviors on animation ...and basically I suggested simply using JavaScript.

Are you having the same problem?

If so, I'll have a YouTube video online in a few of days. (Hopefully, HA HA!) It sounds like I picked a useful topic. But if you don't want to wait, here's the short version...

First, select all the elements...

var maps = document.querySelectorAll(".🗺"); // Don't forget the dot, very important 😊

(Yes, I use emoji as class names — it's valid :crazy_face:)

Then, I just hide them all...

 maps.forEach((e) => { e.style.opacity = 0; });

So basically, that's what I do.

Then, I make the elements I want appear. In this case, it's changing the opacity, but changing the display is also another option.

Here I get the selected map from the form/input...

var selectedMap = document.querySelector("input[name='🌎']:checked").value;

...and then I make it visible...

document.getElementById(selectedMap).style.opacity = 1;

I'm really excited about this video, so maybe it will be helpful to you too when it's done. It should be easier to understand when you can see it.

Photics,
The Rogue button post is no longer has active links to view the project. But, it sounds like you are hiding all with the opacity value and then bringing back those you want to see by targeting a select element and then changing just that elements opacity to show..?

My case is I have a function that reveals hidden elements BUT the user can still click on other "links" which continue to reveal more elements. The result is a bunch of stacked on top of each other elements (not desirable).

Currently, I put a simple button that reloads the page ( Clear ). It works but a more elegant solution would be to put the prior/last clicked element into a variable and then on the next click, show the new element and re-hide the prior.

Something like:
IF var current is not null (undefined){
hide current
then show new current } else { show current }

But I have no idea how to do that in JavaScript. It took me long enough to get the current JavaScript working. I'll put it on my list :slight_smile:
It's a transitory object of sorts. If no priors were selected go ahead and show it. But if there is a prior selected element, hide that one and now show the new one. If this were PHP I could set a $_SESSION value then check to see if it exists and then pull from it or the incoming elementID. Or populate an Array and search that for 1 value as we are not looking at all elements just IF there is one prior selected or if this is the first click.

That's right. I use opacity to fade between images, looks nicer, but I could have used style.display = none

Ah, in the map project, that is the desired outcome. They're supposed to be stacked.

It sounds similar to this project...

https://photics.com/free-template-tuesday-11-tumult-hype-multilingual/

It uses LocalStorage to get the previously selected language. So, if I select "Great Britain", that's stored locally and then that value is retrieved when the project is loaded again. If there is no value, use the browser's language. If that's not a match, default to English US.

This is that code...

// Check if a flag was selected or the language has been set already

if (element.id.length >= 2 && element.id.length <= 5){
column(element.id); // Search for a data column that matches the selected flag
localStorage.nl = id; // Save the prefered Navigator Language column ID number.
console.log(localStorage.nl);
} else if (localStorage.nl > 0) {
var id = localStorage.nl;
} else {
	if (data[0].indexOf(nl) > 0) {
	column(nl);  // Use the browser language if there's a match
	} else {
	column("en-US"); // Default to "en-US" if all else fails
	}
}

I have a different way of checking for undefined. HA HA... but basically it's looking for something between two and five characters.

If you don't understand that code, it's OK. The main idea is... maybe LocalStorage is what you're looking for?

1 Like

just add a common class like 'popup' to those elements
then add

var currSceneEl = document.getElementById(hypeDocument.currentSceneId());
var popUpEls = [ ... currSceneEl.querySelectorAll('.popup') ];
popUpEls.forEach(function(el){el.style.display='none'});

at the top of your function that shows up the elements

Maybe LayerRevealer helps.

PS: I also got a version that works with multiple revealer groups on my hard disk. Most user only need only one revealer group… else let me know.

Hmm,
If I understand right.
I would think all you need to do is give each element group a class name.
Then just use the simple trick of hiding them all at the beginning of the showElement2() function

function showElement2(val){
		//var hypeDocument = getHypeDocument();
		var blockEl_ = document.querySelectorAll('.blockEl')
		for (let i = 0; i < blockEl_.length; i++) { 
  				
  					hypeDocument.getElementById(blockEl_[i].id).style.display='none';
			}
		
		console.log(val);
		var target = (val);
		// alert(target);
		hypeDocument.getElementById(target).style.display='block';
		};

ShowOnClick.hype.zip (55.9 KB)

1 Like

Thanks to everyone that contributed in helping me solve this issue. Using MarkHunte's code it worked great for hiding any prior displayed elements.

I now need to run off and look up to understand "let" .

I'd really like to retire but like the line from the Godfather; "Just when I thought I was out, they pull me back in" both with JavaScript , C# in asp .net and also Azure Cloud... :tired_face: :slight_smile:

Thanks again, you guys are really great!

1 Like

I'm running into a bit of a problem... The Hype file works as expected when isolated in it's own html document. BUT if the same is wrapped in a theme (not WordPress) I get an Uncaught TypeError: hypeDocument is undefined error when an element clicked to execute the showElement function.

The Hype document shows and actually works on everything accept the showElement function.

I've tried creating a conditional case looking for if (hypeDocument !== undefined) { which did not help. I've tried declaring using "let" which also does not help.

Is there something else I should be doing to extend the hypeDocument to work within another pages framework?

Using getHypeDocument

I am not sure we’re you are running this code? Also the getHypeDocument function is meant to be used only if you are trying to use script inside an Hype rectangle on stage (inner HTML). It basically traverse the DOM tree upwards to find the corresponding hypeDocument. I am also not seeing you actually using it or assign the result?

Also, it doesn’t work when you extract the JavaScript into an external file. For that kind of scenario you would use the Hype event callbacks to hook up a Hype document to some code.

Register Hype Eventlistener

In that approach you an use an external listener to be notified about event in Hype (hence external code file or Head HTML).

Using a Hype function on a scene event

Then there is also the simple case of just using a Hype function on Scene load or prepare for display right in the IDE

Max, I'm currently taking apart the document that Hype generates and the one I need to work (themed). In other words the pages I provide here may change but I have taken the working one:
https://sgdesign.com/slm/SLM_DB_R2.html
and the one being culled of all other content to see just why one works and one does not:
https://sgdesign.com/slm/test2.php

It's interesting that at this point they are almost identical yet one works and the other fails Just on the click firing showElement()

SLM_DB_R2.hype.zip (147.3 KB)

Problem found... Super weird to me but it was due to a < script > with commented out content..

Edit to add: The same script, commented or not, does not interfere if it is above the hype script in the document. Looks like a bug.

It looks like the issue is getHypeDocument() is making a fallback assumption that the last script must be the one where the Hype document comes from:

var ds = document.scripts, hd=HYPE.documents
var e = e || ds[ds.length-1];

In your document, that last script tag is being used instead of the script tag for the *_hype_generated_script.js file, and so it is not properly finding a Hype document.

I'm not really sure why @MaxZieb wrote it that way, but in your document since you only have a single hype document on the page, you can probably just add this as the first line inside of showElement() and be okay:

var hypeDocument = Object.values(HYPE.documents)[0];

Because it it meant to be called from inside a script tag that needs it. As that script tag is being executed it is always just in that moment the last script tag. This works but is not ment to be used outside of a rectangle. It is specially written for getting the hypeDocument from rectangles containing code inside of Hype. Please check the following post for correct usage:

1 Like

Yes, adding the following solves the problem:
But what is this telling the doc? The var declaration using "let" did not work and I am far from a Javascript pro so can you tell me like a 5 year old? :slight_smile:

Hey Max,
What rectangle?

The scripts are in the HTML Head so exported as separate in the generated publish file. I don't see a way to make them self encapsulated in the hype js doc. Maybe I missed a setting?

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).