Skip to content

Commit

Permalink
v2.0.0: move element from function param to object, to better mirror …
Browse files Browse the repository at this point in the history
…jquery
  • Loading branch information
ericbutler555 committed Feb 14, 2022
1 parent 44ede23 commit 11f01c5
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 136 deletions.
23 changes: 9 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,27 @@ Check out [the demo page](https://ericbutler555.github.io/plain-js-slidetoggle/d

## How To Use

slideToggle(element, duration, callback);
element.slideToggle(duration, callback); // opens and closes an element

slideUp(element, duration, callback);
element.slideUp(duration, callback); // closes/collapses an element

slideDown(element, duration, callback);
element.slideDown(duration, callback); // opens/expands an element

- element: *HTMLElement*. Required.
- duration: *Number*. Optional. In milliseconds. Default 400.
- callback: *Function*. Optional. Called once animation completes.
- callback: *Function*. Optional. Called once slide animation completes.

That's it.

## Example Usage

<button class="btn">Click me</button>
<div class="div-to-toggle">
...content...
</div>
<button class="myBtn">Click me</button>
<div class="myDiv">blah blah blah</div>

<script src="slideToggle.min.js"></script>
<script>
// when you click the button, slide the div up and down:
const divToToggle = document.querySelector('.div-to-toggle');
document.querySelector('.btn').addEventListener('click', () => {
slideToggle(divToToggle, 500, () => {
console.log('This is the callback, the slide has finished!');
});
// when you click the button, open and close the div:
document.querySelector('.myBtn').addEventListener('click', () => {
document.querySelector('.myDiv').slideToggle();
});
</script>
157 changes: 64 additions & 93 deletions demo-styles.css
Original file line number Diff line number Diff line change
@@ -1,56 +1,91 @@
/* TL;DR: here are the styles relevant to the sliding nav menu */
@media (max-width: 899px) {
.site-navigation {
display: none; /* hides navigation by default until it's toggled open */
}
}
@media (min-width: 900px) {
.site-navigation {
display: block !important; /* overrides any inline styles to ensure the nav always displays on wider screens */
}
}
/* end TL;DR */


/* Header */
header {
position: relative; /* for anchoring .site-navigation */
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 20px;
padding: 0 0 0 10px;
background: white;
border-bottom: 1px solid #ddd;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

/* Hamburger icon */
.hamburger {
display: none; /* don't show the hamburger icon on wider screens */
display: block;
flex: 0 0 64px; /* keep this exactly 64px wide */
margin-left: auto; /* keep it flush right */
width: 64px;
height: 64px;
border-radius: 0;
border: 0;
padding: 0;
background: black;
cursor: pointer;
transition: all 0.2s;
}
.hamburger rect {
fill: white; /* SVGs use "fill", not "background-color" */
transform-origin: center center; /* for line transforms later */
transition: all 0.2s;
}

/* Fancy icon toggle styling */
.hamburger:hover,
.hamburger.is-active {
background: #eb4;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
}
.is-active #line1 {
transform: rotate(-135deg) translate(-1px, 5px);
fill: black;
}
.is-active #line2 {
transform: rotate(-135deg) translate(-1px, -3px);
fill: black;
}
.is-active #line3 {
transform: rotate(135deg) translate(1px, -11px);
fill: black;
}

/* Navigation menu for wider screens */
/* Navigation menu */
.site-navigation {
margin-left: auto; /* keep it flush right */
display: none; /* hides navigation by default until it's toggled open */
position: absolute;
top: 100%; /* with absolute position, anchor to bottom of header */
left: 0;
right: 0;
background-color: white;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.site-navigation ul {
display: flex;
display: block;
list-style: none;
margin: 0;
padding: 0;
}
.site-navigation a {
display: block;
padding: 30px 20px;
padding: 20px;
border-bottom: 1px solid #ddd;
color: inherit;
font-size: 24px;
font-weight: bold;
text-decoration: none;
transition: background-color 0.2s;
}
.site-navigation a:hover,
.site-navigation a:focus {
background-color: #eb4;
border-bottom-color: black;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.2);
text-shadow: 0px 1px 1px white;
}

/* Accordion */
.accordion {
list-style: none;
margin: 0 auto 2em;
Expand All @@ -77,79 +112,6 @@ header {
display: block;
}

/* Media query adjustments for narrower screens -
I made the breakpoint wider than usual for demo purposes */
@media (max-width: 899px) {

header {
position: relative; /* for anchoring .site-navigation */
padding: 0 0 0 10px;
}

/* Hamburger icon */
.hamburger {
display: block; /* show the icon on narrower screens */
flex: 0 0 64px; /* keep this exactly 64px wide */
margin-left: auto; /* keep it flush right */
width: 64px;
height: 64px;
border-radius: 0;
border: 0;
padding: 0;
background: black;
cursor: pointer;
transition: all 0.2s;
}
.hamburger rect {
fill: white; /* SVGs use "fill", not "background-color" */
transform-origin: center center; /* for line transforms later */
transition: all 0.2s;
}

/* Fancy icon toggle styling */
.hamburger:hover,
.hamburger.is-active {
background: #eb4;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
}
.is-active #line1 {
transform: rotate(-135deg) translate(-1px, 5px);
fill: black;
}
.is-active #line2 {
transform: rotate(-135deg) translate(-1px, -3px);
fill: black;
}
.is-active #line3 {
transform: rotate(135deg) translate(1px, -11px);
fill: black;
}

