Skip to content

Commit

Permalink
Merge pull request #10969 from SassNinja/fix/10585_offcanvas_incanvas…
Browse files Browse the repository at this point in the history
…_option

Fix Off-canvas In-canvas feature
  • Loading branch information
ncoden authored Apr 9, 2018
2 parents 1db078c + 4858ec5 commit 98591d9
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
8 changes: 6 additions & 2 deletions docs/pages/off-canvas.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,17 @@ For an example of off-canvas, checkout this top bar with off-canvas navigation a

## In-Canvas to Off-Canvas

With this feature you can have a standard page element move off-canvas at a particular breakpoint. Use the new class <code>.in-canvas-for-[BREAKPOINT]</code> for this. This differs from the <a href="#reveal-on-larger-screens">Reveal on Larger Screens</a> feature it doesn't actually open the off-canvas for specific screen sizes but overrides the off-canvas styles so it behaves as a regular page element. This way you can place an element anywhere on the page and move it into off-canvas for e.g. small screens.
With this feature you can have a standard page element move off-canvas at a particular breakpoint. Use the <code>inCanvasOn</code> option for this. In-Canvas differs from the <a href="#reveal-on-larger-screens">Reveal on Larger Screens</a> feature as it doesn't actually open the off-canvas for specific screen sizes but overrides the off-canvas styles so it behaves as a regular page element. This way you can place an element anywhere on the page and move it into off-canvas for e.g. small screens only.

<div class="primary callout">
<p>The <code>inCanvasOn</code> option will automatically add the <code>.in-canvas-for-[BREAKPOINT]</code> class since most of the work is done via CSS only. However you may also add this class yourself which will override the option.</p>
</div>

```html_example
<button type="button" class="button hide-for-large" data-toggle="inCanvasExample">
Open in-canvas that is off-canvas now
</button>
<div class="off-canvas in-canvas-for-large position-right" id="inCanvasExample" data-off-canvas>
<div class="off-canvas position-right" id="inCanvasExample" data-off-canvas data-options="inCanvasFor:large;">
<div class="callout">I'm in-canvas for medium screen size and move off-canvas for medium down.</div>
</div>
```
Expand Down
45 changes: 43 additions & 2 deletions js/foundation.offcanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class OffCanvas extends Plugin {
this.position = 'left';
this.$content = $();
this.nested = !!(this.options.nested);
this.isInCanvas = false;

// Defines the CSS transition/position classes of the off-canvas content container.
$(['push', 'overlap']).each((index, val) => {
Expand Down Expand Up @@ -136,6 +137,20 @@ class OffCanvas extends Plugin {
this.$element.css('transition-duration', this.options.transitionTime);
}

let inCanvasFor = this.$element.attr('class').match(/\bin-canvas-for-(\w+)/);

if (inCanvasFor && inCanvasFor.length === 2) {
// Set `inCanvasOn` option if found in-canvas-for-[BREAKPONT] CSS class
this.options.inCanvasOn = inCanvasFor[1];
} else if (this.options.inCanvasOn) {
// Ensure the CSS class is set
this.$element.addClass(`in-canvas-for-${this.options.inCanvasOn}`);
}

if (this.options.inCanvasOn) {
this._checkInCanvas();
}

// Initally remove all transition/position CSS classes from off-canvas content container.
this._removeContentClasses();
}
Expand All @@ -157,6 +172,13 @@ class OffCanvas extends Plugin {
var $target = this.options.contentOverlay ? this.$overlay : this.$content;
$target.on({'click.zf.offCanvas': this.close.bind(this)});
}

if (this.options.inCanvasOn) {
$(window).on('changed.zf.mediaquery', () => {
this._checkInCanvas();
});
}

}

/**
Expand All @@ -181,6 +203,17 @@ class OffCanvas extends Plugin {
});
}

/**
* Checks if InCanvas on current breakpoint and adjust off-canvas accordingly
* @private
*/
_checkInCanvas() {
this.isInCanvas = MediaQuery.atLeast(this.options.inCanvasOn);
if (this.isInCanvas === true) {
this.close();
}
}

/**
* Removes the CSS transition/position classes of the off-canvas content container.
* Removing the classes is important when another off-canvas gets opened that uses the same content container.
Expand Down Expand Up @@ -285,7 +318,7 @@ class OffCanvas extends Plugin {
* @todo also trigger 'open' event?
*/
open(event, trigger) {
if (this.$element.hasClass('is-open') || this.isRevealed) { return; }
if (this.$element.hasClass('is-open') || this.isRevealed || this.isInCanvas) { return; }
var _this = this;

if (trigger) {
Expand Down Expand Up @@ -533,7 +566,15 @@ OffCanvas.defaults = {
revealOn: null,

/**
* Force focus to the OffCanvas on open. If true, will focus the opening trigger on close.
* Breakpoint at which the off-canvas gets moved into canvas content and acts as regular page element.
* @option
* @type {?string}
* @default null
*/
inCanvasOn: null,

/**
* Force focus to the offcanvas on open. If true, will focus the opening trigger on close.
* @option
* @type {boolean}
* @default true
Expand Down

0 comments on commit 98591d9

Please sign in to comment.