1(function ($, window, document, undefined) { 2 "use strict"; 3 4 var pluginName = "stickThis", 5 defaults = { 6 target:null, 7 top: null, 8 position: "top", 9 minscreenwidth: null, 10 maxscreenwidth: null, 11 screen_small: true, 12 screen_medium: true, 13 screen_large: true, 14 screen_extralarge: true, 15 zindex: 1, 16 bottom_trigger: "0", 17 legacymode: false, 18 dynamicmode: false, 19 debugmode: false, 20 pushup: "", 21 adminbar: false, 22 detach: false, 23 opacity: 100, 24 scroll_range_min: 0, 25 scroll_range_max: 100, 26 fade_in: false, 27 slide_down: false, 28 bg_color: false, 29 custom_css: false 30 }; 31 32 var $activeEl = null; 33 var bottomTrigger = 0; 34 35 function Plugin(element, options) { 36 this.element = element; 37 this.settings = $.extend({}, defaults, options); 38 this._defaults = defaults; 39 this._name = pluginName; 40 this.init(); 41 } 42 43 $.extend(Plugin.prototype, { 44 init: function () { 45 $activeEl = $(this.element); 46 var numElements = $(this.element).length; 47 var numPushElements = $(this.settings.pushup).length; 48 if (numPushElements < 1) { 49 // There are no elements on the page with the called selector for the Push-up Element. 50 if (this.settings.debugmode == true && this.settings.pushup) { 51 console.error('STICKY ANYTHING DEBUG: There are no elements with the selector/class/ID you selected for the Push-up element ("' + this.settings.pushup + '").'); 52 } 53 this.settings.pushup = ""; 54 } else if (numPushElements > 1) { 55 // You can't use more than one element to push up the sticky element. 56 // Make sure that you use a selector that applies to only ONE SINGLE element on the page. 57 // Want to find out quickly where all the elements are that you targeted? Uncomment the next line to debug. 58 // $(settings.pushup).css('border','solid 3px #ff0000'); 59 if (this.settings.debugmode == true) { 60 console.error("STICKY ANYTHING DEBUG: There are " + numPushElements + ' elements on the page with the selector/class/ID you selected for the push-up element ("' + this.settings.pushup + '"). You can select only ONE element to push the sticky element up.'); 61 } 62 // Resetting it to NOTHING. 63 this.settings.pushup = ""; 64 } 65 66 if (numElements < 1) { 67 // There are no elements on the page with the called selector. 68 if (this.settings.debugmode == true) { 69 console.error('STICKY ANYTHING DEBUG: There are no elements with the selector/class/ID you selected for the sticky element ("' + this.selector + '").'); 70 } 71 } else if (numElements > 1) { 72 // This is not going to work either. You can't make more than one element sticky. They will only get in eachother's way. 73 // Make sure that you use a selector that applies to only ONE SINGLE element on the page. 74 // Want to find out quickly where all the elements are that you targeted? Uncomment the next line to debug. 75 // $(this).css('border','solid 3px #00ff00'); 76 if (this.settings.debugmode == true) { 77 console.error("STICKY ANYTHING DEBUG: There There are " + numPushElements + ' elements with the selector/class/ID you selected for the sticky element ("' + this.selector + '"). You can only make ONE element sticky.'); 78 } 79 } 80 81 if (this.settings.top == null) { 82 this.settings.top = 0; 83 } else { 84 if (isNaN(parseInt(this.settings.top))) { 85 this.settings.top = $(this.settings.top).height(); 86 } else { 87 this.settings.top = parseInt(this.settings.top); 88 } 89 } 90 91 /** 92 * Modern way 93 */ 94 $(this.element).addClass("sticky-element-original element-is-not-sticky sticky-element-active"); 95 var orgAssignedStyles = this.cssStyles(); // All original element styles, assigned by CSS. 96 var orgInlineStyles = $(this.element).attr("style"); 97 if (orgInlineStyles == null) { 98 orgInlineStyles = ""; 99 } 100 this.createPlaceholder($(this.element)); 101 102 if (this.settings.position == "bottom") { 103 if (this.settings.bottom_trigger.indexOf("%") > 0) { 104 var percentage = parseInt(this.settings.bottom_trigger.substr(0, this.settings.bottom_trigger.indexOf("%"))); 105 bottomTrigger = $("body").height() * (percentage / 100); 106 } else { 107 bottomTrigger = parseInt(this.settings.bottom_trigger); 108 } 109 } 110 111 var _debounceScroll = 0; 112 var instance = this; 113 $(window).scroll(function () { 114 clearTimeout(_debounceScroll); 115 _debounceScroll = setTimeout(function () { 116 instance.check(instance.settings, orgInlineStyles); 117 }, 10); 118 }); 119 120 var _debounceResize = 0; 121 $(window).resize(function () { 122 clearTimeout(_debounceResize); 123 _debounceResize = setTimeout(function () { 124 instance.unstickIt(orgInlineStyles); 125 instance.check(instance.settings, orgInlineStyles, orgAssignedStyles); 126 }, 50); 127 }); 128 129 this.check(this.settings, orgInlineStyles, orgAssignedStyles); 130 }, 131 cssStyles: function () { 132 var o = {}; 133 var el = $(this.element); 134 135 o["display"] = el.css("display"); 136 o["float"] = el.css("float"); 137 o["flex"] = el.css("flex"); 138 o["box-sizing"] = el.css("box-sizing"); 139 o["clear"] = el.css("clear"); 140 o["overflow"] = el.css("overflow"); 141 o["transform"] = el.css("transform"); 142 143 return o; 144 }, 145 createPlaceholder: function ($originalelement) {
146 var $placeholder = $('<div class="sticky-element-placeholder" style="width:0; height:0;margin:0; padding:0; visibility:hidden;"></div>'); 147 $(this.element).before($placeholder).data("placeholder", $placeholder); 148 }, 149 createClone: function (cloneTop, cloneZindex) { 150 var $clone = $(this.element).clone(); 151 $(this.element).data("clone", $clone); 152 $clone 153 .insertAfter(this.element) 154 .addClass("sticky-element-cloned") 155 .removeClass("element-is-not-sticky") 156 .addClass("element-is-sticky") 157 .css("position", "fixed") 158 .css("top", cloneTop + "px") 159 .css("margin-left", "0") 160 .css("z-index", cloneZindex) 161 .removeClass("sticky-element-original") 162 .hide(); 163 }, 164 check: function (settings, originalInlineStyles, originalAssignedStyles) { 165 // Calculating actual viewport width 166 var e = window, 167 a = "inner"; 168 if (!("innerWidth" in window)) { 169 a = "client"; 170 e = document.documentElement || document.body; 171 } 172 var viewport = e[a + "Width"]; 173 var viewporth = e[a + "Height"]; 174 175 var usingCsutomScreenSize = settings.minscreenwidth != null && settings.maxscreenwidth != null; 176 if (usingCsutomScreenSize && (viewport < settings.minscreenwidth || viewport > settings.maxscreenwidth)) return; 177 178 if (!usingCsutomScreenSize) { 179 if (viewport < 768 && !settings.screen_small) return; 180 181 if (viewport >= 768 && viewport < 992 && !settings.screen_medium) return; 182 183 if (viewport >= 992 && viewport < 1200 && !settings.screen_large) return; 184 185 if (viewport > 1200 && !settings.screen_extralarge) return; 186 } 187 188 var $listenerElement = $(this.element).hasClass("sticky-element-active") ? $(this.element) : $(this.element).data("placeholder"); 189 190 var orgElementPos = $listenerElement.offset(); 191 var orgElementTop = orgElementPos.top; 192 193 var pushElementTop = 0; 194 if (settings.pushup) { 195 var pushElementPos = $(settings.pushup).offset(); 196 pushElementTop = pushElementPos.top; 197 } 198 199 var adminBarHeight = 0; 200 if (settings.adminbar && $("body").hasClass("admin-bar") && viewport > 600) { 201 // below 600, the adminbar is not fixed 202 adminBarHeight = $("#wpadminbar").height(); 203 } 204 205 var elementHeight = $(this.element).outerHeight(); 206 var amountToScroll = orgElementTop - settings.top - adminBarHeight; 207 if (settings.fade_in || settings.slide_down) { 208 amountToScroll += elementHeight; 209 } 210 211 var conditionIfTop = $(window).scrollTop() > amountToScroll; 212 var conditionIfBottom = $(window).scrollTop() > bottomTrigger; 213 214 var scroll_percent = ($(window).scrollTop() / viewporth) * 100; 215 216 if ((settings.scroll_range_min > 0 && scroll_percent < settings.scroll_range_min) || (settings.scroll_range_max < 100 && scroll_percent > settings.scroll_range_max)) { 217 conditionIfTop = false; 218 conditionIfBottom = false; 219 } 220 221 var elementHeight = $(this.element).outerHeight(); 222 if ($(this.element).data("isAnimating")) { 223 return; 224 } 225 226 var isPushedUp = false; 227 if ((settings.position == "top" && conditionIfTop) || (settings.position == "bottom" && conditionIfBottom)) { 228 var isAlreadySticky = $(this.element).hasClass("element-is-sticky"); 229 230 if (settings.pushup && $(window).scrollTop() > pushElementTop - settings.top - elementHeight - adminBarHeight) { 231 //this.unstickIt(originalInlineStyles); 232 var $listenerElement = $(this.element).hasClass("sticky-element-active") ? $(this.element) : $(this.element).data("placeholder"); 233 this.stickIt(settings, $listenerElement, originalAssignedStyles, adminBarHeight, pushElementTop, elementHeight, originalInlineStyles); 234 isPushedUp = true; 235 } else { 236 if($(this.element).hasClass("sticky-is-pushed-up")){ 237 this.unstickIt(originalInlineStyles); 238 $(this.element).removeClass("sticky-is-pushed-up"); 239 } 240 if (!isAlreadySticky){ 241 //var $listenerElement = $(this.element); 242 this.stickIt(settings, $listenerElement, originalAssignedStyles, adminBarHeight, pushElementTop, elementHeight, originalInlineStyles); 243 } 244 } 245 246 if (!isAlreadySticky && !isPushedUp) { 247 this.stickIt(settings, $listenerElement, originalAssignedStyles, adminBarHeight, pushElementTop, elementHeight, originalInlineStyles); 248 } 249 } else { 250 // not scrolled past the menu; only show the original element. 251 this.unstickIt(originalInlineStyles); 252 $(this.element).data("sticky", false); 253 } 254 }, 255 stickIt: function (settings, $listenerElement, originalAssignedStyles, adminBarHeight, pushElementTop, elementHeight, originalInlineStyles) { 256 if ($(this.element).data("isAnimating")) { 257 return; 258 } 259 // We've scrolled PAST the original position; this is where we need to make the element sticky. 260 261 // Placeholder element should always have same left position as original element (see c
261omment below). 262 // The sticky element will NOT have a TOP or the LEFT margin. This is because the left/top reference point of the original 263 // element does not consider the margin. So, we're checking the left/top point of the actual original element and then 264 // use that position for the sticky element. 265 266 // LEFT POSITION 267 var coordsOrgElement = $listenerElement.offset(); 268 var leftOrgElement = coordsOrgElement.left; // This is the position REGARDLESS of the margin. 269 270 // WIDTH/HEIGHT 271 // The placeholder needs to have the width and height of the original element, WITHOUT the margins but WITH the padding and borders 272 // Whatever margins the original has, the placeholder needs to have that too. 273 274 var widthPlaceholder = $listenerElement[0].getBoundingClientRect().width; 275 if (!widthPlaceholder) { 276 widthPlaceholder = $listenerElement.css("width"); // FALLBACK for subpixels 277 } 278 widthPlaceholder = (widthPlaceholder + "").replace(/px/, ""); 279 280 var heightPlaceholder = $listenerElement[0].getBoundingClientRect().height; 281 if (!heightPlaceholder) { 282 heightPlaceholder = $listenerElement.css("height"); // FALLBACK for subpixels 283 } 284 heightPlaceholder = (heightPlaceholder + "").replace(/px/, ""); 285 286 // WIDTH/HEIGHT OF STICKY ELEMENT 287 // The original element though, needs to have the inner width and height of the original (non-sticky) element 288 // No padding, no borders, because that will be applied later anyway, regardless of box-sizing 289 var widthSticky = $(this.element).css("width"); 290 if (widthSticky == "0px") { 291 widthSticky = this.element.getBoundingClientRect().width; 292 } 293 var heightSticky = $(this.element).height(); 294 295 // PADDING 296 // If padding is percentages, convert to pixels when it becomes sticky 297 // Just a leftover from the old method. We will not use padding for the placeholder 298 var paddingOrgElement = [$(this.element).css("padding-top"), $(this.element).css("padding-right"), $(this.element).css("padding-bottom"), $(this.element).css("padding-left")]; 299 var paddingSticky = paddingOrgElement.join(" "); 300 301 // MARGIN 302 var marginOrgElement = [$listenerElement.css("margin-top"), $listenerElement.css("margin-right"), $listenerElement.css("margin-bottom"), $listenerElement.css("margin-left")]; 303 var marginPlaceholder = marginOrgElement.join(" "); 304 305 // OTHER ELEMENTS 306 // if original has float, display, etc., we need to assign that to the placeholder 307 // Though not as important as the width/height/margin/padding 308 309 var assignedStyles = ""; 310 for (var importantStyle in originalAssignedStyles) { 311 if (originalAssignedStyles[importantStyle] == "inline") { 312 assignedStyles += importantStyle + ":inline-block; "; 313 } else { 314 assignedStyles += importantStyle + ":" + originalAssignedStyles[importantStyle] + "; "; 315 } 316 } 317 318 // If scrolled position = pushup-element (top coordinate) - space between top and element - element height - admin bar 319 // In other words, if the pushup element hits the bottom of the sticky element 320 321 if (settings.pushup && $(window).scrollTop() > pushElementTop - settings.top - elementHeight - adminBarHeight) { 322 settings.topMargin = pushElementTop - settings.top - elementHeight - $(window).scrollTop(); 323 $(this.element).addClass('sticky-is-pushed-up'); 324 } else { 325 settings.topMargin = adminBarHeight; 326 } 327 328 assignedStyles += "height:" + heightPlaceholder + "px; margin:" + marginPlaceholder + ";"; 329 console.log(settings); 330 if(settings.detach){ 331 var sticky_element = $(this.element).detach(); 332 $(this.element).addClass('sticky-is-detached'); 333 $('body').append(sticky_element); 334 } 335 336 $(this.element) 337 .removeClass("sticky-element-active") 338 .removeClass("element-is-not-sticky") 339 .addClass("element-is-sticky") 340 .css("cssText", originalInlineStyles + "margin-top: " + settings.topMargin + "px !important; margin-left: 0 !important;" ) // 341 .css("position", "fixed") 342 .css("left", leftOrgElement + "px") 343 .css("width", widthSticky) 344 .css("padding", paddingSticky) 345 .css("z-index", settings.zindex) 346 .css(settings.position, settings.top - elementHeight) 347 .css("opacity", 0); 348 349 if(settings.bg_color && settings.bg_color.length>2){ 350 $(this.element).css("background-color", settings.bg_color); 351 } 352 353 if($(this.element).attr("style").indexOf('/**/') == -1){ 354 $(this.element).attr("style", $(this.element).attr("style") + '/**/' + settings.custom_css); 355 } 356 357 var isAlreadySticky = $(this.element).data("sticky"); 358 var durationFadeIn = settings.fade_in && !isAlreadySticky ? 500 : 0; 359 var durationSlide = settings.slide_down && !isAlreadySticky ? 500 : 0; 360 361 if (durationFadeIn == 500 || durationSlide == 500) { 362 $(this.element).data("isAnimating", true); 363 var $el = $(this.element); 364 setTimeout(function () { 365 $el.data("isAnimating", false); 366 }, 500); 367 } 368 369 $(this.element).fadeTo(durationFadeIn, settings.opacity / 100); 370 var animation = {}; 371 animation[settings.position] = settings.top; 372 $(this.element).animate(animation, { 373 duration: durationSlide, 374 queue: false, 375 }); 376 377 if (!$(this.element).data("placeholder").hasClass("sticky-element-active")) { 378 $(this.element).data("placeholder").addClass("sticky-element-active").attr("style", assignedStyles); 379 } 380 $(this.element).data("sticky", true); 381 }, 382 unstickIt: function (originalInlineStyles) { 383 if($(this.element).hasClass('sticky-is-detached')){ 384 var sticky_element = $(this.element).detach(); 385 var parent_element = $(this.element).data("placeholder").parent(); 386 parent_element.append(sticky_element); 387 } 388 389 $(this.element).addClass("sticky-element-active").removeClass("element-is-sticky").addClass("element-is-not-sticky").attr("style", originalInlineStyles); 390 if ($(this.element).data("placeholder").hasClass("sticky-element-active")) { 391 $(this.element).data("placeholder").removeClass("sticky-element-active").removeAttr("style").css("width", "0").css("height", "0").css("margin", "0").css("padding", "0"); 392 } 393 }, 394 });
395 396 $.fn[pluginName] = function (options) { 397 return this.each(function () { 398 if (!$.data(this, "plugin_" + pluginName)) { 399 $.data(this, "plugin_" + pluginName, new Plugin(this, options)); 400 } 401 }); 402 }; 403 })(jQuery, window, document); 404
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.