1/** 2 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level 3 * directory of this distribution and at 4 * https://github.com/marcj/css-element-queries/blob/master/LICENSE. 5 */ 6; 7(function() { 8 9 /** 10 * Class for dimension change detection. 11 * 12 * @param {Element|Element[]|Elements|jQuery} element 13 * @param {Function} callback 14 * 15 * @constructor 16 */ 17 var ResizeSensor = function(element, callback) { 18 /** 19 * 20 * @constructor 21 */ 22 function EventQueue() { 23 this.q = []; 24 this.add = function(ev) { 25 this.q.push(ev); 26 }; 27 28 var i, j; 29 this.call = function() { 30 for (i = 0, j = this.q.length; i < j; i++) { 31 this.q[i].call(); 32 } 33 }; 34 } 35 36 /** 37 * @param {HTMLElement} element 38 * @param {String} prop 39 * @returns {String|Number} 40 */ 41 function getComputedStyle(element, prop) { 42 if (element.currentStyle) { 43 return element.currentStyle[prop]; 44 } else if (window.getComputedStyle) { 45 return window.getComputedStyle(element, null).getPropertyValue(prop); 46 } else { 47 return element.style[prop]; 48 } 49 } 50 51 /** 52 * 53 * @param {HTMLElement} element 54 * @param {Function} resized 55 */ 56 function attachResizeEvent(element, resized) { 57 if (!element.resizedAttached) { 58 element.resizedAttached = new EventQueue(); 59 element.resizedAttached.add(resized); 60 } else if (element.resizedAttached) { 61 element.resizedAttached.add(resized); 62 return; 63 } 64 65 element.resizeSensor = document.createElement('div'); 66 element.resizeSensor.className = 'resize-sensor'; 67 var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;'; 68 var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;'; 69 70 element.resizeSensor.style.cssText = style; 71 element.resizeSensor.innerHTML = 72 '<div class="resize-sensor-expand" style="' + style + '">' + 73 '<div style="' + styleChild + '"></div>' + 74 '</div>' + 75 '<div class="resize-sensor-shrink" style="' + style + '">' + 76 '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' + 77 '</div>'; 78 element.appendChild(element.resizeSensor); 79 80 if (!{fixed: 1, absolute: 1}[getComputedStyle(element, 'position')]) { 81 element.style.position = 'relative'; 82 } 83 84 var expand = element.resizeSensor.childNodes[0]; 85 var expandChild = expand.childNodes[0]; 86 var shrink = element.resizeSensor.childNodes[1]; 87 var shrinkChild = shrink.childNodes[0]; 88 89 var lastWidth, lastHeight; 90 91 var reset = function() { 92 expandChild.style.width = expand.offsetWidth + 10 + 'px'; 93 expandChild.style.height = expand.offsetHeight + 10 + 'px'; 94 expand.scrollLeft = expand.scrollWidth; 95 expand.scrollTop = expand.scrollHeight; 96 shrink.scrollLeft = shrink.scrollWidth; 97 shrink.scrollTop = shrink.scrollHeight; 98 lastWidth = element.offsetWidth; 99 lastHeight = element.offsetHeight; 100 }; 101 102 reset(); 103 104 var changed = function() { 105 if (element.resizedAttached) { 106 element.resizedAttached.call(); 107 } 108 }; 109 110 var addEvent = function(el, name, cb) { 111 if (el.attachEvent) { 112 el.attachEvent('on' + name, cb); 113 } else { 114 el.addEventListener(name, cb); 115 } 116 }; 117 118 var onScroll = function() { 119 if (element.offsetWidth != lastWidth || element.offsetHeight != lastHeight) { 120 changed(); 121 } 122 reset(); 123 }; 124 125 addEvent(expand, 'scroll', onScroll); 126 addEvent(shrink, 'scroll', onScroll); 127 } 128 129 var elementType = Object.prototype.toString.call(element); 130 var isCollectionTyped = ('[object Array]' === elementType 131 || ('[object NodeList]' === elementType) 132 || ('[object HTMLCollection]' === elementType) 133 || ('undefined' !== typeof jQuery && element instanceof jQuery) //jquery 134 || ('undefined' !== typeof Elements && element instanceof Elements) //mootools 135 ); 136 137 if (isCollectionTyped) { 138 var i = 0, j = element.length; 139 for (; i < j; i++) { 140 attachResizeEvent(element[i], callback); 141 } 142 } else { 143 attachResizeEvent(element, callback); 144 } 145 146 this.detach = function() { 147 if (isCollectionTyped) { 148 var i = 0, j = element.length; 149 for (; i < j; i++) { 150 ResizeSensor.detach(element[i]); 151 } 152 } else { 153 ResizeSensor.detach(element); 154 } 155 }; 156 }; 157 158 ResizeSensor.detach = function(element) { 159 if (element.resizeSensor) { 160 element.removeChild(element.resizeSensor); 161 delete element.resizeSensor; 162 delete element.resizedAttached; 163 } 164 }; 165 166 // make available to common module loader 167 if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 168 module.exports = ResizeSensor; 169 } 170 else { 171 window.ResizeSensor = ResizeSensor; 172 } 173 174})(); 175 176//# sourceMappingURL=maps/ResizeSensor.js.map 177/*! 178 * Theia Sticky Sidebar v1.7.0 179 * https://github.com/WeCodePixels/theia-sticky-sidebar 180 * 181 * Glues your website's sidebars, making them permanently visible while scrolling. 182 * 183 * Copyright 2013-2016 WeCodePixels and other contributors 184 * Released under the MIT license 185 */ 186 187(function ($) { 188 $.fn.theiaStickySidebar = function (options) { 189 var defaults = { 190 'containerSelector': '', 191 'additionalMarginTop': 0, 192 'additionalMarginBottom': 0, 193 'updateSidebarHeight': true, 194 'minWidth': 0, 195 'disableOnResponsiveLayouts': true, 196 'sidebarBehavior': 'modern', 197 'defaultPosition': 'relative', 198 'namespace': 'TSS' 199 }; 200 options = $.extend(defaults, options); 201 202 // Validate options 203 options.additionalMarginTop = parseInt(options.additionalMarginTop) || 0; 204 options.additionalMarginBottom = parseInt(options.additionalMarginBottom) || 0; 205 206 tryInitOrHookIntoEvents(options, this); 207 208 // Try doing init, otherwise hook into window.resize and document.scroll and try again then. 209 function tryInitOrHookIntoEvents(options, $that) { 210 var success = tryInit(options, $that); 211 212 if (!success) {
213 console.log('TSS: Body width smaller than options.minWidth. Init is delayed.'); 214 215 $(document).on('scroll.' + options.namespace, function (options, $that) { 216 return function (evt) { 217 var success = tryInit(options, $that); 218 219 if (success) { 220 $(this).unbind(evt); 221 } 222 }; 223 }(options, $that)); 224 $(window).on('resize.' + options.namespace, function (options, $that) { 225 return function (evt) { 226 var success = tryInit(options, $that); 227 228 if (success) { 229 $(this).unbind(evt); 230 } 231 }; 232 }(options, $that)) 233 } 234 } 235 236 // Try doing init if proper conditions are met. 237 function tryInit(options, $that) { 238 if (options.initialized === true) { 239 return true; 240 } 241 242 if ($('body').width() < options.minWidth) { 243 return false; 244 } 245 246 init(options, $that); 247 248 return true; 249 } 250 251 // Init the sticky sidebar(s). 252 function init(options, $that) { 253 options.initialized = true; 254 255 // Add CSS 256 var existingStylesheet = $('#theia-sticky-sidebar-stylesheet-' + options.namespace); 257 if (existingStylesheet.length === 0) { 258 $('head').append($('<style id="theia-sticky-sidebar-stylesheet-' + options.namespace + '">.theiaStickySidebar:after {content: ""; display: table; clear: both;}</style>')); 259 } 260 261 $that.each(function () { 262 var o = {}; 263 264 o.sidebar = $(this); 265 266 // Save options 267 o.options = options || {}; 268 269 // Get container 270 o.container = $(o.options.containerSelector); 271 if (o.container.length == 0) { 272 o.container = o.sidebar.parent(); 273 } 274 275 // Create sticky sidebar 276 o.sidebar.parents().css('-webkit-transform', 'none'); // Fix for WebKit bug - https://code.google.com/p/chromium/issues/detail?id=20574 277 o.sidebar.css({ 278 'position': o.options.defaultPosition, 279 'overflow': 'visible', 280 // The "box-sizing" must be set to "content-box" because we set a fixed height to this element when the sticky
280sidebar has a fixed position. 281 '-webkit-box-sizing': 'border-box', 282 '-moz-box-sizing': 'border-box', 283 'box-sizing': 'border-box' 284 }); 285 286 // Get the sticky sidebar element. If none has been found, then create one. 287 o.stickySidebar = o.sidebar.find('.theiaStickySidebar'); 288 if (o.stickySidebar.length == 0) { 289 // Remove <script> tags, otherwise they will be run again when added to the stickySidebar. 290 var javaScriptMIMETypes = /(?:text|application)\/(?:x-)?(?:javascript|ecmascript)/i; 291 o.sidebar.find('script').filter(function (index, script) { 292 return script.type.length === 0 || script.type.match(javaScriptMIMETypes); 293 }).remove(); 294 295 o.stickySidebar = $('<div>').addClass('theiaStickySidebar').append(o.sidebar.children()); 296 o.sidebar.append(o.stickySidebar); 297 } 298 299 // Get existing top and bottom margins and paddings 300 o.marginBottom = parseInt(o.sidebar.css('margin-bottom')); 301 o.paddingTop = parseInt(o.sidebar.css('padding-top')); 302 o.paddingBottom = parseInt(o.sidebar.css('padding-bottom')); 303
304 // Add a temporary padding rule to check for collapsable margins. 305 var collapsedTopHeight = o.stickySidebar.offset().top; 306 var collapsedBottomHeight = o.stickySidebar.outerHeight(); 307 o.stickySidebar.css('padding-top', 1); 308 o.stickySidebar.css('padding-bottom', 1); 309 collapsedTopHeight -= o.stickySidebar.offset().top; 310 collapsedBottomHeight = o.stickySidebar.outerHeight() - collapsedBottomHeight - collapsedTopHeight; 311 if (collapsedTopHeight == 0) { 312 o.stickySidebar.css('padding-top', 0); 313 o.stickySidebarPaddingTop = 0; 314 } 315 else { 316 o.stickySidebarPaddingTop = 1; 317 } 318 319 if (collapsedBottomHeight == 0) { 320 o.stickySidebar.css('padding-bottom', 0); 321 o.stickySidebarPaddingBottom = 0; 322 } 323 else { 324 o.stickySidebarPaddingBottom = 1; 325 } 326 327 // We use this to know whether the user is scrolling up or down. 328 o.previousScrollTop = null; 329 330 // Scroll top (value) when the sidebar has fixed position. 331 o.fixedScrollTop = 0; 332 333 // Set sidebar to default values. 334 resetSidebar(); 335 336 o.onScroll = function (o) { 337 // Stop if the sidebar isn't visible. 338 if (!o.stickySidebar.is(":visible")) { 339 return; 340 } 341 342 // Stop if the window is too small. 343 if ($('body').width() < o.options.minWidth) { 344 resetSidebar(); 345 return; 346 } 347 348 // Stop if the sidebar width is larger than the container width (e.g. the theme is responsive and the sidebar is now below the content) 349 if (o.options.disableOnResponsiveLayouts) { 350 var sidebarWidth = o.sidebar.outerWidth(o.sidebar.css('float') == 'none'); 351 352 if (sidebarWidth + 50 > o.container.width()) { 353 resetSidebar(); 354 return; 355 } 356 } 357 358 var scrollTop = $(document).scrollTop(); 359 var position = 'static'; 360 361 // If the user has scrolled down enough for the sidebar to be clipped at the top, then we can consider changing its position. 362 if (scrollTop >= o.sidebar.offset().top + (o.paddingTop - o.options.additionalMarginTop)) { 363 // The top and bottom offsets, used in various calculations. 364 var offsetTop = o.paddingTop + options.additionalMarginTop; 365 var offsetBottom = o.paddingBottom + o.marginBottom + options.additionalMarginBottom; 366 367 // All top and bottom positions are relative to the window, not to the parent elemnts. 368 var containerTop = o.sidebar.offset().top; 369 var containerBottom = o.sidebar.offset().top + getClearedHeight(o.container); 370 371 // The top and bottom offsets relative to the window screen top (zero) and bottom (window height). 372 var windowOffsetTop = 0 + options.additionalMarginTop; 373 var windowOffsetBottom; 374 375 var sidebarSmallerThanWindow = (o.stickySidebar.outerHeight() + offsetTop + offsetBottom) < $(window).height(); 376 if (sidebarSmallerThanWindow) { 377 windowOffsetBottom = windowOffsetTop + o.stickySidebar.outerHeight(); 378 } 379 else { 380 windowOffsetBottom = $(window).height() - o.marginBottom - o.paddingBottom - options.additionalMarginBottom; 381 } 382 383 var staticLimitTop = containerTop - scrollTop + o.paddingTop; 384 var staticLimitBottom = containerBottom - scrollTop - o.paddingBottom - o.marginBottom; 385 386 var top = o.stickySidebar.offset().top - scrollTop; 387 var scrollTopDiff = o.previousScrollTop - scrollTop; 388 389 // If the sidebar position is fixed, then it won't move up or down by itself. So, we manually adjust the top coordinate. 390 if (o.stickySidebar.css('position') == 'fixed') { 391 if (o.options.sidebarBehavior == 'modern') { 392 top += scrollTopDiff; 393 } 394 } 395 396 if (o.options.sidebarBehavior == 'stick-to-top') { 397 top = options.additionalMarginTop; 398 } 399 400 if (o.options.sidebarBehavior == 'stick-to-bottom') { 401 top = windowOffsetBottom - o.stickySidebar.outerHeight(); 402 } 403 404 if (scrollTopDiff > 0) { // If the user is scrolling up. 405 top = Math.min(top, windowOffsetTop); 406 } 407 else { // If the user is scrolling down. 408 top = Math.max(top, windowOffsetBottom - o.stickySidebar.outerHeight()); 409 } 410 411 top = Math.max(top, staticLimitTop); 412 413 top = Math.min(top, staticLimitBottom - o.stickySidebar.outerHeight()); 414 415 // If the sidebar is the same height as the container, we won't use fixed positioning. 416 var sidebarSameHeightAsContainer = o.container.height() == o.stickySidebar.outerHeight(); 417 418 if (!sidebarSameHeightAsContainer && top == windowOffsetTop) { 419 position = 'fixed'; 420 } 421 else if (!sidebarSameHeightAsContainer && top == windowOffsetBottom - o.stickySidebar.outerHeight()) { 422 position = 'fixed'; 423 } 424 else if (scrollTop + top - o.sidebar.offset().top - o.paddingTop <= options.additionalMarginTop) { 425 // Stuck to the top of the page. No special behavior. 426 position = 'static'; 427 } 428 else { 429 // Stuck to the bottom of the page. 430 position = 'absolute'; 431 } 432 } 433 434 /*
435 * Performance notice: It's OK to set these CSS values at each resize/scroll, even if they don't change. 436 * It's way slower to first check if the values have changed. 437 */ 438 if (position == 'fixed') { 439 var scrollLeft = $(document).scrollLeft(); 440 441 o.stickySidebar.css({ 442 'position': 'fixed', 443 'width': getWidthForObject(o.stickySidebar) + 'px', 444 'transform': 'translateY(' + top + 'px)', 445 'left': (o.sidebar.offset().left + parseInt(o.sidebar.css('padding-left')) - scrollLeft) + 'px', 446 'top': '0px' 447 }); 448 } 449 else if (position == 'absolute') { 450 var css = {}; 451 452 if (o.stickySidebar.css('position') != 'absolute') { 453 css.position = 'absolute'; 454 css.transform = 'translateY(' + (scrollTop + top - o.sidebar.offset().top - o.stickySidebarPaddingTop - o.stickySidebarPaddingBottom) + 'px)'; 455 css.top = '0px'; 456 } 457 458 css.width = getWidthForObject(o.stickySidebar) + 'px'; 459 css.left = ''; 460 461 o.stickySidebar.css(css); 462 } 463 else if (position == 'static') { 464 resetSidebar(); 465 } 466 467 if (position != 'static') { 468 if (o.options.updateSidebarHeight == true) { 469 o.sidebar.css({ 470 'min-height': o.stickySidebar.outerHeight() + o.stickySidebar.offset().top - o.sidebar.offset().top + o.paddingBottom 471 }); 472 } 473 } 474 475 o.previousScrollTop = scrollTop; 476 }; 477 478 // Initialize the sidebar's position. 479 o.onScroll(o); 480 481 // Recalculate the sidebar's position on every scroll and resize. 482 $(document).on('scroll.' + o.options.namespace, function (o) { 483 return function () { 484 o.onScroll(o); 485 }; 486 }(o)); 487 $(window).on('resize.' + o.options.namespace, function (o) { 488 return function () { 489 o.stickySidebar.css({'position': 'static'}); 490 o.onScroll(o); 491 }; 492 }(o)); 493 494 // Recalculate the sidebar's position every time the sidebar changes its size. 495 if (typeof ResizeSensor !== 'undefined') { 496 new ResizeSensor(o.stickySidebar[0], function (o) { 497 return function () { 498 o.onScroll(o); 499 }; 500 }(o)); 501 } 502 503 // Reset the sidebar to its default state 504 function resetSidebar() { 505 o.fixedScrollTop = 0; 506 o.sidebar.css({ 507 'min-height': '1px' 508 }); 509 o.stickySidebar.css({ 510 'position': 'static', 511 'width': '', 512 'transform': 'none' 513 }); 514 } 515 516 // Get the height of a div as if its floated children were cleared. Note that this function fails if the floats are more than one level deep. 517 function getClearedHeight(e) { 518 var height = e.height(); 519 520 e.children().each(function () { 521 height = Math.max(height, $(this).height()); 522 }); 523 524 return height; 525 } 526 }); 527 } 528 529 function getWidthForObject(object) { 530 var width; 531 532 try { 533 width = object[0].getBoundingClientRect().width; 534 } 535 catch (err) { 536 } 537 538 if (typeof width === "undefined") { 539 width = object.width(); 540 } 541 542 return width; 543 } 544 545 return this; 546 } 547})(jQuery); 548 549//# sourceMappingURL=maps/theia-sticky-sidebar.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.