Provides extensive html element toggling support
Update your project's package.json
, this will download the @skrepr/zicht-js.toggle
plugin
to your node_modules
directory.
npm install @skrepr/zicht-js.toggle
Initialize the toggle code by adding the following to your project's main.ts
.
import {ToggleContainer} from '@skrepr/zicht-js.toggle/src/toggle-container';
import {TemplateEventInterface, TemplateEventType, TemplateView} from '@skrepr/zicht-js.util/src/view/template-view';
// Find and load all .js-toggle--container elements in `window.document.body`
ToggleContainer.findAndCreate();
// When a view updates its template, we may find elements in there that require javascript
TemplateView.templateEvent.attach((event:TemplateEventInterface) => {
if (event.type === TemplateEventType.After) {
ToggleContainer.findAndCreate(event.element, {includeContainer: false});
}
});
- Unit test:
npm run test
- Lint test:
npm run tslint
- Publish a release to npmjs.com:
npm publish
new PolyfillInjectorPlugin({
polyfills: [
'Element.prototype.closest',
'Element.prototype.dataset',
'Element.prototype.matches',
'Map'
]
})
//
// Animations
//
@import "../../node_modules/@skrepr/zicht-js.toggle/sass/helpers/mixins";
@import "../../node_modules/@skrepr/zicht-js.toggle/sass/animations/base";
@import "../../node_modules/@skrepr/zicht-js.toggle/sass/animations/slide-enter/slideInDown";
@import "../../node_modules/@skrepr/zicht-js.toggle/sass/animations/slide-enter/slideOutUp";
The case where you want your toggle button to change between the texts "Show" and "Hide", when a content element is visible or hidden:
<div class="js-toggle--container">
<div class="js-toggle--trigger">
<script type="text/template">
<% if (isVisible) { %>
<button>Hide</button> <img src="arrow-down.png">
<% } else { %>
<button>Show</button> <img src="arrow-up.png">
<% } %>
</script>
</div>
<div class="js-toggle--content u-hidden">
This block will be initially hidden, and will toggle between hidden and visible when the trigger is clicked.
<div class="js-toggle--trigger">
<button>Hide</button> <img src="arrow-up.png">
</div>
</div>
</div>
Case: a hidden form
The case where you want to encapsulate a form
element, and automatically make the form visible, and scroll to it,
when it contains an error.
<div class="js-toggle--container">
<div class="js-toggle--trigger">Show and hide</div>
<div class="js-toggle--content u-hidden"
data-toggle-visible-on-match=".has-errors"
data-toggle-scroll='{}'>
This block will be initially hidden, but when toggled open, or when an element with `.has-errors` is found,
the block will be visible and centered on the screen.
<form>
...
</form>
</div>
</div>
The case where the toggled content is opened on initial pageload and uses an animation to slide up (closed) and down (opened) when the user clicks the toggle trigger (.js-toggle--trigger
). See description below which classes need to be added to .js-toggle--content
.
<div class="js-toggle--container">
<div class="js-toggle--trigger">Show and hide</div>
<div class="js-toggle--content" data-toggle-animated="true">
This content will be initially visible (no specific classes need to be specified), when toggled (.js-toggle--trigger), the block will slide up (closed). When toggled again it will slide down (opened).
</div>
</div>
The case where the toggled content is closed on initial pageload and uses an animation to slide down (opened) and up (closed) when the user clicks the toggle trigger (.js-toggle--trigger
). See description below which classes need to be added to js-toggle--content
.
<div class="js-toggle--container">
<div class="js-toggle--trigger">Show and hide</div>
<div class="js-toggle--content u-hidden slideOutUp" data-toggle-animated="true">
This content will be initially hidden (because of `u-hidden slideOutUp`), when toggled (.js-toggle--trigger), the block will slide down (opened). When toggled again it will slide up (closed).
</div>
</div>
The @skrepr/zicht-js.toggle
library provides a simple way to show or hide elements in the browser. It ranges from
very simple, even trivial examples, to more complex nested toggled that automatically determine their state based on
criteria, persisted state, or external queues through Backbone.
The simplest example would be a js-toggle--container
with a js-toggle--trigger
and a js-toggle--content
. When the
trigger element is clicked, the content toggles the u-hidden
class on the content element.
<div class="js-toggle--container">
<div class="js-toggle--trigger">Click HERE to toggle</div>
<div class="js-toggle--content u-hidden">This content is initially hidden and visible when the trigger is clicked</div>
</div>
The following elements are available:
-
js-toggle--container
: the wrapper element, this must encapsulate all other related elements -
js-toggle--info
: a helper element, can be used to show or hide elements -
js-toggle--content
: similar to the info element, except that this element also determines the visibility state -
js-toggle--trigger
: an element that listens to a click event to toggle the visibility state -
js-toggle--radio
: an element that mirrors the visibility state with the selected state of a radio element -
js-toggle--select-option
: an element that mirrors the visibility state with the selected state of a select-option element
Every container maintains its own visibility state, which is a boolean stored in the pageState
Backbone model. All
toggle elements that are encapsulated within the container will follow this visibility state, unless they are explicitly
given a data-toggle-group
attribute.
The following data properties are available:
-
data-toggle-state-name
: Optionally specify state name, defaults to a unique value -
data-toggle-group
: Optionally specify a toggle group name, when specified, only encapsulatedjs-toggle--content
,js-toggle--trigger
, andjs-toggle--info
elements with this group name are used -
data-toggle-only-one
: Optionally specify a current-container state name, when specified, out of all the containers with this name, only one will be visible at a time -
data-toggle-persist
: Optionally specify how the visibility state should be persisted. Values can be either "local-storage" or "session-storage". Once the state is known, it will be persisted, and used on the next page load
For example:
<div class="js-toggle--container"
data-toggle-state-name="navigation-state"
data-toggle-only-one="only-one-navigation-state"
data-toggle-group="navigation"
data-toggle-persist="local-storage">
...
</div>
An info element can be encapsulated within a js-toggle--container
. An info element will toggle the classes
u-visible
and u-hidden
based on the visibility state, but an info element does not influence the visibility state
(for that you will need to use js-toggle--content
).
The following data properties are available:
-
data-toggle-group
: Optionally specify a toggle group name, this should only be used when the parentjs-toggle--container
has a group name specified -
data-toggle-is-inverse
: Optionally specify if this content element must behave as the inverse of the toggle visibility state. Values can be either "true" or "false", and is considered "false" when not specified -
data-toggle-hidden-class
: Optionally specify a different class to toggle on when the visibility state is false. This class also influences the initial visibility state. The class name "u-hidden" is used when left unspecified -
data-toggle-visible-class
: Optionally specify a different class to toggle on when the visibility state is true. This class also influences the initial visibility state The class name "u-visible" is used as default -
data-toggle-animated
: Optionally specify this attribute with value "yes" in order to animate the content. Checkout the quick blueprints when the initial state needs to be closed or opened
The js-toggle--info
element can optionally encapsulate a HTMLScriptElement
. In this case an underscore template will
be created and called whenever the visibility changes. This can be used to, i.e. change a text based on the visibility
state.
<div class="js-toggle--container" data-toggle-group="navigation">
<div class="js-toggle--info"
data-toggle-group="navigation"
data-toggle-is-inverse=""
data-toggle-hidden-class="u-hidden"
data-toggle-visible-class="u-visible">
<script type="text/template">
<% if (isVisible) { %> ... <% } else { %> ... <% } %>
</script>
</div>
</div>
The js-toggle--info
is also possible on the js-toggle--container
div. In this case it behaves exactly the same.
<div class="js-toggle--container js-toggle--info">
...
</div>
One or more content elements are usually encapsulated within a js-toggle--container
. A content element is very
similar to an info element, with the exception that they determine the visibility state (except when a the state is
persisted). This is done by looking at the classes u-visible
and u-hidden
, and whether there are specific matches
on the optional data-toggle-visible-on-match
and data-toggle-hidden-on-match
css selectors.
The following data properties are available:
-
data-toggle-group
: Inherited fromjs-toggle--info
-
data-toggle-is-inverse
: Inherited fromjs-toggle--info
-
data-toggle-hidden-class
: Inherited fromjs-toggle--info
-
data-toggle-visible-class
: Inherited fromjs-toggle--info
-
data-toggle-scroll
: Optionally specify scroll rules. When this content element becomes visible, the scroll rules are automatically applied. Scrolling uses the library smooth-scroll-into-view-if-needed and the json encoded data applied indata-toggle-scroll
is given as options. -
data-toggle-visible-on-match
: Optionally specify a css class selector that will set the initial visibility state to true when it is found within the content element -
data-toggle-hidden-on-match
: Optionally specify a css class selector that will set the initial visibility state to false when it is found within the content element -
data-toggle-animated
: Optionally specify this attribute with value "yes" in order to animate the content. Checkout the quick blueprints when the initial state needs to be closed or opened
The js-toggle--content
element also inherits its ability to optionally encapsulate an HTMLScriptElement
, as is shown
in the example below.
<div class="js-toggle--container" data-toggle-group="navigation">
<div class="js-toggle--content"
data-toggle-group="navigation"
data-toggle-is-inverse=""
data-toggle-hidden-class="u-hidden"
data-toggle-visible-class="u-visible"
data-toggle-scroll='{"behavior": "smooth", "duration": 300, "ease": "easeOutQuint"}'
data-toggle-visible-on-match=".has-errors"
data-toggle-hidden-on-match=".nothing-to-see-here">
<script type="text/template">
<% if (isVisible) { %> ... <% } else { %> ... <% } %>
</script>
</div>
</div>
One or more trigger elements are usually encapsulated within a js-toggle--container
. A trigger element listens to
click events and will toggle the visibility state, resulting in the various info and content elements to apply their
changes.
The following data properties are available:
-
data-toggle-group
: Optionally specify a toggle group name, this should only be used when the parent -
data-toggle-prevent-default
: Optionally specify whetherevent.preventDefault()
should be called when the click event is received. Values can be either "true" or "false", and is considered "true" when not specified
The js-toggle--trigger
element can optionally encapsulate a HTMLScriptElement
. In this case an underscore template
will be created and called whenever the visibility changes. This can be used to, i.e. change a text based on the
visibility state.
<div class="js-toggle--container" data-toggle-group="navigation">
<div class="js-toggle--trigger"
data-toggle-group="navigation"
data-toggle-prevent-default="true"
<script type="text/template">
<% if (isVisible) { %> ... <% } else { %> ... <% } %>
</script>
</div>
</div>
A radio element can be encapsulated within a js-toggle--container
resulting in the visibility state following the
selected state of this radio element.
The following data properties are available:
-
data-toggle-group
: Optionally specify a toggle group name, this should only be used when the parent -
data-toggle-prevent-default
: Optionally specify whetherevent.preventDefault()
should be called when the click event is received. Values can be either "true" or "false", and is considered "true" when not specified
<div class="js-toggle--container" data-toggle-group="navigation">
<input type="radio" class="js-toggle--radio"
data-toggle-group="navigation"
data-toggle-prevent-default="true">
...
</input>
</div>
A checkbox element can be used in the same way as the radio-element.
A select element can be encapsulated with it's option elements within a js-toggle--container
resulting in the visibility state following the
selected state of the option element (state is being detected on an option's parent element which is the select element).
The following data properties are available:
-
data-toggle-group
: Optionally specify a toggle group name, this should only be used when the parent -
data-toggle-prevent-default
: Optionally specify whetherevent.preventDefault()
should be called when the click event is received. Values can be either "true" or "false", and is considered "true" when not specified
<div class="js-toggle--container" data-toggle-group="navigation">
<select>
<option class="js-toggle--select-option"
data-toggle-group="navigation"
data-toggle-prevent-default="true">
...
</option>
</select>
</div>
- Boudewijn Schoon boudewijn@skrepr.zicht-nl