diff --git a/src/js/full-menu.js b/src/js/full-menu.js index 8f0611f..ce69b82 100644 --- a/src/js/full-menu.js +++ b/src/js/full-menu.js @@ -1,4 +1,4 @@ -(function($) { +;(function($) { $(function() { @@ -7,14 +7,24 @@ $burger = $('[data-js-open-menu]'); $burger.click(function() { - var $this = $(this); - isOpen = !isOpen; + toggleMenu(isOpen); + }); - $this.toggleClass('is-active', isOpen); - $overlay.toggleClass('is-open', isOpen); + $(document).bind(window.mq.event, function() { + console.log('resize'); + console.log(isOpen, window.mq.query({ from: 'large' })); + if (isOpen === true && window.mq.query({ from: 'large' })) { + isOpen = false; + toggleMenu(isOpen); + } + }); - if (isOpen) { + function toggleMenu(state) { + $burger.toggleClass('is-active', state); + $overlay.toggleClass('is-open', state); + + if (state) { window.noScroll.on(); $overlay.attr('aria-hidden', 'false'); $burger.attr('aria-expanded', 'true'); @@ -23,7 +33,7 @@ $overlay.attr('aria-hidden', 'true'); $burger.attr('aria-expanded', 'false'); } - }); + } }); diff --git a/src/js/mediaqueries.js b/src/js/mediaqueries.js new file mode 100644 index 0000000..eb4eb37 --- /dev/null +++ b/src/js/mediaqueries.js @@ -0,0 +1,111 @@ +/** + * Trigger custom events when changing breakpoint, get breakpoints from CSS properties + * + * @license APLv2 + * + * @example + * // Listen to custom (debounced) event to react to viewport changes: + * $document.on(window.mq.event, function(event, prevBreakpoint, currentBreakpoint) { + * console.log(prevBreakpoint); // { name: "small", value: "768px" } + * console.log(parseInt(prevBreakpoint.value)); // "768" + * }); + * + * // Check the current breakpoint: + * if (window.mq.currentBreakpoint.name === 'large') { + * this.destroySmall(); + * this.initLarge(); + * } + * + * // Check the current viewport against a specific breakpoint: + * if (window.mq.query({ from: 'small' })) { + * this.destroySmall(); + * this.initLarge(); + * } + * // or + * if (window.mq.query({ from: 'small', to: 'medium' })) { + * this.destroySmall(); + * this.initMedium(); + * } + */ + +;(function($, undefined) { + 'use strict'; + + function parseCssProperty(str) { + return $.parseJSON($.trim(str.replace(/^('|")|(\\)|('|")$/g, ''))); + } + + var $document = $(document), + mqevent = 'mq', + $head = $document.find('head'), + $title = $head.find('title'), + breakpointsString = $head.css('font-family'), + currentBreakpointString = $title.css('font-family'), + breakpoints = parseCssProperty(breakpointsString), + currentBreakpoint = parseCssProperty(currentBreakpointString); + + $(window).bind('resize' + '.mq', function() { + var breakpoint = parseCssProperty($title.css('font-family')), + prevBreakpoint = window.mq.currentBreakpoint; + + if (breakpoint && breakpoint.name !== window.mq.currentBreakpoint.name) { + window.mq.currentBreakpoint = breakpoint; + + $document.triggerHandler(mqevent, [prevBreakpoint, breakpoint]); + } + }); + + function getBreakpointValue(breakpoint) { + var value = 0; + + if (typeof breakpoints[breakpoint] !== 'undefined') { + value = parseInt(breakpoints[breakpoint], 10); + } else { + throw 'Breakpoint not found: "' + breakpoint + '"'; + } + + return value; + } + + function query(options) { + var breakpointFrom, breakpointTo, + breakpointCurrent = parseInt(window.mq.currentBreakpoint.value, 10); + + if (typeof options !== 'object') { + // No or wrong arguments passed + throw 'Illegal argument of type "' + typeof options + '", expected "object"'; + } else if (typeof options.to !== 'undefined' && typeof options.from !== 'undefined') { + breakpointFrom = getBreakpointValue(options.from); + breakpointTo = getBreakpointValue(options.to); + + // "from" cannot be larger than "to" + if (breakpointFrom > breakpointTo) { + throw 'Breakpoint ' + breakpointFrom + ' is larger than ' + breakpointTo + ''; + } + + // The breakpoint needs to smaller than the "to" (exclusive) + // but larger or the same as "from" (inclusive) + return breakpointFrom <= breakpointCurrent && breakpointCurrent < breakpointTo; + } else if (typeof options.to !== 'undefined') { + breakpointTo = getBreakpointValue(options.to); + + // Breakpoint needs to smaller than the "to" (exclusive) + return breakpointCurrent < breakpointTo; + } else if (typeof options.from !== 'undefined') { + breakpointFrom = getBreakpointValue(options.from); + + // Breakpoint needs larger or the same as "from" (inclusive) + return breakpointCurrent >= breakpointFrom; + } else { + throw 'No values for "to" or "from" received'; + } + } + + window.mq = { + event: mqevent, + query: query, + breakpoints: breakpoints, + currentBreakpoint: currentBreakpoint + }; + +})(jQuery); diff --git a/src/scss/global/_mediaqueries_sync.scss b/src/scss/global/_mediaqueries_sync.scss new file mode 100644 index 0000000..8873cc6 --- /dev/null +++ b/src/scss/global/_mediaqueries_sync.scss @@ -0,0 +1,27 @@ +/** + * Sync breakpoints with JavaScript + * + * font-family property of title element contains the current breakpoint + * font-family property of head element contains all breakpoints + */ + +@include mq($from: 0px) { + title { + font-family: mqGetBreakpointJSON("tiny", "0px"); + } +} + +@each $name in map-keys($mqBreakpoints) { + $value: map-get($mqBreakpoints, $name); + + @include mq($from: $name) { + title { + font-family: mqGetBreakpointJSON($name, $value); + } + } +} + +head { + font-family: mqGetBreakpointsJSON($mqBreakpoints); + display: none; +} diff --git a/src/scss/main.scss b/src/scss/main.scss index d87d2d7..6f13b6b 100644 --- a/src/scss/main.scss +++ b/src/scss/main.scss @@ -6,6 +6,7 @@ @import "global/directives"; @import "global/mixins"; @import "global/mediaqueries"; +@import "global/mediaqueries_sync"; @import "global/typography"; @import "layout"; @import "grid";