/* Navigation menu */
.site-navigation {
position: absolute;
top: 100%; /* with absolute position, anchor to bottom of header */
left: 0;
right: 0;
background-color: white;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.site-navigation ul {
display: block; /* undo flexbox */
}
.site-navigation a {
padding: 20px;
border-bottom: 1px solid #ddd;
font-size: 24px;
}
.site-navigation a:hover,
.site-navigation a:focus {
border-bottom: 1px solid black;
}
}

/* Other unrelated stuff */
* {
box-sizing: border-box;
Expand All @@ -166,13 +128,22 @@ h1 {
line-height: 1.2;
}
h2 {
display: inline-block;
margin: 1.5em 0 0;
padding: 0.5em 0.75em;
font-size: 1.1em;
background: black;
color: #eb4;
}
p {
padding-left: 1em;
}
code {
padding: 5px;
background: #ddd;
border-radius: 3px;
font-size: 0.875em;
}
main {
max-width: 1000px;
margin: 0 auto;
Expand Down
38 changes: 21 additions & 17 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@
</div>
</header>
<main>

<h1>slideToggle Demo - no jQuery necessary!</h1>
<p>Plain JavaScript version of the great slideToggle() function in jQuery. Slightly simplified.</p>
<p>Also includes slideUp() and slideDown().</p>
<p>Plain JavaScript version of the great <code>slideToggle()</code> function in jQuery. Slightly simplified.</p>
<p>Also includes <code>slideUp()</code> and <code>slideDown()</code>.</p>

<h2>Navigation Menu Demo</h2>
<p><strong>On narrow screens,</strong> click/tap the icon in the upper-right to open and close the navigation menu.</p>
<p><strong>On wider screens,</strong> the navigation menu displays in a static horizontal row so you won't see anything to toggle.</p>
<p><strong>Click/tap the hamburger icon</strong> in the upper-right to open and close the navigation menu.</p>

<h2>Accordion Demo</h2>
<p><strong>Click the different tabs</strong> to open a panel with more information. The other tabs will close as you open new ones, but you can adjust your own code if you want them to stay open.</p>

<ul class="accordion">
<li>
<div class="tab">Accordion Tab One</div>
Expand All @@ -51,45 +54,46 @@ <h2>Accordion Demo</h2>
<li>
<div class="tab">Accordion Tab Three</div>
<div class="panel">
<img src="https://www.placecage.com/c/200/150" alt="Sample image"><br>
All about accordion tab number three!
<img src="https://www.placecage.com/c/200/250" alt="Sample image"><br>
Content for accordion tab number three
</div>
</li>
</ul>

<h2>Like It?</h2>
<p>Head over to <a href="https://github.com/ericbutler555/plain-js-slidetoggle">the GitHub repo</a>, click the star button and download for your own personal and commercial use.</p>

</main>
<footer>
Created by Eric Butler in 2020
</footer>

<!-- Include slideToggle.min.js in your project -->
<script src="slideToggle.min.js"></script>

<!-- Then you can call .slideToggle(), .slideUp() and .slideDown() on elements just like in jQuery -->
<script>
// MENU FUNCTIONALITY:
var hamburger = document.querySelector('.hamburger');
var siteNav = document.querySelector('.site-navigation');
var confirmation = () => console.info('slideToggle animation complete!');

// HEADER MENU FUNCTIONALITY:
var hamburger = document.querySelector('.hamburger');
hamburger.addEventListener('click', function(e) {
e.preventDefault();
hamburger.classList.toggle('is-active');
slideToggle(siteNav, 400, confirmation);
document.querySelector('.site-navigation').slideToggle(300);
});

// ACCORDION FUNCTIONALITY:
var allPanels = document.querySelectorAll('.accordion .panel'); // only needed if collapsing other panels when opening

document.querySelector('.accordion').addEventListener('click', function(e) {
if (e.target.classList.contains('tab')) {
var nextPanel = e.target.nextElementSibling;
slideToggle(nextPanel, 200);

nextPanel.slideToggle(200);
// to make other panels collapse when you open one:
allPanels.forEach(function(el) {
if (el.style.display !== "none" && el !== nextPanel) slideUp(el, 200);
document.querySelectorAll('.accordion .panel').forEach(function(el) {
if (el.style.display !== "none" && el !== nextPanel) { el.slideUp(200); }
});
}
});

</script>
</body>
</html>
22 changes: 11 additions & 11 deletions slideToggle.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/* plain JS slideToggle https://github.com/ericbutler555/plain-js-slidetoggle */

function slideToggle(el, duration, callback) {
if (el.clientHeight === 0) {
_s(el, duration, callback, true);
HTMLElement.prototype.slideToggle = function(duration, callback) {
if (this.clientHeight === 0) {
_s(this, duration, callback, true);
} else {
_s(el, duration, callback);
_s(this, duration, callback);
}
}
};

function slideUp(el, duration, callback) {
_s(el, duration, callback);
}
HTMLElement.prototype.slideUp = function(duration, callback) {
_s(this, duration, callback);
};

function slideDown(el, duration, callback) {
_s(el, duration, callback, true);
}
HTMLElement.prototype.slideDown = function (duration, callback) {
_s(this, duration, callback, true);
};

function _s(el, duration, callback, isDown) {

Expand Down
2 changes: 1 addition & 1 deletion slideToggle.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 11f01c5

Please sign in to comment.