bitandblack-matomo-optout
Version:
Custom OptOut in Matomo (Piwik) with AJAX. Doesn't need an iframe.
274 lines (273 loc) • 10.7 kB
JavaScript
"use strict";
/**
* MatomoOptOut
*
* @copyright Copyright (c) 2020, Bit&Black
* @author Tobias Köngeter <hello@bitandblack.com>
* @link https://www.bitandblack.com
*/
exports.__esModule = true;
exports.MatomoOptOut = void 0;
var http_jsonp_1 = require("http-jsonp");
/**
* MatomoOptOut.
*/
var MatomoOptOut = /** @class */ (function () {
/**
* Constructor.
*
* @param matomoRoot The root URL to your Matomo instance.
* @param trackingEnabledElement The html element holding text and checkbox when tracking is enabled.
* @param trackingDisabledElement The html element holding text and checkbox when tracking is disabled.
*/
function MatomoOptOut(matomoRoot, trackingEnabledElement, trackingDisabledElement) {
var _this = this;
/**
* The HTML element for error messages.
*
* @private
*/
this.errorMessage = null;
/**
* The callback when an error appears.
*
* @private
*/
this.errorCallback = null;
/**
* The callback when the status has changed.
*
* @private
*/
this.onStatusChangeCallback = null;
/**
* The CSS class to make an element visible.
*
* @private
*/
this.classElementIsVisible = null;
/**
* The CSS class to make an element invisible.
*
* @private
*/
this.classElementIsInvisible = null;
/**
* If classes should be used to show or hide HTML.
*
* @private
*/
this.useClassesForVisibility = false;
/**
* Returns if a element is child of another element.
*
* @param child
* @param parent
*/
this.isChildOf = function (child, parent) {
var node = child.parentNode;
while (node !== null) {
if (node === parent) {
return true;
}
node = node.parentNode;
}
return false;
};
/**
* Updates the HTML output. This will be called as a callback after requesting the tracking status.
*
* @param response
*/
this.updateHTMLOutput = function (response) {
var status = response.value;
if (true === _this.useClassesForVisibility) {
_this.trackingEnabledElement.classList.remove(_this.classElementIsVisible);
_this.trackingDisabledElement.classList.remove(_this.classElementIsVisible);
_this.trackingEnabledElement.classList.add(_this.classElementIsInvisible);
_this.trackingDisabledElement.classList.add(_this.classElementIsInvisible);
}
else {
_this.trackingEnabledElement.style.display = "none";
_this.trackingDisabledElement.style.display = "none";
}
var inputs = _this.getElements(_this.trackingEnabledElement.querySelectorAll("input[type='checkbox']"), _this.trackingDisabledElement.querySelectorAll("input[type='checkbox']"));
var currentTrackingElement = true === status
? _this.trackingEnabledElement
: _this.trackingDisabledElement;
inputs.forEach(function (input) {
input.checked = status;
});
if (true === _this.useClassesForVisibility) {
currentTrackingElement.classList.remove(_this.classElementIsInvisible);
currentTrackingElement.classList.add(_this.classElementIsVisible);
}
else {
currentTrackingElement.style.display = "block";
}
_this.checkStatusChange(status);
};
/**
* Gets the matomo tracking status.
*
* @param callback The callback when requesting the tracking status.
*/
this.getMatomoTrackingStatus = function (callback) {
http_jsonp_1["default"]({
url: _this.matomoTrackingURL + ".isTracked",
callbackProp: "callback",
callback: callback || {}
});
};
/**
* Sets the tracking status.
*
* @param status The new status
* @param callback The callback when the changing the status
*/
this.setMatomoTrackingStatus = function (status, callback) {
if (callback === void 0) { callback = null; }
var setter = true === status ? ".doTrack" : ".doIgnore";
http_jsonp_1["default"]({
url: _this.matomoTrackingURL + setter,
callbackProp: "callback",
callback: callback || {}
});
};
/**
* Checks if the status changed.
*
* @param statusNew
*/
this.checkStatusChange = function (statusNew) {
if (_this.isTrackingActive === statusNew) {
if (null !== _this.errorMessage) {
if (true === _this.useClassesForVisibility) {
_this.errorMessage.classList.remove(_this.classElementIsInvisible);
_this.errorMessage.classList.add(_this.classElementIsVisible);
}
else {
_this.errorMessage.style.display = "block";
}
}
if (null !== _this.errorCallback) {
_this.errorCallback();
}
return false;
}
_this.isTrackingActive = statusNew;
if (null !== _this.errorMessage) {
if (true === _this.useClassesForVisibility
&& _this.errorMessage.classList.contains(_this.classElementIsVisible)) {
_this.errorMessage.classList.remove(_this.classElementIsVisible);
_this.errorMessage.classList.add(_this.classElementIsInvisible);
}
else if (_this.errorMessage.style.display === "block") {
_this.errorMessage.style.display = "none";
}
}
if (null !== _this.onStatusChangeCallback) {
_this.onStatusChangeCallback(_this.isTrackingActive);
}
};
/**
* Sets an HTML element with a custom error message in case the tracking status could not changed.
*
* @param element
*/
this.setErrorMessage = function (element) {
_this.errorMessage = element;
_this.setErrorMessageVisibility();
return _this;
};
/**
* Sets a custom error callback.
*
* @param errorCallback
*/
this.setErrorCallback = function (errorCallback) {
_this.errorCallback = errorCallback;
return _this;
};
/**
* Sets a custom callback for when the tracking status has changed.
*
* @param onStatusChangeCallback
*/
this.setOnStatusChangeCallback = function (onStatusChangeCallback) {
_this.onStatusChangeCallback = onStatusChangeCallback;
return _this;
};
/**
* Sets CSS classes to handle the visibility of the HTML elements.
*
* @param classElementIsVisible The class name for visible elements.
* @param classElementIsInvisible The class name for invisible elements.
*/
this.setCSSClasses = function (classElementIsVisible, classElementIsInvisible) {
_this.classElementIsVisible = classElementIsVisible;
_this.classElementIsInvisible = classElementIsInvisible;
_this.useClassesForVisibility = true;
_this.setErrorMessageVisibility();
return _this;
};
/**
* Enables a constant check for the current tracking status.
*
* @param seconds The interval in seconds.
*/
this.watchStatusChange = function (seconds) {
clearInterval(_this.interval);
_this.interval = window.setInterval(_this.getMatomoTrackingStatus, seconds * 1000);
return _this;
};
/**
* Concat multiple selectors together.
*
* @param elements
*/
this.getElements = function () {
var elements = [];
for (var _i = 0; _i < arguments.length; _i++) {
elements[_i] = arguments[_i];
}
var elementsAll = [];
elements.forEach(function (element) {
elementsAll = elementsAll.concat(Array.prototype.slice.call(element));
});
return elementsAll;
};
this.setErrorMessageVisibility = function () {
if (true === _this.useClassesForVisibility) {
_this.errorMessage.style.removeProperty("display");
_this.errorMessage.classList.remove(_this.classElementIsVisible, _this.classElementIsInvisible);
_this.errorMessage.classList.add(_this.classElementIsInvisible);
}
else {
_this.errorMessage.style.display = "none";
}
};
this.matomoRoot = matomoRoot.replace(/\/+$/, "");
this.trackingEnabledElement = trackingEnabledElement;
this.trackingDisabledElement = trackingDisabledElement;
this.matomoTrackingURL = this.matomoRoot + "/index.php?module=API&format=json&method=AjaxOptOut";
this.updateHTMLOutput.bind(this);
var inputs = this.getElements(this.trackingEnabledElement.querySelectorAll("input[type='checkbox']"), this.trackingDisabledElement.querySelectorAll("input[type='checkbox']"));
inputs.forEach(function (input) {
input.addEventListener("change", function (event) {
event.stopPropagation();
event.preventDefault();
var doTrack = _this.isChildOf(event.target, _this.trackingDisabledElement);
_this.setMatomoTrackingStatus(doTrack, function () {
_this.getMatomoTrackingStatus(function (response) { return _this.updateHTMLOutput(response); });
});
});
});
/**
* Initial call
*/
this.getMatomoTrackingStatus(function (response) { return _this.updateHTMLOutput(response); });
}
return MatomoOptOut;
}());
exports.MatomoOptOut = MatomoOptOut;