Last active
November 28, 2024 00:49
-
-
Save rhysburnie/580cadb6a95f40dc0730 to your computer and use it in GitHub Desktop.
Responsive tier change watcher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function($){ | |
| /** | |
| * @author Rhys Burnie | |
| * @license MIT | |
| * | |
| * The MIT License (MIT) | |
| * Copyright (c) 2015 Rhys Burnie | |
| * https://opensource.org/licenses/MIT | |
| * | |
| * Responsive Tier Watcher | |
| * ======================= | |
| * | |
| * Tl;dr | |
| * | |
| * Listen for tier change: | |
| * `$.tierwatcher.on('tierchange', function(e, tier){})` | |
| * | |
| * Start watching or add new tier test classes | |
| * `$.tierwatcher()` | |
| * | |
| * Get current tier key: | |
| * `$.tierwatcher.tier()` | |
| * | |
| * | |
| * Sets up a resize listener that tests which of the supplied test | |
| * classes are currently visible and if the tier has changed | |
| * fires a `tierchange` event. | |
| * | |
| * The visibility of the classes must be defined in css media queries | |
| * by default the script will use the default tiers in bootstrap. | |
| * The default tier names are as per bootstraps short tier names | |
| * ie. `xs`, `sm`, `md` and `lg` | |
| * | |
| * You can add or redefine more test classes as you start the watcher. | |
| * | |
| * NOTE: the assumption is that the bootstrap utility classes for | |
| * visibility exist. If this is not the case they will most | |
| * likely test as visible. | |
| * If you dont want the default tests define them as null in | |
| * the setup ie. `$.tierwatcher({xs:null` etc. | |
| * | |
| * USAGE | |
| * ===== | |
| * | |
| * Start watching: | |
| * | |
| * `$.tierwatcher(); // watch the bootstrap tier defaults` | |
| * | |
| * Listen to tier change: | |
| * The `tierchange` event will only fire as it enters a new tier | |
| * not on every resize event | |
| * | |
| * ``` | |
| * $.tierwatcher.on('tierchange', function(e, tier) { | |
| * console.log('tier is now ', tier); | |
| * }); | |
| * ``` | |
| * | |
| * You can also chain the listener when you start watching: | |
| * | |
| * ``` | |
| * $.tierwatcher().on('tierchange', function(e, tier, previousTier) { | |
| * console.log('tier was ', previousTier, ' is now ', tier); | |
| * }); | |
| * ``` | |
| * | |
| * And add other listeners at other points | |
| * | |
| * `$.tierwatcher.on('tierchange', function(){});` | |
| * | |
| * NOTE: `$.tierwatcher.on` is an alias for `$(document).on('tierchange', function(){});` | |
| * so binding on document instead will also work | |
| * | |
| * Check what the current tier is: | |
| * | |
| * `var currentTier = $.tierwatcher.tier();` | |
| */ | |
| var bootstrapTesters = { | |
| xs: 'visible-xs-block', | |
| sm: 'visible-sm-block', | |
| md: 'visible-md-block', | |
| lg: 'visible-lg-block' | |
| }; | |
| var testers = {}, $testers, timer, lastKnownTier, locked = false; | |
| function checkTiers() | |
| { | |
| var tier, previousTier = lastKnownTier; | |
| for(key in testers) { | |
| if(tier) break; | |
| if(testers.hasOwnProperty(key)) { | |
| if( $testers.find('.'+testers[key]).is(':visible') && lastKnownTier != key) { | |
| tier = lastKnownTier = key; | |
| } | |
| } | |
| } | |
| if(tier) { | |
| $testers.data('tier', tier); | |
| $(document).trigger('tierchange', [tier, previousTier]); | |
| } | |
| locked = false | |
| } | |
| $.tierwatcher = function(tests) | |
| { | |
| testers = $.extend(bootstrapTesters, testers, tests); | |
| if(!$testers) { | |
| $testers = $('<div>').addClass('tierwatcher').css({ | |
| position: 'absolute', | |
| overflow: 'hidden', | |
| left: -9999, | |
| width: 1, | |
| height: 1 | |
| }).appendTo('body'); | |
| var resizeTimeoutMS = 50; | |
| if(testers.hasOwnProperty('resizeTimeoutMS')) { | |
| resizeTimeoutMS = testers.resizeTimeoutMS; | |
| delete testers.resizeTimeoutMS; | |
| } | |
| $(window).on('resize', function(){ | |
| if(locked) return; | |
| locked = true; | |
| timer = setTimeout(checkTiers, resizeTimeoutMS); | |
| }); | |
| } | |
| for(key in testers) { | |
| if(testers.hasOwnProperty(key) && typeof(testers[key]) == 'string') { | |
| if(!$testers.find('.'+testers[key]).length) { | |
| $testers.append('<div class="'+testers[key]+'">'); | |
| } | |
| } | |
| } | |
| checkTiers(); | |
| return $.tierwatcher; | |
| }; | |
| $.tierwatcher.tier = function() | |
| { | |
| return lastKnownTier; | |
| } | |
| // basicly an alias for `$(document).on('tierchange', fn)` | |
| // you MUST specify the event `'tierchange'` | |
| $.tierwatcher.on = function(evn,fn) | |
| { | |
| // only accepts this event | |
| // but want user to specify for clarity | |
| if(evn == 'tierchange') { | |
| $(document).on(evn, fn); | |
| } | |
| }; | |
| }(jQuery)); |
Author
Author
$.teirwatcher().on('tierchange', function(e, tier, previousTier) {
if(tier !== 'xs') {
// do something every time it enters a tier that isn't 'xs'
}
if(tier === 'xs') {
// do something when it enters 'xs'
}
if(tier === 'sm' && previousTier === 'xs') {
// do something when tier has changed and it was 'xs'
// (generally this would be 'sm') but usefull for 'sm' things only
// when entering from that previous breakpoint
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Emit a
'tierchange'event (on thedocument) when browser width enters a new defined (mobile first) tier -argument[0]is the tier name.Tier change is detected by checking the display of test elements off screen at
left:-9999px;width:1px;height:1px;ie. uses css result as authority on what is accurate.As long as the test tier element
.is(':visible')it will test true.The default test elements classes are bootstrap visibility classes
'visible-xs-block'to'visible-lg-block'.NB: obviously multiple test elements that are visible at the same time will skew results, only the first found will be the result - so be aware (there is no issue with the defaults
'xs','sm','md'and'lg'as on they don't overlap).