|
| 1 | +/*! |
| 2 | + * Responsive Bootstrap Toolkit |
| 3 | + * Author: Maciej Gurban |
| 4 | + * License: MIT |
| 5 | + * Version: 2.5.1 (2015-11-02) |
| 6 | + * Origin: https://github.com/maciej-gurban/responsive-bootstrap-toolkit |
| 7 | + */ |
| 8 | +var ResponsiveBootstrapToolkit = (function($){ |
| 9 | + |
| 10 | + // Internal methods |
| 11 | + var internal = { |
| 12 | + |
| 13 | + /** |
| 14 | + * Breakpoint detection divs for each framework version |
| 15 | + */ |
| 16 | + detectionDivs: { |
| 17 | + // Bootstrap 3 |
| 18 | + bootstrap: { |
| 19 | + 'xs': $('<div class="device-xs visible-xs visible-xs-block"></div>'), |
| 20 | + 'sm': $('<div class="device-sm visible-sm visible-sm-block"></div>'), |
| 21 | + 'md': $('<div class="device-md visible-md visible-md-block"></div>'), |
| 22 | + 'lg': $('<div class="device-lg visible-lg visible-lg-block"></div>') |
| 23 | + }, |
| 24 | + // Foundation 5 |
| 25 | + foundation: { |
| 26 | + 'small': $('<div class="device-xs show-for-small-only"></div>'), |
| 27 | + 'medium': $('<div class="device-sm show-for-medium-only"></div>'), |
| 28 | + 'large': $('<div class="device-md show-for-large-only"></div>'), |
| 29 | + 'xlarge': $('<div class="device-lg show-for-xlarge-only"></div>') |
| 30 | + } |
| 31 | + }, |
| 32 | + |
| 33 | + /** |
| 34 | + * Append visibility divs after DOM laoded |
| 35 | + */ |
| 36 | + applyDetectionDivs: function() { |
| 37 | + $(document).ready(function(){ |
| 38 | + $.each(self.breakpoints, function(alias){ |
| 39 | + self.breakpoints[alias].appendTo('.responsive-bootstrap-toolkit'); |
| 40 | + }); |
| 41 | + }); |
| 42 | + }, |
| 43 | + |
| 44 | + /** |
| 45 | + * Determines whether passed string is a parsable expression |
| 46 | + */ |
| 47 | + isAnExpression: function( str ) { |
| 48 | + return (str.charAt(0) == '<' || str.charAt(0) == '>'); |
| 49 | + }, |
| 50 | + |
| 51 | + /** |
| 52 | + * Splits the expression in into <|> [=] alias |
| 53 | + */ |
| 54 | + splitExpression: function( str ) { |
| 55 | + |
| 56 | + // Used operator |
| 57 | + var operator = str.charAt(0); |
| 58 | + // Include breakpoint equal to alias? |
| 59 | + var orEqual = (str.charAt(1) == '=') ? true : false; |
| 60 | + |
| 61 | + /** |
| 62 | + * Index at which breakpoint name starts. |
| 63 | + * |
| 64 | + * For: >sm, index = 1 |
| 65 | + * For: >=sm, index = 2 |
| 66 | + */ |
| 67 | + var index = 1 + (orEqual ? 1 : 0); |
| 68 | + |
| 69 | + /** |
| 70 | + * The remaining part of the expression, after the operator, will be treated as the |
| 71 | + * breakpoint name to compare with |
| 72 | + */ |
| 73 | + var breakpointName = str.slice(index); |
| 74 | + |
| 75 | + return { |
| 76 | + operator: operator, |
| 77 | + orEqual: orEqual, |
| 78 | + breakpointName: breakpointName |
| 79 | + }; |
| 80 | + }, |
| 81 | + |
| 82 | + /** |
| 83 | + * Returns true if currently active breakpoint matches the expression |
| 84 | + */ |
| 85 | + isAnyActive: function( breakpoints ) { |
| 86 | + var found = false; |
| 87 | + $.each(breakpoints, function( index, alias ) { |
| 88 | + // Once first breakpoint matches, return true and break out of the loop |
| 89 | + if( self.breakpoints[ alias ].is(':visible') ) { |
| 90 | + found = true; |
| 91 | + return false; |
| 92 | + } |
| 93 | + }); |
| 94 | + return found; |
| 95 | + }, |
| 96 | + |
| 97 | + /** |
| 98 | + * Determines whether current breakpoint matches the expression given |
| 99 | + */ |
| 100 | + isMatchingExpression: function( str ) { |
| 101 | + |
| 102 | + var expression = internal.splitExpression( str ); |
| 103 | + |
| 104 | + // Get names of all breakpoints |
| 105 | + var breakpointList = Object.keys(self.breakpoints); |
| 106 | + |
| 107 | + // Get index of sought breakpoint in the list |
| 108 | + var pos = breakpointList.indexOf( expression.breakpointName ); |
| 109 | + |
| 110 | + // Breakpoint found |
| 111 | + if( pos !== -1 ) { |
| 112 | + |
| 113 | + var start = 0; |
| 114 | + var end = 0; |
| 115 | + |
| 116 | + /** |
| 117 | + * Parsing viewport.is('<=md') we interate from smallest breakpoint ('xs') and end |
| 118 | + * at 'md' breakpoint, indicated in the expression, |
| 119 | + * That makes: start = 0, end = 2 (index of 'md' breakpoint) |
| 120 | + * |
| 121 | + * Parsing viewport.is('<md') we start at index 'xs' breakpoint, and end at |
| 122 | + * 'sm' breakpoint, one before 'md'. |
| 123 | + * Which makes: start = 0, end = 1 |
| 124 | + */ |
| 125 | + if( expression.operator == '<' ) { |
| 126 | + start = 0; |
| 127 | + end = expression.orEqual ? ++pos : pos; |
| 128 | + } |
| 129 | + /** |
| 130 | + * Parsing viewport.is('>=sm') we interate from breakpoint 'sm' and end at the end |
| 131 | + * of breakpoint list. |
| 132 | + * That makes: start = 1, end = undefined |
| 133 | + * |
| 134 | + * Parsing viewport.is('>sm') we start at breakpoint 'md' and end at the end of |
| 135 | + * breakpoint list. |
| 136 | + * Which makes: start = 2, end = undefined |
| 137 | + */ |
| 138 | + if( expression.operator == '>' ) { |
| 139 | + start = expression.orEqual ? pos : ++pos; |
| 140 | + end = undefined; |
| 141 | + } |
| 142 | + |
| 143 | + var acceptedBreakpoints = breakpointList.slice(start, end); |
| 144 | + |
| 145 | + return internal.isAnyActive( acceptedBreakpoints ); |
| 146 | + |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | + }; |
| 151 | + |
| 152 | + // Public methods and properties |
| 153 | + var self = { |
| 154 | + |
| 155 | + /** |
| 156 | + * Determines default debouncing interval of 'changed' method |
| 157 | + */ |
| 158 | + interval: 300, |
| 159 | + |
| 160 | + /** |
| 161 | + * |
| 162 | + */ |
| 163 | + framework: null, |
| 164 | + |
| 165 | + /** |
| 166 | + * Breakpoint aliases, listed from smallest to biggest |
| 167 | + */ |
| 168 | + breakpoints: null, |
| 169 | + |
| 170 | + /** |
| 171 | + * Returns true if current breakpoint matches passed alias |
| 172 | + */ |
| 173 | + is: function( str ) { |
| 174 | + if( internal.isAnExpression( str ) ) { |
| 175 | + return internal.isMatchingExpression( str ); |
| 176 | + } |
| 177 | + return self.breakpoints[ str ] && self.breakpoints[ str ].is(':visible'); |
| 178 | + }, |
| 179 | + |
| 180 | + /** |
| 181 | + * Determines which framework-specific breakpoint detection divs to use |
| 182 | + */ |
| 183 | + use: function( frameworkName, breakpoints ) { |
| 184 | + self.framework = frameworkName.toLowerCase(); |
| 185 | + |
| 186 | + if( self.framework === 'bootstrap' || self.framework === 'foundation') { |
| 187 | + self.breakpoints = internal.detectionDivs[ self.framework ]; |
| 188 | + } else { |
| 189 | + self.breakpoints = breakpoints; |
| 190 | + } |
| 191 | + |
| 192 | + internal.applyDetectionDivs(); |
| 193 | + }, |
| 194 | + |
| 195 | + /** |
| 196 | + * Returns current breakpoint alias |
| 197 | + */ |
| 198 | + current: function(){ |
| 199 | + var name = 'unrecognized'; |
| 200 | + $.each(self.breakpoints, function(alias){ |
| 201 | + if (self.is(alias)) { |
| 202 | + name = alias; |
| 203 | + } |
| 204 | + }); |
| 205 | + return name; |
| 206 | + }, |
| 207 | + |
| 208 | + /* |
| 209 | + * Waits specified number of miliseconds before executing a callback |
| 210 | + */ |
| 211 | + changed: function(fn, ms) { |
| 212 | + var timer; |
| 213 | + return function(){ |
| 214 | + clearTimeout(timer); |
| 215 | + timer = setTimeout(function(){ |
| 216 | + fn(); |
| 217 | + }, ms || self.interval); |
| 218 | + }; |
| 219 | + } |
| 220 | + |
| 221 | + }; |
| 222 | + |
| 223 | + // Create a placeholder |
| 224 | + $(document).ready(function(){ |
| 225 | + $('<div class="responsive-bootstrap-toolkit"></div>').appendTo('body'); |
| 226 | + }); |
| 227 | + |
| 228 | + if( self.framework === null ) { |
| 229 | + self.use('bootstrap'); |
| 230 | + } |
| 231 | + |
| 232 | + return self; |
| 233 | + |
| 234 | +})(jQuery); |
0 commit comments