[Feature] Mediaqueries Sync: add sync between css and js so the breakpoints can be queried from the js

This commit is contained in:
0xfff 2016-11-01 02:37:19 +01:00
parent 774970b974
commit 373cc64526
4 changed files with 156 additions and 7 deletions

View file

@ -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');
}
});
}
});

111
src/js/mediaqueries.js Normal file
View file

@ -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);

View file

@ -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;
}

View file

@ -6,6 +6,7 @@
@import "global/directives";
@import "global/mixins";
@import "global/mediaqueries";
@import "global/mediaqueries_sync";
@import "global/typography";
@import "layout";
@import "grid";