1/** 2 * jquery-backToTop 3 * 4 * @license MIT 5 * @author Pablo Pizarro @ppizarror.com 6 */ 7 8;(function (factory) { 9 /** @namespace define.amd */ 10 if (typeof define === 'function' && define.amd) { 11 // AMD. Register as an anonymous module 12 define(['jquery'], factory) 13 } else { 14 // Browser globals 15 factory(jQuery) 16 } 17}(function ($) { 18 "use scrict"; 19 20 /** 21 * BackToTop class 22 * 23 * @class 24 * @param {object=} options - Initial creation options 25 * @private 26 */ 27 let _BackToTop = function (options) { 28 29 /** 30 * Version 31 * @type {string} 32 * @private 33 */ 34 this._version = '0.2.3'; 35 36 /** 37 * Saves body selector 38 * @type {jQuery | JQuery | HTMLElement} 39 * @private 40 */ 41 this._body = $('body'); 42 43 /** 44 * Default options 45 * @private 46 * @since 0.0.1 47 */ 48 let _defaults = { 49 backgroundColor: '#5D5D5D', // [theme] Background color of the backToTop 50 bottom: 20, // Bottom position (px)
51 color: '#FFFFFF', // [theme] Text color 52 container: this._body, // Container of the object 53 divFloat: 'right', // Float left,right 54 effect: 'spin', // Effect of the button 55 enabled: true, // backToTop enabled when created 56 height: 70, // Height of the button (px) 57 icon: 'fas fa-chevron-up', // [theme] Font-awesome icon 58 left: 20, // Left fixed position (px) 59 pxToTrigger: 600, // Scroll px to trigger the backToTop 60 right: 20, // Right fixed position (px) 61 scrollAnimation: 0, // Scroll animation 62 theme: 'default', // Theme of the button 63 width: 70, // Width of the button (px) 64 zIndex: 999, // z-Index of the div 65 }; 66 this._options = $.extend(_defaults, options); 67 68 /** 69 * backToTop main div 70 * @type {jQuery | HTMLElement | JQuery | null} 71 * @private 72 * @since 0.0.1 73 */ 74 this._obj = null; 75 76 /** 77 * Indicates the current status of the backToTop 78 * @type {boolean} 79 * @private 80 * @since 0.0.1 81 */ 82 this._opened = false; 83 84 /** 85 * Actual button theme 86 * @type {string} 87 * @private 88 * @since 0.0.3 89 */ 90 this._actualTheme = ''; 91 92 /** 93 * Actual effect theme 94 * @private 95 * @since 0.0.3 96 */ 97 this._actualEffect = { 98 off: '', 99 on: '', 100 }; 101 102 /** 103 * Indicates that position is fixed, used for 'body' container 104 * @type {boolean} 105 * @private 106 */ 107 this._fixed = false; 108 109 /** 110 * Indicates that the container is $(window) 111 * @type {boolean} 112 * @private 113 */ 114 this._isWindowContainer = false; 115 116 /** 117 * Saves pointer to object 118 * @type {_BackToTop} 119 * @private 120 * @since 0.0.1 121 */ 122 let self = this; 123 124 /** 125 * Generates safe random ID, https://stackoverflow.com/a/2117523 126 * @function 127 * @returns {string} 128 */ 129 this._randomID = function () { 130 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 131 let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); 132 return v.toString(16); 133 }); 134 }; 135 136 /** 137 * Converts to number 138 * @function 139 * @param {number | string} n - Number 140 * @private 141 * @since 0.2.0 142 * @returns {number} 143 */ 144 this._parseNumber = function (n) { 145 return parseFloat(n.toString()); 146 }; 147 148 /** 149 * Throw warn to console 150 * @function 151 * @param {string} msg - Console warning message 152 * @private 153 * @since 0.2.0 154 */ 155 this._warn = function (msg) { 156 console.warn('jquery-backToTop v' + this._version + ': ' + msg.toString()); 157 }; 158 159 /** 160 * Apply a theme to the button 161 * @function 162 * @param {string} theme - Theme of the button 163 * @private 164 * @since 0.0.3 165 */ 166 this._applyTheme = function (theme) { 167 168 /** 169 * If button is has not been built returns 170 */ 171 if (this._obj === null) return; 172 173 /** 174 * If previous theme has been applied 175 */ 176 if (this._actualTheme !== '') { 177 this._obj.removeClass(this._actualTheme); 178 } 179 180 /** 181 * Generates CSS theme name 182 */ 183 this._actualTheme = 'jquery-back-to-top-theme-' + theme; 184 185 /** 186 * Apply theme class 187 */ 188 this._obj.addClass(this._actualTheme); 189 190 /** 191 * Defines default styles (width,size,color,etc) 192 */ 193 this._obj.css({ 194 'background-color': this._options.backgroundColor, 195 'bottom': this._options.bottom + 'px', 196 'color': this._options.color, 197 'float': this._options.divFloat, 198 'right': this._options.right + 'px', 199 'width': this._options.width + 'px', 200 'z-index': this._options.zIndex, 201 }); 202 this.resize(this._options.width, this._options.height); 203 204 /** 205 * Apply lateral margin 206 */ 207 if (this._options.divFloat === 'right') { 208 this._obj.css('right', this._options.right + 'px') 209 } else { 210 this._obj.css('left', this._options.left + 'px') 211 } 212 213 /** 214 * Set button position 215 */ 216 if (!this._fixed) { 217 this._obj.css('position', 'sticky'); 218 } else { 219 this._obj.css('position', 'fixed'); 220 } 221 222 }; 223 224 /** 225 * Resize button 226 * @function 227 * @param {number} w - Width (px) 228 * @param {number} h - Height(px) 229 * @since 0.2.1 230 */ 231 this.resize = function (w, h) { 232 this._obj.css({ 233 'height': this._parseNumber(h) + 'px', 234 'line-height': this._parseNumber(h) + 'px', 235 'width': this._parseNumber(w) + 'px', 236 }); 237 }; 238 239 /** 240 * Public function that changes button theme 241 * @function 242 * @param {string} theme - Theme name 243 * @since 0.0.6 244 */ 245 this.changeTheme = function (theme) { 246 this._options.theme = theme; 247 this._applyTheme(theme); 248 if (this._opened) this.show(true); 249 }; 250 251 /** 252 * Apply effect 253 * @function 254 * @param {string} effect - Effect name 255 * @private 256 * @since 0.0.5 257 */ 258 this._applyEffect = function (effect) { 259 260 /** 261 * If button is has not been built returns 262 */ 263 if (this._obj === null) return; 264 265 /** 266 * Remove classes if present 267 */ 268 if (this._actualEffect.on !== '') this._obj.removeClass(this._actualEffect.on); 269 if (this._actualEffect.off !== '') this._obj.removeClass(this._actualEffect.off); 270 271 /** 272 * Create class name 273 */ 274 this._actualEffect.on = 'jquery-back-to-top-status-on jquery-back-to-top-effect-' + effect + '-on'; 275 this._actualEffect.off = 'jquery-back-to-top-status-off jquery-back-to-top-effect-' + effect + '-off'; 276 277 }; 278 279 /** 280 * Public function that changes button effect 281 * @function 282 * @param {string} effect - Effect name 283 * @since 0.0.6 284 */ 285 this.changeEffect = function (effect) { 286 this._options.effect = effect; 287 this._applyEffect(effect); 288 if (this._opened) this.show(true); 289 }; 290 291 /** 292 * Opens the button 293 * @function 294 * @param {boolean=} disableEffect - Open with no efect 295 * @since 0.0.6 296 */ 297 this.show = function (disableEffect) { 298 if (self._options.container.scrollTop() > self._options.pxToTrigger) { 299 this._obj.removeClass(this._actualEffect.off); 300 if (disableEffect) { 301 this._obj.addClass('jquery-back-to-top-status-on'); 302 } else { 303 this._obj.addClass(this._actualEffect.on); 304 } 305 self._opened = true; 306 } 307 }; 308 309 /** 310 * Hide the button 311 * @function 312 * @param {boolean=} disableEffect - Hide with no efect 313 * @since 0.0.6 314 */ 315 this.hide = function (disableEffect) { 316 this._obj.removeClass(this._actualEffect.on); 317 if (disableEffect) { 318 this._obj.addClass('jquery-back-to-top-status-off'); 319 } else { 320 this._obj.addClass(this._actualEffect.off); 321 } 322 self._opened = false; 323 }; 324 325 /** 326 * Toggles the button 327 * @function 328 * @param {boolean=} disableEffect - Disables the effect 329 * @since 0.1.1 330 */ 331 this.toggle = function (disableEffect) { 332 if (self._opened) { 333 this.hide(disableEffect); 334 } else { 335 this.show(disableEffect); 336 } 337 }; 338 339 /** 340 * Enables/disables the button 341 * @function 342 * @param {boolean} status - true: enables, false: disables 343 * @param {boolean=} disableEffect - Disables the effect 344 * @since 0.1.1 345 */ 346 this.enable = function (status, disableEffect) { 347 this._options.enabled = status; 348 if (!this._options.enabled && this._opened) this.hide(disableEffect); 349 if (this._options.enabled && !this._options) this.show(disableEffect); 350 }; 351 352 /** 353 * Check window scroll, if scrolled px is greater than options then open, otherwise close 354 * @function 355 * @private 356 * @since 0.0.4 357 */ 358 this._checkScroll = function () { 359 360 /** 361 * Object is disabled 362 */ 363 if (!self._options.enabled) return; 364 365 /** 366 * Open-Close depending of the scroll 367 */ 368 if (self._options.container.scrollTop() > self._options.pxToTrigger) { // Open 369 if (self._opened) return; 370 self.show(); 371 } else { // Close 372 if (!self._opened) return; 373 self.hide(); 374 } 375 376 }; 377 378 /** 379 * Init main scroll event 380 * @function 381 * @private 382 */ 383 this._initEvent = function () { 384 385 /** 386 * Generates event ID 387 */ 388 let $id = this._randomID(); 389 390 /** 391 * Apply window scroll event 392 */ 393 self._options.container.on('scroll.' + $id, function () { 394 self._checkScroll(); 395 }); 396 397 /** 398 * Button click 399 */ 400 this._obj.off('click.backToTop'); 401 this._obj.on('click.backToTop', function (e) { 402 e.preventDefault(); 403 if (self._options.scrollAnimation === 0) { 404 self._options.container.scrollTop(0); 405 } else { 406 if (self._isWindowContainer) { // If window container is used 407 $('html,body').stop().animate({scrollTop: 0}, self._options.scrollAnimation); 408 } else { 409 self._options.container.animate({ 410 scrollTop: 0 411 }, self._options.scrollAnimation); 412 } 413 } 414 }); 415 416 }; 417 418 /** 419 * Init 420 */ 421 if ($(this._options.container).find('.back-to-top-container').length === 0) { 422 423 /** 424 * Parse input 425 */ 426 this._options.bottom = this._parseNumber(this._options.bottom); 427 this._options.left = this._parseNumber(this._options.left); 428 this._options.pxToTrigger = Math.max(0, this._parseNumber(this._options.pxToTrigger)); 429 this._options.right = this._parseNumber(this._options.right); 430 this._options.scrollAnimation = Math.max(0, this._parseNumber(this._options.scrollAnimation)); 431 this._options.zIndex = this._parseNumber(this._options.zIndex); 432 433 /** 434 * Check that parent exists, if not uses body 435 */ 436 if (!(this._options.container instanceof jQuery) || this._options.container.length === 0) { 437 this._warn('Container is not jQuery instance or it\'s empty, using container=body and enabled=false'); 438 this._options.container = this._body; 439 this._options.enabled = false; 440 } 441 442 /** 443 * Check that divFloat is correct 444 */ 445 this._options.divFloat = this._options.divFloat.toLowerCase(); 446 if (['left', 'right'].indexOf(this._options.divFloat) === -1) { 447 this._warn('divFloat=' + this._options.divFloat + ' parameter is not correct. Valid=left,right. Using default parameter=right'); 448 this._options.divFloat = 'right'; 449 } 450 451 /** 452 * Creates object 453 */ 454 let $id = this._randomID(); 455 $(this._options.container).append('<div id="' + $id + '" class="jquery-back-to-top"><i class="' + this._options.icon + '"></i></div>'); 456 self._obj = $('#' + $id); 457 458 /** 459 * If container is body changes to window 460 */ 461 if (this._options.container.get(0) === this._body.get(0)) { 462 self._isWindowContainer = true; 463 self._options.container = $(window); 464 self._fixed = true; // fixed instead of sticky 465 } 466 467 /** 468 * Apply theme and effect 469 */ 470 this._applyTheme(this._options.theme); 471 472 /** 473 * Set effects 474 */ 475 this._applyEffect(this._options.effect); 476 477 /** 478 * Init events 479 */ 480 this._initEvent(); 481 482 } 483 484 }; 485 486 /** 487 * Create jQuery plugin 488 */ 489 $.backToTop = function (options) { 490 return new _BackToTop(options); 491 }; 492 493}));
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.