UNPKG

bitandblack-matomo-optout

Version:

Custom OptOut in Matomo (Piwik) with AJAX. Doesn't need an iframe.

274 lines (273 loc) 10.7 kB
"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;