Make <a> link activate expand text button - javascript

I have a button that looks like this:
<button class="button-global button-a" id="more" target="1">More Info</button>
It triggers expanded text with this:
$('.p2').hide();
$('#more').click(function (ev) {
var t = ev.target
$('#expanded' + $(this).attr('target')).toggle(50, function(){
console.log(ev.target)
$(t).html($(this).is(':visible')? 'Simplify' : 'More Info')
});
return false;
});
I want this link (only the aboutus link):
<a class="pcnav navlinks" href="#aboutus-target">About Us</a>
to also trigger the expanded text when clicked but not if expanded is already visible, I don't want the text to change on aboutus like it does for the button,
(made it more straightforward for new people seeing the post as it's gotten a bit confusing)
Any help would be great!

Class Driven jQuery
Multiple <a> & <button> Solution
Each <a>, <button>, & <section class='content...'> has:
one "common static class": .x
two "shared state classes": .on and .off
In order to control different tags with the same set of classes, CSS/jQuery selectors are declared as combos thereby establishing specific behavior for multiple tags while sharing a class that allows easy access to all of the tags as a group. Review the comments in the CSS section of Demo 2 for details.
Fiddle✱
Demo 2
Details are commented in demo.
$('.more').on('click', function() {
// Get the #id of the closest article.p
var page = $(this).closest('.p').attr('id');
// Toggle .on/.off on all .x within article.p
$(`#${page} .x`).toggleClass('on off');
});
/*
Exclude .link.on to ensure click event is only
triggered when .off class is assigned to .link
*/
$('.link').not('.on').on('click', function() {
/*+ Expand .content located within the same .p
var page = $(this).closest('.p').attr('id');
$(`#${page} .x`).addClass('on').removeClass('off');
//-*/
//*- Expand .content located at this.href
var jump = $(this).attr('href');
$(`${jump} .x`).addClass('on').removeClass('off');
//-*/
// Scroll to this.href
$('html, body').animate({
scrollTop: $(jump).offset().top
}, 550);
});
html {
overflow-y: scroll;
overflow-x: hidden;
}
html,
body {
background: #fff;
padding: 20px;
font: 400 small-caps 16px/1.45 Arial;
}
main {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
article {
background: none;
display: table;
width: 100%;
}
nav,
section,
footer {
background: #222;
color: #fc3;
padding: 20px;
text-align: center;
font-size: 1rem;
margin: 0 auto;
width: 300px;
}
nav {
padding: 10px 20px;
margin: 0em auto -0.5em;
border-top-right-radius: 8px;
border-top-left-radius: 8px;
}
section p {
text-align: left;
}
footer {
padding: 15px 20px 10px;
margin: -2.8em auto 2.25em;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
}
.link,
footer b {
font-size: 1.5rem;
color: #fc3;
}
nav b {
display: inline-block;
font-size: 1.5rem;
width: 1em;
}
button {
background: #fc3;
color: #000;
border: none;
border-radius: 5px;
padding: 8px 14px;
font: inherit;
font-size: 1.2rem;
cursor: pointer;
width: 150px;
}
/*
The next four rulesets demonstrate how only two
classes can be shared between multiple tags and still
provide different behavior and purpose.
*/
.content.off {
max-height: 0;
font-size: 0;
color: transparent;
opacity: 0;
transition: color 0.65s, max-height 0.95s, font-size 0.95s, opacity 2.5s;
}
.content.on {
height: auto;
max-height: 5000px;
font-size: 1.1rem;
color: #fc3;
opacity: 1;
transition: all 0.75s;
}
.more.off::before {
content: 'More Info';
}
.more.on::before {
content: 'Simplify';
}
<main id='doc'>
<article id='p1' class='p'>
<nav>
<a class="link x off" href="#p2">Next</a>
</nav>
<section>
<button class="more x off"></button>
</section>
<section class="content x off">
<p>A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart.</p>
<p>I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.</p>
<p>I am so happy, my dear friend, so absorbed in the exquisite...</p>
</section>
<footer>
<b>1</b>
</footer>
</article>
<article id='p2' class='p'>
<nav>
<a class="link x off" href="#p1">Prev</a>
<b>|</b>
<a class="link x off" href="#p3">Next</a>
</nav>
<section>
<button class="more x off"></button>
</section>
<section class="content x off">
<p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p>
<p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</p>
<p>The bedding was hardly...</p>
</section>
<footer>
<b>2</b>
</footer>
</article>
<article id='p3' class='p'>
<nav>
<a class="link x off" href="#p2">Prev</a>
</nav>
<section>
<button class="more x off"></button>
</section>
<section class="content x off">
<p>The quick, brown fox jumps over a lazy dog. DJs flock by when MTV ax quiz prog.</p>
<p>Junk MTV quiz graced by fox whelps. Bawds jog, flick quartz, vex nymphs.</p>
<p>Waltz, bad nymph, for quick jigs vex! Fox nymphs grab quick-jived waltz. Brick quiz whangs jumpy veldt fox. Bright vixens jump; dozy fowl quack.</p>
</section>
<footer>
<b>3</b>
</footer>
</article>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Single <a> & <button> Solution
Ternary Conditions
The following demo assigns the click event to both button and link individually. A ternary condition is structured like so:
variable = condition ? TRUE : FALSE;
. Also, .class (.more) is used instead of #id (#more) as a better alternative, but it is not necessary.
Demo 1
$('.content').hide();
$('.more').on('click', function() {
var txt = $(this).text() === 'Simplify' ? 'More Info' : 'Simplify';
$(this).text(txt);
$('.content').toggle();
});
$('.navLink').on('click', function() {
$('.content').show();
$('.more').text('Simplify');
});
<button class="more">More Info</button><br>
<a class="navLink" href="#about">About Us</a>
<p class='content'>
Content.
</p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
✱A fork of Ryan Wheale's nicely styled Fiddle.

You will want to trigger the click event for the #more button. Something like this:
$('a[href="#aboutus-target"]').click((ev) => {
ev.preventDefault();
$('#more').trigger('click');
});
If you only want the nav item to expand the text and never collapse the text, you will need to do something like this:
$('a[href="#aboutus-target"]').click((ev) => {
ev.preventDefault();
const $more = $('#more');
const $targ = $('#expanded' + $more.attr('target'));
// only if the target is not visible
if( !$targ.is(':visible') ) {
$more.trigger('click');
}
});
Here is a fiddle showing it working:
https://jsfiddle.net/tvbhfom8/

I know it's a little late, but I think this may add something here.
The solution without javascript: use <details> tag:
<details>
<summary>Epcot Center</summary>
<p>Epcot is a theme park at Walt Disney World Resort featuring...</p>
</details>

Related

Close all open drop downs and consolidate code if possible

What I need to be able to do is to have the text drop downs close when another is selected so that I do not end up with a bunch of drop downs open on the page at the same time.
I have two text dropdowns that will be used one after the other alternating on a page. In other words accordion1, accordion2, accordion1, accordion2 and so on the reason I have accordion1 and accordion2 is that with my limited experience it is the only way I could figure out change the button color so the list could alternate colors. It would be nice to consolidate the code, but I can live with the extra code if need be.
Here is the code for accordion1
var acc = document.getElementsByClassName("accordion1");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active1");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
var acc = document.getElementsByClassName("accordion2");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active1");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
.accordion1 {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
.accordion2 {
background-color: #8461E8;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
/* Add a background color to the button if it is clicked on (add the
.active class with JS), and when you move the mouse over it (hover) */
.active1,
.accordion1:hover {
background-color: #ccc;
}
/* Style the accordion panel. Note: hidden by default */
.panel1 {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
.accordion1:after {
content: '\02795';
/* Unicode character for "plus" sign (+) */
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.accordion2:after {
content: '\02795';
/* Unicode character for "plus" sign (+) */
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.active1:after {
content: "\2796";
/* Unicode character for "minus" sign (-) */
}
<Section><button class="accordion1"><h3>Alternators and regulators</h3>
</button>
<div id="accordion1-div" class="panel1">
<p>First group of words go here></div>
</Section>
<Section><button class="accordion2"><h3>Batteries and Inverters</h3>
</button>
<div id="accordion-div" class="panel1">
<p>Second set of words go here.</p>
</div>
</Section>
<Section><button class="accordion1"><h3>AC and DC Panels </h3>
</button>
<div id="accordian1-div" class="panel1">
<p>Third set of words reusing "accordion1 go here"</p>
</div>
</Section>
Any help or resources to figure out the needed code would be greatly appreciated.
Question 1 — "How do I not end up with a bunch of drop downs open on the page at the same time":
You close all dropdowns before opening another one. You can also create css rules to display or hide the dropdown. This way, it will be easier to find the currently active dropdown. See code below.
Question 2 — "How can I make the list alternate colors"
You can add more than one class to an element. Simply create color classes and add them to the right elements. See code below.
Notes:
Use the CSS selectors instead of JavaScript to show/hide the panel
Element h3 is not allowed as child of element button. Do it the other way round.
Use the same JavaScript code and CSS for all accordions.
Edit (scrollIntoView)
I added code to automatically scroll the window so that the active tab is visible.
It works only on Chrome, Firefox and Opera. Use this polyfill iamdustan/smoothscroll to use it in other browsers. See compatibility here and all functions here.
// Query all accordions
var accordions = document.querySelectorAll('.accordion');
for (var i = 0; i < accordions.length; i++) {
accordions[i].addEventListener('click', function() {
// Get the currently active accordion
var active = document.querySelector('.accordion.active');
// If there is one, deactivate it
if (active) {
active.classList.remove('active');
}
// Activate the new accordion, if it's not the one you just deactivated
if (active !== this) {
this.classList.add('active');
// Use scrollIntoView to adjust the window scroll position to show the content.
this.scrollIntoView({
behavior: 'smooth'
});
}
});
}
.accordion .header button {
text-align: left;
padding: 18px;
background: transparent;
border: none;
outline: none;
cursor: pointer;
width: 100%;
color: #444;
width: 100%;
transition: 0.4s;
}
/* Set the color according to the modifier class */
.accordion.gray button {
background-color: #eee;
}
.accordion.purple button {
background-color: #8461E8;
}
.accordion.active button,
.accordion button:hover {
background-color: #ccc;
}
.accordion .panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
/* Show the panel if the accordion is active */
.accordion.active .panel {
display: block;
}
.accordion button:after {
content: '\02795';
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.accordion.active button:after {
content: "\2796";
}
<section>
<!-- Each accordion is wrapped by a div with the class 'accordion' -->
<!-- 'accordion' is the component, 'gray' is the color modifier -->
<div class="accordion gray">
<!-- h3 can contain a button -->
<h3 class="header">
<button>Alternators and regulators</button>
</h3>
<div class="panel">
<p>
First group of words go here.<br/> I'm afraid I just blue myself. No… but I'd like to be asked! Michael! It's called 'taking advantage.' It's what gets you ahead in life. Now, when you do this without getting punched in the chest, you'll have
more fun.
</p>
</div>
</div>
</section>
<section>
<!-- Use the 'purple' modifier class here -->
<div class="accordion purple">
<h3 class="header">
<button>Batteries and Inverters</button>
</h3>
<div class="panel">
<p>
Second set of words go here.<br/> Steve Holt! I don't criticize you! And if you're worried about criticism, sometimes a diet is the best defense. That's why you always leave a note! Well, what do you expect, mother? I don't criticize you! And
if you're worried about criticism, sometimes a diet is the best defense.<br/>
<br/> Across from where? As you may or may not know, Lindsay and I have hit a bit of a rough patch. Now, when you do this without getting punched in the chest, you'll have more fun. No… but I'd like to be asked!
</p>
</div>
</div>
</section>
<section>
<div class="accordion gray">
<h3 class="header">
<button>AC and DC Panels
</button>
</h3>
<div class="panel">
<p>
Third set of words go here.<br/> That's why you always leave a note! Not tricks, Michael, illusions. As you may or may not know, Lindsay and I have hit a bit of a rough patch. It's called 'taking advantage.' It's what gets you ahead in life.<br/>
<br/> Say goodbye to these, because it's the last time! First place chick is hot, but has an attitude, doesn't date magicians. I'm afraid I just blue myself. I'm afraid I just blue myself. I'm afraid I just blue myself.
</p>
</div>
</div>
</section>

only change classes inside a hovered element

So I'm creating a page about user-submitted recipes. Some users have submitted a short quote about the recipe, others have not. I wanted to have the quote, if it exists, to display when the user hovers over the image of the recipe.
Right now, I'm using this:
$(".recipe").hover(function(){
$(".slider-submit").hide();
$(".slider-description").show();
},
function(){
$(".slider-submit").show();
$(".slider-description").hide();
});
The first problem is that it changes for all the recipes, not just the one that is hovered on. The second problem is, I'm unsure how to check if the 'slider description' exists for that recipe or not.
Here is a fiddle of what I'm working on. I'm still learning JQuery so give me any tips, please!
Change your JS like this:
$(".recipe").hover(function(){
$(this).find(".slider-submit").hide();
$(this).find(".slider-description").show();
},
function(){
$(this).find(".slider-submit").show();
$(this).find(".slider-description").hide();
});
This way you will only target the sliders that belong to the element that is being hovered over, instead of target them all.
Here's one solution with checking for non existent descriptions as well as using a more efficient hover function:
$(".recipe").hover(function(){
if ($(".slider-description",this)[0]){
$(".slider-submit",this).toggle();
}
$(".slider-description",this).toggle();
});
It uses the lesser known $(selector, context) notation to only select the text elements within the hovered .recipe element.
JS Fiddle
The trick is to use this that gets passed in with the hover event to find the elements inside.
$(".recipe").hover(function() {
$(this).find(".slider-submit").hide();
$(this).find(".slider-description").show();
},
function() {
$(this).find(".slider-submit").show();
$(this).find(".slider-description").hide();
});
.recipe {
position: relative;
display: inline-block;
white-space: nowrap;
overflow-y: hidden;
font-family: 'Nunito', sans-serif;
font-weight: 600;
text-align: center
}
.slider-text {
position: absolute;
bottom: 0;
width: 200px;
padding: 0% 3% 3% 3%;
color: white;
white-space: normal;
background: rgba(0, 0, 0, 0.45);
overflow: hidden;
z-index: 100;
margin-left: 3px;
}
.slider-text:not(.asparagus-slider) {
padding: 6% 3% 3% 3%;
}
.slider-text>h3 {
font-size: 15px;
}
#asparagus {
font-size: 14px;
padding: 0% 3% 3% 3%;
}
.slider-info {
padding-bottom: 30px;
}
.slider-description {
display: none;
}
#chili-img,
#asparagus-img,
#macCheese-img,
#noBakePie-img {
width: 200px;
height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid">
<div class="row">
<div class="col-md-3 recipe">
<div class="slider-text">
<h3>Bear Creek Chili</h3>
<p class="slider-submit">
Submitted by: Dottie User
</p>
</div>
<img id="chili-img" src="http://mystateoffitness.com/wp-content/uploads/2016/07/big-game-chili.jpg">
</div>
<div class="col-md-3 recipe">
<div class="slider-text asparagus-slider">
<h3 id="asparagus">Beer Battered Asparagus with Lemon Herb Dipping Sauce</h3>
<p class="slider-submit">
Submitted by: Chris User
</p>
<p class="slider-description">
<em>"This is the only way that I can enjoy asparagus"</em>
</p>
</div>
<img id="asparagus-img" src="http://food.fnr.sndimg.com/content/dam/images/food/fullset/2007/9/10/0/IP0211_Beer_Battered_Asparagus.jpg.rend.hgtvcom.616.462.jpeg">
</div>
<div class="col-md-3 recipe">
<div class="slider-text">
<h3>Mac n' Cheese</h3>
<p class="slider-submit">
Submitted by: Annette User
</p>
</div>
<img id="macCheese-img" src="https://images-gmi-pmc.edge-generalmills.com/c41ffe09-8520-4d29-9b4d-c1d63da3fae6.jpg">
</div>
<div class="col-md-3 recipe">
<div class="slider-text">
<h3>No Bake Peanut Butter Pie</h3>
<p class="slider-submit">
Submitted by: Shari User
</p>
<p class="slider-description">
<em>"This recipe makes enough for two pies - one for your guests and one just for you!"</em>
</p>
</div>
<img id="noBakePie-img" src="http://cdn2.tmbi.com/TOH/Images/Photos/37/300x300/exps17834_CCT1227369D54B.jpg">
</div>
</div>
</div>
To expound on Lixus, the issue that you're facing is that in jQuery, when you do a selection, you are selecting EVERYTHING in the DOM. What you wanted to do is limit your selection scope.
For example, look at the following JS:
$(".slider-submit").hide(); // Global selection
$(this).find(".slider-submit").hide(); // Limit search to only descendants of "this"
In jQuery, generally when you enter into a function passed into a jQuery object (like the event handler in the "hover" function) the this context will be the DOM element and not the jQuery object, so wrapping this with jQuery will give you the jQuery object like normal.
I updated your JSFiddle with this code. https://jsfiddle.net/bkyn40f8/5/

Using javascript for multiple elements [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I would like to handle several elements that require a specific functionality in our development stage for toggle-like buttons that open and close divs. I say toggle-like because it isn't your standard toggle setup.
The code I have works for a single instance of the buttons and container. Now I need to learn how to apply this to a dozen more which should function independent of each other.
This fiddle shows four examples where the first CSS button is the only one working.
https://jsfiddle.net/e2fexbqp/12/
This is the code that is creating the working example of a single block - two buttons and our div - which should be functional for several other button / div areas.
HTML
<a class="button" id="open">Open</a>
<div id="click-drop" style="display:none">
<h2>Hello World</h2>
<p>You can see me! I'm open! Type your code below.</p>
<textarea></textarea>
<p><a class="button" id="close" style="display:none">Close</a></p>
</div>
Javascript
var open = document.getElementById("open");
var close = document.getElementById("close");
function show(target) {
document.getElementById(target).style.display = 'block';
}
function hide(target) {
document.getElementById(target).style.display = 'none';
}
function hideButton() {
var x = document.getElementById("open");
x.style.display = "none";
var x = document.getElementById("close");
x.style.display = "";
}
function showButton() {
var x = document.getElementById("open");
x.style.display = "";
var x = document.getElementById("close");
x.style.display = "none";
}
open.onclick = function() {show('click-drop');hideButton()}
close.onclick = function() {hide('click-drop');showButton()
I would like something clean and concise as well as unobtrusive.
This demo is pure JavaScript as it is indicated in the tags and implied by the provided code in the question. It has only one eventListener and multiple event.targets BTW, unique ids can only be given to one element. You cannot have multiple ids with the same value. So you'll notice I used only classes no ids.
Advantages
Pure JavaScript and no dependencies on plugins.
Cross-browser with modern browsers.
Having to use only one eventListener is very memory efficient.
It determines exactly which button is clicked without creating an array, or NodeList to iterate through in a loop.
Disadvantages
If you need to be compatible with IE9, then classList has to be replaced with className.
The HTML layout must be in strict pattern. Key elements must be positioned in a predetermined sequence. That's not much of a problem if you have a habit of making organized patterns in markup.
Step by step description is commented in the source.
FIDDLE
SNIPPET
// Reference the parent element
var box = document.querySelector('.box');
// add an eventListener to parent
box.addEventListener('click', toggleBtn, false);
function toggleBtn(event) {
/* This will prevent the <a>nchors from
behaving like normal anchors which
jump from one location to another
*/
event.preventDefault();
// event.target is the element that was clicked (.open/.close .button)
// event.currentTarget is the element that listens for an event (.box)
if (event.target != event.currentTarget) {
var clicked = event.target;
/* If the clicked element has .open class
find the sibling element that was before it and
show it by adding .show class and removing .hide
Then hide clicked element.
*/
if (clicked.classList.contains('open')) {
var drop = clicked.previousElementSibling;
drop.classList.remove('hide');
drop.classList.add('show');
clicked.classList.remove('show');
clicked.classList.add('hide');
} else {
/* Else find clicked parent and hide it
and then show the parent's sibling that is after it.
*/
var drop = clicked.parentElement;
var open = drop.nextElementSibling;
drop.classList.remove('show');
drop.classList.add('hide');
open.classList.remove('hide');
open.classList.add('show');
}
}
/* This prevents the bubbling phase from continuing
up the event chain and triggering any unnecessary
eventListeners
*/
event.stopPropagation();
}
* {
/* Prefix no longer needed */
box-sizing: border-box;
}
.box {
/* Just for demo */
border: 1px dashed red;
}
.button {
text-decoration: none;
font-size: 13px;
line-height: 26px;
height: 28px;
width: 48px;
margin: 0;
padding: 1px;
cursor: pointer;
border-width: 1px;
border-style: solid;
-webkit-appearance: none;
/* Prefix no longer needed for years */
border-radius: 3px;
text-align: center;
}
.click-drop {
border: solid 1px;
border-radius: 3px;
padding: 10px 25px;
}
.hide {
display: none;
}
.show {
display: block;
}
.button.show {
display: inline-block;
}
.close {
display: block;
}
<!--[The order in which elements are positioned is important which will be evident when you review the JavaScript]-->
<!--.box is the 'ancestor/parent' element and event.currentTarget-->
<section class="box">
<h1>Header Content</h1>
<!--Each .click-drop is initially hidden hence it has .hide as a class as well-->
<div class="click-drop hide">
<!--All descendants/children of each .click-drop inherits display:none prop/val from .click-drop.hide-->
<p>Header style</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<!--Each .open.button follows it's corresponding .click-drop-->
<a class="open button show">CSS</a>
<div class="click-drop hide">
<p>Header content</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<a class="open button show">HTML</a>
<h1>Footer Content</h1>
<div class="click-drop hide">
<p>Footer style</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<a class="open button show">CSS</a>
<div class="click-drop hide">
<p>Footer content</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<a class="open button show">HTML</a>
</section>
Use event target to style the individual element that got clicked.
anchors = doc.getElementsByClassName("button");
for (var i = 0; i < anchors.length; i++) {
anchors[i].addEventListener("click", function(e){
e.target.classList.toggle('hide');
});
}
Let's explain some points :
IDs in HTML, in a page, shall be unique.
Using classes and jQuery you can achieve this pretty much easily.
I added a span over all the "open button + its corresponding zone" that I set a "zone" class
I put an "open" class to all open links.
I put a "close" class to all close links.
I registered the click for '.zone .open' elements so they hide themselves and show the contained DIV in their parent.
I registered the click for '.zone .close' elements so they hide the DIV under '.zone' element containing them and show the '.open' link under them.
So here is what I've done :
https://jsfiddle.net/e2fexbqp/13/
$(document).ready(function() {
$('.zone .open').click(function() {
$(this).hide();
$(this).parent().find('div').show();
});
$('.zone .close').click(function() {
var parent = $(this).parents('.zone');
parent.children('div').hide();
parent.children('a.open').show();
});
});
.button {
display: inline-block;
text-decoration: none;
font-size: 13px;
line-height: 26px;
height: 28px;
margin: 0;
padding: 0 10px 1px;
cursor: pointer;
border-width: 1px;
border-style: solid;
-webkit-appearance: none;
-webkit-border-radius: 3px;
border-radius: 3px;
white-space: nowrap;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.zone div {
border: solid 1px;
border-radius: 3px;
padding: 10px 25px;
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1>Header Content</h1>
<span class="zone">
<a class="button open">CSS</a>
<div>
<p>Header style</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span>
<span class="zone">
<a class="button open">HTML</a>
<div>
<p>Header content</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span>
<h1>Footer Content</h1>
<span class="zone">
<a class="button open">CSS</a>
<div>
<p>Footer style</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span><span class="zone">
<a class="button open">HTML</a>
<div>
<p>Footer content</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span>

toggle on hover and click not working properly

I've created this little toggle, since i"m starting with javascript, but it's not working as I would like to. The brown box should appear and disappear both on hover and click (for ipad mostly).
Right now it's fine for hover, but not for clicking on ipad, it just appears once, and thats it.
I think it's also getting confused with my sharing icons.
Any help is appreciated.
jsfiddle
function toggleDisplay (toBlock, toNone) {
document.getElementById(toBlock).style.display = 'block';
document.getElementById(toNone).style.display = 'none';
}
#toggle_hero
{
float:left;
}
.leftHalf
{
display: block;
height: 100%;
width: 50%;
float: left;
position: absolute;
z-index: 2;
}
.leftHalf div
{
display:none;
}
.leftHalf:hover
{
}
.leftHalf:hover div
{
display:block;
width: 100%;
height: 23%;
overflow: auto;
margin: auto;
position: absolute;
left: 0;
bottom: 70px;
right: 0;
background: white;
color: #fff;
background-color:rgba(207,167,80,0.7);
padding:10px;
font-size: 0.8em;
font-weight: 200;
}
.leftHalf:hover div h3
{
font-weight: 500;
float:left;
}
.leftHalf:hover div span{
float:right;
text-align: center;
padding-bottom:5px;
color:black;
}
hover (on a pc) or click me (on ipad)
<div id="toggle_hero" onclick="toggleDisplay('comment', 'toggle_hero')">
<div class="leftHalf clearfix" id="comment">
<div>
<span>
<a target="_blank" class="icon-facebook fa fa-facebook" href="https://www.facebook.com/sharer/sharer.php?u=http://google.com" onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;">facebook </a>
<a target="_blank" href="http://twitter.com/share?url=http://google.com" class="fa fa-twitter"> twitter</a>
</span>
<h3>this text should appear both on hover and click (for ipad)</h3>
</div>
</div>
</div>
You could just create an event listener that captures the current toggled state in a var.
var toggle = false;
var myDiv = document.getElementById('myDiv');
myDiv.addEventListener('click', function() {
if (toggle === false) {
this.getElementsByTagName('p')[0].style.display = 'none';
toggle = true;
} else {
this.getElementsByTagName('p')[0].style.display = 'initial';
toggle = false;
}
});
http://jsfiddle.net/scott88/bLkdt6mc/
You can add another listener for the 'mouseover'.
Your HTML structure is a bit weird. The text that you want to hover/click is actually outside of the target area for your click event. It happens to work for me locally because of the absolute positioning, but I wouldn't be surprised if the iPad browser behaves differently.
I would suggest defining a clear target for what is to be clicked/hovered, apply a class on click/hover, and handle the rest in CSS. I put together a sample of what I envision. You can remove the mouseenter and mouseleave events to simulate on a computer how it works with the touch events. I'm not sure exactly how you want it to behave, but hopefully this is enough to get you started.
function setHover(isHover) {
var element = document.getElementById("toggle_hero");
if (isHover)
element.className = "hovered";
else
element.className = "";
}
function toggleHover() {
var element = document.getElementById("toggle_hero");
setHover(element.className === "");
}
#toggle_hero {
float:left;
}
#comment {
display:none;
width: 100%;
height: 23%;
overflow: auto;
margin: auto;
position: absolute;
left: 0;
right: 0;
background: white;
color: #fff;
background-color:rgba(207,167,80,0.7);
padding:10px;
font-size: 0.8em;
font-weight: 200;
}
.hovered #comment {
display: block;
}
<div id="toggle_hero" onclick="toggleHover()" onmouseenter="setHover(true);" onmouseleave="setHover(false);">
hover (on a pc) or click me (on ipad)
<div id="comment">
<div>
<span>
<a target="_blank" class="icon-facebook fa fa-facebook" href="https://www.facebook.com/sharer/sharer.php?u=http://google.com" onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;">facebook </a>
<a target="_blank" href="http://twitter.com/share?url=http://google.com" class="fa fa-twitter"> twitter</a>
</span>
<h3>this text should appear both on hover and click (for ipad)</h3>
</div>
</div>
</div>

Toggle control - how to create plus minus button?

My toggle control is working, but I would like to add a plus-minus button: when content appears it becomes "-" and when content is hidden it changes to "+". Can you help please?
<div class='toggle'>
<h2>Read More</h2>
<div class="togglebox">
<div class="content">
<h3>
<p>
A new exciting way to broadcast your business to customers
A new exciting way to broadcast your business.Lorem ipsum
</p>
</h3>
<!--Content Here-->
</div>
</div>
</div>
<script>
$(document).ready(function(){
//Hide the tooglebox when page load
$(".togglebox").hide();
//slide up and down when click over heading 2
$("h2").click(function(){
// slide toggle effect set to slow you can set it to fast too.
$(this).next(".togglebox").slideToggle("slow");
return true;
});
});
</script>
I have modified your script. You can try this
<script>
$(document).ready(function(){
//Hide the tooglebox when page load
$(".togglebox").hide();
//slide up and down when click over heading 2
$("h2").click(function(){
// slide toggle effect set to slow you can set it to fast too.
var x = $(this).next(".togglebox").css("display");
if(x=="block")
$(this).text("+ Read More");
else
$(this).text("- Read More");
$(this).next(".togglebox").slideToggle("slow");
return true;
});
});
</script>
Please check out following tutorial easy toggle jquery tutorial
You have to use css to change the header with + or -
HTML
<h2 class="trigger">Toggle Header</h2>
<div class="toggle_container">
<div class="block">
<h3>Content Header</h3>
<!--Content-->
</div>
</div>
css
h2.trigger {
padding: 0 0 0 50px;
margin: 0 0 5px 0;
background: url(h2_trigger_a.gif) no-repeat;
height: 46px;
line-height: 46px;
width: 450px;
font-size: 2em;
font-weight: normal;
float: left;
}
h2.trigger a {
color: #fff;
text-decoration: none;
display: block;
}
h2.trigger a:hover { color: #ccc; }
h2.active {background-position: left bottom;} /*--When toggle is triggered, it will shift the image to the bottom to show its "opened" state--*/
.toggle_container {
margin: 0 0 5px;
padding: 0;
border-top: 1px solid #d6d6d6;
background: #f0f0f0 url(toggle_block_stretch.gif) repeat-y left top;
overflow: hidden;
font-size: 1.2em;
width: 500px;
clear: both;
}
.toggle_container .block {
padding: 20px; /*--Padding of Container--*/
background: url(toggle_block_btm.gif) no-repeat left bottom; /*--Bottom rounded corners--*/
}
jquery
$(document).ready(function(){
//Hide (Collapse) the toggle containers on load
$(".toggle_container").hide();
//Switch the "Open" and "Close" state per click then slide up/down (depending on open/close state)
$("h2.trigger").click(function(){
$(this).toggleClass("active").next().slideToggle("slow");
return false; //Prevent the browser jump to the link anchor
});
});
I made an example of an expandable list that has exactly that, maybe is useful:
http://jasalguero.com/ledld/development/web/expandable-list/
Create a new element and insert it after the "Read More" heading:
var expand_button = document.createElement("A");
expand_button.attr("href", "#");
$(expand_button).text("+");
$(expand_button).click(function(event){
event.preventDefault();
$(".togglebox").slideToggle("slow");
if ($(".togglebox").is(":visible")) {
$(this).text("-");
} else {
$(this).text("+");
}
});
$(expand_button).insertAfter("h2");

Categories

Resources