2019-09-02 14:24:02 +01:00
|
|
|
(function(global) {
|
2016-03-02 17:36:20 +00:00
|
|
|
"use strict";
|
|
|
|
|
|
2016-06-11 12:02:47 +01:00
|
|
|
var queues = {};
|
2022-01-27 10:44:20 +00:00
|
|
|
var morphdom = global.GOVUK.vendor.morphdom;
|
2020-04-16 13:21:24 +01:00
|
|
|
var defaultInterval = 2000;
|
2020-04-08 17:55:53 +01:00
|
|
|
var interval = 0;
|
|
|
|
|
|
|
|
|
|
var calculateBackoff = responseTime => parseInt(Math.max(
|
|
|
|
|
(250 * Math.sqrt(responseTime)) - 1000,
|
|
|
|
|
1000
|
|
|
|
|
));
|
2016-04-27 09:28:42 +01:00
|
|
|
|
2022-02-08 11:33:13 +00:00
|
|
|
// Methods to ensure the DOM fragment is clean of classes added by JS before diffing
|
|
|
|
|
// and that they are replaced afterwards.
|
2022-02-15 11:26:17 +00:00
|
|
|
//
|
|
|
|
|
// Added to allow the use of JS, in main.js, to apply styles which in future could be
|
|
|
|
|
// achieved with the :has pseudo-class. If :has is available in our supported browsers,
|
|
|
|
|
// this can be removed in favour of a CSS-only solution.
|
2022-02-16 16:08:48 +00:00
|
|
|
var ClassesPersister = function ($contents) {
|
|
|
|
|
this._$contents = $contents;
|
|
|
|
|
this._classNames = [];
|
|
|
|
|
this._classesTo$ElsMap = {};
|
|
|
|
|
};
|
|
|
|
|
ClassesPersister.prototype.addClassName = function (className) {
|
|
|
|
|
if (this._classNames.indexOf(className) === -1) {
|
|
|
|
|
this._classNames.push(className);
|
2022-02-08 11:33:13 +00:00
|
|
|
}
|
|
|
|
|
};
|
2022-02-16 16:08:48 +00:00
|
|
|
ClassesPersister.prototype.remove = function () {
|
|
|
|
|
// Store references to any elements with class names to persist
|
|
|
|
|
this._classNames.forEach(className => {
|
|
|
|
|
var $elsWithClassName = $('.' + className, this._$contents).removeClass(className);
|
2022-02-08 11:33:13 +00:00
|
|
|
|
2022-02-16 16:08:48 +00:00
|
|
|
if ($elsWithClassName.length > 0) {
|
|
|
|
|
this._classesTo$ElsMap[className] = $elsWithClassName;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
ClassesPersister.prototype.replace = function () {
|
2022-02-18 11:55:13 +00:00
|
|
|
var replaceClasses = (idx, el) => {
|
|
|
|
|
|
|
|
|
|
// Avoid updating elements that are no longer present.
|
|
|
|
|
// elements removed will still exist in memory but won't be attached to the DOM any more
|
|
|
|
|
if (global.document.body.contains(el)) {
|
|
|
|
|
$(el).addClass(className);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
2022-02-16 16:08:48 +00:00
|
|
|
var className;
|
|
|
|
|
|
|
|
|
|
for (className in this._classesTo$ElsMap) {
|
2022-02-18 11:55:13 +00:00
|
|
|
this._classesTo$ElsMap[className].each(replaceClasses);
|
2022-02-16 16:08:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove references to elements
|
|
|
|
|
this._classesTo$ElsMap = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var getRenderer = ($contents, key, classesPersister) => response => {
|
2022-02-11 15:35:04 +00:00
|
|
|
classesPersister.remove();
|
2022-02-08 11:33:13 +00:00
|
|
|
morphdom(
|
2022-02-04 11:48:43 +00:00
|
|
|
$contents.get(0),
|
|
|
|
|
$(response[key]).get(0)
|
2022-02-08 11:33:13 +00:00
|
|
|
);
|
2022-02-11 15:35:04 +00:00
|
|
|
classesPersister.replace();
|
2022-02-08 11:33:13 +00:00
|
|
|
};
|
2016-03-02 17:36:20 +00:00
|
|
|
|
2016-06-11 12:02:47 +01:00
|
|
|
var getQueue = resource => (
|
|
|
|
|
queues[resource] = queues[resource] || []
|
|
|
|
|
);
|
2016-03-02 17:36:20 +00:00
|
|
|
|
2016-06-11 12:02:47 +01:00
|
|
|
var flushQueue = function(queue, response) {
|
|
|
|
|
while(queue.length) queue.shift()(response);
|
2016-03-02 17:36:20 +00:00
|
|
|
};
|
|
|
|
|
|
2016-06-12 08:40:56 +01:00
|
|
|
var clearQueue = queue => (queue.length = 0);
|
|
|
|
|
|
2020-04-08 17:55:53 +01:00
|
|
|
var poll = function(renderer, resource, queue, form) {
|
|
|
|
|
|
|
|
|
|
let startTime = Date.now();
|
2016-06-11 12:02:47 +01:00
|
|
|
|
2022-10-27 11:12:39 -04:00
|
|
|
if (document.visibilityState !== "hidden" && queue.push(renderer) === 1) {
|
|
|
|
|
$.ajax(
|
|
|
|
|
resource,
|
|
|
|
|
{
|
|
|
|
|
'method': form ? 'post' : 'get',
|
|
|
|
|
'data': form ? $('#' + form).serialize() : {}
|
2019-05-20 17:32:40 +01:00
|
|
|
}
|
2022-10-27 11:12:39 -04:00
|
|
|
).done(
|
|
|
|
|
response => {
|
|
|
|
|
flushQueue(queue, response);
|
|
|
|
|
if (response.stop === 1) {
|
|
|
|
|
poll = function(){};
|
|
|
|
|
}
|
|
|
|
|
interval = calculateBackoff(Date.now() - startTime);
|
|
|
|
|
}
|
|
|
|
|
).fail(
|
|
|
|
|
() => poll = function(){}
|
|
|
|
|
);
|
|
|
|
|
}
|
2016-06-11 12:02:47 +01:00
|
|
|
|
2016-08-04 12:06:04 +01:00
|
|
|
setTimeout(
|
2019-04-17 12:40:49 +01:00
|
|
|
() => poll.apply(window, arguments), interval
|
2016-06-11 12:02:47 +01:00
|
|
|
);
|
|
|
|
|
};
|
2016-03-02 17:36:20 +00:00
|
|
|
|
2019-09-02 14:24:02 +01:00
|
|
|
global.GOVUK.Modules.UpdateContent = function() {
|
2016-03-02 17:36:20 +00:00
|
|
|
|
2022-02-08 11:33:13 +00:00
|
|
|
this.start = component => {
|
|
|
|
|
var $component = $(component);
|
2022-02-04 11:48:43 +00:00
|
|
|
var $contents = $component.children().eq(0);
|
|
|
|
|
var key = $component.data('key');
|
|
|
|
|
var resource = $component.data('resource');
|
|
|
|
|
var form = $component.data('form');
|
2022-02-16 16:08:48 +00:00
|
|
|
var classesPersister = new ClassesPersister($contents);
|
2022-02-04 11:48:43 +00:00
|
|
|
|
2022-02-15 11:26:17 +00:00
|
|
|
// Replace component with contents.
|
|
|
|
|
// The renderer does this anyway when diffing against the first response
|
2022-02-04 11:48:43 +00:00
|
|
|
$component.replaceWith($contents);
|
2022-02-08 11:33:13 +00:00
|
|
|
|
2022-02-15 11:26:17 +00:00
|
|
|
// Store any classes that should persist through updates
|
|
|
|
|
//
|
|
|
|
|
// Added to allow the use of JS, in main.js, to apply styles which in future could be
|
|
|
|
|
// achieved with the :has pseudo-class. If :has is available in our supported browsers,
|
|
|
|
|
// this can be removed in favour of a CSS-only solution.
|
2022-02-08 11:33:13 +00:00
|
|
|
if ($contents.data('classesToPersist') !== undefined) {
|
|
|
|
|
$contents.data('classesToPersist')
|
|
|
|
|
.split(' ')
|
2022-02-11 15:40:47 +00:00
|
|
|
.forEach(className => classesPersister.addClassName(className));
|
2022-02-08 11:33:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setTimeout(
|
|
|
|
|
() => poll(
|
2022-02-16 16:08:48 +00:00
|
|
|
getRenderer($contents, key, classesPersister),
|
2022-02-04 11:48:43 +00:00
|
|
|
resource,
|
|
|
|
|
getQueue(resource),
|
|
|
|
|
form
|
2022-02-08 11:33:13 +00:00
|
|
|
),
|
|
|
|
|
defaultInterval
|
|
|
|
|
);
|
|
|
|
|
};
|
2016-03-02 17:36:20 +00:00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2020-04-08 17:55:53 +01:00
|
|
|
global.GOVUK.Modules.UpdateContent.calculateBackoff = calculateBackoff;
|
|
|
|
|
|
2019-09-02 14:24:02 +01:00
|
|
|
})(window);
|