I am making a Story Map (ArcGIS/Esri product that allows you to make various types of georeferenced presentations) that allows you to use embedded HTML and CSS (within <style> tags). The problem I am running into is that I want to have a show/hide for additional information on different topics, but I have been unable to successfully implement this functionality.
I tried the collapse Bootstrap method, which works initially but after a few hours it no longer works (with the button method the button stops working, with the href method it just opens the Story Map again in a new page). Here is the code for that:
<p>
<button aria-controls="collapseFlowers" aria-expanded="false"
class="btn btn-primary" data-target="#collapseFlowers"
data-toggle="collapse"
type="button">
More information on Wildflower
</button>
</p>
<div class="collapse">
<div class="card card-body">
<img alt="" src="https://i.imgur.com/Bidb7cR.png" />
</div>
</div>
From what I've gathered, this issue is because the Story Map lacks the Bootstrap dependencies, but I have no idea why it would work initially if that were the case.
I've also tried all of the solutions here, none of which have worked. When I save and exit the HTML editor, it seems to "compile" the code, removing parts of it that are required for it to function. This is probably an inadequate explanation but I can include examples if needed.
Story Maps do support JavaScript and other, deeper HTML work, but you have to download the source and rehost it, which is not an option for this project. I am experienced in Java, C, and some other languages but know very little about HTML and how it is implemented, so this is driving me crazy. Any help is appreciated!
Listen for click events on button,
Using only JavaScript,
const btn = document.querySelector('.btn');
const collapse = document.querySelector('.collapse');
// initially hide the image
collapse.style.display = "none";
var hidden = true;
// click event listener
btn.addEventListener('click', handleClick);
// click event handler
function handleClick (e) {
if (hidden) {
hidden = false;
collapse.style.display = "block";
}
else {
hidden = true;
collapse.style.display = "none";
}
}
<p><button aria-controls="collapseFlowers" aria-expanded="false" class="btn btn-primary" data-target="#collapseFlowers" data-toggle="collapse" type="button">More information on Wildflowers</button></p>
<div class="collapse">
<div class="card card-body"><img alt="" src="https://i.imgur.com/Bidb7cR.png" /></div>
</div>
Using only CSS,
label {
cursor: pointer;
}
div.collapse {
display: none;
}
#btn-checkbox {
width: 0;
height: 0;
opacity: 0;
}
#btn-checkbox:checked + div.collapse {
display: block;
}
<button><label for="btn-checkbox">More information on Wildflower</label></button>
<input id="btn-checkbox" type="checkbox"/>
<div class="collapse">
<div class="card card-body"><img alt="" src="https://i.imgur.com/Bidb7cR.png" /></div>
</div>
I've done some changes to the above code, so that it can work comfortably.
Link relevant to this post,CSS-tricks
Related
I'm trying to use expand-collapse feature of bootstrap 4 and was encountering a weird issue with the use of *ngIf for expansion and collapse.
Whenever I try to use *ngIf as follows, the jquery doesn't work but works when *ngIf is deleted.
HTML:
<div class="collapse-group">
<div class="row">
<div class="col-md-7" id="row">
<div id="link_text_div" *ngIf="this.collapseExpandArrowFlag==true">
<span id="collapse_all" class="close-button" (click)="arrowFunc($event)" style="cursor: pointer;" >
Collapse all
</span>
</div>
<div id="link_text_div" *ngIf="this.collapseExpandArrowFlag==false">
<span id="expand_all" class="open-button" (click)="arrowFunc($event)" style="cursor: pointer;"
>
Expand all
</span>
</div>
</div>
</div>
</div>
.Ts:
collapseExpandArrowFlag = true;
arrowFunc(event) {
if(event.srcElement.id === "collapse_all") { //On-Click Collapse Logic
this.collapseExpandArrowFlag = false;
$(".close-button").on("click", function() {
$(this).closest('.collapse-group').find('.multi-collapse').collapse('hide');
});
}
if(event.srcElement.id === "expand_all") {
this.collapseExpandArrowFlag = true;
$(".open-button").on("click", function() {
$(this).closest('.collapse-group').find('.multi-collapse').collapse('show');
});
}
Try to remove "this" in the ngIf like this:
*ngIf="collapseExpandArrowFlag==true"
Please remove the 'this.' from the *ngIf and just write
*ngIf="collapseExpandArrowFlag"
If this not working , try to change *ngIf to
[hidden]="collapseExpandArrowFlag"
and
[hidden]="!collapseExpandArrowFlag"
This will add the element and the event on the dom on load time. and will keep it there (with a display : none property in css).
Plus take into consideration how you need to work with external library code like JQuery.
See references:
Use jQuery script with Angular 6 CLI project
Change you ts file as follows
collapseExpandArrowFlag = true;
arrowFunc(event) {
if(event.srcElement.id === "collapse_all") { //On-Click Collapse Logic
this.collapseExpandArrowFlag = false;
$(this).closest('.collapse-group').find('.multi-collapse').collapse('hide');
}
if(event.srcElement.id === "expand_all") {
this.collapseExpandArrowFlag = true;
$(this).closest('.collapse-group').find('.multi-collapse').collapse('show');
}
What's happening here is, when you click the button, inside ts code,
this.collapseExpandArrowFlag = false;
is called, and in the template the close-button is removed.
But in the very next line of ts code,
$(".close-button")
is called, But in this state that element is removed from the DOM
And make sure you've removed this. from *ngIf statements
I'm quite new in coding, trying to educate myself because i'm interested. So, sorry if it's going to be a bit dumb question or not so specific or not really correct...
On my "practicing site" i'm having some navigation links, which are referring to different innerHTML contents (like different pages). I used the 'onClick' event to make them show up, for example like this:
<div class="nav" onClick="changeNavigation('a')">menu</div>
It works with texts perfectly, but my problem is that i don't know how to make the same with an image. So when i click on the image, i want to be redirected to that innerHTML page, like i did it with the text based button. I tried to do it like these two ways, but none of them worked.
<img src="picture.png" onClick="changeNavigation('a')" />
<div onClick="changeNavigation('a')"><img src="picture.png"></div>
Is it possible to make this with an image and the 'onClick' event? Or how else can i make this work?
By the way this is my script to make innerHTML show up:
<script>
function changeNavigation(id) {
document.getElementById('main').innerHTML = document.getElementById(id).innerHTML
}
</script>
I also tried to add my image an id that says 'main' like in the script this way, but with no result.
<img id="main" onClick="changeNavigation('f')" src="picture.png" />
Can you help me please? I would appreciate any answer, because i already searched about this and i didn't find anything that could've helped solve my problem and i'm really stuck right now.
(Sorry if my english isn't the best, it's not my native language.)
I have updated my answer to what you want. You need to the divs id you want to display as a parameter to the function you use for onclick. A sample is below.
var divs = ["Menu1", "Menu2", "Menu3", "Menu4"];
var visibleDivId = null;
function toggleVisibility(divId) {
if(visibleDivId === divId) {
visibleDivId = null;
} else {
visibleDivId = divId;
}
hideNonVisibleDivs();
}
function hideNonVisibleDivs() {
var i, divId, div;
for(i = 0; i < divs.length; i++) {
divId = divs[i];
div = document.getElementById(divId);
if(visibleDivId === divId) {
div.style.display = "block";
} else {
div.style.display = "none";
}
}
}
.main_div{text-align:center; background: #00C492; padding:20px; width: 400px;}
.inner_div{background: #fff; margin-top:20px; height: 100px;}
.buttons a{font-size: 16px;}
.buttons a:hover{cursor:pointer; font-size: 16px;}
img {cursor:pointer}
<div class="main_div">
<div class="buttons">
<img src="http://www.clker.com/cliparts/J/g/2/D/p/I/one-hi.png" width="50px" onclick="toggleVisibility('Menu1');"> <img src="http://www.clker.com/cliparts/E/x/J/x/m/z/blue-number-two-hi.png" width="50px" onclick="toggleVisibility('Menu2');">
<img src="http://www.clker.com/cliparts/L/H/T/b/g/N/three-md.png" width="50px" onclick="toggleVisibility('Menu3');">
<img src="http://www.clker.com/cliparts/v/G/G/A/D/s/four-md.png" width="50px" onclick="toggleVisibility('Menu4');">
</div>
<div class="inner_div">
<div id="Menu1">I'm container one</div>
<div id="Menu2" style="display: none;">I'm container two</div>
<div id="Menu3" style="display: none;">I'm container three</div>
<div id="Menu4" style="display: none;">I'm container four</div>
</div>
</div>
You can just keep all of the sections as children of #main, and selectively show them when the section button in clicked. E.g.,
HTML
<nav>
<button type="button" data-index=0>Show one</button>
<button type="button" data-index=1>Show two</button>
<button type="button" data-index=2>Show three</button>
</nav>
<main id="main">
<section>One</section>
<section class="hidden">Two</section>
<section class="hidden">Three</section>
</main>
CSS
.hidden {
display: none;
}
JavaScript
const buttons = Array.from(document.querySelectorAll('button'));
const contentBlocks = Array.from(document.querySelectorAll('section'));
function hideSections (arr) {
arr.forEach(a => {
a.classList.add('hidden');
});
}
function showSection (index, sections) {
// Just a basic check, not exhaustive by any stretch
if (index !== undefined && sections !== undefined) {
hideSections(sections);
sections[index].classList.remove('hidden');
}
}
buttons.forEach(button => {
button.addEventListener('click', () => {
const contentBlocks = Array.from(document.querySelectorAll('section'));
const index = button.getAttribute('data-index');
showSection(index, contentBlocks);
});
});
Obviously you'll have to adjust your selectors for your use case, but Here's a pen
Here's a GitHub Gist pointing to some examples I created on JSFiddle based off of your specific use case (Stack Overflow doesn't let me post links to JSFiddle directly without including code here, but it's easier to follow along/experiment entirely in JSFiddle):
https://gist.github.com/andresn/f100386f06ee28e35bd83c62d9219890
More advanced stuff:
Ideally, you'd use what's called event delegation instead of adding an onclick to every anchor (DRY = Don't Repeat Yourself is good to always keep in mind while programming and so is KISS = Keep It Simple Silly). Here is a resource explaining event delegation:
https://davidwalsh.name/event-delegate
You can even take this further by preloading all your images so they load behind the scenes when the user first loads the page:
https://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
So I'm working with Angular and I'm trying to make a button that when clicked disappears. I have tried to use [hidden], (click)="showHide = !showHide", and a bunch of other methods. Nothing is working so far.
My html (currently):
<div class="rows">
<div class="a-bunch-of-styles-for-my-button">
<a type="button" class="more-styles" (click)="inboundClick = !inboundClick" [routerLink]="['/inbound']" href="">
</a>
</div>
</div>
and my component:
export class AppComponent {
inboundClick = false;
}
In essence I have 2 buttons on a page and when one button is clicked I want to hide both buttons and display a set of new buttons.
I'm very new to Angular and I'm very confused why this won't work.
Your HTML
<div class="yourCssClass" *ngIf="this.isButtonVisible" (click)="this.isButtonVisible = false">
...
</div>
Your TypeScript
export class AppComponent {
private isButtonVisible = true;
}
This should do the job. *ngIf automatically hides the element, if the condition evaluates false, so setting the variable to false is sufficient.
The problem I see here is, that you don't control the visibility at any point. Using [ngClass] to add a specific class, if a condition is met, or *ngIf is helpful, whenever you try to change elements on user interaction.
For more information on [ngClass], you can read about its usage here: https://angular.io/api/common/NgClass
You can read about *ngIf here: https://angular.io/api/common/NgIf
Especially the "Common Use" part should be interesting for you.
Edit:
Reading your comment below it seems you did not notice what [hidden] and (click) actually do. [hidden] controls the visibility of the element, usually dependent on a certain condition. (click) however is a quick way to bind a Click-Event to your element.
Using both of those tools enables to hide an element, by changing a variable, if a user clicks on your element (the new value of the variable may be assigned by a function called by (click) or inline, as demonstrated in the example code).
Edit2: Yep, you meant Angular2/4 ;) So this should do the job.
Here is how you can achieve that:
In your component.html:
<a type="button" class="more-styles"
[hidden]="!inboundClick"
(click)="inboundClick = !inboundClick"
[routerLink]="['/inbound']" href="">
</a>
<a type="button" class="more-styles"
[hidden]="!outboundClick "
(click)="outboundClick = !outboundClick "
[routerLink]="['/outbound']" href="">
</a>
... and in your AppComponent:
export class AppComponent {
inboundClick = true;
outboundClick = true;
}
PLUNKER DEMO
Here is a neat way to hide/remove items, specially handy if there is a list of items.
Note how it takes advantage of Angular's template variables (#ListItem).
So your template can either be something like:
<a type="button" #ButtonA
(click)="onClick(ButtonA)"
[routerLink]="['/inbound']" href="">
</a>
<a type="button" #ButtonB
(click)="onClick(ButtonB)"
[routerLink]="['/outbound']" href="">
</a>
Or like this:
<ng-container *ngFor="let item of list">
<div #ListItem>
<button (click)="onClick(ListItem)">
</div>
</ng-container>
Depending on how you want to hide - if you want to remove it from DOM, or just hide it with CSS. And depending if you want to toggle it or just remove it completely. There are a few options:
Remove element from DOM (no way to get it back):
close(e: HTMLElement) {
e.remove();
}
Hiding it with the hidden attribute - beware that the hidden attribute can be overriden by CSS, it will happen if you are changing the display property and the rule has more precedence:
close(e: HTMLElement) {
e.toggleAttribute('hidden');
}
Hiding it "manually" with CSS:
close(e: HTMLElement) {
e.classList.toggle('hide-element');
}
.hide-element {
display: none;
}
I added at my website created with Google Sites a button to hide/show a block of text. The problem is that in Chrome/Firefox it works, but in Safari it does not work.
I did not use javascript/JQuery because in google sites is not simply to handle.
In the following the simple code i added.
How do I can solve this problem?
<div class="nascosto">
<input type="button" value="Abstract" onclick="
if (this.parentNode.nextSibling.childNodes[0].style.display != '')
{ this.parentNode.nextSibling.childNodes[0].style.display = ''; this.value = 'Abstract'; }
else { this.parentNode.nextSibling.childNodes[0].style.display = 'none'; this.value = 'Abstract'; }" />
</div><div><div class="nascosto" style="display: none;">
<p>Insert here
</p>
</div></div>
for me there is an error in firefox, too. I've found out, that the next sibling of the first div is a text-element. I found this out with a console.log of the nodename. You can see it in the code-example below. For me the following code is working now, but I cannot test this in safari.
Also the function is not called childNodes, but children. Maybe this is a problem for safari.
Please put the functionality in an separate function on top or at the bottom of the page. The way you've done it is not really great.
function doSomething(element) {
console.log(element.parentNode.nextSibling.nodeName);
if (element.parentNode.nextSibling.nextSibling.children[0].style.display != 'block') {
element.parentNode.nextSibling.nextSibling.children[0].style.display = 'block';
this.value = 'Abstract';
} else {
element.parentNode.nextSibling.nextSibling.children[0].style.display = 'none';
this.value = 'Abstract';
}
}
<div class="hide">
<input type="button" value="Abstract" onclick="doSomething(this)" />
</div>
<div id="test2">
<div class="hide" style="display: none;">
<p>Insert text here</p>
</div>
</div>
The goal its to have a menu activated by a button.
This menu can have any type of content inside, so it must adapt according to its content.
In this example i have an accordion, but could be just a grid, or a form, since i'm making it as a bootstrap/jquery widget.
The problem is that the menu changes size after opening and closing it several times.
How can i improve it to make it adaptable to content and consistent, regarding that it will accept different contents.
Code
http://jsfiddle.net/fpmsusm5/
Javascript:
var button = $('#button');
var dialog = $('#modal');
button.on('click', function () {
dialog.toggleClass('hide');
dialog.position({
my: "right top",
at: "right-2 bottom",
of: button
});
})
$("#openpanel1").on("click", function () {
var curr_panel = $("#panel1")
curr_panel.toggleClass('show hide');
curr_panel.collapse(curr_panel.hasClass('show') ? 'show' : 'hide');
});
...
/* ensure any open panels are closed before showing selected */
$('#accordion').on('show.bs.collapse', function () {
$('#accordion .in').collapse('hide');
});
HTML:
<div class="pull-right">
<a id="button" class="btn">Settings</a>
</div>
<div id="modal" class="modal hide" style="overflow- y:hidden;width:auto;height:auto;max-height:100%; max-width:100% ">
<div class="modal-body" style="overflow-y:hidden; width:auto; height:auto; max-height:100%; max-width:100%">
<div id="accordion">
<button id="openpanel1" type="button" class="btn" style="width:100%;text-align:left"><i
class="icon-search"></i>Page Information
</button>
<div id="panel1" class="collapse">
<div class="panel-body">
Contents panel 1
</div>
</div>
....
</div>
</div>
</div>
Thanks for your insights.
Every time you position the dialog, it's changing the left property, and that's causing it to resize.
You don't have to reposition it every time you show/hide it, you can just do it once:
var dialog = $('#modal');
dialog.position({
my: "right top",
at: "right-2 bottom",
of: button
});
button.on('click', function () {
dialog.toggleClass('hide');
});
Then it stays the same size. Updated fiddle: http://jsfiddle.net/fpmsusm5/1/