@squirrel-forge/mediaquery-events

0.8.2 • Public • Published

@squirrel-forge/mediaquery-events

Use css media queries as javascript event names. Simply don't worry about matching css media queries with custom javascript code, just bind a listener with the query as the event name and be done, the actual module, depending on how you use or implement it will be ~5kb in size.

Installation

npm i @squirrel-forge/mediaquery-events

Technical background and compatibility

Under the hood this uses window.matchMedia, MediaQueryListEvent and CustomEvent, it is, therefore only compatible with the more recent browsers, see details on caniuse MediaQueryListEvent if the module would work for you.

There is a ponyFill available for browsers, for example: Safari < 14, that do not allow MediaQueryListEvent objects to be constructed manually, but it must be included explicitly and is not included in the precompiled version.

Polyfilling the missing parts is possible, please feel free to add a polyfill setup to make it compatible with older browsers such as IE11. The big desktop and mobile browsers such as Edge, Chrome, Opera, Firefox all support the required abilities of the api. There are currently no explicit plans to supply any complete polyfill for browsers that do not support all required features beyond the optional ponyFill for the MediaQueryListEvent constructor.


Recommended usage:

Using es10 modules

Import the required class and or ponyFill from the module, you have full control.

import { MediaQueryEvents, MediaQueryListEventPonyFill } from '@squirrel-forge/mediaquery-events';

Create an instance with your preferred options.

const media = new MediaQueryEvents( {
    
    // Default target is the window object
    //  target can be anything that provides the basic event methods:
    //  addEventListener, removeEventListener, dispatchEvent
    target : ( window | document | HTMLElement | Object ),
    
    // By default the ponyfill is null and not available
    //  if set it will be used instead when the MediaQueryListEvent constructor cannot be called natively. 
    ponyfill : ( null | MediaQueryListEventPonyFill ),
    
    // By default debug is null
    //  if set to console, it will supply error and event related information for debugging.
    debug : ( null | console ),
} );

Now you can start binding events.


Legacy usage:

Using the precompiled and minified webpack build

Import or include a precompiled webpack version that attempts to bind to window.media and window.mqe as long as these are previously undefined.

import '@squirrel-forge/mediaquery-events/build/mediaquery-events.min.js';

Or:

<script src=".../@squirrel-forge/mediaquery-events/build/mediaquery-events.min.js"

The media binding can be overridden by setting your own names as following:

window.mqe_OVERRIDE = [ 'reference' ];

The window.mqe binding is always made unless defined and therefore blocked before loading the module. Now you can start binding events.


Binding and using media query events

for es10 and legacy

Define your event handlers.

/**
 * Event handler 
 * @private
 * @param {CustomEvent} event - Mediaquery custom event
 * @return {void}
 */
const _event_handler = ( event ) => {

    // The event name the listener was bound to
    //  if this is equal to event.detail.query this is not a global event
    const listener = event.type;

    // The media query string that is subject to this event
    const query = event.detail.query;

    // The query state
    //  note this can be overridden when manually using MediaQueryEvents.dispatchEvent() to trigger a media query event
    const matches = event.detail.event.matches;
    
    // Do something with this information
    console.log( { listener, query, matches } );
};

For example, bind your handlers to queries that cover mobile, tablet and desktop:

media.addEventListener( '(max-width: 767px)', _event_handler );
media.addEventListener( '(min-width: 768px) and (max-width: 1024px)', _event_handler );
media.addEventListener( '(min-width: 1025px)', _event_handler );

You may also bind global events, these will fire for any query that was previously bound or required and changes it's state.

media.addEventListener( 'media.on', _event_handler );
media.addEventListener( 'media.off', _event_handler );
media.addEventListener( 'media.change', _event_handler );

Note, that these only fire when at least one actual media query was bound or required.

All events can be bound to the given event target even before initializing the MediaQueryEvents Object:

window.addEventListener( 'media.change', _event_handler );
window.addEventListener( '(max-width: 375px)', _event_handler );

but it is important to note that the events will only fire if the query is bound or required explicitly at some point:

media.addEventListener( '(max-width: 375px)', _event_handler );

// OR

media.requireQueries( [ '(max-width: 375px)' ] );

If you do not wish to bind the media queries directly and want to use the global events only, you can initialize multiple required queries easily without binding any handlers.

// Require an Array of queries
media.requireQueries( [
    '(max-width: 767px)',
    '(min-width: 768px) and (max-width: 1024px)',
    '(min-width: 1025px)',
] );

Using the MediaQueryEvents.matches() method returns the queries matching state. It will create the given media query like the requireQueries method if it does not exist.

// Check a queries state manually
if ( media.matches( '(max-width: 767px)' ) ) {
    // Do something
}

Check the example for working code demo.js source file.


Class definitions

MediaQueryEvents

MediaQueryEvents class - Supplies media query event functionality.

Class overview

class MediaQueryEvents {
    constructor( { target = window, ponyfill = null, debug = null } ) {}
    target : window|document|HTMLElement|Object // Read only
    debug : null|console // Settable Object
    matches( query ) {} // Boolean|Null
    requireQueries( queries ) {} // MediaQueryEvents
    dispatchEvent( query, matches = null ) {} // MediaQueryEvents
    addEventListener( query, callback, useCapture = false, dontFire = false ) {} // MediaQueryEvents
    removeEventListener( query, callback, useCapture = false ) {} // MediaQueryEvents
}

For more details check the MediaQueryEvents source file.

Media query events

  • {css media query} - Fired whenever a query changes its state and matches.

Global events

  • media.on - Fired once when a query goes active.
  • media.off - Fired once when a query goes inactive.
  • media.change - Fires in both cases described above.

MediaQueryListEventPonyFill

MediaQueryListEventPonyFill class - PonyFill class that provides a replacement object for when MediaQueryListEvent cannot be constructed.

Class overview

class MediaQueryListEventPonyFill {
    constructor( media, matches ) {}
    media : string // read only
    matches : boolean // ready only
}

For more details check the MediaQueryListEventPonyFill source file.


Issues

If you encounter any issues, please report here.


Check the sourcecode on github for detailed comments.

Package Sidebar

Install

npm i @squirrel-forge/mediaquery-events

Weekly Downloads

1

Version

0.8.2

License

MIT

Unpacked Size

98 kB

Total Files

18

Last publish

Collaborators

  • dasiux