PageSourceSearch

https://nazarenespace.com/assets/1c191ac3/js/humhub.live.poll.js?v=1723430289

js nazarenespace.com collected 2026-10-02 13:08:38 UTC 8,932 bytes, 310 lines download raw bytes

1humhub.module('live.poll', function (module, require, $) {
2    var client = require('client');
3    var event = require('event');
4    var object = require('util').object;
5
6    var DEFAULT_MIN_INTERVAL = 10;
7    var DEFAULT_MAX_INTERVAL = 45;
8
9    var DEFAULT_IDLE_FACTOR = 0.1;
10    var DEFAULT_IDLE_INTERVAL = 20;
11
12    var EVENT_TYPE_REQUEST = 'request';
13    var EVENT_TYPE_FOCUS = 'focus';
14    var EVENT_TYPE_UPDATE = 'update';
15
16    var counter = {
17        requests: 0,
18        updates: 0
19    };
20
21    var PollClient = function (options) {
22        if (!options) {
23            module.log.error('Could not initialize PollClient. No options given!');
24            return;
25        }
26
27        this.options = options;
28        this.options.minInterval = options.minInterval || DEFAULT_MIN_INTERVAL;
29        this.options.maxInterval = options.maxInterval || DEFAULT_MAX_INTERVAL;
30        this.options.idleFactor = options.idleFactor || DEFAULT_IDLE_FACTOR;
31        this.options.idleInterval = options.idleDelay || DEFAULT_IDLE_INTERVAL;
32        this.options.initTime = options.initTime || Date.now();
33
34        this.init();
35    };
36
37    PollClient.prototype.init = function () {
38        if (!this.options.url) {
39            module.log.error('Could not initialize PollClient. No url option given!');
40            return;
41        }
42
43        this.subscriberId = this.generateSubscriberId();
44        this.focus = true;
45        this.delay = this.options.minInterval;
46        this.call = this.update.bind(this);
47        this.handle = this.handleUpdate.bind(this);
48        this.handleError = this.handleUpdateError.bind(this);
49        this.lastTs = this.options.initTime;
50
51        $(window)
52            .on('blur', this.onWindowBlur.bind(this))
53            .on('focus', this.onWindowFocus.bind(this));
54
55        var that = this;
56        $(document).on('mousemove keydown mousedown touchstart', object.debounce(function () {
57            that.stopIdle();
58        }, 200));
59
60        this.resetPollTimeout();
61        this.startIdleTimer();
62
63        this.initBroadCast();
64    };
65
66    PollClient.prototype.generateSubscriberId = function () {
67        return '_' + Math.random().toString(36).substr(2, 9);
68    };
69
70    PollClient.prototype.initBroadCast = function () {
71        if (!window.BroadcastChannel) {
72            return;
73        }
74
75        this.channel = new BroadcastChannel('live.poll');
76
77        var that = this;
78        this.channel.onmessage = function (evt) {
79            if (!evt.data) {
80                return;
81            }
82
83            if (evt.data.subscriberId === that.subscriberId) {
84                // We triggered the event, so nothing todo
85                return;
86            }
87
88            if (!that.focus) {
89                // Seems this is an inactive tab, so let others do the job...
90                that.resetPollTimeout(that.options.maxInterval);
91            }
92
93            switch (evt.data.type) {
94                case EVENT_TYPE_REQUEST:
95                    // Another tab just started a request, so delay the timeout
96                    that.resetPollTimeout();
97                    break;
98                case EVENT_TYPE_FOCUS:
99                    // Another tab was focused, so increase delay and reset timeout
100                    that.resetPollTimeout(that.options.maxInterval);
101                    break;
102                case EVENT_TYPE_UPDATE:
103                    // We received a response from another tab
104                    that.handleUpdate(evt.data);
105                    break;
106            }
107        }
108    };
109
110    /**
111     * Handler called once the window was focused
112     */
113    PollClient.prototype.onWindowFocus = function () {
114        this.focus = true;
115        this.stopIdle();
116        this.broadCast(EVENT_TYPE_FOCUS);
117    };
118
119    /**
120     * Handler called once the window was blurred
121     */
122    PollClient.prototype.onWindowBlur = function () {
123        this.focus = false;
124        this.updateIdle();
125    };
126
127    /**
128     * Resets current timeout if set and starts polling with current delay
129     */
130    PollClient.prototype.resetPollTimeout = function (delay) {
131        clearTimeout(this.timeout);
132
133        if (delay) {
134            this.setDelay(delay);
135        }
136
137        this.timeout = setTimeout(this.call, this.getDelay());
138    };
139
140    /**
141     * Resets current timeout if set and starts polling with current delay
142     */
143    PollClient.prototype.startIdleTimer = function () {
144        setInterval($.proxy(this.updateIdle, this), (this.options.idleInterval * 1000));
145    };
146
147    /**
148     * Stops the idle behavior by resetting the delay to the min delay
149     */
150    PollClient.prototype.stopIdle = function () {
151        this.setDelay(this.options.minInterval);
152
153        // Make sure we do not have to wait too long after idle end.
154        if (new Date() - this.lastTs > this.options.minInterval) {
155            this.resetPollTimeout();
156        }
157    };
158
159    /**
160     * Updates the delay by means of the idleFactor.
161     */
162    PollClient.prototype.updateIdle = function () {
163        if (this.delay < this.options.maxInterval) {
164            this.setDelay(Math.ceil(this.delay + (this.delay * this.options.idleFactor)));
165        }
166
167        if (this.delay > this.options.maxInterval) {
168            this.setDelay(this.options.maxInterval);
169        }
170    };
171
172    /**
173     * Runs an live update call and resets the timeout.
174     */
175    PollClient.prototype.update = function () {
176        this.broadCast(EVENT_TYPE_REQUEST);
177        counter.requests++;
178
179        client.get(this.getCallOptions())
180            .then(this.handle)
181            .catch(this.handleError);
182
183    };
184
185    /**
186     * Returns the ajax call options
187     */
188    PollClient.prototype.getCallOptions = function () {
189        return {
190            url: this.options.url,
191            data: {
192                last: this.lastTs
193            }
194        };
195    };
196
197    /**
198     * Handles the live update response.
199     */
200    PollClient.prototype.handleUpdate = function (response) {
201
202        if (this.lastTs >= response.queryTime) {
203            // We already have a more recent update
204            return;
205        }
206
207        if (this.subscriberId === response.subscriberId) {
208            // Just to make sure we do not handle our own broadcast event
209            return;
210        }
211
212        // used for debugging only
213        counter.updates++;
214
215        this.lastTs = response.queryTime;
216
217        this.resetPollTimeout();
218
219        if (!response.subscriberId) {
220            // If subscriberId is present, this data was already sent
221            this.broadCast(EVENT_TYPE_UPDATE, {
222                queryTime: response.queryTime,
223                events: response.events
224            });
225        }
226
227        this.triggerEventUpdates(response);
228    };
229
230    PollClient.prototype.triggerEventUpdates = function (response) {
231        if (object.isObject(response.events)) {
232            var events = this.groupEvents(response.events);
233
234            $.each(events, function (type, events) {
235                try {
236                    // humhub.module.bla -> humhub:module:bla
237                    event.trigger(type.replace(/\./g, ':'), [events, response]);
238                } catch (e) {
239                    module.log.error(e);
240                }
241            });
242
243            this.lastIds = Object.keys(response.events);
244        }
245    };
246
247    PollClient.prototype.broadCast = function (type, data) {
248        data = data || {};
249
250        if (!this.channel || data.subscriberId) {
251            return;
252        }
253
254        data.subscriberId = this.subscriberId;
255        data.type = type;
256
257        this.channel.postMessage(data);
258    };
259
260    /**
261     * Groups the liveEvents by type and filters out duplicates.
262     */
263    PollClient.prototype.groupEvents = function (events) {
264        var result = {};
265        var that = this;
266        $.each(events, function (id, liveEvent) {
267            // Filter out already triggered events.
268            if (that.lastIds && that.lastIds.indexOf(id) > -1) {
269                return; // continue
270            }
271
272            if (!result[liveEvent.type]) {
273                result[liveEvent.type] = [liveEvent];
274            } else {
275                result[liveEvent.type].push(liveEvent);
276            }
277        });
278
279        return result;
280    };
281
282    PollClient.prototype.handleUpdateError = function (e) {
283        if (!navigator.onLine) {
284            this.resetPollTimeout(this.options.maxInterval);
285            module.log.info('Poll request blocked due to offline status');
286        } else {
287            module.log.error(e);
288        }
289    };
290
291    /**
292     * Returns the delay in milliseconds.
293     * @returns {Number}
294     */
295    PollClient.prototype.getDelay = function () {
296        return this.delay * 1000;
297    };
298
299    /**
300     * Sets the delay in seconds
301     * @returns {Number}
302     */
303    PollClient.prototype.setDelay = function (seconds) {
304        this.delay = seconds;
305    };
306
307    module.export({
308        PollClient: PollClient
309    });
310});

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.