PageSourceSearch

https://shop.advisers.com.tw/skin/frontend/ultimo/default/js/stickyheader.js

js advisers.com.tw collected 2026-10-02 18:09:46 UTC 8,187 bytes, 238 lines download raw bytes

1;(function ($, window, document, undefined) {
2
3    $.widget("infortis.stickyheader", {
4
5        options: {
6            stickyThreshold: 770
7            , cartBlockSelector: '#minicart'
8        }
9
10        , isSticky: false
11        , isSuspended: false
12        , headerContainer: undefined
13        , stickyContainer: undefined
14        , compareBlock: undefined
15        , cartBlock: undefined
16        , navHolderBlock1: undefined
17        , navHolderBlock2: undefined
18        , stickyContainerOffsetTop: 55 //Position of the bottom edge of the sticky container relative to the viewport
19        , requiredRecalculation: false //Flag: required recalculation of the position of the bottom edge of the sticky container
20
21        , _create: function() {
22            this._initPlugin();
23        }
24
25        , _initPlugin: function(customOptions)
26        {
27            var _self = this;
28
29            //Initialize plugin basic properties
30            this.headerContainer = this.element;
31            this.stickyContainer = $('.sticky-container'); //Important: by default it's the same element as headerContainer
32            this.compareBlock = $('#mini-compare');
33            this.cartBlock = $(this.options.cartBlockSelector);
34            this.navHolderBlock1 = $('#nav-holder2'); //"#nav-holder1" is reserved for search box
35            this.navHolderBlock2 = $('#nav-holder3');
36            this.cartMarkerRegular = $('#mini-cart-marker-regular');
37            this.compareMarkerRegular = $('#mini-compare-marker-regular');
38
39            //After initializing plugin basic properties
40            this.hookToActivatedDeactivated(); //Important: call before activateSticky is called
41            this.calculateStickyContainerOffsetTop();
42            this.applySticky();
43            this.hookToScroll();
44            this.hookToResize();
45
46            if (this.options.stickyThreshold > 0)
47            {
48                enquire.register('(max-width: ' + (this.options.stickyThreshold - 1) + 'px)', {
49                    match: function() {
50                        _self.suspendSticky();
51                    },
52                    unmatch: function() {
53                        _self.unsuspendSticky();
54                    }
55                });
56            }
57
58        } //end: _initPlugin
59
60        , calculateStickyContainerOffsetTop: function()
61        {
62            //Calculate the position of the bottom edge of the sticky container relative to the viewport
63            this.stickyContainerOffsetTop = this.stickyContainer.offset().top + this.stickyContainer.outerHeight();
64
65            //Important: disable flag
66            this.requiredRecalculation = false;
67        }
68
69        , applySticky: function()
70        {
71            if (this.isSuspended) return;
72
73            //If recalculation required
74            if (this.requiredRecalculation)
75            {
76                //Important: recalculate only when header is not sticky
77                if (!this.isSticky)
78                {
79                    this.calculateStickyContainerOffsetTop();
80                }
81            }
82
83            var viewportOffsetTop = $(window).scrollTop();
84
85            if (viewportOffsetTop > this.stickyContainerOffsetTop)
86            {
87                if (!this.isSticky)
88                {
89                    this.activateSticky();
90                }
91            }
92            else
93            {
94                if (this.isSticky)
95                {
96                    this.deactivateSticky();
97                }
98            }
99        }
100
101        , activateSticky: function()
102        {
103            var stickyContainerHeight = this.stickyContainer.outerHeight();
104            var originalHeaderHeight = this.headerContainer.css('height');
105
106            //Compensate the change of the header height after the sticky container was removed from its normal position
107            this.headerContainer.css('height', originalHeaderHeight);
108
109            //Important: trigger event just before making the header sticky
110            //this.print('trigger: activate-STICKY-header'); ///
111            $(document).trigger("activate-sticky-header");
112
113            //Make the header sticky
114            this.headerContainer.addClass('sticky-header');
115            this.isSticky = true;
116
117            //Effect
118            this.stickyContainer.css('margin-top', '-' + stickyContainerHeight + 'px').animate({'margin-top': '0'}, 200, 'easeOutCubic');
119            //this.stickyContainer.css('opacity', '0').animate({'opacity': '1'}, 300, 'easeOutCubic');
120        }
121
122        , deactivateSticky: function()
123        {
124            //Remove the compensation of the header height change
125            this.headerContainer.css('height', '');
126
127            this.headerContainer.removeClass('sticky-header');
128            this.isSticky = false;
129
130            //this.print('trigger: deactivate-STICKY-header'); ///
131            $(document).trigger("deactivate-sticky-header");
132        }
133
134        , suspendSticky: function()
135        {
136            this.isSuspended = true;
137
138            //Deactivate sticky header.
139            //Important: call method only when sticky header is actually active.
140            if (this.isSticky)
141            {
142                this.deactivateSticky();
143            }
144        }
145
146        , unsuspendSticky: function()
147        {
148            this.isSuspended = false;
149
150            //Activate sticky header.
151            //Important: call applySticky instead of activateSticky to check if activation is needed.
152            this.applySticky();
153        }
154
155        , hookToScroll: function()
156        {
157            var _self = this;
158
159            $(window).on("scroll", function(e) {
160                _self.applySticky();
161            }); //end: on event
162        }
163
164        , hookToScrollDeferred: function()
165        {
166            var _self = this;
167
168            var windowScrollTimeout;
169            $(window).on("scroll", function() {
170                clearTimeout(windowScrollTimeout);
171                windowScrollTimeout = setTimeout(function() {
172                    _self.applySticky();
173                }, 50);
174            }); //end: on event
175        }
176
177        , hookToResize: function()
178        {
179            var _self = this;
180
181            $(window).on('themeResize', function(e) {
182
183                //Require recalculation
184                _self.requiredRecalculation = true;
185
186                //Remove the compensation of the header height change
187                _self.headerContainer.css('height', '');
188            }); //end: on event
189        }
190
191        , hookToActivatedDeactivated: function()
192        {
193            var _self = this;
194
195            //When sticky header was activated
196            $(document).on('activate-sticky-header', function(e) {
197
198                if (_self.cartBlock.parent().hasClass('nav-holder') === false)
199                {
200                    _self.navHolderBlock1.prepend(_self.cartBlock);
201                    _self.cartBlock.data('moved', true);
202                }
203
204                if (_self.compareBlock.parent().hasClass('nav-holder') === false)
205                {
206                    _self.navHolderBlock2.prepend(_self.compareBlock);
207                    _self.compareBlock.data('moved', true);
208                }
209
210            }); //end: on event
211
212            //When sticky header was deactivated
213            $(document).on('deactivate-sticky-header', function(e) {
214
215                // Move the block back to the regular position but only:
216                // - if the block was moved there dynamically by this script (block is marked with 'moved' data)
217                // - if the block is inside a holder
218
219                if (_self.cartBlock.data('moved') && _self.cartBlock.parent().hasClass('nav-holder') === true)
220                {
221                    _self.cartMarkerRegular.after(_self.cartBlock);
222                }
223
224                if (_self.compareBlock.data('moved') && _self.compareBlock.parent().hasClass('nav-holder') === true)
225                {
226                    _self.compareMarkerRegular.after(_self.compareBlock);
227                }
228
229            }); //end: on event
230        }
231
232        // , print: function(msg) {
233        //     console.log(msg);
234        // }
235
236    }); //end: widget
237
238})(jQuery, window, document);

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.