diff --git a/cashtippr.php b/cashtippr.php
index ffcbfea..b8e3f1a 100644
--- a/cashtippr.php
+++ b/cashtippr.php
@@ -3,7 +3,7 @@
* Plugin Name: CashTippr: Bitcoin Cash instant tips & payments for your content
* Plugin URI: https://cashtippr.com/
* Description: Earn money for your content using instant Bitcoin Cash tips (0 conf).
- * Version: 1.1.11
+ * Version: 1.1.13
* Author: Ekliptor
* Author URI: https://twitter.com/ekliptor
* License: GPLv3
@@ -18,7 +18,7 @@
exit ();
}
-define ( 'CASHTIPPR_VERSION', '1.1.11' );
+define ( 'CASHTIPPR_VERSION', '1.1.13' );
define ( 'CASHTIPPR__MINIMUM_WP_VERSION', '4.7' );
define ( 'CASHTIPPR__PLUGIN_DIR', plugin_dir_path ( __FILE__ ) );
diff --git a/classes/Cashtippr.class.php b/classes/Cashtippr.class.php
index bdf62ef..89d5ed0 100644
--- a/classes/Cashtippr.class.php
+++ b/classes/Cashtippr.class.php
@@ -38,6 +38,8 @@ class Cashtippr {
private static $cron_events_hourly = array(
'update_currency_rates'
);
+ /** @var \WC_Log_Handler_File */
+ protected static $logger = null;
/** @var CTIP_Settings */
protected $settings;
@@ -60,6 +62,8 @@ class Cashtippr {
protected $hiddenWords = 0;
/** @var bool */
protected $includedMoneybuttonScript = false;
+ /** @var bool */
+ protected $includedQrCodeTemplate = false;
/** @var string */
protected $qrcodeStatic;
/** @var string */
@@ -68,7 +72,7 @@ class Cashtippr {
protected $loadingImage;
private function __construct() {
- $this->qrcodeStatic = plugins_url( 'img/qrcode.svg', CASHTIPPR__PLUGIN_DIR . 'cashtippr.php' );
+ $this->qrcodeStatic = plugins_url( 'img/qrstatic.png', CASHTIPPR__PLUGIN_DIR . 'cashtippr.php' );
$this->closeImage = plugins_url( 'img/close50.png', CASHTIPPR__PLUGIN_DIR . 'cashtippr.php' );
$this->loadingImage = plugins_url( 'img/loading.gif', CASHTIPPR__PLUGIN_DIR . 'cashtippr.php' );
}
@@ -338,7 +342,7 @@ public function generateQrCodeForAddress(string $txid, string $address, float $a
$qrHash = hash('sha512', $txid);
$fileName = sprintf('data/temp/qr/%s.png', $qrHash);
$fileLocal = CASHTIPPR__PLUGIN_DIR . $fileName;
- $fileUrl = plugins_url( $fileName, CASHTIPPR__PLUGIN_DIR . 'slp-payments.php' );
+ $fileUrl = plugins_url( $fileName, CASHTIPPR__PLUGIN_DIR . 'cashtippr.php' );
if (file_exists($fileLocal) === true)
return $fileUrl; // use it from cache
@@ -359,7 +363,7 @@ public function generateQrCode(string $txid): string {
$qrHash = hash('sha512', $txid);
$fileName = sprintf('data/temp/qr/%s.png', $qrHash);
$fileLocal = CASHTIPPR__PLUGIN_DIR . $fileName;
- $fileUrl = plugins_url( $fileName, CASHTIPPR__PLUGIN_DIR . 'slp-payments.php' );
+ $fileUrl = plugins_url( $fileName, CASHTIPPR__PLUGIN_DIR . 'cashtippr.php' );
if (file_exists($fileLocal) === true)
return $fileUrl; // use it from cache
@@ -426,6 +430,7 @@ public function showTipprButton($attrs, $content = null, $tag = "") {
$btnConf['addQrCode'] = $btnConf['isRestricted'] === false && $btnConf['tag'] === 'tippr_button' && $btnConf['unit'] === 'USD'; // TODO QR code support for more currencies
$btnConf['btnText'] = __('Send', 'ekliptor');
$includedMoneybuttonScript = $this->getIncludedMoneybuttonScript();
+ $includedQrCodeTemplate = $this->includedQrCodeTemplate;
ob_start();
switch ($tag) {
case "tippr_button":
@@ -480,6 +485,7 @@ public function showTipprButton($attrs, $content = null, $tag = "") {
ob_end_clean();
//$this->setIncludedMoneybuttonScript($includedMoneybuttonScript);
$this->setIncludedMoneybuttonScript(true);
+ $this->includedQrCodeTemplate = $includedQrCodeTemplate;
wp_enqueue_script( 'badger-wallet', Cashtippr::BADGER_WALLET_JS, array(), CASHTIPPR_VERSION, true );
return $docHtml;
}
@@ -729,6 +735,14 @@ public function notifyError($subject, $error, $data = null) {
public static function notifyErrorExt($subject, $error, $data = null) {
global $wpdb;
+ if (defined('WC_LOG_DIR') === true) {
+ if (static::$logger === null)
+ static::$logger = new \WC_Log_Handler_File();
+ $logMsg = $subject . "\r\n" . print_r($error, true);
+ if ($data !== null)
+ $logMsg .= "\r\n" . print_r($data, true);
+ static::$logger->handle(time(), 'error', $logMsg, array('source' => 'cashtippr'));
+ }
if (static::DEBUG === false)
return;
$table = static::getTableName("messages_system");
diff --git a/classes/CashtipprAdmin.class.php b/classes/CashtipprAdmin.class.php
index c477b13..b1c1689 100644
--- a/classes/CashtipprAdmin.class.php
+++ b/classes/CashtipprAdmin.class.php
@@ -88,6 +88,8 @@ public function showAllSettings() {
public function initCurrentScreen(WP_Screen $screen) {
// id: [id] => toplevel_page_cashtippr or cashtippr_page_cashtippr_shout <- this is always the hook
+ if (strpos($screen->base, 'cashtippr') === false)
+ return;
$this->pageHook = $screen->base;
add_action( $this->pageHook . '_settings_page_boxes', array( $this, 'showAllSettings' ) );
diff --git a/classes/DatabaseMigration.php b/classes/DatabaseMigration.php
index ea28540..fb21421 100644
--- a/classes/DatabaseMigration.php
+++ b/classes/DatabaseMigration.php
@@ -2,7 +2,7 @@
namespace Ekliptor\Cashtippr;
class DatabaseMigration {
- /** @var string */
+ /** @var string Latest DB version. Only updated with plugin version if there are migrations. */
protected $lastVersion;
/** @var string */
protected $currentVersion;
@@ -11,23 +11,28 @@ class DatabaseMigration {
public function __construct(string $lastVersion, string $currentVersion) {
if (!$lastVersion)
- $lastVersion = '1';
+ $lastVersion = '1'; // when we added migration. shouldn't be needed
$this->lastVersion = $lastVersion;
$this->currentVersion = $currentVersion;
}
public static function checkAndMigrate() {
- add_action('plugins_loaded', function() {
- $lastVersion = get_option('cashtippr_version');
- if ($lastVersion === CASHTIPPR_VERSION)
- return;
+ $lastVersion = get_option('cashtippr_version');
+ if ($lastVersion === CASHTIPPR_VERSION)
+ return;
+ add_action('plugins_loaded', function() use ($lastVersion) {
$migrate = new DatabaseMigration($lastVersion, CASHTIPPR_VERSION);
- if ($migrate->ensureLatestVersion() === false) { // TODO can be switched to migrate() call just like in plugin_activcation()
- \Cashtippr::notifyErrorExt("Error ensuring latest DB version on migration", $migrate->getLastError());
- return;
+ try {
+ if ($migrate->migrate() === false) {
+ \Cashtippr::notifyErrorExt("Error ensuring latest DB version on migration", $migrate->getLastError());
+ return;
+ }
+ update_option( 'cashtippr_version', CASHTIPPR_VERSION ); // should already be done in main plugin class
+ }
+ catch (\Exception $e) {
+ \Cashtippr::notifyErrorExt("Exception during DB migration: " . get_class(), $e->getMessage());
}
- update_option ( 'cashtippr_version', CASHTIPPR_VERSION );
- });
+ }, 200); // load after other plugins
}
public function migrate(): bool {
@@ -52,6 +57,7 @@ public function migrate(): bool {
/**
* Fix function if migrate() didn't work on some instances previously.
*/
+ /*
public function ensureLatestVersion(): bool {
$table = \Cashtippr::getTableName('transactions');
if ($this->columnExists($table, 'amount') === false) {
@@ -60,6 +66,7 @@ public function ensureLatestVersion(): bool {
}
return true;
}
+ */
public function getLastError(): array {
return $this->lastError;
diff --git a/img/qrcode.svg b/img/qrcode.svg
deleted file mode 100644
index 3c3dac7..0000000
--- a/img/qrcode.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/readme.txt b/readme.txt
index 5c13dbb..5965d43 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,9 +3,9 @@ Contributors: ekliptor
Tags: bitcoin, bch, ecommerce, e-commerce, blog, tipping, store, sales, sell, shop, bitcoin cash, btc
Donate link: https://cashtippr.com/
Requires at least: 4.7
-Tested up to: 5.2
+Tested up to: 5.3
Requires PHP: 7.1
-Stable tag: 1.1.11
+Stable tag: 1.1.13
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -20,6 +20,7 @@ Earn money for your content using instant Bitcoin Cash tips (0 conf).
* earn tips from your content
* add tip buttons for voluntary donations or
* hide parts of your posts to require users to tip
+* AdBlock detection: show custom message to AdBlock users
* 0 coding skills required
Check the demo at [CashTippr.com](https://cashtippr.com/ "CashtTippr") and send me a tip to support development.
diff --git a/tpl/admin/metaboxAds.php b/tpl/admin/metaboxAds.php
index 98cc479..fe35561 100644
--- a/tpl/admin/metaboxAds.php
+++ b/tpl/admin/metaboxAds.php
@@ -59,7 +59,7 @@
),
$this->makeCheckbox(
'adblockDisable',
- esc_html__( 'Disable page for AdBlock users', 'ekliptor' ) . ' ' . $adblockDisableInfo,
+ esc_html__( 'Disable page for AdBlock users with 0 tips', 'ekliptor' ) . ' ' . $adblockDisableInfo,
'',
false
),
diff --git a/tpl/css/cashtippr.css b/tpl/css/cashtippr.css
index b1b4575..cb3f0a6 100644
--- a/tpl/css/cashtippr.css
+++ b/tpl/css/cashtippr.css
@@ -29,6 +29,13 @@
.ct-button-text {
font-weight: bold;
}
+.ct-qrcode-img-wrap {
+ line-height: 1.0;
+ padding-right: 5px;
+}
+.ct-qr-btn-txt {
+ padding-left: 4px;
+}
.money-button-iframe-wrapper {
}
diff --git a/tpl/js/bundle.js b/tpl/js/bundle.js
index 42fe2ac..1cdcb6f 100644
--- a/tpl/js/bundle.js
+++ b/tpl/js/bundle.js
@@ -1,2 +1,2 @@
-!function(t){var e={};function o(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}o.m=t,o.c=e,o.d=function(t,e,i){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)o.d(i,n,function(e){return t[e]}.bind(null,n));return i},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=2)}([function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=function(){return function(t,e){void 0===e&&(e=null),this.cashtippr=t,this.webHelpers=e||this.cashtippr.getWebHelpers()}}();e.AbstractModule=i},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=o(3),n=o(4),r=o(5),s=o(6),a=o(7),c=o(8),p=o(9),d=o(11),l=o(12),u=function(){function t(e,o){var u=this;this.window=e,this.$=o,this.config=this.window.cashtipprCfg||{},this.config.consentCookieName=t.CONSENT_COOKIE_NAME,this.config.confirmCookiesMsg=t.CONFIRM_COOKIES_MSG,this.config.confirmCookiesBtn=t.CONFIRM_COOKIES_BTN,this.webHelpers=new n.WebHelpers(this.window,this.$,this.config),this.tooltips=new i.Tooltips(this,this.webHelpers),this.adminControls=new l.AdminControls(this),this.badger=new c.BadgerWallet(this,this.webHelpers,!0),this.qr=new a.QrCode(this,this.webHelpers),this.adBlockDetect=new d.AdBlockDetect(this,this.webHelpers),this.blurryImage=new r.BlurryImage(this,this.webHelpers),this.shout=new s.Shout(this,this.webHelpers),this.woocommerce=new p.Woocommerce(this,this.webHelpers),this.$(this.window.document).ready(function(t){u.adminControls.init(),u.webHelpers.checkCookieConsent()})}return t.toSatoshis=function(t){return Math.floor(1e8*t)},t.prototype.getConfig=function(){return this.config},t.prototype.getTooltips=function(){return this.tooltips},t.prototype.getWebHelpers=function(){return this.webHelpers},t.prototype.getPluginPaymentID=function(t){return t.attr("id").replace(/^ct-btn-wrap-/,"")},t.prototype.addCopyInputListeners=function(){var t=this;this.$(".ct-copy-field").click(function(e){e.preventDefault();var o=t.$(e.target).parent().find("input[type='text']");o.select();try{t.window.document.execCommand("copy")}catch(t){}o.select()}),this.$("#ct-qrcode-form input[type='text']").click(function(e){t.$(e.target).select()}),!0===this.webHelpers.isAppleIOS()&&this.$("#ct-qrcode-form .ct-copy-field").addClass("hidden")},t.CONSENT_COOKIE_NAME="ct-ck",t.CONFIRM_COOKIES_MSG="#ct-cookieMsg",t.CONFIRM_COOKIES_BTN="#ct-confirmCookies",t}();e.CashTippr=u},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=new(o(1).CashTippr)(window,jQuery);window.cashtippr=i},function(t,e,o){"use strict";var i,n=this&&this.__extends||(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},function(t,e){function o(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)});Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){function e(e,o){return t.call(this,e,o)||this}return n(e,t),e.prototype.initToolTips=function(){var t,e=this.cashtippr.window,o=this.cashtippr.$,i=this,n={debug:!1},r=0,s=!1,a=function(t,e){void 0===e&&(e=!1),e=e||!1;var i="pointerdown.tsfTT touchstart.tsfTT click.tsfTT",n=o(t);e?(n.off("mousemove mouseleave mouseout ct-tooltip-update"),o(document.body).off(i)):(n.on({mousemove:p,mouseleave:d,mouseout:d}),o(document.body).off(i).on(i,l)),n.on("ct-tooltip-update",c)},c=function(t){if(t.target.classList.contains("ct-tooltip-item")){var e=t.target.querySelector(".ct-tooltip-text");e instanceof Element&&(e.innerHTML=t.target.dataset.desc)}},p=function(t){var e=o(t.target),i=e.find(".ct-tooltip"),n=i.find(".ct-tooltip-arrow"),r=i.data("overflow"),s=i.data("overflowDir");if(r=parseInt(r,10),r=isNaN(r)?0:-Math.round(r))n.css(s,r+"px");else{var a=t.originalEvent&&t.originalEvent.pageX||t.pageX,c=e.closest(".ct-tooltip-wrap"),p=a-c.offset().left-8,d=i.find(".ct-tooltip-text-wrap"),l=d.outerWidth(!0),u=i.data("adjust"),h=i.data("adjustDir"),f=l-16-7;if(u=parseInt(u,10),u=isNaN(u)?0:Math.round(u))if(p+=u="left"===h?-u:u,f-u>c.outerWidth(!0))f=d.find(".ct-tooltip-text").outerWidth(!0)-16-7;p<=7?n.css("left","7px"):p>=f?n.css("left",f+"px"):n.css("left",p+"px")}},d=function(t){var e;s||(o(t.target).find(".ct-tooltip").remove(),e=t.target,a(e,!0))},l=function(t){s=!0,clearTimeout(r),r=setTimeout(function(){s=!1},250);var e,i=o(t.target);if(i.hasClass("ct-tooltip-item")&&(e=i.find(".ct-tooltip")),!e){var n=i.children(".ct-tooltip-item");n.length&&(e=n.find(".ct-tooltip"))}e&&e.length?o(".ct-tooltip").not(e).remove():o(".ct-tooltip").remove()},u=function(t){if(!s){var e=!1;switch(t.type){case"mouseenter":break;case"pointerdown":case"touchstart":e=!0}if(t.target.classList.contains("ct-tooltip-item"))e&&l(t),function(t){var e=o(t.target),i=t.target.dataset.desc;if(i&&0===e.find("div").length){t.target.title="";var n=o('
');e.append(n);var r=e.closest(".ct-tooltip-boundary");r=r.length&&r||o(document.body);var s=e.outerHeight()+9,a=n.offset().top-s;r.offset().top-(r.prop("scrolltop")||0)>a?(n.addClass("ct-tooltip-down"),n.css("top",s+"px")):n.css("bottom",s+"px");var c=e.closest(".ct-tooltip-wrap"),p=n.find(".ct-tooltip-text-wrap"),d=p.find(".ct-tooltip-text"),l=c.width(),u=p.outerWidth(!0),h=d.outerWidth(!0),f=p.offset().left,g=f+h,w=r.offset().left-(r.prop("scrollLeft")||0),m=w+r.outerWidth();if(fm){var b,y;(b=m-g-l-12)<-(y=parseInt(p.css("flex-basis"),10))&&(b=-y),n.css("left",b+"px"),n.data("overflow",b),n.data("overflowDir","left")}else if(l<42)n.css("left","-15px"),n.data("overflow",-15),n.data("overflowDir","left");else if(l>u){var v=(t.originalEvent&&t.originalEvent.pageX||t.pageX)-c.offset().left-u/2,_=v+u;v<0?v=0:_>l&&(v=l-h),n.css("left",v+"px"),n.data("adjust",v),n.data("adjustDir","left")}}}(t),p(t),a(t.target);else{var i=t.target.querySelector(".ct-tooltip-item:hover"),r=new o.Event(t.type);r.pageX=t.originalEvent&&t.originalEvent.pageX||t.pageX,i?(n.debug&&console.log("Tooltip event warning: delegation"),o(i).trigger(r)):(n.debug&&console.log("Tooltip event warning: bubbling"),o(t.target).closest(".ct-tooltip-wrap").find(".ct-tooltip-item:hover").trigger(r))}t.stopPropagation()}},h=function(){var t=o(".ct-tooltip-wrap");t.off("mouseenter pointerdown touchstart"),t.on("mouseenter pointerdown touchstart",".ct-tooltip-item",u)};h(),o(e).on("ct-reset-tooltips",h),t=o("#wpcontent"),i.addTooltipBoundary(t)},e.prototype.addTooltipBoundary=function(t){jQuery(t).addClass("ct-tooltip-boundary")},e.prototype._triggerTooltipReset=function(){jQuery(window).trigger("ct-reset-tooltips")},e.prototype._triggerTooltipUpdate=function(t){jQuery(t).trigger("ct-tooltip-update")},e}(o(0).AbstractModule);e.Tooltips=r},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=function(){function t(t,e,o){this.cssSelectors=[],this.window=t,this.$=e,this.config=o}return t.prototype.getBrowserLang=function(){return this.window.navigator.language.substr(0,2).toLowerCase()},t.prototype.getCookie=function(t){var e,o,i,n=this.window.document.cookie.split(";");for(e=0;e0&&"\\"===t.charAt(i-1))i++;else{if(-1===(n=t.indexOf("}",i))){this.log("Can not find end position while translating HTML");break}var r=t.substring(i+1,n),s=null;if("tr:"===r.substring(0,3)){var a=r.substring(3);s=this.tr(a)}else if("object"==typeof e){var c=e[r];void 0!==c&&(s="boolean"==typeof o&&o?c:this.escapeOutput(c))}if(null!==s){var p=new RegExp("\\{"+r+"\\}","g");t=t.replace(p,s)}else if(null!==r.match("^[A-Za-z0-9_]+$")){this.log("No translation found for place holder: "+r);p=new RegExp("\\{"+r+"\\}","g");t=t.replace(p,"MISSING: "+this.escapeOutput(r))}else i+=r.length}return t=t.replace(/\\\\\\{/,"{")},t.prototype.escapeOutput=function(t,e){return void 0===e&&(e=!0),"string"!=typeof t?t:(t=t.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'"),void 0!==e&&!0!==e||(t=t.replace(/\r?\n/g,"
")),t)},t.prototype.escapeRegex=function(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},t.prototype.tr=function(t){return t},t.prototype.log=function(t){"object"==typeof this.window.console&&"function"==typeof this.window.console.log&&this.window.console.log(arguments)},t.prototype.isAppleIOS=function(){return/iPad|iPhone|iPod/.test(this.window.navigator.userAgent)&&!this.window.MSStream},t.prototype.getAllCssSelectors=function(t){if(void 0===t&&(t=!0),!0===t&&0!==this.cssSelectors.length)return this.cssSelectors;this.cssSelectors=[];try{for(var e=new RegExp("^"+this.escapeRegex(this.window.document.location.origin),"i"),o=0;o0&&setTimeout(i.checkPaymentStatus.bind(i,!0),1e3),0!==i.cashtippr.$("#ct-qrcode-form").length&&i.addPaymentFormEvents(i.cashtippr.$("#ct-qrcode-form").eq(0))}),i}return n(e,t),e.prototype.onPayment=function(t){this.sendPaymentForValidation(t)},e.prototype.sendPaymentForValidation=function(t){var e=this,o=this.cashtippr.$(".ct-btn-wrap-top"),i={txid:t.txid,dbtxid:this.cashtippr.getPluginPaymentID(o),am:t.amount};this.webHelpers.getApi("/wp-json/cashtippr-wc/v1/validate",i,function(t){1===t.data.length&&e.cashtippr.window.document.location.assign(t.data[0].url)})},e.prototype.addPaymentFormEvents=function(t){this.cashtippr.addCopyInputListeners()},e.prototype.checkPaymentStatus=function(t){var e=this;void 0===t&&(t=!0);var o=this.cashtippr.getConfig();if(!(void 0===o.nonce||o.orderID<=0)){var i={n:o.nonce,oid:o.orderID};this.webHelpers.getApi("/wp-json/cashtippr-wc/v1/order-status",i,function(t){if(o.checkPaymentIntervalSec>0&&setTimeout(e.checkPaymentStatus.bind(e,!0),1e3*o.checkPaymentIntervalSec),!0!==t.error){if(t.data&&t.data.length>=1){var i=Object.assign(new r.Order,t.data[0]);if("paid"===i.status)return void e.showPaymentReceived();if(i.bchAmountReceived>0)return void e.showPartialPayment(i)}}else e.cashtippr.window.console.error("Error checking BCH payment status: %s",t.errorMsg)})}},e.prototype.showPartialPayment=function(t){var e=this.cashtippr.getConfig().paymentCommaDigits,o=t.calculateRemaningAmount().toFixed(e);this.cashtippr.$("#ct-pay-amount-txt").text()!==o&&(this.cashtippr.$("#ct-pay-amount-txt").text(o),this.cashtippr.$("#ct-payment-remaining").fadeIn("slow"),this.cashtippr.$("#ct-qr-code-image").attr("src",t.qrcode),this.cashtippr.$("#ct-address").val(t.uri),this.cashtippr.$("#ct-pay-app").attr("href",t.uri),this.cashtippr.$(".ct-badger-button").attr("data-satoshis",t.calculateRemaningAmount()))},e.prototype.showPaymentReceived=function(){this.cashtippr.$("#ct-payment-status").text(this.cashtippr.getConfig().paidTxt),this.cashtippr.$("#ct-payment-pending, #ct-pay-instructions, .ct-payment-option").fadeOut("slow")},e.prototype.addButtonLinkClass=function(){var t=this.cashtippr.$("#ct-pay-app");0!==t.length&&(!0===this.webHelpers.isExistingCssSelector("a.btn")?t.addClass("btn"):!0===this.webHelpers.isExistingCssSelector("a.button")?t.addClass("button"):t.addClass("ct-button-link"))},e}(o(0).AbstractModule);e.Woocommerce=s},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=function(){function t(){}return t.prototype.calculateRemaningAmount=function(){return Math.max(0,this.bchAmount-this.bchAmountReceived)},t}();e.Order=i},function(t,e,o){"use strict";var i,n=this&&this.__extends||(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},function(t,e){function o(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)});Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){function e(e,o){var i=t.call(this,e,o)||this;return i.cashtippr.$(i.cashtippr.window.document).ready(function(t){!0!==i.cashtippr.$("body").hasClass("wp-admin")&&(!1===i.cashtippr.getConfig().detect_adblock||i.cashtippr.getConfig().tipAmount>0||i.loadLib())}),i}return n(e,t),e.prototype.loadLib=function(){var t=this,e=this.cashtippr.window;if(!0===this.cashtippr.getConfig().adblockNoConflict||void 0===e.fuckAdBlock&&void 0===e.FuckAdBlock){e.fuckAdBlock=null;var o=this.cashtippr.window.document.createElement("script");o.onload=function(){e.fuckAdBlock=new e.FuckAdBlock({checkOnLoad:!0,resetOnEnd:!0,loopCheckTime:55,loopMaxNumber:6,baitClass:"pub_300x250 pub_300x250m pub_728x90 text-ad textAd banner_ad text_ad text_ads text-ads text-ad-links",baitStyle:"width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important;",debug:!1}),e.fuckAdBlock.onDetected(t.onAdBlockDetected.bind(t)),e.fuckAdBlock.onNotDetected(t.onAdBlockNotDetected.bind(t))},o.onerror=function(){t.onAdBlockDetected()},o.integrity="sha256-f5s2H2XgAi/4M/ipOOw8pxmim1o7cTOWL72QbKu0lSc=",o.crossOrigin="anonymous",o.src=this.cashtippr.getConfig().adBlockScript,this.cashtippr.window.document.head.appendChild(o)}else this.onAdBlockDetected()},e.prototype.onPayment=function(t){this.cashtippr.window.document.location.reload()},e.prototype.onAdBlockNotDetected=function(t){void 0===t&&(t=!1),!1===t&&this.loadAdFrame()},e.prototype.onAdBlockDetected=function(t){var e=this;void 0===t&&(t=!1);var o=this.cashtippr.window;"function"==typeof o&&o.ctipAdblockDetected();var i=!0===this.cashtippr.getConfig().adblockDisable;if(!0===i){var n=this.webHelpers.translate(this.cashtippr.$("#ct-modal-adblock-dialog-tpl").html(),{dialog_class:"dialog-adbl",title:"",text:""});this.cashtippr.$("body").append(n)}var r={msg:!0===i?"1":"0"};this.webHelpers.getApi("/wp-json/cashtippr/v1/get-post-notice",r,function(t){if(e.cashtippr.$(".dialog-adbl").remove(),!0===i)if(!0!==t.error){var o=t.data[0].post.title,n=t.data[0].post.content,r=e.webHelpers.translate(e.cashtippr.$("#ct-modal-adblock-dialog-tpl").html(),{dialog_class:"dialog-adbl",title:o,text:n},!0);e.cashtippr.$("body").append(r),e.cashtippr.$("#ct-modal-adblock-dialog .ct-qrcode-wrap").css("display","none")}else e.cashtippr.$("#ct-adbl-title").text(t.errorMsg)})},e.prototype.loadAdFrame=function(){var t=this;if(!0!==e.loadedAdFrame){e.loadedAdFrame=!0;var o=this.cashtippr.window.document.createElement("script"),i=this.cashtippr.window;o.onload=function(){setTimeout(function(){!0!==i.ctipAdblockOk?t.onAdBlockDetected(!0):t.onAdBlockNotDetected(!0)},100)},o.onerror=function(){t.onAdBlockDetected(!0)},o.integrity="sha256-YrKAEKiVnq8uOpnEBYck9fbjgMBcJgjFcltgKGhtpkA=",o.crossOrigin="anonymous",o.src=this.cashtippr.getConfig().adFrameBaitUrl,this.cashtippr.window.document.head.appendChild(o)}},e.loadedAdFrame=!1,e}(o(0).AbstractModule);e.AdBlockDetect=r},function(t,e,o){"use strict";var i,n=this&&this.__extends||(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},function(t,e){function o(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)});Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.init=function(){var t=this;-1!==this.cashtippr.$("body").attr("class").indexOf("cashtippr")&&(this.cashtippr.getTooltips().initToolTips(),this.cashtippr.$(this.cashtippr.window.document).ready(function(e){t.enableAdblockSettings()}),this.cashtippr.$("#cashtippr_settings\\[detect_adblock\\]").on("change",function(e){t.enableAdblockSettings()}))},e.prototype.enableAdblockSettings=function(){var t="#cashtippr_settings\\[adblockDisable\\], #cashtippr_settings\\[adblock_page\\], #cashtippr_settings\\[adblockNoConflict\\]";!1===(!0===this.cashtippr.$("#cashtippr_settings\\[detect_adblock\\]").is(":checked"))?this.cashtippr.$(t).prop("disabled",!0):this.cashtippr.$(t).removeProp("disabled")},e}(o(0).AbstractModule);e.AdminControls=r}]);
+!function(t){var e={};function o(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}o.m=t,o.c=e,o.d=function(t,e,i){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)o.d(i,n,function(e){return t[e]}.bind(null,n));return i},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=2)}([function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=function(){return function(t,e){void 0===e&&(e=null),this.cashtippr=t,this.webHelpers=e||this.cashtippr.getWebHelpers()}}();e.AbstractModule=i},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=o(3),n=o(4),r=o(5),s=o(6),a=o(7),c=o(8),p=o(9),d=o(11),l=o(12),u=function(){function t(e,o){var u=this;this.window=e,this.$=o,this.config=this.window.cashtipprCfg||{},this.config.consentCookieName=t.CONSENT_COOKIE_NAME,this.config.confirmCookiesMsg=t.CONFIRM_COOKIES_MSG,this.config.confirmCookiesBtn=t.CONFIRM_COOKIES_BTN,this.webHelpers=new n.WebHelpers(this.window,this.$,this.config),this.tooltips=new i.Tooltips(this,this.webHelpers),this.adminControls=new l.AdminControls(this),this.badger=new c.BadgerWallet(this,this.webHelpers,!0),this.qr=new a.QrCode(this,this.webHelpers),this.adBlockDetect=new d.AdBlockDetect(this,this.webHelpers),this.blurryImage=new r.BlurryImage(this,this.webHelpers),this.shout=new s.Shout(this,this.webHelpers),this.woocommerce=new p.Woocommerce(this,this.webHelpers),this.$(this.window.document).ready(function(t){u.adminControls.init(),u.webHelpers.checkCookieConsent()})}return t.toSatoshis=function(t){return Math.floor(1e8*t)},t.prototype.getConfig=function(){return this.config},t.prototype.getTooltips=function(){return this.tooltips},t.prototype.getWebHelpers=function(){return this.webHelpers},t.prototype.getPluginPaymentID=function(t){return t.attr("id").replace(/^ct-btn-wrap-/,"")},t.prototype.addCopyInputListeners=function(){var t=this;this.$(".ct-copy-field").click(function(e){e.preventDefault();var o=t.$(e.target).parent().find("input[type='text']");o.select();try{t.window.document.execCommand("copy")}catch(t){}o.select()}),this.$("#ct-qrcode-form input[type='text']").click(function(e){t.$(e.target).select()}),!0===this.webHelpers.isAppleIOS()&&this.$("#ct-qrcode-form .ct-copy-field").addClass("hidden")},t.CONSENT_COOKIE_NAME="ct-ck",t.CONFIRM_COOKIES_MSG="#ct-cookieMsg",t.CONFIRM_COOKIES_BTN="#ct-confirmCookies",t}();e.CashTippr=u},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=new(o(1).CashTippr)(window,jQuery);window.cashtippr=i},function(t,e,o){"use strict";var i,n=this&&this.__extends||(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},function(t,e){function o(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)});Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){function e(e,o){return t.call(this,e,o)||this}return n(e,t),e.prototype.initToolTips=function(){var t,e=this.cashtippr.window,o=this.cashtippr.$,i=this,n={debug:!1},r=0,s=!1,a=function(t,e){void 0===e&&(e=!1),e=e||!1;var i="pointerdown.tsfTT touchstart.tsfTT click.tsfTT",n=o(t);e?(n.off("mousemove mouseleave mouseout ct-tooltip-update"),o(document.body).off(i)):(n.on({mousemove:p,mouseleave:d,mouseout:d}),o(document.body).off(i).on(i,l)),n.on("ct-tooltip-update",c)},c=function(t){if(t.target.classList.contains("ct-tooltip-item")){var e=t.target.querySelector(".ct-tooltip-text");e instanceof Element&&(e.innerHTML=t.target.dataset.desc)}},p=function(t){var e=o(t.target),i=e.find(".ct-tooltip"),n=i.find(".ct-tooltip-arrow"),r=i.data("overflow"),s=i.data("overflowDir");if(r=parseInt(r,10),r=isNaN(r)?0:-Math.round(r))n.css(s,r+"px");else{var a=t.originalEvent&&t.originalEvent.pageX||t.pageX,c=e.closest(".ct-tooltip-wrap"),p=a-c.offset().left-8,d=i.find(".ct-tooltip-text-wrap"),l=d.outerWidth(!0),u=i.data("adjust"),h=i.data("adjustDir"),f=l-16-7;if(u=parseInt(u,10),u=isNaN(u)?0:Math.round(u))if(p+=u="left"===h?-u:u,f-u>c.outerWidth(!0))f=d.find(".ct-tooltip-text").outerWidth(!0)-16-7;p<=7?n.css("left","7px"):p>=f?n.css("left",f+"px"):n.css("left",p+"px")}},d=function(t){var e;s||(o(t.target).find(".ct-tooltip").remove(),e=t.target,a(e,!0))},l=function(t){s=!0,clearTimeout(r),r=setTimeout(function(){s=!1},250);var e,i=o(t.target);if(i.hasClass("ct-tooltip-item")&&(e=i.find(".ct-tooltip")),!e){var n=i.children(".ct-tooltip-item");n.length&&(e=n.find(".ct-tooltip"))}e&&e.length?o(".ct-tooltip").not(e).remove():o(".ct-tooltip").remove()},u=function(t){if(!s){var e=!1;switch(t.type){case"mouseenter":break;case"pointerdown":case"touchstart":e=!0}if(t.target.classList.contains("ct-tooltip-item"))e&&l(t),function(t){var e=o(t.target),i=t.target.dataset.desc;if(i&&0===e.find("div").length){t.target.title="";var n=o('');e.append(n);var r=e.closest(".ct-tooltip-boundary");r=r.length&&r||o(document.body);var s=e.outerHeight()+9,a=n.offset().top-s;r.offset().top-(r.prop("scrolltop")||0)>a?(n.addClass("ct-tooltip-down"),n.css("top",s+"px")):n.css("bottom",s+"px");var c=e.closest(".ct-tooltip-wrap"),p=n.find(".ct-tooltip-text-wrap"),d=p.find(".ct-tooltip-text"),l=c.width(),u=p.outerWidth(!0),h=d.outerWidth(!0),f=p.offset().left,g=f+h,m=r.offset().left-(r.prop("scrollLeft")||0),w=m+r.outerWidth();if(fw){var y,b;(y=w-g-l-12)<-(b=parseInt(p.css("flex-basis"),10))&&(y=-b),n.css("left",y+"px"),n.data("overflow",y),n.data("overflowDir","left")}else if(l<42)n.css("left","-15px"),n.data("overflow",-15),n.data("overflowDir","left");else if(l>u){var v=(t.originalEvent&&t.originalEvent.pageX||t.pageX)-c.offset().left-u/2,_=v+u;v<0?v=0:_>l&&(v=l-h),n.css("left",v+"px"),n.data("adjust",v),n.data("adjustDir","left")}}}(t),p(t),a(t.target);else{var i=t.target.querySelector(".ct-tooltip-item:hover"),r=new o.Event(t.type);r.pageX=t.originalEvent&&t.originalEvent.pageX||t.pageX,i?(n.debug&&console.log("Tooltip event warning: delegation"),o(i).trigger(r)):(n.debug&&console.log("Tooltip event warning: bubbling"),o(t.target).closest(".ct-tooltip-wrap").find(".ct-tooltip-item:hover").trigger(r))}t.stopPropagation()}},h=function(){var t=o(".ct-tooltip-wrap");t.off("mouseenter pointerdown touchstart"),t.on("mouseenter pointerdown touchstart",".ct-tooltip-item",u)};h(),o(e).on("ct-reset-tooltips",h),t=o("#wpcontent"),i.addTooltipBoundary(t)},e.prototype.addTooltipBoundary=function(t){jQuery(t).addClass("ct-tooltip-boundary")},e.prototype._triggerTooltipReset=function(){jQuery(window).trigger("ct-reset-tooltips")},e.prototype._triggerTooltipUpdate=function(t){jQuery(t).trigger("ct-tooltip-update")},e}(o(0).AbstractModule);e.Tooltips=r},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=function(){function t(t,e,o){this.cssSelectors=[],this.window=t,this.$=e,this.config=o}return t.prototype.getBrowserLang=function(){return this.window.navigator.language.substr(0,2).toLowerCase()},t.prototype.getCookie=function(t){var e,o,i,n=this.window.document.cookie.split(";");for(e=0;e0&&"\\"===t.charAt(i-1))i++;else{if(-1===(n=t.indexOf("}",i))){this.log("Can not find end position while translating HTML");break}var r=t.substring(i+1,n),s=null;if("tr:"===r.substring(0,3)){var a=r.substring(3);s=this.tr(a)}else if("object"==typeof e){var c=e[r];void 0!==c&&(s="boolean"==typeof o&&o?c:this.escapeOutput(c))}if(null!==s){var p=new RegExp("\\{"+r+"\\}","g");t=t.replace(p,s)}else if(null!==r.match("^[A-Za-z0-9_]+$")){this.log("No translation found for place holder: "+r);p=new RegExp("\\{"+r+"\\}","g");t=t.replace(p,"MISSING: "+this.escapeOutput(r))}else i+=r.length}return t=t.replace(/\\\\\\{/,"{")},t.prototype.escapeOutput=function(t,e){return void 0===e&&(e=!0),"string"!=typeof t?t:(t=t.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'"),void 0!==e&&!0!==e||(t=t.replace(/\r?\n/g,"
")),t)},t.prototype.escapeRegex=function(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},t.prototype.tr=function(t){return t},t.prototype.log=function(t){"object"==typeof this.window.console&&"function"==typeof this.window.console.log&&this.window.console.log(arguments)},t.prototype.isAppleIOS=function(){return/iPad|iPhone|iPod/.test(this.window.navigator.userAgent)&&!this.window.MSStream},t.prototype.getAllCssSelectors=function(t){if(void 0===t&&(t=!0),!0===t&&0!==this.cssSelectors.length)return this.cssSelectors;this.cssSelectors=[];try{for(var e=new RegExp("^"+this.escapeRegex(this.window.document.location.origin),"i"),o=0;o0&&setTimeout(i.checkPaymentStatus.bind(i,!0),1e3),0!==i.cashtippr.$("#ct-qrcode-form").length&&i.addPaymentFormEvents(i.cashtippr.$("#ct-qrcode-form").eq(0))}),i}return n(e,t),e.prototype.onPayment=function(t){this.sendPaymentForValidation(t)},e.prototype.sendPaymentForValidation=function(t){var e=this,o=this.cashtippr.$(".ct-btn-wrap-top"),i={txid:t.txid,dbtxid:this.cashtippr.getPluginPaymentID(o),am:t.amount};this.webHelpers.getApi("/wp-json/cashtippr-wc/v1/validate",i,function(t){1===t.data.length&&e.cashtippr.window.document.location.assign(t.data[0].url)})},e.prototype.addPaymentFormEvents=function(t){this.cashtippr.addCopyInputListeners()},e.prototype.checkPaymentStatus=function(t){var e=this;void 0===t&&(t=!0);var o=this.cashtippr.getConfig();if(!(void 0===o.nonce||o.orderID<=0)){var i={n:o.nonce,oid:o.orderID};this.webHelpers.getApi("/wp-json/cashtippr-wc/v1/order-status",i,function(i){if(!0===t&&o.checkPaymentIntervalSec>0&&(clearTimeout(e.checkServerPaymentTimerID),e.checkServerPaymentTimerID=setTimeout(e.checkPaymentStatus.bind(e,!0),1e3*o.checkPaymentIntervalSec)),!0!==i.error){if(i.data&&i.data.length>=1){var n=Object.assign(new r.Order,i.data[0]);if("paid"===n.status)return void e.showPaymentReceived();if(n.bchAmountReceived>0)return void e.showPartialPayment(n)}}else e.cashtippr.window.console.error("Error checking BCH payment status: %s",i.errorMsg)})}},e.prototype.showPartialPayment=function(t){var e=this.cashtippr.getConfig().paymentCommaDigits,o=t.calculateRemaningAmount().toFixed(e);this.cashtippr.$("#ct-pay-amount-txt").text()!==o&&(this.cashtippr.$("#ct-pay-amount-txt").text(o),this.cashtippr.$("#ct-payment-remaining").fadeIn("slow"),this.cashtippr.$("#ct-qr-code-image").attr("src",t.qrcode),this.cashtippr.$("#ct-address").val(t.uri),this.cashtippr.$("#ct-pay-app").attr("href",t.uri),this.cashtippr.$(".ct-badger-button").attr("data-satoshis",t.calculateRemaningAmount()))},e.prototype.showPaymentReceived=function(){!0!==this.fullyPaid&&(this.fullyPaid=!0,clearTimeout(this.checkServerPaymentTimerID),this.cashtippr.$("#ct-payment-status").text(this.cashtippr.getConfig().paidTxt),this.cashtippr.$("#ct-payment-pending, #ct-pay-instructions, .ct-payment-option").fadeOut("slow"))},e.prototype.addButtonLinkClass=function(){var t=this.cashtippr.$("#ct-pay-app");0!==t.length&&(!0===this.webHelpers.isExistingCssSelector("a.btn")?t.addClass("btn"):!0===this.webHelpers.isExistingCssSelector("a.button")?t.addClass("button"):t.addClass("ct-button-link"))},e}(o(0).AbstractModule);e.Woocommerce=s},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=function(){function t(){}return t.prototype.calculateRemaningAmount=function(){return Math.max(0,this.bchAmount-this.bchAmountReceived)},t}();e.Order=i},function(t,e,o){"use strict";var i,n=this&&this.__extends||(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},function(t,e){function o(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)});Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){function e(e,o){var i=t.call(this,e,o)||this;return i.cashtippr.$(i.cashtippr.window.document).ready(function(t){!0!==i.cashtippr.$("body").hasClass("wp-admin")&&(!1===i.cashtippr.getConfig().detect_adblock||i.cashtippr.getConfig().tipAmount>0||i.loadLib())}),i}return n(e,t),e.prototype.loadLib=function(){var t=this,e=this.cashtippr.window;if(!0===this.cashtippr.getConfig().adblockNoConflict||void 0===e.fuckAdBlock&&void 0===e.FuckAdBlock){e.fuckAdBlock=null;var o=this.cashtippr.window.document.createElement("script");o.onload=function(){e.fuckAdBlock=new e.FuckAdBlock({checkOnLoad:!0,resetOnEnd:!0,loopCheckTime:55,loopMaxNumber:6,baitClass:"pub_300x250 pub_300x250m pub_728x90 text-ad textAd banner_ad text_ad text_ads text-ads text-ad-links",baitStyle:"width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important;",debug:!1}),e.fuckAdBlock.onDetected(t.onAdBlockDetected.bind(t)),e.fuckAdBlock.onNotDetected(t.onAdBlockNotDetected.bind(t))},o.onerror=function(){t.onAdBlockDetected()},o.integrity="sha256-f5s2H2XgAi/4M/ipOOw8pxmim1o7cTOWL72QbKu0lSc=",o.crossOrigin="anonymous",o.src=this.cashtippr.getConfig().adBlockScript,this.cashtippr.window.document.head.appendChild(o)}else this.onAdBlockDetected()},e.prototype.onPayment=function(t){this.cashtippr.window.document.location.reload()},e.prototype.onAdBlockNotDetected=function(t){void 0===t&&(t=!1),!1===t&&this.loadAdFrame()},e.prototype.onAdBlockDetected=function(t){var e=this;void 0===t&&(t=!1);var o=this.cashtippr.window;"function"==typeof o&&o.ctipAdblockDetected();var i=!0===this.cashtippr.getConfig().adblockDisable;if(!0===i){var n=this.webHelpers.translate(this.cashtippr.$("#ct-modal-adblock-dialog-tpl").html(),{dialog_class:"dialog-adbl",title:"",text:""});this.cashtippr.$("body").append(n)}var r={msg:!0===i?"1":"0"};this.webHelpers.getApi("/wp-json/cashtippr/v1/get-post-notice",r,function(t){if(e.cashtippr.$(".dialog-adbl").remove(),!0===i)if(!0!==t.error){var o=t.data[0].post.title,n=t.data[0].post.content,r=e.webHelpers.translate(e.cashtippr.$("#ct-modal-adblock-dialog-tpl").html(),{dialog_class:"dialog-adbl",title:o,text:n},!0);e.cashtippr.$("body").append(r),e.cashtippr.$("#ct-modal-adblock-dialog .ct-qrcode-wrap").css("display","none")}else e.cashtippr.$("#ct-adbl-title").text(t.errorMsg)})},e.prototype.loadAdFrame=function(){var t=this;if(!0!==e.loadedAdFrame){e.loadedAdFrame=!0;var o=this.cashtippr.window.document.createElement("script"),i=this.cashtippr.window;o.onload=function(){setTimeout(function(){!0!==i.ctipAdblockOk?t.onAdBlockDetected(!0):t.onAdBlockNotDetected(!0)},100)},o.onerror=function(){t.onAdBlockDetected(!0)},o.integrity="sha256-YrKAEKiVnq8uOpnEBYck9fbjgMBcJgjFcltgKGhtpkA=",o.crossOrigin="anonymous",o.src=this.cashtippr.getConfig().adFrameBaitUrl,this.cashtippr.window.document.head.appendChild(o)}},e.loadedAdFrame=!1,e}(o(0).AbstractModule);e.AdBlockDetect=r},function(t,e,o){"use strict";var i,n=this&&this.__extends||(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},function(t,e){function o(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)});Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.init=function(){var t=this;-1!==this.cashtippr.$("body").attr("class").indexOf("cashtippr")&&(this.cashtippr.getTooltips().initToolTips(),this.cashtippr.$(this.cashtippr.window.document).ready(function(e){t.enableAdblockSettings()}),this.cashtippr.$("#cashtippr_settings\\[detect_adblock\\]").on("change",function(e){t.enableAdblockSettings()}))},e.prototype.enableAdblockSettings=function(){var t="#cashtippr_settings\\[adblockDisable\\], #cashtippr_settings\\[adblock_page\\], #cashtippr_settings\\[adblockNoConflict\\]";!1===(!0===this.cashtippr.$("#cashtippr_settings\\[detect_adblock\\]").is(":checked"))?this.cashtippr.$(t).prop("disabled",!0):this.cashtippr.$(t).removeProp("disabled")},e}(o(0).AbstractModule);e.AdminControls=r}]);
//# sourceMappingURL=bundle.js.map
\ No newline at end of file
diff --git a/tpl/js/bundle.js.map b/tpl/js/bundle.js.map
index da5d257..ea393d3 100644
--- a/tpl/js/bundle.js.map
+++ b/tpl/js/bundle.js.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/AbstractModule.ts","webpack:///./src/CashTippr.ts","webpack:///./index.ts","webpack:///./src/admin/Tooltips.ts","webpack:///./src/WebHelpers.ts","webpack:///./src/BlurryImage.ts","webpack:///./src/Shout.ts","webpack:///./src/QrCode.ts","webpack:///./src/BadgerWallet.ts","webpack:///./src/Woocommerce.ts","webpack:///./src/structs/Order.ts","webpack:///./src/AdBlockDetect.ts","webpack:///./src/admin/AdminControls.ts"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","AbstractModule","cashtippr","webHelpers","this","getWebHelpers","Tooltips_1","WebHelpers_1","BlurryImage_1","Shout_1","QrCode_1","BadgerWallet_1","Woocommerce_1","AdBlockDetect_1","AdminControls_1","CashTippr","window","$","_this","config","consentCookieName","CONSENT_COOKIE_NAME","confirmCookiesMsg","CONFIRM_COOKIES_MSG","confirmCookiesBtn","CONFIRM_COOKIES_BTN","WebHelpers","tooltips","Tooltips","adminControls","AdminControls","badger","BadgerWallet","qr","QrCode","adBlockDetect","AdBlockDetect","blurryImage","BlurryImage","shout","Shout","woocommerce","Woocommerce","document","ready","init","checkCookieConsent","toSatoshis","bch","Math","floor","getConfig","getTooltips","getPluginPaymentID","paymentControlsWrapper","attr","replace","addCopyInputListeners","click","event","preventDefault","inputEl","target","parent","find","select","execCommand","err","isAppleIOS","addClass","jQuery","_super","__extends","initToolTips","e","that","tsfL10n","debug","touchBuffer","inTouchBuffer","setEvents","unset","touchEvents","$target","off","body","on","mousemove","mouseMove","mouseleave","mouseLeave","mouseout","touchRemove","updateDesc","classList","contains","tooltipText","querySelector","Element","innerHTML","dataset","desc","$tooltip","$arrow","overflow","data","overflowDir","parseInt","isNaN","round","css","pagex","originalEvent","pageX","$hoverItemWrap","closest","mousex","offset","left","arrowWidth","$textWrap","textWrapWidth","outerWidth","adjust","adjustDir","boundaryRight","arrowBoundary","remove","clearTimeout","setTimeout","$keepBalloon","hasClass","$children","children","length","not","loadToolTip","isTouch","type","$hoverItem","title","append","$boundary","tooltipHeight","outerHeight","tooltipTop","top","prop","$innerText","hoverItemWrapWidth","width","textWidth","textLeft","textRight","boundaryLeft","horIndent","basis","indent","right","mouseEnter","item","_event","Event","console","log","trigger","stopPropagation","initTooltips","$wrap","addTooltipBoundary","_triggerTooltipReset","_triggerTooltipUpdate","cssSelectors","getBrowserLang","navigator","language","substr","toLowerCase","getCookie","c_name","x","y","ARRcookies","cookie","split","indexOf","decodeURI","setCookie","expireDays","date","Date","getTime","cookieLifeDays","toUTCString","cookiePath","removeCookie","confirmCookies","fromBase64","atob","error","toBase64","btoa","translate","text","variables","safeHtml","toString","start","end","charAt","placeHolder","substring","translation","tr","textPiece","escapeOutput","reg","RegExp","match","convertNewlines","escapeRegex","str","args","arguments","test","userAgent","MSStream","getAllCssSelectors","cached","originRegex","location","origin","styleSheets","sheet","href","rules","u","selectorText","push","imports","isExistingCssSelector","selector","selectors","getApi","path","callback","dataType","undefined","url","siteUrl","textStatus","jqXHR","scheduleUpdateTimerID","updateRemainingChars","addEventListeners","addConfirmDeleteMessages","onPayment","payment","domID","submit","forms","each","index","formEl","val","remaining","fadeOut","fadeIn","keyup","scheduleCharsUpdate","change","question","confirm","showQrDialog","paymentButtonWrapper","txid","paymentCtrlWrapper","amount","params","am","dialog","html","dialog_class","errorMsg","CashTippr_1","globalCallbacks","onBadgerPayment","sendPaymentReceived","updateButtonAmount","isInstalled","web4bch","isLoggedIn","wnd","defaultAccount","buttonData","buttonDataObj","JSON","parse","buttonId","show_search_engines","ajaxConfirm","days","postHide","res","reload","open","INSTALL_URL","alert","badgerLocked","sendPayment","button","Web4Bch","currentProvider","btn","txParams","to","from","sendTransaction","keep","keepTransaction","btnContainer","amountNewUserCurrency","parseFloat","Number","NaN","currency","display_currency","amountSats","rate","Order_1","addButtonLinkClass","checkPaymentIntervalSec","checkPaymentStatus","addPaymentFormEvents","eq","sendPaymentForValidation","firstButton","dbtxid","assign","paymentFormEl","repeat","nonce","orderID","oid","order","Order","status","showPaymentReceived","bchAmountReceived","showPartialPayment","numDecimals","paymentCommaDigits","remainingAmount","calculateRemaningAmount","toFixed","qrcode","uri","paidTxt","buttons","max","bchAmount","detect_adblock","tipAmount","loadLib","adblockNoConflict","fuckAdBlock","FuckAdBlock","importFAB","createElement","onload","checkOnLoad","resetOnEnd","loopCheckTime","loopMaxNumber","baitClass","baitStyle","onDetected","onAdBlockDetected","onNotDetected","onAdBlockNotDetected","onerror","integrity","crossOrigin","src","adBlockScript","head","appendChild","secondTry","loadAdFrame","ctipAdblockDetected","disablePage","adblockDisable","msg","postTitle","post","postContent","content","loadedAdFrame","importScript","ctipAdblockOk","adFrameBaitUrl","enableAdblockSettings","adblockSettingsSelector","is","removeProp"],"mappings":"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","file":"bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 2);\n","import {CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\n\n\nexport class AbstractModule {\n protected cashtippr: CashTippr;\n protected webHelpers: WebHelpers;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers = null) {\n this.cashtippr = cashtippr;\n this.webHelpers = webHelpers ? webHelpers : this.cashtippr.getWebHelpers();\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n}\n","import {Tooltips} from \"./admin/Tooltips\";\nimport {WebHelpers, WebHelpersConfig} from \"./WebHelpers\";\nimport {BlurryImage} from \"./BlurryImage\";\nimport {Shout} from \"./Shout\";\nimport {QrCode} from \"./QrCode\";\nimport {BadgerWallet} from \"./BadgerWallet\";\nimport {Woocommerce} from \"./Woocommerce\";\nimport {AdBlockDetect} from \"./AdBlockDetect\";\nimport {AdminControls} from \"./admin/AdminControls\";\n\nexport interface BitcoinCashConversionRate {\n [fiatCurrency: string]: number;\n}\nexport interface CashTipprConfig extends WebHelpersConfig {\n // same keys as in php\n show_search_engines: boolean;\n display_currency: string;\n rate: BitcoinCashConversionRate;\n ajaxConfirm?: boolean;\n keepTransaction?: boolean; // keep the transaction in mysql so that plugin addons can use them after payment\n paymentCommaDigits: number;\n\n detect_adblock: boolean;\n adblockDisable: boolean;\n adBlockScript: string;\n adblockNoConflict: boolean;\n adFrameBaitUrl: string;\n tipAmount: number;\n\n // present after order is placed\n orderID?: number;\n nonce?: string;\n checkPaymentIntervalSec: number;\n\n // localizations\n badgerLocked: string;\n paidTxt: string;\n}\n\nexport interface AbstractPayment {\n domID: string; // the full ID of the wrapper div for the payment control\n txid: string; // the blockchain transaction ID/hash\n amount: number; // the amount in the website's currency (USD,...)\n}\n\nexport interface CashtipprApiRes {\n error: boolean;\n errorMsg: string;\n data: any[];\n}\n\nexport class CashTippr {\n protected static readonly CONSENT_COOKIE_NAME = \"ct-ck\";\n protected static readonly CONFIRM_COOKIES_MSG = \"#ct-cookieMsg\";\n protected static readonly CONFIRM_COOKIES_BTN = \"#ct-confirmCookies\";\n // TODO separate entryPoints + classes for admin + public code? but tooltips and other admin stuff can be used publicly too (and is quite small)\n\n public readonly window: Window;\n public readonly $: JQueryStatic;\n public readonly badger: BadgerWallet;\n public readonly qr: QrCode;\n public readonly adBlockDetect: AdBlockDetect;\n public readonly blurryImage: BlurryImage;\n public readonly shout: Shout;\n public readonly woocommerce: Woocommerce;\n\n protected config: CashTipprConfig;\n protected webHelpers: WebHelpers;\n protected adminControls: AdminControls;\n protected tooltips: Tooltips;\n\n constructor(window: Window, $: JQueryStatic) {\n this.window = window;\n this.$ = $;\n this.config = this.window['cashtipprCfg'] || {};\n this.config.consentCookieName = CashTippr.CONSENT_COOKIE_NAME;\n this.config.confirmCookiesMsg = CashTippr.CONFIRM_COOKIES_MSG;\n this.config.confirmCookiesBtn = CashTippr.CONFIRM_COOKIES_BTN;\n\n this.webHelpers = new WebHelpers(this.window, this.$, this.config);\n this.tooltips = new Tooltips(this, this.webHelpers);\n this.adminControls = new AdminControls(this);\n this.badger = new BadgerWallet(this, this.webHelpers, true);\n this.qr = new QrCode(this, this.webHelpers);\n this.adBlockDetect = new AdBlockDetect(this, this.webHelpers);\n this.blurryImage = new BlurryImage(this, this.webHelpers);\n this.shout = new Shout(this, this.webHelpers);\n this.woocommerce = new Woocommerce(this, this.webHelpers);\n this.$(this.window.document).ready(($) => {\n this.adminControls.init();\n this.webHelpers.checkCookieConsent();\n });\n }\n\n public static toSatoshis(bch: number) {\n return Math.floor(bch * 100000000);\n }\n\n public getConfig() {\n return this.config;\n }\n\n public getTooltips() {\n return this.tooltips;\n }\n\n public getWebHelpers() {\n return this.webHelpers;\n }\n\n public getPluginPaymentID(paymentControlsWrapper: JQuery) {\n return paymentControlsWrapper.attr(\"id\").replace(/^ct-btn-wrap-/, \"\");\n }\n\n public addCopyInputListeners() {\n this.$(\".ct-copy-field\").click((event) => {\n event.preventDefault();\n const inputEl = this.$(event.target).parent().find(\"input[type='text']\");\n //let text = inputEl.val();\n inputEl.select();\n try {\n this.window.document.execCommand(\"copy\");\n }\n catch (err) { // try-catch shouldn't be needed except for some really old browsers\n }\n inputEl.select(); // ensure it's selected again for iOS devices to copy it manually. not working, remove?\n });\n this.$(\"#ct-qrcode-form input[type='text']\").click((event) => {\n this.$(event.target).select();\n });\n if (this.webHelpers.isAppleIOS() === true) // copy to clipboard button doesn't work there\n this.$(\"#ct-qrcode-form .ct-copy-field\").addClass(\"hidden\");\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n}\n","import {CashTippr} from \"./src/CashTippr\";\n\nlet cashtippr = new CashTippr(window, jQuery);\n(window as any).cashtippr = cashtippr;","import {CashTippr} from \"../CashTippr\";\nimport {AbstractModule} from \"../AbstractModule\";\nimport {WebHelpers} from \"../WebHelpers\";\n\nexport class Tooltips extends AbstractModule {\n protected cashtippr: CashTippr;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n }\n\n /**\n * Initializes status bar hover entries.\n */\n public initToolTips() {\n const window = this.cashtippr.window;\n const jQuery = this.cashtippr.$;\n const that = this;\n const tsfL10n = { // TODO localization\n states: {\n debug: false\n }\n }\n\n let touchBuffer = 0,\n inTouchBuffer = false;\n\n const setTouchBuffer = function() {\n inTouchBuffer = true;\n clearTimeout( touchBuffer );\n touchBuffer = setTimeout( function() {\n inTouchBuffer = false;\n }, 250 );\n }\n\n const setEvents = function( target, unset = false ) {\n\n unset = unset || false;\n\n let touchEvents = 'pointerdown.tsfTT touchstart.tsfTT click.tsfTT',\n $target = jQuery( target );\n\n if ( unset ) {\n $target.off( 'mousemove mouseleave mouseout ct-tooltip-update' );\n jQuery( document.body ).off( touchEvents );\n } else {\n $target.on( {\n 'mousemove' : mouseMove,\n 'mouseleave' : mouseLeave,\n 'mouseout' : mouseLeave,\n } );\n jQuery( document.body ).off( touchEvents ).on( touchEvents, touchRemove );\n }\n\n $target.on( 'ct-tooltip-update', updateDesc );\n }\n const unsetEvents = function( target ) {\n setEvents( target, true );\n }\n const updateDesc = function( event ) {\n if ( event.target.classList.contains( 'ct-tooltip-item' ) ) {\n let tooltipText = event.target.querySelector( '.ct-tooltip-text' );\n if ( tooltipText instanceof Element )\n tooltipText.innerHTML = event.target.dataset.desc;\n }\n }\n const mouseEnter = function( event ) {\n let $hoverItem = jQuery( event.target ),\n desc = event.target.dataset.desc;\n\n if ( desc && 0 === $hoverItem.find( 'div' ).length ) {\n //= Remove any titles attached.\n event.target.title = \"\";\n\n let $tooltip = jQuery(\n ''\n );\n $hoverItem.append( $tooltip );\n\n let $boundary = $hoverItem.closest( '.ct-tooltip-boundary' );\n $boundary = $boundary.length && $boundary || jQuery( document.body );\n\n //= 9 = arrow (8) + shadow (1)\n let tooltipHeight = $hoverItem.outerHeight() + 9,\n tooltipTop = $tooltip.offset().top - tooltipHeight,\n boundaryTop = $boundary.offset().top - ( $boundary.prop( 'scrolltop' ) || 0 );\n\n if ( boundaryTop > tooltipTop ) {\n $tooltip.addClass( 'ct-tooltip-down' );\n $tooltip.css( 'top', tooltipHeight + 'px' );\n } else {\n $tooltip.css( 'bottom', tooltipHeight + 'px' );\n }\n\n let $hoverItemWrap = $hoverItem.closest( '.ct-tooltip-wrap' ),\n $textWrap = $tooltip.find( '.ct-tooltip-text-wrap' ),\n $innerText = $textWrap.find( '.ct-tooltip-text' ),\n hoverItemWrapWidth = $hoverItemWrap.width(),\n textWrapWidth = $textWrap.outerWidth( true ),\n textWidth = $innerText.outerWidth( true ),\n textLeft = $textWrap.offset().left,\n textRight = textLeft + textWidth,\n boundaryLeft = $boundary.offset().left - ( $boundary.prop( 'scrollLeft' ) || 0 ),\n boundaryRight = boundaryLeft + $boundary.outerWidth();\n\n //= RTL and LTR are normalized to abide to left.\n let direction = 'left';\n\n if ( textLeft < boundaryLeft ) {\n //= Overflown over left boundary (likely window)\n //= Add indent relative to boundary. 24px width of arrow / 2 = 12 middle\n let horIndent = boundaryLeft - textLeft + 12,\n basis = parseInt( $textWrap.css( 'flex-basis' ), 10 );\n\n /**\n * If the overflow is greater than the tooltip flex basis,\n * the tooltip was grown. Shrink it back to basis and use that.\n */\n if ( horIndent < -basis )\n horIndent = -basis;\n\n $tooltip.css( direction, horIndent + 'px' );\n $tooltip.data( 'overflow', horIndent );\n $tooltip.data( 'overflowDir', direction );\n } else if ( textRight > boundaryRight ) {\n //= Overflown over right boundary (likely window)\n //= Add indent relative to boundary. Add 12px for visual appeal.\n let horIndent = boundaryRight - textRight - hoverItemWrapWidth - 12,\n basis = parseInt( $textWrap.css( 'flex-basis' ), 10 );\n\n /**\n * If the overflow is greater than the tooltip flex basis,\n * the tooltip was grown. Shrink it back to basis and use that.\n */\n if ( horIndent < -basis )\n horIndent = -basis;\n\n $tooltip.css( direction, horIndent + 'px' );\n $tooltip.data( 'overflow', horIndent );\n $tooltip.data( 'overflowDir', direction );\n } else if ( hoverItemWrapWidth < 42 ) {\n //= Small tooltip container. Add indent to make it visually appealing.\n let indent = -15;\n $tooltip.css( direction, indent + 'px' );\n $tooltip.data( 'overflow', indent );\n $tooltip.data( 'overflowDir', direction );\n } else if ( hoverItemWrapWidth > textWrapWidth ) {\n //= Wrap is bigger than tooltip. Adjust accordingly.\n let pagex = event.originalEvent && event.originalEvent.pageX || event.pageX, // iOS touch support,\n hoverItemLeft = $hoverItemWrap.offset().left,\n center = pagex - hoverItemLeft,\n left = center - textWrapWidth / 2,\n right = left + textWrapWidth;\n\n if ( left < 0 ) {\n //= Don't overflow left.\n left = 0;\n } else if ( right > hoverItemWrapWidth ) {\n //= Don't overflow right.\n //* Use textWidth instead of textWrapWidth as it gets squashed in flex.\n left = hoverItemWrapWidth - textWidth;\n }\n\n $tooltip.css( direction, left + 'px' );\n $tooltip.data( 'adjust', left );\n $tooltip.data( 'adjustDir', direction );\n }\n }\n }\n const mouseMove = function( event ) {\n let $target = jQuery( event.target ),\n $tooltip = $target.find( '.ct-tooltip' ),\n $arrow = $tooltip.find( '.ct-tooltip-arrow' ),\n overflow = $tooltip.data( 'overflow' ),\n overflowDir = $tooltip.data( 'overflowDir' );\n\n overflow = parseInt( overflow, 10 );\n overflow = isNaN( overflow ) ? 0 : - Math.round( overflow );\n\n if ( overflow ) {\n //= Static arrow based on static overflow.\n $arrow.css( overflowDir, overflow + \"px\" );\n } else {\n let pagex = event.originalEvent && event.originalEvent.pageX || event.pageX, // iOS touch support\n arrowBoundary = 7,\n arrowWidth = 16,\n $hoverItemWrap = $target.closest( '.ct-tooltip-wrap' ),\n mousex = pagex - $hoverItemWrap.offset().left - arrowWidth / 2,\n originalMousex = mousex,\n $textWrap = $tooltip.find( '.ct-tooltip-text-wrap' ),\n textWrapWidth = $textWrap.outerWidth( true ),\n adjust = $tooltip.data( 'adjust' ),\n adjustDir = $tooltip.data( 'adjustDir' ),\n boundaryRight = textWrapWidth - arrowWidth - arrowBoundary;\n\n //= mousex is skewed, adjust.\n adjust = parseInt( adjust, 10 );\n adjust = isNaN( adjust ) ? 0 : Math.round( adjust );\n if ( adjust ) {\n adjust = 'left' === adjustDir ? -adjust : adjust;\n mousex = mousex + adjust;\n\n //= Use textWidth for right boundary if adjustment exceeds.\n if ( boundaryRight - adjust > $hoverItemWrap.outerWidth( true ) ) {\n let $innerText = $textWrap.find( '.ct-tooltip-text' ),\n textWidth = $innerText.outerWidth( true );\n boundaryRight = textWidth - arrowWidth - arrowBoundary;\n }\n }\n\n if ( mousex <= arrowBoundary ) {\n //* Overflown left.\n $arrow.css( 'left', arrowBoundary + \"px\" );\n } else if ( mousex >= boundaryRight ) {\n //* Overflown right.\n $arrow.css( 'left', boundaryRight + \"px\" );\n } else {\n //= Somewhere in the middle.\n $arrow.css( 'left', mousex + \"px\" );\n }\n }\n }\n const mouseLeave = function( event ) {\n\n //* @see touchMove\n if ( inTouchBuffer )\n return;\n\n jQuery( event.target ).find( '.ct-tooltip' ).remove();\n unsetEvents( event.target );\n }\n /**\n * ^^^\n * These two methods conflict eachother in EdgeHTML.\n * Thusly, touch buffer.\n * vvv\n */\n const touchRemove = function( event ) {\n\n //* @see mouseLeave\n setTouchBuffer();\n\n let itemSelector = '.ct-tooltip-item',\n balloonSelector = '.ct-tooltip';\n\n let $target = jQuery( event.target ),\n $keepBalloon;\n\n if ( $target.hasClass( 'ct-tooltip-item' ) ) {\n $keepBalloon = $target.find( balloonSelector );\n }\n if ( ! $keepBalloon ) {\n let $children = $target.children( itemSelector );\n if ( $children.length ) {\n $keepBalloon = $children.find( balloonSelector );\n }\n }\n\n if ( $keepBalloon && $keepBalloon.length ) {\n //= Remove all but this.\n jQuery( balloonSelector ).not( $keepBalloon ).remove();\n } else {\n //= Remove all.\n jQuery( balloonSelector ).remove();\n }\n }\n\n /**\n * Loads tooltips within wrapper.\n * @function\n */\n const loadToolTip = function( event ) {\n\n if ( inTouchBuffer )\n return;\n\n let isTouch = false;\n\n switch ( event.type ) {\n case 'mouseenter' :\n //= Most likely, thus placed first.\n break;\n\n case 'pointerdown' :\n case 'touchstart' :\n isTouch = true;\n break;\n\n default :\n break;\n }\n\n if ( event.target.classList.contains( 'ct-tooltip-item' ) ) {\n //= Removes previous items and sets buffer.\n isTouch && touchRemove( event );\n\n mouseEnter( event );\n //= Initiate placement directly for Windows Touch or when overflown.\n mouseMove( event );\n\n setEvents( event.target );\n } else {\n //= Delegate or bubble, and go back to this method with the correct item.\n let item = event.target.querySelector( '.ct-tooltip-item:hover' ),\n _event = new jQuery.Event( event.type );\n\n _event.pageX = event.originalEvent && event.originalEvent.pageX || event.pageX;\n\n if ( item ) {\n if ( tsfL10n.states.debug ) console.log( 'Tooltip event warning: delegation' );\n jQuery( item ).trigger( _event );\n } else {\n if ( tsfL10n.states.debug ) console.log( 'Tooltip event warning: bubbling' );\n jQuery( event.target ).closest( '.ct-tooltip-wrap' ).find( '.ct-tooltip-item:hover' ).trigger( _event );\n }\n }\n\n //* Stop further propagation.\n event.stopPropagation();\n }\n\n /**\n * Initializes tooltips.\n * @function\n */\n const initTooltips = function() {\n let $wrap = jQuery( '.ct-tooltip-wrap' );\n\n $wrap.off( 'mouseenter pointerdown touchstart' );\n $wrap.on( 'mouseenter pointerdown touchstart', '.ct-tooltip-item', loadToolTip );\n }\n initTooltips();\n jQuery( window ).on( 'ct-reset-tooltips', initTooltips );\n\n (function() {\n let e = jQuery( '#wpcontent' );\n that.addTooltipBoundary( e );\n })();\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n /**\n * Adds tooltip boundaries.\n */\n protected addTooltipBoundary( e ) {\n jQuery( e ).addClass( 'ct-tooltip-boundary' );\n }\n\n /**\n * Triggers tooltip reset.\n */\n protected _triggerTooltipReset() { // not used yet\n jQuery( window ).trigger( 'ct-reset-tooltips' );\n }\n\n /**\n * Triggers active tooltip update.\n */\n protected _triggerTooltipUpdate(item) { // not used yet\n jQuery( item ).trigger( 'ct-tooltip-update' );\n }\n}\n","\nexport interface WebHelpersConfig {\n cookieLifeDays: number;\n cookiePath: string;\n siteUrl: string;\n\n // DOM ids of elements of cookie consent message\n consentCookieName: string;\n confirmCookiesMsg: string;\n confirmCookiesBtn: string;\n}\n\nexport class WebHelpers {\n public readonly window: Window;\n public readonly $: JQueryStatic;\n\n protected config: WebHelpersConfig;\n protected cssSelectors: string[] = [];\n\n constructor(window: Window, $: JQueryStatic, config: WebHelpersConfig) {\n this.window = window;\n this.$ = $;\n this.config = config;\n }\n\n public getBrowserLang() {\n return this.window.navigator.language.substr(0, 2).toLowerCase();\n }\n\n public getCookie(c_name: string) {\n let i, x, y;\n let ARRcookies = this.window.document.cookie.split(\";\");\n for (i = 0; i < ARRcookies.length; i++)\n {\n x = ARRcookies[i].substr(0, ARRcookies[i].indexOf(\"=\"));\n y = ARRcookies[i].substr(ARRcookies[i].indexOf(\"=\") + 1);\n x = x.replace(/^\\s+|\\s+$/g,\"\");\n if (x == c_name)\n return decodeURI(y);\n }\n return null;\n }\n\n public setCookie(name: string, value: any, expireDays: number) {\n let date = new Date();\n date = new Date(date.getTime()+1000*60*60*24* (expireDays ? expireDays : this.config.cookieLifeDays));\n //document.cookie = name + \"=\" + value + \"; expires=\" + date.toGMTString() + \"; path=\" + pageData.cookiePath + \"; domain=.\" + location.host;\n this.window.document.cookie = name + \"=\" + value + \"; expires=\" + date.toUTCString() + \"; path=\" + this.config.cookiePath;\n }\n\n public removeCookie(name: string) {\n //document.cookie = name + \"=; expires=Thu, 02 Jan 1970 00:00:00 UTC; path=\" + pageData.cookiePath + \"; domain=.\" + location.host;\n this.window.document.cookie = name + \"=; expires=Thu, 02 Jan 1970 00:00:00 UTC; path=\" + this.config.cookiePath;\n }\n\n public checkCookieConsent() {\n this.$(this.config.confirmCookiesBtn).click(() => {\n this.confirmCookies();\n });\n if (this.getCookie(this.config.consentCookieName) !== null)\n this.$(this.config.confirmCookiesMsg).remove(); // we recently showed the cookie confirm message. some pages might still be in browser cache\n }\n\n public fromBase64(data: string) {\n if (typeof this.window.atob !== \"function\") {\n this.window.console.error(\"Base64 decoding is not supported in your browser\");\n return \"\";\n }\n return this.window.atob(data);\n }\n\n public toBase64(data: string) {\n if (typeof this.window.btoa !== \"function\") {\n this.window.console.error(\"Base64 encoding is not supported in your browser\");\n return \"\";\n }\n return this.window.btoa(data);\n }\n\n /**\n * Populate a html template\n * @param text {String}: The html template (or just normal text with variables)\n * @param variables {Object}: the key-value pairs with variables names and their content to be set in text\n * @param safeHtml {boolean, default false}: don't escape html characters if set to true\n * @returns {String} the translated html\n */\n public translate(text: string, variables: any, safeHtml: boolean = false) {\n if (typeof text !== \"string\") {\n try {\n // @ts-ignore\n text = text.toString();\n }\n catch (e) {\n this.log(\"Text to translate is not a string\");\n return text;\n }\n }\n let start = 0, end = 0;\n while ((start = text.indexOf(\"{\", start)) !== -1)\n {\n if (start > 0 && text.charAt(start-1) === \"\\\\\") { // escaped javascript code beginning\n start++;\n continue;\n }\n end = text.indexOf(\"}\", start);\n if (end === -1) {\n this.log(\"Can not find end position while translating HTML\");\n break;\n }\n let placeHolder = text.substring(start+1, end);\n let translation = null;\n if (placeHolder.substring(0, 3) === \"tr:\") {\n let key = placeHolder.substring(3);\n //translation = this.tr(key.toUpperCase());\n translation = this.tr(key);\n }\n else if (typeof variables === \"object\") {\n let textPiece = variables[placeHolder];\n if (typeof textPiece !== \"undefined\") {\n if (typeof safeHtml === \"boolean\" && safeHtml)\n translation = textPiece;\n else\n translation = this.escapeOutput(textPiece);\n }\n }\n if (translation !== null) {\n let reg = new RegExp(\"\\\\{\" + placeHolder + \"\\\\}\", \"g\");\n text = text.replace(reg, translation);\n }\n else if (placeHolder.match(\"^[A-Za-z0-9_]+$\") !== null) {\n this.log(\"No translation found for place holder: \" + placeHolder);\n let reg = new RegExp(\"\\\\{\" + placeHolder + \"\\\\}\", \"g\");\n text = text.replace(reg, \"MISSING: \" + this.escapeOutput(placeHolder));\n }\n else\n start += placeHolder.length;\n }\n text = text.replace(/\\\\\\\\\\\\{/, \"{\");\n return text;\n }\n\n public escapeOutput(text: string, convertNewlines: boolean = true) {\n if (typeof text !== \"string\")\n return text;\n text = text.replace(/&/g, \"&\").replace(//g, \">\").replace(/\"/g, \""\").replace(/'/g, \"'\");\n if (typeof convertNewlines === \"undefined\" || convertNewlines === true)\n text = text.replace(/\\r?\\n/g, \"
\");\n return text;\n }\n\n public escapeRegex(str: string) {\n return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n }\n\n public tr(key: string) {\n //if (typeof language[key] === \"undefined\")\n //return \"MISSING: \" + key;\n //return language[key];\n //return i18next.t(key) // will just print the key if it doesn't exist and debug is disabled\n return key; // we don't have client-side translation support on this WP plugin yet. just return the key // TODO do we need this if we make our plugin use more ajax?\n }\n\n public log(args) {\n if (//typeof pageData.debugLog !== \"boolean\" || pageData.debugLog === false || // TODO add in CashTipprConfig\n typeof this.window.console !== \"object\" || typeof this.window.console.log !== \"function\")\n return;\n this.window.console.log(arguments);\n }\n\n public isAppleIOS() {\n // https://stackoverflow.com/questions/9038625/detect-if-device-is-ios\n return /iPad|iPhone|iPod/.test(this.window.navigator.userAgent) && !(this.window as any).MSStream;\n }\n\n public getAllCssSelectors(cached = true): string[] {\n if (cached === true && this.cssSelectors.length !== 0)\n return this.cssSelectors;\n\n this.cssSelectors = [];\n try {\n const originRegex = new RegExp(\"^\" + this.escapeRegex(this.window.document.location.origin), \"i\");\n for (let i = 0; i < this.window.document.styleSheets.length; i++)\n {\n const sheet: any = this.window.document.styleSheets[i];\n if (sheet.href && originRegex.test(sheet.href) === false)\n continue; // can't access it\n if (sheet.rules) {\n for (let u = 0; u < sheet.rules.length; u++)\n {\n if (sheet.rules[u].selectorText)\n this.cssSelectors.push(sheet.rules[u].selectorText);\n }\n }\n if (sheet.imports) {\n for (let x = 0; x < sheet.imports.length; x++)\n {\n for (let u = 0; u < sheet.imports[x].rules.length; u++)\n {\n if (sheet.imports[x].rules[u].selectorText)\n this.cssSelectors.push(sheet.imports[x].rules[u].selectorText);\n }\n }\n }\n }\n }\n catch (err) {\n this.window.console.error(\"Error getting CSS selectors\", err);\n }\n return this.cssSelectors;\n }\n\n public isExistingCssSelector(selector: string): boolean {\n const selectors = this.getAllCssSelectors();\n for (let i = 0; i < selectors.length; i++)\n {\n if (selectors[i] === selector) // css props case insensitive, class names in HTML case sensitive\n return true;\n }\n return false;\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected confirmCookies() {\n /* // no data stored in session\n this.getApi('/json/cookies', function(data) {\n if (data.error)\n //Hlp.showMsg(i18next.t('errorSending'), 'danger');\n console.error(\"Error sending data\");\n else {\n }\n })\n */\n this.$(this.config.confirmCookiesMsg).remove();\n this.setCookie(this.config.consentCookieName, \"1\", this.config.cookieLifeDays);\n }\n\n public getApi(path: string, data?: any, callback?: (data: any, textStatus: string, jqXHR: JQueryXHR) => any, dataType?: string) {\n if (typeof data === \"function\") {\n callback = data;\n data = null;\n }\n else if (data === undefined)\n data = null;\n let url = path;\n if (url.toLowerCase().indexOf(\"http\") !== 0)\n url = this.config.siteUrl + url;\n return this.$.get(url, data, (data, textStatus, jqXHR) => {\n callback(data, textStatus, jqXHR);\n }, dataType);\n }\n}\n","import {CashTippr} from \"./CashTippr\";\nimport {AbstractModule} from \"./AbstractModule\";\nimport {WebHelpers} from \"./WebHelpers\";\n\n/**\n * The class for displaying blurry images.\n * We bundle it together with all our JavaScript instead of with the addon because\n * a 2nd JS WebPack project would create unnecessary dependency + bootstrap overhead.\n */\nexport class BlurryImage extends AbstractModule {\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers)\n // TODO implement events this class (and other addons) can listen to so that we don't have to call functions in here directly\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n}\n","import {AbstractPayment, CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n/**\n * The class for displaying the shout addon.\n * We bundle it together with all our JavaScript instead of with the addon because\n * a 2nd JS WebPack project would create unnecessary dependency + bootstrap overhead.\n */\nexport class Shout extends AbstractModule {\n protected scheduleUpdateTimerID = 0;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n // TODO implement events this class (and other addons) can listen to so that we don't have to call functions in here directly\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n if (this.cashtippr.$(\".ct-message\").length !== 0) {\n this.updateRemainingChars();\n this.addEventListeners();\n }\n });\n\n // admin area\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.addConfirmDeleteMessages();\n })\n }\n\n public onPayment(payment: AbstractPayment) {\n setTimeout(() => { // shouldn't be needed, but BadgerWallet is really fast (running locally). just be sure the WP backend processed our payment\n this.cashtippr.$(\"#\" + payment.domID).parent().parent().submit();\n }, 500);\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected updateRemainingChars() {\n const forms = this.cashtippr.$(\".ct-message\").parent().parent();\n this.cashtippr.$.each(forms, (index, value) => {\n const formEl = this.cashtippr.$(value);\n let text = formEl.find(\".ct-message\").val();\n let maxChars = parseInt(formEl.find(\".ct-max-chars\").val());\n const remaining = maxChars - text.length;\n formEl.find(\".ct-chars-left\").text(remaining);\n if (remaining < 0) {\n formEl.find(\".ct-chars-left\").css(\"color\", \"red\");\n formEl.find(\".ct-shout\").prop(\"disabled\", true);\n formEl.find(\".ct-button\").fadeOut(\"slow\");\n }\n else {\n formEl.find(\".ct-chars-left\").css(\"color\", \"\");\n if (text.length === 0) { // don't let the user submit empty messages\n formEl.find(\".ct-shout\").prop(\"disabled\", true);\n formEl.find(\".ct-button\").fadeOut(\"slow\");\n }\n else {\n formEl.find(\".ct-shout\").prop(\"disabled\", false);\n formEl.find(\".ct-button\").fadeIn(\"slow\");\n }\n }\n });\n }\n\n protected addEventListeners() {\n this.cashtippr.$(\".ct-message\").keyup((event) => {\n this.scheduleCharsUpdate();\n });\n this.cashtippr.$(\".ct-message\").change((event) => {\n this.scheduleCharsUpdate();\n });\n this.cashtippr.$(\".ct-shout-form\").on(\"submit.cashtippr\", (event) => { // fix for badger wallet submitting form on click (before payment)\n event.preventDefault();\n this.cashtippr.$(event.target).off(\"submit.cashtippr\");\n });\n }\n\n protected addConfirmDeleteMessages() {\n this.cashtippr.$(\".ct-delete-shout-link\").on(\"click\", (event) => {\n const question = this.cashtippr.$(\"#ct-delete-shout-confirm\").text();\n if (this.cashtippr.window.confirm(question) === true)\n return;\n event.preventDefault();\n return false; // should't be needed anymore in 2018\n });\n }\n\n protected scheduleCharsUpdate() {\n if (this.scheduleUpdateTimerID !== 0)\n clearTimeout(this.scheduleUpdateTimerID);\n this.scheduleUpdateTimerID = setTimeout(() => {\n this.updateRemainingChars();\n }, 50);\n }\n}\n","import {AbstractPayment, CashTippr, CashtipprApiRes} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n\nexport class QrCode extends AbstractModule {\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.cashtippr.$(\".ct-qrcode-btn\").click((event) => {\n this.showQrDialog(event.target);\n });\n });\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected showQrDialog(target: Element) {\n const paymentButtonWrapper = this.cashtippr.$(target).parent().parent().parent();\n const txid = this.cashtippr.getPluginPaymentID(paymentButtonWrapper);\n const paymentCtrlWrapper = paymentButtonWrapper.parent();\n let amount = 0.0;\n if (paymentCtrlWrapper.find(\"input[name='amount']\").length !== 0)\n amount = paymentCtrlWrapper.find(\"input[name='amount']\").val(); // custom editable amount by user\n let params = {\n txid: txid,\n am: amount\n }\n let dialog = this.webHelpers.translate(this.cashtippr.$(\"#ct-modal-qrcode-dialog-tpl\").html(), {\n dialog_class: \"dialog-\" + txid\n });\n this.cashtippr.$(\"body\").append(dialog); // its position is fixed relative to the viewport\n\n this.webHelpers.getApi(\"/wp-json/cashtippr/v1/qrcode\", params, (data) => {\n this.cashtippr.$(\".ct-loading\").remove();\n if (data.error === true) {\n this.cashtippr.window.console.error(\"Error starting QR code tip\");\n this.cashtippr.window.console.error(data.errorMsg);\n return;\n }\n this.cashtippr.$(\".ct-qr-code\").fadeIn(\"slow\").attr(\"src\", data.data[0]);\n });\n\n this.cashtippr.$(\".ct-close-dialog\").click((event) => {\n this.cashtippr.$(\".dialog-\" + txid).remove();\n });\n this.cashtippr.addCopyInputListeners();\n }\n}\n","import {AbstractPayment, CashTippr, CashtipprApiRes} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\nexport interface BadgerWalletPayment extends AbstractPayment {\n buttonId: string; // unique ID, tx ID in our case\n txid: string;\n amount: number;\n currency: string;\n buttonData: string; // JSON string \"{}\" or base64 data in our app\n buttonDataObj: any; // unserialized JS object from buttonData\n}\n\nexport class BadgerWallet extends AbstractModule {\n protected static readonly INSTALL_URL = \"https://badger.bitcoin.com/\";\n\n protected cashtippr: CashTippr;\n protected webHelpers: WebHelpers;\n protected globalCallbacks: boolean; // expose callback functions to window object because BadgerButton currently doesn't support functions on objects\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers, globalCallbacks = false) {\n super(cashtippr, webHelpers);\n this.globalCallbacks = globalCallbacks;\n\n if (this.globalCallbacks === true) {\n setTimeout(() => { // must be done after constructor or else functions are undefined\n this.cashtippr.window['onBadgerPayment'] = this.onBadgerPayment;\n this.cashtippr.window['onBadgerClientPayment'] = this.sendPaymentReceived;\n }, 0);\n }\n\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.cashtippr.$(\".ct-input-amount\").keyup((event) => {\n this.updateButtonAmount(event.target);\n });\n this.cashtippr.$(\".ct-input-amount\").change((event) => {\n this.updateButtonAmount(event.target);\n });\n this.addEventListeners();\n });\n }\n\n public isInstalled() {\n return (this.cashtippr.window as any).web4bch !== undefined;\n }\n\n public isLoggedIn() {\n const wnd: any = this.cashtippr.window;\n return typeof wnd.web4bch.bch.defaultAccount === \"string\" && wnd.web4bch.bch.defaultAccount !== \"\";\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected onBadgerPayment(payment: BadgerWalletPayment) {\n if (typeof payment.buttonData === \"string\" && payment.buttonData.length !== 0 && payment.buttonData[0] !== \"{\")\n payment.buttonDataObj = JSON.parse(this.cashtippr.getWebHelpers().fromBase64(payment.buttonData)) || {}; // this.webHelpers is undefined\n if (payment.domID === undefined)\n payment.domID = \"ct-btn-wrap-\" + payment.buttonId;\n //console.log(\"Badger Payment\", payment);\n\n // TODO make an ajax call to WP to check if the payment has actually been received (will an extension support some webhook callback? likely not)\n // then depending on if the content is hidden with CSS: modify style or reload page (server can tell this, or we add a variable)\n // simply always remove the style\n const config = this.cashtippr.getConfig();\n if (config.show_search_engines === true || config.ajaxConfirm === true) {\n //this.cashtippr.$(\".ct-hidden-text\").css(\"cssText\", \"display: inherit!important;\");\n // especially with editable + hidden button on same page\n\n if (!payment.buttonDataObj || payment.buttonDataObj.days !== 0) { // show everything for full passes\n this.cashtippr.$(\".ct-hidden-text\").fadeIn(\"slow\");\n this.cashtippr.$(\".ct-more, .ct-button-text, .ct-image-blurry\").fadeOut(\"slow\");\n }\n else { // only show the contents hidden in this button\n this.cashtippr.$(\"#ct-hidden-\" + payment.buttonId).fadeIn(\"slow\");\n this.cashtippr.$(\"#ct-button-text-\" + payment.buttonId + \", #ct-image-blurry-\" + payment.buttonId).fadeOut(\"slow\");\n if (payment.buttonDataObj.postHide === true) // auto hide of the full post. there can only be 1 such element\n this.cashtippr.$(\".ct-more\").fadeOut(\"slow\");\n }\n //this.sendPaymentReceived(payment);\n this.cashtippr.window['onBadgerClientPayment'].call(this.cashtippr.badger, payment, (res: CashtipprApiRes) => {\n if (payment.buttonDataObj && payment.buttonDataObj.shout === true)\n this.cashtippr.shout.onPayment(payment);\n if (payment.buttonDataObj && payment.buttonDataObj.woocommerce === true)\n this.cashtippr.woocommerce.onPayment(payment);\n this.cashtippr.adBlockDetect.onPayment(payment);\n });\n // TODO increment tips received and donation goal progress with JS\n if (typeof this.cashtippr.window['onCashtipprPayment'] === \"function\")\n this.cashtippr.window['onCashtipprPayment'].call(this.cashtippr.window, {badger: payment});\n return;\n }\n\n this.cashtippr.window['onBadgerClientPayment'].call(this.cashtippr.badger, payment, (res: CashtipprApiRes) => {\n if (payment.buttonDataObj && payment.buttonDataObj.shout === true) {\n this.cashtippr.shout.onPayment(payment);\n return; // this will already reload the page\n }\n // TODO add random query param to bypass caching? look at different WP caching plugins first\n // some might ignore query strings\n // better way would be to implement WP hooks to bypass cache for paid users (if provided by cache plugins)\n // to make it work with full-page caching we have to fetch params such as TXID via ajax either way\n this.cashtippr.window.location.reload(true);\n });\n }\n\n protected addEventListeners() {\n this.cashtippr.$(\".ct-badger-button\").click((event) => {\n if (this.isInstalled() === false)\n this.cashtippr.window.open(BadgerWallet.INSTALL_URL, \"\", \"\");\n else if (this.isLoggedIn() === false) {\n event.preventDefault();\n this.cashtippr.window.alert(this.cashtippr.getConfig().badgerLocked);\n }\n else\n this.sendPayment(event.target);\n });\n }\n\n protected sendPayment(button: Element) {\n const wnd: any = this.cashtippr.window;\n let web4bch = wnd.web4bch;\n web4bch = new wnd.Web4Bch(web4bch.currentProvider);\n\n const btn = this.cashtippr.$(button);\n let txParams: any = {\n to: btn.attr(\"data-to\"),\n from: web4bch.bch.defaultAccount,\n value: btn.attr(\"data-satoshis\")\n }\n\n web4bch.bch.sendTransaction(txParams, (err, res) => {\n if (err) {\n this.cashtippr.window.console.log(\"Error sending payment\", err);\n return;\n }\n // call the corresponding inline-javascript for this button\n let callback = btn.attr(\"data-success-callback\");\n if (callback && typeof this.cashtippr.window[callback] === \"function\")\n this.cashtippr.window[callback](res); // res is just the txid as string\n });\n }\n\n protected sendPaymentReceived(payment: BadgerWalletPayment, callback?: (res: CashtipprApiRes) => void) {\n let params = {\n txid: payment.buttonId,\n am: payment.amount,\n keep: this.cashtippr.getConfig().keepTransaction === true\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr/v1/mb-client\", params, (data) => {\n callback && callback(data);\n });\n }\n\n protected updateButtonAmount(target: Element) {\n const btnContainer = this.cashtippr.$(target).parent().parent();\n const btn = btnContainer.find(\".badger-button\");\n if (!btn) {\n this.cashtippr.window.console.error(\"Unable to find Badger button\", btnContainer);\n return;\n }\n const amountNewUserCurrency = parseFloat(this.cashtippr.$(target).val());\n if (amountNewUserCurrency === 0.0 || amountNewUserCurrency === Number.NaN)\n return;\n const currency = this.cashtippr.getConfig().display_currency;\n const amountSats = CashTippr.toSatoshis(amountNewUserCurrency / this.cashtippr.getConfig().rate[currency]);\n btn.attr(\"data-satoshis\", amountSats);\n btn.find(\".ct-btn-display-amount\").text(amountNewUserCurrency);\n }\n}\n","import {AbstractPayment, CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {Order} from \"./structs/Order\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n/**\n * Class to interact with the Woocommerce store of a WordPress installation.\n */\nexport class Woocommerce extends AbstractModule {\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n const config = this.cashtippr.getConfig();\n this.addButtonLinkClass();\n // check payment stastus sooner on 1st page load to update remaining amount\n if (config.checkPaymentIntervalSec > 0)\n setTimeout(this.checkPaymentStatus.bind(this, true), /*config.checkPaymentIntervalSec*/1*1000);\n //this.addPayButtonListener();\n\n if (this.cashtippr.$(\"#ct-qrcode-form\").length !== 0)\n this.addPaymentFormEvents(this.cashtippr.$(\"#ct-qrcode-form\").eq(0)); // the form after the order has been placed\n });\n }\n\n public onPayment(payment: AbstractPayment) {\n this.sendPaymentForValidation(payment);\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected sendPaymentForValidation(payment: AbstractPayment) {\n const firstButton = this.cashtippr.$(\".ct-btn-wrap-top\"); // there can only be 1 Woocommerce payment button per payment method\n let params = {\n txid: payment.txid,\n dbtxid: this.cashtippr.getPluginPaymentID(firstButton),\n am: payment.amount\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr-wc/v1/validate\", params, (data) => {\n if (data.data.length === 1) {\n this.cashtippr.window.document.location.assign(data.data[0].url);\n }\n // don't show an error message otherwise, because we likely just wait for more confirmations\n });\n }\n\n protected addPaymentFormEvents(paymentFormEl: JQuery) {\n this.cashtippr.addCopyInputListeners();\n }\n\n protected checkPaymentStatus(repeat = true) {\n const config = this.cashtippr.getConfig();\n if (config.nonce === undefined || config.orderID <= 0)\n return;\n let params = {\n n: config.nonce,\n oid: config.orderID\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr-wc/v1/order-status\", params, (data) => {\n if (config.checkPaymentIntervalSec > 0) // TODO abort checking after x minutes?\n setTimeout(this.checkPaymentStatus.bind(this, true), config.checkPaymentIntervalSec*1000); // always repeat the check even if there was an error\n if (data.error === true) {\n this.cashtippr.window.console.error(\"Error checking BCH payment status: %s\", data.errorMsg);\n return;\n }\n if (data.data && data.data.length >= 1) {\n const order: Order = Object.assign(new Order(), data.data[0]);\n if (order.status === \"paid\") {\n this.showPaymentReceived();\n return;\n }\n else if (order.bchAmountReceived > 0.0) {\n this.showPartialPayment(order);\n return;\n }\n }\n });\n }\n\n protected showPartialPayment(order: Order) {\n const numDecimals = this.cashtippr.getConfig().paymentCommaDigits;\n const remainingAmount = order.calculateRemaningAmount().toFixed(numDecimals);\n if (this.cashtippr.$(\"#ct-pay-amount-txt\").text() === remainingAmount)\n return;\n this.cashtippr.$(\"#ct-pay-amount-txt\").text(remainingAmount);\n this.cashtippr.$(\"#ct-payment-remaining\").fadeIn(\"slow\");\n\n // update payment amount in URI and QR code\n this.cashtippr.$(\"#ct-qr-code-image\").attr(\"src\", order.qrcode);\n this.cashtippr.$(\"#ct-address\").val(order.uri);\n this.cashtippr.$(\"#ct-pay-app\").attr(\"href\", order.uri);\n this.cashtippr.$(\".ct-badger-button\").attr(\"data-satoshis\", order.calculateRemaningAmount());\n }\n\n protected showPaymentReceived() {\n this.cashtippr.$(\"#ct-payment-status\").text(this.cashtippr.getConfig().paidTxt);\n this.cashtippr.$(\"#ct-payment-pending, #ct-pay-instructions, .ct-payment-option\").fadeOut(\"slow\");\n }\n\n protected addButtonLinkClass() {\n const buttons = this.cashtippr.$(\"#ct-pay-app\");\n if (buttons.length === 0)\n return;\n // try to find a native WP theme button style first\n if (this.webHelpers.isExistingCssSelector(\"a.btn\") === true)\n buttons.addClass(\"btn\");\n else if (this.webHelpers.isExistingCssSelector(\"a.button\") === true)\n buttons.addClass(\"button\");\n else\n buttons.addClass(\"ct-button-link\");\n }\n}\n","\nexport type OrderStatus = \"pending\" | \"paid\";\n\n/**\n * Class representing properties to check if a WooCommerce order has been paid.\n */\nexport class Order {\n public readonly id: number; // the unique ID for this order\n public readonly nonce: string; // a nonce to authenticate REST API requests\n public readonly status: OrderStatus;\n public readonly bchAmount: number; // amount requested (total order value)\n public readonly bchAmountReceived: number;\n public readonly qrcode: string; // an image link to the QR code with the (remaining) amount to be paid\n public readonly uri: string; // the payment URI\n\n constructor() {\n }\n\n public calculateRemaningAmount(): number {\n return Math.max(0.0, this.bchAmount - this.bchAmountReceived);\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n}\n","import {AbstractPayment, CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n\nexport class AdBlockDetect extends AbstractModule {\n protected static loadedAdFrame = false;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n\n // TODO add option to store and load adblock lib files from /uploads/{random-filename}.js (created by PHP)\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n if (this.cashtippr.$(\"body\").hasClass(\"wp-admin\") === true)\n return; // don't run in admin panel\n else if (this.cashtippr.getConfig().detect_adblock === false || this.cashtippr.getConfig().tipAmount > 0.0)\n return;\n this.loadLib();\n });\n }\n\n protected loadLib() {\n // We look at whether FuckAdBlock already exists.\n const wnd: any = this.cashtippr.window;\n if(this.cashtippr.getConfig().adblockNoConflict !== true && (typeof wnd.fuckAdBlock !== 'undefined' || typeof wnd.FuckAdBlock !== 'undefined')) {\n // If this is the case, it means that something tries to usurp are identity\n // So, considering that it is a detection\n this.onAdBlockDetected();\n }\n else {\n wnd.fuckAdBlock = null; // prevent automatic instantiation\n const importFAB = this.cashtippr.window.document.createElement('script');\n importFAB.onload = () => {\n wnd.fuckAdBlock = new wnd.FuckAdBlock({\n checkOnLoad: true, // At launch, check if AdBlock is enabled // Uses the method fuckAdBlock.check()\n resetOnEnd: true, // At the end of the check, is that it removes all events added ?\n loopCheckTime: 55, // The number of milliseconds between each check\n loopMaxNumber: 6, // The number of negative checks after which there is considered that AdBlock is not enabled // Time (ms) = 50*(5-1) = 200ms (per default)\n baitClass: 'pub_300x250 pub_300x250m pub_728x90 text-ad textAd banner_ad text_ad text_ads text-ads text-ad-links', // CSS class used by the bait caught AdBlock\n baitStyle: 'width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important;', // CSS style used to hide the bait of the users\n debug: false, // Displays the debug in the console (available only from version 3.2 and more)\n });\n\n // If all goes well, we configure FuckAdBlock\n wnd.fuckAdBlock.onDetected(this.onAdBlockDetected.bind(this));\n wnd.fuckAdBlock.onNotDetected(this.onAdBlockNotDetected.bind(this));\n };\n importFAB.onerror = () => {\n // If the script does not load (blocked, integrity error, ...)\n // Then a detection is triggered\n this.onAdBlockDetected();\n };\n importFAB.integrity = 'sha256-f5s2H2XgAi/4M/ipOOw8pxmim1o7cTOWL72QbKu0lSc=';\n importFAB.crossOrigin = 'anonymous';\n importFAB.src = this.cashtippr.getConfig().adBlockScript;\n this.cashtippr.window.document.head.appendChild(importFAB);\n }\n }\n\n public onPayment(payment: AbstractPayment) {\n //this.cashtippr.$(\".dialog-adbl\").remove(); // better reload the page because we don't know if the webmaster modified it more with our JS callback\n this.cashtippr.window.document.location.reload();\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected onAdBlockNotDetected(secondTry: boolean = false) {\n //console.log('AdBlock is not enabled');\n if (secondTry === false)\n this.loadAdFrame();\n }\n\n protected onAdBlockDetected(secondTry: boolean = false) {\n //console.log('AdBlock is enabled');\n const wnd: any = this.cashtippr.window;\n if (typeof wnd === \"function\")\n wnd.ctipAdblockDetected();\n // blank out the page immediately, even if a version of adblock tries to block the AJAX request below\n const disablePage = this.cashtippr.getConfig().adblockDisable === true;\n if (disablePage === true) {\n let dialog = this.webHelpers.translate(this.cashtippr.$(\"#ct-modal-adblock-dialog-tpl\").html(), {\n dialog_class: \"dialog-adbl\",\n title: \"\",\n text: \"\"\n });\n this.cashtippr.$(\"body\").append(dialog); // its position is fixed relative to the viewport\n }\n let data = {\n msg: disablePage === true ? \"1\" : \"0\"\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr/v1/get-post-notice\", data, (data) => { // always call this to fire PHP adblock detection hook\n this.cashtippr.$(\".dialog-adbl\").remove(); // we have to add it with content or else it doesn't resize properly\n if (disablePage !== true)\n return;\n if (data.error === true) {\n this.cashtippr.$(\"#ct-adbl-title\").text(data.errorMsg);\n //this.cashtippr.$(\"#ct-adbl-content\").html();\n return;\n }\n const postTitle = data.data[0].post.title;\n const postContent = data.data[0].post.content;\n let dialog = this.webHelpers.translate(this.cashtippr.$(\"#ct-modal-adblock-dialog-tpl\").html(), {\n dialog_class: \"dialog-adbl\",\n title: postTitle,\n text: postContent\n }, true);\n this.cashtippr.$(\"body\").append(dialog);\n // TODO generate 1-time addresses and enable qr-code. then check with WP cron for payment and store in session\n this.cashtippr.$(\"#ct-modal-adblock-dialog .ct-qrcode-wrap\").css(\"display\", \"none\");\n });\n }\n\n protected loadAdFrame() {\n if (AdBlockDetect.loadedAdFrame === true)\n return;\n AdBlockDetect.loadedAdFrame = true;\n const importScript = this.cashtippr.window.document.createElement('script');\n const wnd: any = this.cashtippr.window;\n importScript.onload = () => {\n setTimeout(() => { // delay check to be sure it's evaluated\n if (wnd.ctipAdblockOk !== true)\n this.onAdBlockDetected(true);\n else\n this.onAdBlockNotDetected(true);\n }, 100);\n };\n importScript.onerror = () => {\n this.onAdBlockDetected(true);\n };\n importScript.integrity = 'sha256-YrKAEKiVnq8uOpnEBYck9fbjgMBcJgjFcltgKGhtpkA=';\n importScript.crossOrigin = 'anonymous'; // not really needed here\n importScript.src = this.cashtippr.getConfig().adFrameBaitUrl;\n this.cashtippr.window.document.head.appendChild(importScript);\n }\n}\n","import {AbstractModule} from \"../AbstractModule\";\nimport {CashTippr} from \"../CashTippr\";\n\nexport class AdminControls extends AbstractModule {\n constructor(cashtippr: CashTippr) {\n super(cashtippr);\n }\n\n public init() {\n if (this.cashtippr.$(\"body\").attr(\"class\").indexOf(\"cashtippr\") === -1)\n return; // not our plugin settings page\n\n this.cashtippr.getTooltips().initToolTips();\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.enableAdblockSettings();\n });\n this.cashtippr.$(\"#cashtippr_settings\\\\[detect_adblock\\\\]\").on(\"change\", (event) => {\n this.enableAdblockSettings();\n });\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected enableAdblockSettings() {\n const enabled = this.cashtippr.$(\"#cashtippr_settings\\\\[detect_adblock\\\\]\").is(\":checked\") === true;\n const adblockSettingsSelector = \"#cashtippr_settings\\\\[adblockDisable\\\\], #cashtippr_settings\\\\[adblock_page\\\\], #cashtippr_settings\\\\[adblockNoConflict\\\\]\";\n if (enabled === false)\n this.cashtippr.$(adblockSettingsSelector).prop(\"disabled\", true);\n else\n this.cashtippr.$(adblockSettingsSelector).removeProp(\"disabled\");\n }\n}\n"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/AbstractModule.ts","webpack:///./src/CashTippr.ts","webpack:///./index.ts","webpack:///./src/admin/Tooltips.ts","webpack:///./src/WebHelpers.ts","webpack:///./src/BlurryImage.ts","webpack:///./src/Shout.ts","webpack:///./src/QrCode.ts","webpack:///./src/BadgerWallet.ts","webpack:///./src/Woocommerce.ts","webpack:///./src/structs/Order.ts","webpack:///./src/AdBlockDetect.ts","webpack:///./src/admin/AdminControls.ts"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","AbstractModule","cashtippr","webHelpers","this","getWebHelpers","Tooltips_1","WebHelpers_1","BlurryImage_1","Shout_1","QrCode_1","BadgerWallet_1","Woocommerce_1","AdBlockDetect_1","AdminControls_1","CashTippr","window","$","_this","config","consentCookieName","CONSENT_COOKIE_NAME","confirmCookiesMsg","CONFIRM_COOKIES_MSG","confirmCookiesBtn","CONFIRM_COOKIES_BTN","WebHelpers","tooltips","Tooltips","adminControls","AdminControls","badger","BadgerWallet","qr","QrCode","adBlockDetect","AdBlockDetect","blurryImage","BlurryImage","shout","Shout","woocommerce","Woocommerce","document","ready","init","checkCookieConsent","toSatoshis","bch","Math","floor","getConfig","getTooltips","getPluginPaymentID","paymentControlsWrapper","attr","replace","addCopyInputListeners","click","event","preventDefault","inputEl","target","parent","find","select","execCommand","err","isAppleIOS","addClass","jQuery","_super","__extends","initToolTips","e","that","tsfL10n","debug","touchBuffer","inTouchBuffer","setEvents","unset","touchEvents","$target","off","body","on","mousemove","mouseMove","mouseleave","mouseLeave","mouseout","touchRemove","updateDesc","classList","contains","tooltipText","querySelector","Element","innerHTML","dataset","desc","$tooltip","$arrow","overflow","data","overflowDir","parseInt","isNaN","round","css","pagex","originalEvent","pageX","$hoverItemWrap","closest","mousex","offset","left","arrowWidth","$textWrap","textWrapWidth","outerWidth","adjust","adjustDir","boundaryRight","arrowBoundary","remove","clearTimeout","setTimeout","$keepBalloon","hasClass","$children","children","length","not","loadToolTip","isTouch","type","$hoverItem","title","append","$boundary","tooltipHeight","outerHeight","tooltipTop","top","prop","$innerText","hoverItemWrapWidth","width","textWidth","textLeft","textRight","boundaryLeft","horIndent","basis","indent","right","mouseEnter","item","_event","Event","console","log","trigger","stopPropagation","initTooltips","$wrap","addTooltipBoundary","_triggerTooltipReset","_triggerTooltipUpdate","cssSelectors","getBrowserLang","navigator","language","substr","toLowerCase","getCookie","c_name","x","y","ARRcookies","cookie","split","indexOf","decodeURI","setCookie","expireDays","date","Date","getTime","cookieLifeDays","toUTCString","cookiePath","removeCookie","confirmCookies","fromBase64","atob","error","toBase64","btoa","translate","text","variables","safeHtml","toString","start","end","charAt","placeHolder","substring","translation","tr","textPiece","escapeOutput","reg","RegExp","match","convertNewlines","escapeRegex","str","args","arguments","test","userAgent","MSStream","getAllCssSelectors","cached","originRegex","location","origin","styleSheets","sheet","href","rules","u","selectorText","push","imports","isExistingCssSelector","selector","selectors","getApi","path","callback","dataType","undefined","url","siteUrl","textStatus","jqXHR","scheduleUpdateTimerID","updateRemainingChars","addEventListeners","addConfirmDeleteMessages","onPayment","payment","domID","submit","forms","each","index","formEl","val","remaining","fadeOut","fadeIn","keyup","scheduleCharsUpdate","change","question","confirm","showQrDialog","paymentButtonWrapper","txid","paymentCtrlWrapper","amount","params","am","dialog","html","dialog_class","errorMsg","CashTippr_1","globalCallbacks","onBadgerPayment","sendPaymentReceived","updateButtonAmount","isInstalled","web4bch","isLoggedIn","wnd","defaultAccount","buttonData","buttonDataObj","JSON","parse","buttonId","show_search_engines","ajaxConfirm","days","postHide","res","reload","open","INSTALL_URL","alert","badgerLocked","sendPayment","button","Web4Bch","currentProvider","btn","txParams","to","from","sendTransaction","keep","keepTransaction","btnContainer","amountNewUserCurrency","parseFloat","Number","NaN","currency","display_currency","amountSats","rate","Order_1","fullyPaid","checkServerPaymentTimerID","addButtonLinkClass","checkPaymentIntervalSec","checkPaymentStatus","addPaymentFormEvents","eq","sendPaymentForValidation","firstButton","dbtxid","assign","paymentFormEl","repeat","nonce","orderID","oid","order","Order","status","showPaymentReceived","bchAmountReceived","showPartialPayment","numDecimals","paymentCommaDigits","remainingAmount","calculateRemaningAmount","toFixed","qrcode","uri","paidTxt","buttons","max","bchAmount","detect_adblock","tipAmount","loadLib","adblockNoConflict","fuckAdBlock","FuckAdBlock","importFAB","createElement","onload","checkOnLoad","resetOnEnd","loopCheckTime","loopMaxNumber","baitClass","baitStyle","onDetected","onAdBlockDetected","onNotDetected","onAdBlockNotDetected","onerror","integrity","crossOrigin","src","adBlockScript","head","appendChild","secondTry","loadAdFrame","ctipAdblockDetected","disablePage","adblockDisable","msg","postTitle","post","postContent","content","loadedAdFrame","importScript","ctipAdblockOk","adFrameBaitUrl","enableAdblockSettings","adblockSettingsSelector","is","removeProp"],"mappings":"aACA,IAAAA,EAAA,GAGA,SAAAC,EAAAC,GAGA,GAAAF,EAAAE,GACA,OAAAF,EAAAE,GAAAC,QAGA,IAAAC,EAAAJ,EAAAE,GAAA,CACAG,EAAAH,EACAI,GAAA,EACAH,QAAA,IAUA,OANAI,EAAAL,GAAAM,KAAAJ,EAAAD,QAAAC,IAAAD,QAAAF,GAGAG,EAAAE,GAAA,EAGAF,EAAAD,QAKAF,EAAAQ,EAAAF,EAGAN,EAAAS,EAAAV,EAGAC,EAAAU,EAAA,SAAAR,EAAAS,EAAAC,GACAZ,EAAAa,EAAAX,EAAAS,IACAG,OAAAC,eAAAb,EAAAS,EAAA,CAA0CK,YAAA,EAAAC,IAAAL,KAK1CZ,EAAAkB,EAAA,SAAAhB,GACA,oBAAAiB,eAAAC,aACAN,OAAAC,eAAAb,EAAAiB,OAAAC,YAAA,CAAwDC,MAAA,WAExDP,OAAAC,eAAAb,EAAA,cAAiDmB,OAAA,KAQjDrB,EAAAsB,EAAA,SAAAD,EAAAE,GAEA,GADA,EAAAA,IAAAF,EAAArB,EAAAqB,IACA,EAAAE,EAAA,OAAAF,EACA,KAAAE,GAAA,iBAAAF,QAAAG,WAAA,OAAAH,EACA,IAAAI,EAAAX,OAAAY,OAAA,MAGA,GAFA1B,EAAAkB,EAAAO,GACAX,OAAAC,eAAAU,EAAA,WAAyCT,YAAA,EAAAK,UACzC,EAAAE,GAAA,iBAAAF,EAAA,QAAAM,KAAAN,EAAArB,EAAAU,EAAAe,EAAAE,EAAA,SAAAA,GAAgH,OAAAN,EAAAM,IAAqBC,KAAA,KAAAD,IACrI,OAAAF,GAIAzB,EAAA6B,EAAA,SAAA1B,GACA,IAAAS,EAAAT,KAAAqB,WACA,WAA2B,OAAArB,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAH,EAAAU,EAAAE,EAAA,IAAAA,GACAA,GAIAZ,EAAAa,EAAA,SAAAiB,EAAAC,GAAsD,OAAAjB,OAAAkB,UAAAC,eAAA1B,KAAAuB,EAAAC,IAGtD/B,EAAAkC,EAAA,GAIAlC,IAAAmC,EAAA,mFC9EA,IAAAC,EAAA,WAWA,OAPI,SAAYC,EAAsBC,QAAA,IAAAA,MAAA,MAC9BC,KAAKF,UAAYA,EACjBE,KAAKD,WAAaA,GAA0BC,KAAKF,UAAUG,iBANnE,GAAatC,EAAAkC,gGCJb,IAAAK,EAAAzC,EAAA,GACA0C,EAAA1C,EAAA,GACA2C,EAAA3C,EAAA,GACA4C,EAAA5C,EAAA,GACA6C,EAAA7C,EAAA,GACA8C,EAAA9C,EAAA,GACA+C,EAAA/C,EAAA,GACAgD,EAAAhD,EAAA,IACAiD,EAAAjD,EAAA,IA2CAkD,EAAA,WAoBI,SAAAA,EAAYC,EAAgBC,GAA5B,IAAAC,EAAAd,KACIA,KAAKY,OAASA,EACdZ,KAAKa,EAAIA,EACTb,KAAKe,OAASf,KAAKY,OAAqB,cAAK,GAC7CZ,KAAKe,OAAOC,kBAAoBL,EAAUM,oBAC1CjB,KAAKe,OAAOG,kBAAoBP,EAAUQ,oBAC1CnB,KAAKe,OAAOK,kBAAoBT,EAAUU,oBAE1CrB,KAAKD,WAAa,IAAII,EAAAmB,WAAWtB,KAAKY,OAAQZ,KAAKa,EAAGb,KAAKe,QAC3Df,KAAKuB,SAAW,IAAIrB,EAAAsB,SAASxB,KAAMA,KAAKD,YACxCC,KAAKyB,cAAgB,IAAIf,EAAAgB,cAAc1B,MACvCA,KAAK2B,OAAS,IAAIpB,EAAAqB,aAAa5B,KAAMA,KAAKD,YAAY,GACtDC,KAAK6B,GAAK,IAAIvB,EAAAwB,OAAO9B,KAAMA,KAAKD,YAChCC,KAAK+B,cAAgB,IAAItB,EAAAuB,cAAchC,KAAMA,KAAKD,YAClDC,KAAKiC,YAAc,IAAI7B,EAAA8B,YAAYlC,KAAMA,KAAKD,YAC9CC,KAAKmC,MAAQ,IAAI9B,EAAA+B,MAAMpC,KAAMA,KAAKD,YAClCC,KAAKqC,YAAc,IAAI7B,EAAA8B,YAAYtC,KAAMA,KAAKD,YAC9CC,KAAKa,EAAEb,KAAKY,OAAO2B,UAAUC,MAAM,SAAC3B,GAChCC,EAAKW,cAAcgB,OACnB3B,EAAKf,WAAW2C,uBA8C5B,OA1CkB/B,EAAAgC,WAAd,SAAyBC,GACrB,OAAOC,KAAKC,MAAY,IAANF,IAGfjC,EAAAlB,UAAAsD,UAAP,WACI,OAAO/C,KAAKe,QAGTJ,EAAAlB,UAAAuD,YAAP,WACI,OAAOhD,KAAKuB,UAGTZ,EAAAlB,UAAAQ,cAAP,WACI,OAAOD,KAAKD,YAGTY,EAAAlB,UAAAwD,mBAAP,SAA0BC,GACtB,OAAOA,EAAuBC,KAAK,MAAMC,QAAQ,gBAAiB,KAG/DzC,EAAAlB,UAAA4D,sBAAP,eAAAvC,EAAAd,KACIA,KAAKa,EAAE,kBAAkByC,MAAM,SAACC,GAC5BA,EAAMC,iBACN,IAAMC,EAAU3C,EAAKD,EAAE0C,EAAMG,QAAQC,SAASC,KAAK,sBAEnDH,EAAQI,SACR,IACI/C,EAAKF,OAAO2B,SAASuB,YAAY,QAErC,MAAOC,IAEPN,EAAQI,WAEZ7D,KAAKa,EAAE,sCAAsCyC,MAAM,SAACC,GAChDzC,EAAKD,EAAE0C,EAAMG,QAAQG,YAEY,IAAjC7D,KAAKD,WAAWiE,cAChBhE,KAAKa,EAAE,kCAAkCoD,SAAS,WA/EhCtD,EAAAM,oBAAsB,QACtBN,EAAAQ,oBAAsB,gBACtBR,EAAAU,oBAAsB,qBAkFpDV,EArFA,GAAahD,EAAAgD,2FCnDb,IAEIb,EAAY,IAFhBrC,EAAA,GAEoBkD,WAAUC,OAAQsD,QACrCtD,OAAed,UAAYA,mYCF5B,IAGA0B,EAAA,SAAA2C,GAGI,SAAA3C,EAAY1B,EAAsBC,UAC9BoE,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,KAqWpC,OAzW8BoE,EAAA5C,EAAA2C,GAUnB3C,EAAA/B,UAAA4E,aAAP,WACI,IAkUQC,EAlUF1D,EAASZ,KAAKF,UAAUc,OACxBsD,EAASlE,KAAKF,UAAUe,EACxB0D,EAAOvE,KACPwE,EACM,CACJC,OAAO,GAIXC,EAAc,EACdC,GAAgB,EAUdC,EAAY,SAAUlB,EAAQmB,QAAA,IAAAA,OAAA,GAEhCA,EAAQA,IAAS,EAEjB,IAAIC,EAAc,iDACdC,EAAUb,EAAQR,GAEjBmB,GACDE,EAAQC,IAAK,mDACbd,EAAQ3B,SAAS0C,MAAOD,IAAKF,KAE7BC,EAAQG,GAAI,CACRC,UAAeC,EACfC,WAAeC,EACfC,SAAeD,IAEnBpB,EAAQ3B,SAAS0C,MAAOD,IAAKF,GAAcI,GAAIJ,EAAaU,IAGhET,EAAQG,GAAI,oBAAqBO,IAK/BA,EAAa,SAAUlC,GACzB,GAAKA,EAAMG,OAAOgC,UAAUC,SAAU,mBAAsB,CACxD,IAAIC,EAAcrC,EAAMG,OAAOmC,cAAe,oBACzCD,aAAuBE,UACxBF,EAAYG,UAAYxC,EAAMG,OAAOsC,QAAQC,QA4GnDb,EAAY,SAAU7B,GACxB,IAAIwB,EAAUb,EAAQX,EAAMG,QACxBwC,EAAWnB,EAAQnB,KAAM,eACzBuC,EAASD,EAAStC,KAAM,qBACxBwC,EAAWF,EAASG,KAAM,YAC1BC,EAAcJ,EAASG,KAAM,eAKjC,GAHAD,EAAWG,SAAUH,EAAU,IAC/BA,EAAWI,MAAOJ,GAAa,GAAMvD,KAAK4D,MAAOL,GAI7CD,EAAOO,IAAKJ,EAAaF,EAAW,UACjC,CACH,IAAIO,EAAQpD,EAAMqD,eAAiBrD,EAAMqD,cAAcC,OAAStD,EAAMsD,MAGlEC,EAAiB/B,EAAQgC,QAAS,oBAClCC,EAASL,EAAQG,EAAeG,SAASC,KAAOC,EAEhDC,EAAYlB,EAAStC,KAAM,yBAC3ByD,EAAgBD,EAAUE,YAAY,GACtCC,EAASrB,EAASG,KAAM,UACxBmB,EAAYtB,EAASG,KAAM,aAC3BoB,EAAgBJ,EARH,GADG,EAcpB,GAFAE,EAAShB,SAAUgB,EAAQ,IAC3BA,EAASf,MAAOe,GAAW,EAAI1E,KAAK4D,MAAOc,GAMvC,GAHAP,GADAO,EAAS,SAAWC,GAAaD,EAASA,EAIrCE,EAAgBF,EAAST,EAAeQ,YAAY,GAGrDG,EAFiBL,EAAUxD,KAAM,oBACN0D,YAAY,GApB9B,GADG,EA0BfN,GA1Be,EA4BhBb,EAAOO,IAAK,OAAQgB,OACZV,GAAUS,EAElBtB,EAAOO,IAAK,OAAQe,EAAgB,MAGpCtB,EAAOO,IAAK,OAAQM,EAAS,QAInC1B,EAAa,SAAU/B,GAxKT,IAAUG,EA2KrBiB,IAGLT,EAAQX,EAAMG,QAASE,KAAM,eAAgB+D,SA9KnBjE,EA+KbH,EAAMG,OA9KnBkB,EAAWlB,GAAQ,KAsLjB8B,EAAc,SAAUjC,GAnN1BoB,GAAgB,EAChBiD,aAAclD,GACdA,EAAcmD,WAAY,WACtBlD,GAAgB,GACjB,KAoNH,IAIImD,EADA/C,EAAUb,EAAQX,EAAMG,QAM5B,GAHKqB,EAAQgD,SAAU,qBACnBD,EAAe/C,EAAQnB,KANL,iBAQfkE,EAAe,CAClB,IAAIE,EAAYjD,EAAQkD,SAVT,oBAWVD,EAAUE,SACXJ,EAAeE,EAAUpE,KAXX,gBAejBkE,GAAgBA,EAAaI,OAE9BhE,EAjBkB,eAiBQiE,IAAKL,GAAeH,SAG9CzD,EApBkB,eAoBQyD,UAQ5BS,EAAc,SAAU7E,GAE1B,IAAKoB,EAAL,CAGA,IAAI0D,GAAU,EAEd,OAAS9E,EAAM+E,MACX,IAAK,aAED,MAEJ,IAAK,cACL,IAAK,aACDD,GAAU,EAOlB,GAAK9E,EAAMG,OAAOgC,UAAUC,SAAU,mBAElC0C,GAAW7C,EAAajC,GAtOb,SAAUA,GACzB,IAAIgF,EAAarE,EAAQX,EAAMG,QAC3BuC,EAAO1C,EAAMG,OAAOsC,QAAQC,KAEhC,GAAKA,GAAQ,IAAMsC,EAAW3E,KAAM,OAAQsE,OAAS,CAEjD3E,EAAMG,OAAO8E,MAAQ,GAErB,IAAItC,EAAWhC,EACX,4FACE+B,EACF,4DAEJsC,EAAWE,OAAQvC,GAEnB,IAAIwC,EAAYH,EAAWxB,QAAS,wBACpC2B,EAAYA,EAAUR,QAAUQ,GAAaxE,EAAQ3B,SAAS0C,MAG9D,IAAI0D,EAAgBJ,EAAWK,cAAgB,EAC3CC,EAAa3C,EAASe,SAAS6B,IAAMH,EACvBD,EAAUzB,SAAS6B,KAAQJ,EAAUK,KAAM,cAAiB,GAE3DF,GACf3C,EAASjC,SAAU,mBACnBiC,EAASQ,IAAK,MAAOiC,EAAgB,OAErCzC,EAASQ,IAAK,SAAUiC,EAAgB,MAG5C,IAAI7B,EAAiByB,EAAWxB,QAAS,oBACrCK,EAAYlB,EAAStC,KAAM,yBAC3BoF,EAAa5B,EAAUxD,KAAM,oBAC7BqF,EAAqBnC,EAAeoC,QACpC7B,EAAgBD,EAAUE,YAAY,GACtC6B,EAAYH,EAAW1B,YAAY,GACnC8B,EAAWhC,EAAUH,SAASC,KAC9BmC,EAAYD,EAAWD,EACvBG,EAAeZ,EAAUzB,SAASC,MAASwB,EAAUK,KAAM,eAAkB,GAC7EtB,EAAgB6B,EAAeZ,EAAUpB,aAK7C,GAAK8B,EAAWE,GAGRC,EAAYD,EAAeF,EAAW,MACtCI,EAAQjD,SAAUa,EAAUV,IAAK,cAAgB,OAOjD6C,GAAaC,GAEjBtD,EAASQ,IAfG,OAea6C,EAAY,MACrCrD,EAASG,KAAM,WAAYkD,GAC3BrD,EAASG,KAAM,cAjBH,aAkBT,GAAKgD,EAAY5B,EAAgB,CAGpC,IAAI8B,EACAC,GADAD,EAAY9B,EAAgB4B,EAAYJ,EAAqB,MAC7DO,EAAQjD,SAAUa,EAAUV,IAAK,cAAgB,OAOjD6C,GAAaC,GAEjBtD,EAASQ,IA/BG,OA+Ba6C,EAAY,MACrCrD,EAASG,KAAM,WAAYkD,GAC3BrD,EAASG,KAAM,cAjCH,aAkCT,GAAK4C,EAAqB,GAG7B/C,EAASQ,IArCG,OAqCa+C,SACzBvD,EAASG,KAAM,YAFF,IAGbH,EAASG,KAAM,cAvCH,aAwCT,GAAK4C,EAAqB5B,EAAgB,CAE7C,IAGIH,GAHQ3D,EAAMqD,eAAiBrD,EAAMqD,cAAcC,OAAStD,EAAMsD,OAClDC,EAAeG,SAASC,KAExBG,EAAgB,EAChCqC,EAAQxC,EAAOG,EAEdH,EAAO,EAERA,EAAO,EACCwC,EAAQT,IAGhB/B,EAAO+B,EAAqBE,GAGhCjD,EAASQ,IAzDG,OAyDaQ,EAAO,MAChChB,EAASG,KAAM,SAAUa,GACzBhB,EAASG,KAAM,YA3DH,UA8LhBsD,CAAYpG,GAEZ6B,EAAW7B,GAEXqB,EAAWrB,EAAMG,YACd,CAEH,IAAIkG,EAAOrG,EAAMG,OAAOmC,cAAe,0BACnCgE,EAAS,IAAI3F,EAAO4F,MAAOvG,EAAM+E,MAErCuB,EAAOhD,MAAQtD,EAAMqD,eAAiBrD,EAAMqD,cAAcC,OAAStD,EAAMsD,MAEpE+C,GACIpF,EAAeC,OAAQsF,QAAQC,IAAK,qCACzC9F,EAAQ0F,GAAOK,QAASJ,KAEnBrF,EAAeC,OAAQsF,QAAQC,IAAK,mCACzC9F,EAAQX,EAAMG,QAASqD,QAAS,oBAAqBnD,KAAM,0BAA2BqG,QAASJ,IAKvGtG,EAAM2G,oBAOJC,EAAe,WACjB,IAAIC,EAAQlG,EAAQ,oBAEpBkG,EAAMpF,IAAK,qCACXoF,EAAMlF,GAAI,oCAAqC,mBAAoBkD,IAEvE+B,IACAjG,EAAQtD,GAASsE,GAAI,oBAAqBiF,GAGlC7F,EAAIJ,EAAQ,cAChBK,EAAK8F,mBAAoB/F,IAUvB9C,EAAA/B,UAAA4K,mBAAV,SAA8B/F,GAC1BJ,OAAQI,GAAIL,SAAU,wBAMhBzC,EAAA/B,UAAA6K,qBAAV,WACIpG,OAAQtD,QAASqJ,QAAS,sBAMpBzI,EAAA/B,UAAA8K,sBAAV,SAAgCX,GAC5B1F,OAAQ0F,GAAOK,QAAS,sBAEhCzI,EAzWA,CAHA/D,EAAA,GAG8BoC,gBAAjBlC,EAAA6D,0FCQb,IAAAF,EAAA,WAOI,SAAAA,EAAYV,EAAgBC,EAAiBE,GAFnCf,KAAAwK,aAAyB,GAG/BxK,KAAKY,OAASA,EACdZ,KAAKa,EAAIA,EACTb,KAAKe,OAASA,EAsOtB,OAnOWO,EAAA7B,UAAAgL,eAAP,WACI,OAAOzK,KAAKY,OAAO8J,UAAUC,SAASC,OAAO,EAAG,GAAGC,eAGhDvJ,EAAA7B,UAAAqL,UAAP,SAAiBC,GACb,IAAIlN,EAAGmN,EAAGC,EACNC,EAAalL,KAAKY,OAAO2B,SAAS4I,OAAOC,MAAM,KACnD,IAAKvN,EAAI,EAAGA,EAAIqN,EAAWhD,OAAQrK,IAK/B,GAHAmN,EAAIE,EAAWrN,GAAG+M,OAAO,EAAGM,EAAWrN,GAAGwN,QAAQ,MAClDJ,EAAIC,EAAWrN,GAAG+M,OAAOM,EAAWrN,GAAGwN,QAAQ,KAAO,IACtDL,EAAIA,EAAE5H,QAAQ,aAAa,MAClB2H,EACL,OAAOO,UAAUL,GAEzB,OAAO,MAGJ3J,EAAA7B,UAAA8L,UAAP,SAAiBnN,EAAcU,EAAY0M,GACvC,IAAIC,EAAO,IAAIC,KACfD,EAAO,IAAIC,KAAKD,EAAKE,UAAU,OAAgBH,GAA0BxL,KAAKe,OAAO6K,iBAErF5L,KAAKY,OAAO2B,SAAS4I,OAAS/M,EAAO,IAAMU,EAAQ,aAAe2M,EAAKI,cAAgB,UAAY7L,KAAKe,OAAO+K,YAG5GxK,EAAA7B,UAAAsM,aAAP,SAAoB3N,GAEhB4B,KAAKY,OAAO2B,SAAS4I,OAAS/M,EAAO,kDAAoD4B,KAAKe,OAAO+K,YAGlGxK,EAAA7B,UAAAiD,mBAAP,eAAA5B,EAAAd,KACIA,KAAKa,EAAEb,KAAKe,OAAOK,mBAAmBkC,MAAM,WACxCxC,EAAKkL,mBAE6C,OAAlDhM,KAAK8K,UAAU9K,KAAKe,OAAOC,oBAC3BhB,KAAKa,EAAEb,KAAKe,OAAOG,mBAAmByG,UAGvCrG,EAAA7B,UAAAwM,WAAP,SAAkB5F,GACd,MAAgC,mBAArBrG,KAAKY,OAAOsL,MACnBlM,KAAKY,OAAOmJ,QAAQoC,MAAM,oDACnB,IAEJnM,KAAKY,OAAOsL,KAAK7F,IAGrB/E,EAAA7B,UAAA2M,SAAP,SAAgB/F,GACZ,MAAgC,mBAArBrG,KAAKY,OAAOyL,MACnBrM,KAAKY,OAAOmJ,QAAQoC,MAAM,oDACnB,IAEJnM,KAAKY,OAAOyL,KAAKhG,IAUrB/E,EAAA7B,UAAA6M,UAAP,SAAiBC,EAAcC,EAAgBC,GAC3C,QAD2C,IAAAA,OAAA,GACvB,iBAATF,EACP,IAEIA,EAAOA,EAAKG,WAEhB,MAAOpI,GAEH,OADAtE,KAAKgK,IAAI,qCACFuC,EAIf,IADA,IAAII,EAAQ,EAAGC,EAAM,GAC0B,KAAvCD,EAAQJ,EAAKlB,QAAQ,IAAKsB,KAE9B,GAAIA,EAAQ,GAA8B,OAAzBJ,EAAKM,OAAOF,EAAM,GAC/BA,QADJ,CAKA,IAAa,KADbC,EAAML,EAAKlB,QAAQ,IAAKsB,IACR,CACZ3M,KAAKgK,IAAI,oDACT,MAEJ,IAAI8C,EAAcP,EAAKQ,UAAUJ,EAAM,EAAGC,GACtCI,EAAc,KAClB,GAAoC,QAAhCF,EAAYC,UAAU,EAAG,GAAc,CACvC,IAAI3N,EAAM0N,EAAYC,UAAU,GAEhCC,EAAchN,KAAKiN,GAAG7N,QAErB,GAAyB,iBAAdoN,EAAwB,CACpC,IAAIU,EAAYV,EAAUM,QACD,IAAdI,IAEHF,EADoB,kBAAbP,GAA0BA,EACnBS,EAEAlN,KAAKmN,aAAaD,IAG5C,GAAoB,OAAhBF,EAAsB,CACtB,IAAII,EAAM,IAAIC,OAAO,MAAQP,EAAc,MAAO,KAClDP,EAAOA,EAAKnJ,QAAQgK,EAAKJ,QAExB,GAA6C,OAAzCF,EAAYQ,MAAM,mBAA6B,CACpDtN,KAAKgK,IAAI,0CAA4C8C,GACjDM,EAAM,IAAIC,OAAO,MAAQP,EAAc,MAAO,KAClDP,EAAOA,EAAKnJ,QAAQgK,EAAK,YAAcpN,KAAKmN,aAAaL,SAGzDH,GAASG,EAAY5E,OAG7B,OADAqE,EAAOA,EAAKnJ,QAAQ,UAAW,MAI5B9B,EAAA7B,UAAA0N,aAAP,SAAoBZ,EAAcgB,GAC9B,YAD8B,IAAAA,OAAA,GACV,iBAAThB,EACAA,GACXA,EAAOA,EAAKnJ,QAAQ,KAAM,SAASA,QAAQ,KAAM,QAAQA,QAAQ,KAAM,QAAQA,QAAQ,KAAM,UAAUA,QAAQ,KAAM,eACtF,IAApBmK,IAAuD,IAApBA,IAC1ChB,EAAOA,EAAKnJ,QAAQ,SAAU,SAC3BmJ,IAGJjL,EAAA7B,UAAA+N,YAAP,SAAmBC,GACf,OAAOA,EAAIrK,QAAQ,sCAAuC,SAGvD9B,EAAA7B,UAAAwN,GAAP,SAAU7N,GAKN,OAAOA,GAGJkC,EAAA7B,UAAAuK,IAAP,SAAW0D,GAE4B,iBAAxB1N,KAAKY,OAAOmJ,SAA2D,mBAA5B/J,KAAKY,OAAOmJ,QAAQC,KAE1EhK,KAAKY,OAAOmJ,QAAQC,IAAI2D,YAGrBrM,EAAA7B,UAAAuE,WAAP,WAEI,MAAO,mBAAmB4J,KAAK5N,KAAKY,OAAO8J,UAAUmD,aAAgB7N,KAAKY,OAAekN,UAGtFxM,EAAA7B,UAAAsO,mBAAP,SAA0BC,GACtB,QADsB,IAAAA,OAAA,IACP,IAAXA,GAAgD,IAA7BhO,KAAKwK,aAAatC,OACrC,OAAOlI,KAAKwK,aAEhBxK,KAAKwK,aAAe,GACpB,IAEI,IADA,IAAMyD,EAAc,IAAIZ,OAAO,IAAMrN,KAAKwN,YAAYxN,KAAKY,OAAO2B,SAAS2L,SAASC,QAAS,KACpFtQ,EAAI,EAAGA,EAAImC,KAAKY,OAAO2B,SAAS6L,YAAYlG,OAAQrK,IAC7D,CACI,IAAMwQ,EAAarO,KAAKY,OAAO2B,SAAS6L,YAAYvQ,GACpD,IAAIwQ,EAAMC,OAAyC,IAAjCL,EAAYL,KAAKS,EAAMC,MAAzC,CAEA,GAAID,EAAME,MACN,IAAK,IAAIC,EAAI,EAAGA,EAAIH,EAAME,MAAMrG,OAAQsG,IAEhCH,EAAME,MAAMC,GAAGC,cACfzO,KAAKwK,aAAakE,KAAKL,EAAME,MAAMC,GAAGC,cAGlD,GAAIJ,EAAMM,QACN,IAAK,IAAI3D,EAAI,EAAGA,EAAIqD,EAAMM,QAAQzG,OAAQ8C,IAEtC,IAASwD,EAAI,EAAGA,EAAIH,EAAMM,QAAQ3D,GAAGuD,MAAMrG,OAAQsG,IAE3CH,EAAMM,QAAQ3D,GAAGuD,MAAMC,GAAGC,cAC1BzO,KAAKwK,aAAakE,KAAKL,EAAMM,QAAQ3D,GAAGuD,MAAMC,GAAGC,gBAMzE,MAAO1K,GACH/D,KAAKY,OAAOmJ,QAAQoC,MAAM,8BAA+BpI,GAE7D,OAAO/D,KAAKwK,cAGTlJ,EAAA7B,UAAAmP,sBAAP,SAA6BC,GAEzB,IADA,IAAMC,EAAY9O,KAAK+N,qBACdlQ,EAAI,EAAGA,EAAIiR,EAAU5G,OAAQrK,IAElC,GAAIiR,EAAUjR,KAAOgR,EACjB,OAAO,EAEf,OAAO,GAMDvN,EAAA7B,UAAAuM,eAAV,WAUIhM,KAAKa,EAAEb,KAAKe,OAAOG,mBAAmByG,SACtC3H,KAAKuL,UAAUvL,KAAKe,OAAOC,kBAAmB,IAAKhB,KAAKe,OAAO6K,iBAG5DtK,EAAA7B,UAAAsP,OAAP,SAAcC,EAAc3I,EAAY4I,EAAqEC,GACrF,mBAAT7I,GACP4I,EAAW5I,EACXA,EAAO,WAEO8I,IAAT9I,IACLA,EAAO,MACX,IAAI+I,EAAMJ,EAGV,OAF0C,IAAtCI,EAAIvE,cAAcQ,QAAQ,UAC1B+D,EAAMpP,KAAKe,OAAOsO,QAAUD,GACzBpP,KAAKa,EAAEnC,IAAI0Q,EAAK/I,EAAM,SAACA,EAAMiJ,EAAYC,GAC5CN,EAAS5I,EAAMiJ,EAAYC,IAC5BL,IAEX5N,EAhPA,GAAa3D,EAAA2D,8YCXb,IAQAY,EAAA,SAAAiC,GAEI,SAAAjC,EAAYpC,EAAsBC,UAC9BoE,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,KAOpC,OAViCoE,EAAAlC,EAAAiC,GAUjCjC,EAVA,CARAzE,EAAA,GAQiCoC,gBAApBlC,EAAAuE,+YCPb,IAOAE,EAAA,SAAA+B,GAGI,SAAA/B,EAAYtC,EAAsBC,GAAlC,IAAAe,EACIqD,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,YAHtBc,EAAA0O,sBAAwB,EAK9B1O,EAAKhB,UAAUe,EAAEC,EAAKhB,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,GACL,IAA3CC,EAAKhB,UAAUe,EAAE,eAAeqH,SAChCpH,EAAK2O,uBACL3O,EAAK4O,uBAKb5O,EAAKhB,UAAUe,EAAEC,EAAKhB,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,GACpDC,EAAK6O,+BAsEjB,OArF2BvL,EAAAhC,EAAA+B,GAmBhB/B,EAAA3C,UAAAmQ,UAAP,SAAiBC,GAAjB,IAAA/O,EAAAd,KACI6H,WAAW,WACP/G,EAAKhB,UAAUe,EAAE,IAAMgP,EAAQC,OAAOnM,SAASA,SAASoM,UACzD,MAMG3N,EAAA3C,UAAAgQ,qBAAV,eAAA3O,EAAAd,KACUgQ,EAAQhQ,KAAKF,UAAUe,EAAE,eAAe8C,SAASA,SACvD3D,KAAKF,UAAUe,EAAEoP,KAAKD,EAAO,SAACE,EAAOpR,GACjC,IAAMqR,EAASrP,EAAKhB,UAAUe,EAAE/B,GAC5ByN,EAAO4D,EAAOvM,KAAK,eAAewM,MAEhCC,EADS9J,SAAS4J,EAAOvM,KAAK,iBAAiBwM,OACxB7D,EAAKrE,OAClCiI,EAAOvM,KAAK,kBAAkB2I,KAAK8D,GAC/BA,EAAY,GACZF,EAAOvM,KAAK,kBAAkB8C,IAAI,QAAS,OAC3CyJ,EAAOvM,KAAK,aAAamF,KAAK,YAAY,GAC1CoH,EAAOvM,KAAK,cAAc0M,QAAQ,UAGlCH,EAAOvM,KAAK,kBAAkB8C,IAAI,QAAS,IACvB,IAAhB6F,EAAKrE,QACLiI,EAAOvM,KAAK,aAAamF,KAAK,YAAY,GAC1CoH,EAAOvM,KAAK,cAAc0M,QAAQ,UAGlCH,EAAOvM,KAAK,aAAamF,KAAK,YAAY,GAC1CoH,EAAOvM,KAAK,cAAc2M,OAAO,aAMvCnO,EAAA3C,UAAAiQ,kBAAV,eAAA5O,EAAAd,KACIA,KAAKF,UAAUe,EAAE,eAAe2P,MAAM,SAACjN,GACnCzC,EAAK2P,wBAETzQ,KAAKF,UAAUe,EAAE,eAAe6P,OAAO,SAACnN,GACpCzC,EAAK2P,wBAETzQ,KAAKF,UAAUe,EAAE,kBAAkBqE,GAAG,mBAAoB,SAAC3B,GACvDA,EAAMC,iBACN1C,EAAKhB,UAAUe,EAAE0C,EAAMG,QAAQsB,IAAI,uBAIjC5C,EAAA3C,UAAAkQ,yBAAV,eAAA7O,EAAAd,KACIA,KAAKF,UAAUe,EAAE,yBAAyBqE,GAAG,QAAS,SAAC3B,GACnD,IAAMoN,EAAW7P,EAAKhB,UAAUe,EAAE,4BAA4B0L,OAC9D,IAAgD,IAA5CzL,EAAKhB,UAAUc,OAAOgQ,QAAQD,GAGlC,OADApN,EAAMC,kBACC,KAILpB,EAAA3C,UAAAgR,oBAAV,eAAA3P,EAAAd,KACuC,IAA/BA,KAAKwP,uBACL5H,aAAa5H,KAAKwP,uBACtBxP,KAAKwP,sBAAwB3H,WAAW,WACpC/G,EAAK2O,wBACN,KAEXrN,EArFA,CAPA3E,EAAA,GAO2BoC,gBAAdlC,EAAAyE,yYCPb,IAGAN,EAAA,SAAAqC,GAEI,SAAArC,EAAYhC,EAAsBC,GAAlC,IAAAe,EACIqD,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,YAE5Bc,EAAKhB,UAAUe,EAAEC,EAAKhB,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,GACpDC,EAAKhB,UAAUe,EAAE,kBAAkByC,MAAM,SAACC,GACtCzC,EAAK+P,aAAatN,EAAMG,cAuCxC,OA9C4BU,EAAAtC,EAAAqC,GAedrC,EAAArC,UAAAoR,aAAV,SAAuBnN,GAAvB,IAAA5C,EAAAd,KACU8Q,EAAuB9Q,KAAKF,UAAUe,EAAE6C,GAAQC,SAASA,SAASA,SAASA,SAC3EoN,EAAO/Q,KAAKF,UAAUmD,mBAAmB6N,GACzCE,EAAqBF,EAAqBnN,SAC5CsN,EAAS,EACkD,IAA3DD,EAAmBpN,KAAK,wBAAwBsE,SAChD+I,EAASD,EAAmBpN,KAAK,wBAAwBwM,OAC7D,IAAIc,EAAS,CACTH,KAAMA,EACNI,GAAIF,GAEJG,EAASpR,KAAKD,WAAWuM,UAAUtM,KAAKF,UAAUe,EAAE,+BAA+BwQ,OAAQ,CAC3FC,aAAc,UAAYP,IAE9B/Q,KAAKF,UAAUe,EAAE,QAAQ4H,OAAO2I,GAEhCpR,KAAKD,WAAWgP,OAAO,+BAAgCmC,EAAQ,SAAC7K,GAE5D,GADAvF,EAAKhB,UAAUe,EAAE,eAAe8G,UACb,IAAftB,EAAK8F,MAGL,OAFArL,EAAKhB,UAAUc,OAAOmJ,QAAQoC,MAAM,mCACpCrL,EAAKhB,UAAUc,OAAOmJ,QAAQoC,MAAM9F,EAAKkL,UAG7CzQ,EAAKhB,UAAUe,EAAE,eAAe0P,OAAO,QAAQpN,KAAK,MAAOkD,EAAKA,KAAK,MAGzErG,KAAKF,UAAUe,EAAE,oBAAoByC,MAAM,SAACC,GACxCzC,EAAKhB,UAAUe,EAAE,WAAakQ,GAAMpJ,WAExC3H,KAAKF,UAAUuD,yBAEvBvB,EA9CA,CAHArE,EAAA,GAG4BoC,gBAAflC,EAAAmE,0YCLb,IAAA0P,EAAA/T,EAAA,GAaAmE,EAAA,SAAAuC,GAOI,SAAAvC,EAAY9B,EAAsBC,EAAwB0R,QAAA,IAAAA,OAAA,GAA1D,IAAA3Q,EACIqD,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,YAC5Bc,EAAK2Q,gBAAkBA,GAEM,IAAzB3Q,EAAK2Q,iBACL5J,WAAW,WACP/G,EAAKhB,UAAUc,OAAwB,gBAAIE,EAAK4Q,gBAChD5Q,EAAKhB,UAAUc,OAA8B,sBAAIE,EAAK6Q,qBACvD,GAGP7Q,EAAKhB,UAAUe,EAAEC,EAAKhB,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,GACpDC,EAAKhB,UAAUe,EAAE,oBAAoB2P,MAAM,SAACjN,GACxCzC,EAAK8Q,mBAAmBrO,EAAMG,UAElC5C,EAAKhB,UAAUe,EAAE,oBAAoB6P,OAAO,SAACnN,GACzCzC,EAAK8Q,mBAAmBrO,EAAMG,UAElC5C,EAAK4O,wBAmIjB,OA5JkCtL,EAAAxC,EAAAuC,GA6BvBvC,EAAAnC,UAAAoS,YAAP,WACI,YAAkD1C,IAA1CnP,KAAKF,UAAUc,OAAekR,SAGnClQ,EAAAnC,UAAAsS,WAAP,WACI,IAAMC,EAAWhS,KAAKF,UAAUc,OAChC,MAAiD,iBAAnCoR,EAAIF,QAAQlP,IAAIqP,gBAAkE,KAAnCD,EAAIF,QAAQlP,IAAIqP,gBAMvErQ,EAAAnC,UAAAiS,gBAAV,SAA0B7B,GAA1B,IAAA/O,EAAAd,KACsC,iBAAvB6P,EAAQqC,YAAyD,IAA9BrC,EAAQqC,WAAWhK,QAA0C,MAA1B2H,EAAQqC,WAAW,KAChGrC,EAAQsC,cAAgBC,KAAKC,MAAMrS,KAAKF,UAAUG,gBAAgBgM,WAAW4D,EAAQqC,cAAgB,SACnF/C,IAAlBU,EAAQC,QACRD,EAAQC,MAAQ,eAAiBD,EAAQyC,UAM7C,IAAMvR,EAASf,KAAKF,UAAUiD,YAC9B,IAAmC,IAA/BhC,EAAOwR,sBAAuD,IAAvBxR,EAAOyR,YAyB9C,OArBK3C,EAAQsC,eAAgD,IAA/BtC,EAAQsC,cAAcM,MAKhDzS,KAAKF,UAAUe,EAAE,cAAgBgP,EAAQyC,UAAU/B,OAAO,QAC1DvQ,KAAKF,UAAUe,EAAE,mBAAqBgP,EAAQyC,SAAW,sBAAwBzC,EAAQyC,UAAUhC,QAAQ,SACpE,IAAnCT,EAAQsC,cAAcO,UACtB1S,KAAKF,UAAUe,EAAE,YAAYyP,QAAQ,UAPzCtQ,KAAKF,UAAUe,EAAE,mBAAmB0P,OAAO,QAC3CvQ,KAAKF,UAAUe,EAAE,+CAA+CyP,QAAQ,SAS5EtQ,KAAKF,UAAUc,OAA8B,sBAAE5C,KAAKgC,KAAKF,UAAU6B,OAAQkO,EAAS,SAAC8C,GAC7E9C,EAAQsC,gBAAiD,IAAhCtC,EAAQsC,cAAchQ,OAC/CrB,EAAKhB,UAAUqC,MAAMyN,UAAUC,GAC/BA,EAAQsC,gBAAuD,IAAtCtC,EAAQsC,cAAc9P,aAC/CvB,EAAKhB,UAAUuC,YAAYuN,UAAUC,GACzC/O,EAAKhB,UAAUiC,cAAc6N,UAAUC,UAGgB,mBAAhD7P,KAAKF,UAAUc,OAA2B,oBACjDZ,KAAKF,UAAUc,OAA2B,mBAAE5C,KAAKgC,KAAKF,UAAUc,OAAQ,CAACe,OAAQkO,KAIzF7P,KAAKF,UAAUc,OAA8B,sBAAE5C,KAAKgC,KAAKF,UAAU6B,OAAQkO,EAAS,SAAC8C,GAC7E9C,EAAQsC,gBAAiD,IAAhCtC,EAAQsC,cAAchQ,MAC/CrB,EAAKhB,UAAUqC,MAAMyN,UAAUC,GAOnC/O,EAAKhB,UAAUc,OAAOsN,SAAS0E,QAAO,MAIpChR,EAAAnC,UAAAiQ,kBAAV,eAAA5O,EAAAd,KACIA,KAAKF,UAAUe,EAAE,qBAAqByC,MAAM,SAACC,IACd,IAAvBzC,EAAK+Q,cACL/Q,EAAKhB,UAAUc,OAAOiS,KAAKjR,EAAakR,YAAa,GAAI,KAC9B,IAAtBhS,EAAKiR,cACVxO,EAAMC,iBACN1C,EAAKhB,UAAUc,OAAOmS,MAAMjS,EAAKhB,UAAUiD,YAAYiQ,eAGvDlS,EAAKmS,YAAY1P,EAAMG,WAIzB9B,EAAAnC,UAAAwT,YAAV,SAAsBC,GAAtB,IAAApS,EAAAd,KACUgS,EAAWhS,KAAKF,UAAUc,OAC5BkR,EAAUE,EAAIF,QAClBA,EAAU,IAAIE,EAAImB,QAAQrB,EAAQsB,iBAElC,IAAMC,EAAMrT,KAAKF,UAAUe,EAAEqS,GACzBI,EAAgB,CAChBC,GAAIF,EAAIlQ,KAAK,WACbqQ,KAAM1B,EAAQlP,IAAIqP,eAClBnT,MAAOuU,EAAIlQ,KAAK,kBAGpB2O,EAAQlP,IAAI6Q,gBAAgBH,EAAU,SAACvP,EAAK4O,GACxC,GAAI5O,EACAjD,EAAKhB,UAAUc,OAAOmJ,QAAQC,IAAI,wBAAyBjG,OAD/D,CAKA,IAAIkL,EAAWoE,EAAIlQ,KAAK,yBACpB8L,GAAuD,mBAApCnO,EAAKhB,UAAUc,OAAOqO,IACzCnO,EAAKhB,UAAUc,OAAOqO,GAAU0D,OAIlC/Q,EAAAnC,UAAAkS,oBAAV,SAA8B9B,EAA8BZ,GACxD,IAAIiC,EAAS,CACTH,KAAMlB,EAAQyC,SACdnB,GAAItB,EAAQoB,OACZyC,MAAqD,IAA/C1T,KAAKF,UAAUiD,YAAY4Q,iBAErC3T,KAAKD,WAAWgP,OAAO,kCAAmCmC,EAAQ,SAAC7K,GAC/D4I,GAAYA,EAAS5I,MAInBzE,EAAAnC,UAAAmS,mBAAV,SAA6BlO,GACzB,IAAMkQ,EAAe5T,KAAKF,UAAUe,EAAE6C,GAAQC,SAASA,SACjD0P,EAAMO,EAAahQ,KAAK,kBAC9B,GAAKyP,EAAL,CAIA,IAAMQ,EAAwBC,WAAW9T,KAAKF,UAAUe,EAAE6C,GAAQ0M,OAClE,GAA8B,IAA1ByD,GAAiCA,IAA0BE,OAAOC,IAAtE,CAEA,IAAMC,EAAWjU,KAAKF,UAAUiD,YAAYmR,iBACtCC,EAAa3C,EAAA7Q,UAAUgC,WAAWkR,EAAwB7T,KAAKF,UAAUiD,YAAYqR,KAAKH,IAChGZ,EAAIlQ,KAAK,gBAAiBgR,GAC1Bd,EAAIzP,KAAK,0BAA0B2I,KAAKsH,SATpC7T,KAAKF,UAAUc,OAAOmJ,QAAQoC,MAAM,+BAAgCyH,IAhJlDhS,EAAAkR,YAAc,8BA2J5ClR,EA5JA,CAXAnE,EAAA,GAWkCoC,gBAArBlC,EAAAiE,gZCXb,IAAAyS,EAAA5W,EAAA,IAMA6E,EAAA,SAAA6B,GAII,SAAA7B,EAAYxC,EAAsBC,GAAlC,IAAAe,EACIqD,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,YAJtBc,EAAAwT,WAAqB,EACrBxT,EAAAyT,0BAAoC,EAI1CzT,EAAKhB,UAAUe,EAAEC,EAAKhB,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,GACpD,IAAME,EAASD,EAAKhB,UAAUiD,YAC9BjC,EAAK0T,qBAEDzT,EAAO0T,wBAA0B,GACjC5M,WAAW/G,EAAK4T,mBAAmBrV,KAAKyB,GAAM,GAAyC,KAGxC,IAA/CA,EAAKhB,UAAUe,EAAE,mBAAmBqH,QACpCpH,EAAK6T,qBAAqB7T,EAAKhB,UAAUe,EAAE,mBAAmB+T,GAAG,QAiGjF,OAhHiCxQ,EAAA9B,EAAA6B,GAmBtB7B,EAAA7C,UAAAmQ,UAAP,SAAiBC,GACb7P,KAAK6U,yBAAyBhF,IAMxBvN,EAAA7C,UAAAoV,yBAAV,SAAmChF,GAAnC,IAAA/O,EAAAd,KACU8U,EAAc9U,KAAKF,UAAUe,EAAE,oBACjCqQ,EAAS,CACTH,KAAMlB,EAAQkB,KACdgE,OAAQ/U,KAAKF,UAAUmD,mBAAmB6R,GAC1C3D,GAAItB,EAAQoB,QAEhBjR,KAAKD,WAAWgP,OAAO,oCAAqCmC,EAAQ,SAAC7K,GACxC,IAArBA,EAAKA,KAAK6B,QACVpH,EAAKhB,UAAUc,OAAO2B,SAAS2L,SAAS8G,OAAO3O,EAAKA,KAAK,GAAG+I,QAM9D9M,EAAA7C,UAAAkV,qBAAV,SAA+BM,GAC3BjV,KAAKF,UAAUuD,yBAGTf,EAAA7C,UAAAiV,mBAAV,SAA6BQ,GAA7B,IAAApU,EAAAd,UAA6B,IAAAkV,OAAA,GACzB,IAAMnU,EAASf,KAAKF,UAAUiD,YAC9B,UAAqBoM,IAAjBpO,EAAOoU,OAAuBpU,EAAOqU,SAAW,GAApD,CAEA,IAAIlE,EAAS,CACT5R,EAAGyB,EAAOoU,MACVE,IAAKtU,EAAOqU,SAEhBpV,KAAKD,WAAWgP,OAAO,wCAAyCmC,EAAQ,SAAC7K,GAKrE,IAJe,IAAX6O,GAAmBnU,EAAO0T,wBAA0B,IACpD7M,aAAa9G,EAAKyT,2BAClBzT,EAAKyT,0BAA4B1M,WAAW/G,EAAK4T,mBAAmBrV,KAAKyB,GAAM,GAAwC,IAAjCC,EAAO0T,2BAE9E,IAAfpO,EAAK8F,OAIT,GAAI9F,EAAKA,MAAQA,EAAKA,KAAK6B,QAAU,EAAG,CACpC,IAAMoN,EAAe/W,OAAOyW,OAAO,IAAIX,EAAAkB,MAASlP,EAAKA,KAAK,IAC1D,GAAqB,SAAjBiP,EAAME,OAEN,YADA1U,EAAK2U,sBAGJ,GAAIH,EAAMI,kBAAoB,EAE/B,YADA5U,EAAK6U,mBAAmBL,SAV5BxU,EAAKhB,UAAUc,OAAOmJ,QAAQoC,MAAM,wCAAyC9F,EAAKkL,cAiBpFjP,EAAA7C,UAAAkW,mBAAV,SAA6BL,GACzB,IAAMM,EAAc5V,KAAKF,UAAUiD,YAAY8S,mBACzCC,EAAkBR,EAAMS,0BAA0BC,QAAQJ,GAC5D5V,KAAKF,UAAUe,EAAE,sBAAsB0L,SAAWuJ,IAEtD9V,KAAKF,UAAUe,EAAE,sBAAsB0L,KAAKuJ,GAC5C9V,KAAKF,UAAUe,EAAE,yBAAyB0P,OAAO,QAGjDvQ,KAAKF,UAAUe,EAAE,qBAAqBsC,KAAK,MAAOmS,EAAMW,QACxDjW,KAAKF,UAAUe,EAAE,eAAeuP,IAAIkF,EAAMY,KAC1ClW,KAAKF,UAAUe,EAAE,eAAesC,KAAK,OAAQmS,EAAMY,KACnDlW,KAAKF,UAAUe,EAAE,qBAAqBsC,KAAK,gBAAiBmS,EAAMS,6BAG5DzT,EAAA7C,UAAAgW,oBAAV,YAC2B,IAAnBzV,KAAKsU,YAETtU,KAAKsU,WAAY,EACjB1M,aAAa5H,KAAKuU,2BAClBvU,KAAKF,UAAUe,EAAE,sBAAsB0L,KAAKvM,KAAKF,UAAUiD,YAAYoT,SACvEnW,KAAKF,UAAUe,EAAE,iEAAiEyP,QAAQ,UAGpFhO,EAAA7C,UAAA+U,mBAAV,WACI,IAAM4B,EAAUpW,KAAKF,UAAUe,EAAE,eACV,IAAnBuV,EAAQlO,UAG2C,IAAnDlI,KAAKD,WAAW6O,sBAAsB,SACtCwH,EAAQnS,SAAS,QAC0C,IAAtDjE,KAAKD,WAAW6O,sBAAsB,YAC3CwH,EAAQnS,SAAS,UAEjBmS,EAAQnS,SAAS,oBAE7B3B,EAhHA,CALA7E,EAAA,GAKiCoC,gBAApBlC,EAAA2E,6FCFb,IAAAiT,EAAA,WASI,SAAAA,KAUJ,OAPWA,EAAA9V,UAAAsW,wBAAP,WACI,OAAOlT,KAAKwT,IAAI,EAAKrW,KAAKsW,UAAYtW,KAAK0V,oBAMnDH,EAnBA,GAAa5X,EAAA4X,yYCJb,IAGAvT,EAAA,SAAAmC,GAGI,SAAAnC,EAAYlC,EAAsBC,GAAlC,IAAAe,EACIqD,EAAAnG,KAAAgC,KAAMF,EAAWC,IAAWC,YAG5Bc,EAAKhB,UAAUe,EAAEC,EAAKhB,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,IACE,IAAlDC,EAAKhB,UAAUe,EAAE,QAAQkH,SAAS,eAEiB,IAA9CjH,EAAKhB,UAAUiD,YAAYwT,gBAA4BzV,EAAKhB,UAAUiD,YAAYyT,UAAY,GAEvG1V,EAAK2V,eAsHjB,OAlImCrS,EAAApC,EAAAmC,GAgBrBnC,EAAAvC,UAAAgX,QAAV,eAAA3V,EAAAd,KAEUgS,EAAWhS,KAAKF,UAAUc,OAChC,IAAoD,IAAjDZ,KAAKF,UAAUiD,YAAY2T,wBAA0D,IAApB1E,EAAI2E,kBAA0D,IAApB3E,EAAI4E,YAK7G,CACD5E,EAAI2E,YAAc,KAClB,IAAME,EAAY7W,KAAKF,UAAUc,OAAO2B,SAASuU,cAAc,UAC/DD,EAAUE,OAAS,WACf/E,EAAI2E,YAAc,IAAI3E,EAAI4E,YAAY,CAClCI,aAAa,EACbC,YAAY,EACZC,cAAe,GACfC,cAAe,EACfC,UAAW,uGACXC,UAAW,oIACX5S,OAAO,IAIXuN,EAAI2E,YAAYW,WAAWxW,EAAKyW,kBAAkBlY,KAAKyB,IACvDkR,EAAI2E,YAAYa,cAAc1W,EAAK2W,qBAAqBpY,KAAKyB,KAEjE+V,EAAUa,QAAU,WAGhB5W,EAAKyW,qBAETV,EAAUc,UAAY,sDACtBd,EAAUe,YAAc,YACxBf,EAAUgB,IAAM7X,KAAKF,UAAUiD,YAAY+U,cAC3C9X,KAAKF,UAAUc,OAAO2B,SAASwV,KAAKC,YAAYnB,QA5BhD7W,KAAKuX,qBAgCNvV,EAAAvC,UAAAmQ,UAAP,SAAiBC,GAEb7P,KAAKF,UAAUc,OAAO2B,SAAS2L,SAAS0E,UAMlC5Q,EAAAvC,UAAAgY,qBAAV,SAA+BQ,QAAA,IAAAA,OAAA,IAET,IAAdA,GACAjY,KAAKkY,eAGHlW,EAAAvC,UAAA8X,kBAAV,SAA4BU,GAA5B,IAAAnX,EAAAd,UAA4B,IAAAiY,OAAA,GAExB,IAAMjG,EAAWhS,KAAKF,UAAUc,OACb,mBAARoR,GACPA,EAAImG,sBAER,IAAMC,GAA4D,IAA9CpY,KAAKF,UAAUiD,YAAYsV,eAC/C,IAAoB,IAAhBD,EAAsB,CACtB,IAAIhH,EAASpR,KAAKD,WAAWuM,UAAUtM,KAAKF,UAAUe,EAAE,gCAAgCwQ,OAAQ,CAC5FC,aAAc,cACd9I,MAAO,GACP+D,KAAM,KAEVvM,KAAKF,UAAUe,EAAE,QAAQ4H,OAAO2I,GAEpC,IAAI/K,EAAO,CACPiS,KAAqB,IAAhBF,EAAuB,IAAM,KAEtCpY,KAAKD,WAAWgP,OAAO,wCAAyC1I,EAAM,SAACA,GAEnE,GADAvF,EAAKhB,UAAUe,EAAE,gBAAgB8G,UACb,IAAhByQ,EAEJ,IAAmB,IAAf/R,EAAK8F,MAAT,CAKA,IAAMoM,EAAYlS,EAAKA,KAAK,GAAGmS,KAAKhQ,MAC9BiQ,EAAcpS,EAAKA,KAAK,GAAGmS,KAAKE,QAClCtH,EAAStQ,EAAKf,WAAWuM,UAAUxL,EAAKhB,UAAUe,EAAE,gCAAgCwQ,OAAQ,CAC5FC,aAAc,cACd9I,MAAO+P,EACPhM,KAAMkM,IACP,GACH3X,EAAKhB,UAAUe,EAAE,QAAQ4H,OAAO2I,GAEhCtQ,EAAKhB,UAAUe,EAAE,4CAA4C6F,IAAI,UAAW,aAbxE5F,EAAKhB,UAAUe,EAAE,kBAAkB0L,KAAKlG,EAAKkL,aAiB/CvP,EAAAvC,UAAAyY,YAAV,eAAApX,EAAAd,KACI,IAAoC,IAAhCgC,EAAc2W,cAAlB,CAEA3W,EAAc2W,eAAgB,EAC9B,IAAMC,EAAe5Y,KAAKF,UAAUc,OAAO2B,SAASuU,cAAc,UAC5D9E,EAAWhS,KAAKF,UAAUc,OAChCgY,EAAa7B,OAAS,WAClBlP,WAAW,YACmB,IAAtBmK,EAAI6G,cACJ/X,EAAKyW,mBAAkB,GAEvBzW,EAAK2W,sBAAqB,IAC/B,MAEPmB,EAAalB,QAAU,WACnB5W,EAAKyW,mBAAkB,IAE3BqB,EAAajB,UAAY,sDACzBiB,EAAahB,YAAc,YAC3BgB,EAAaf,IAAM7X,KAAKF,UAAUiD,YAAY+V,eAC9C9Y,KAAKF,UAAUc,OAAO2B,SAASwV,KAAKC,YAAYY,KA/HnC5W,EAAA2W,eAAgB,EAiIrC3W,EAlIA,CAHAvE,EAAA,GAGmCoC,gBAAtBlC,EAAAqE,iZCLb,IAGAN,EAAA,SAAAyC,GACI,SAAAzC,EAAY5B,UACRqE,EAAAnG,KAAAgC,KAAMF,IAAUE,KA2BxB,OA7BmCoE,EAAA1C,EAAAyC,GAKxBzC,EAAAjC,UAAAgD,KAAP,eAAA3B,EAAAd,MACyE,IAAjEA,KAAKF,UAAUe,EAAE,QAAQsC,KAAK,SAASkI,QAAQ,eAGnDrL,KAAKF,UAAUkD,cAAcqB,eAC7BrE,KAAKF,UAAUe,EAAEb,KAAKF,UAAUc,OAAO2B,UAAUC,MAAM,SAAC3B,GACpDC,EAAKiY,0BAET/Y,KAAKF,UAAUe,EAAE,2CAA2CqE,GAAG,SAAU,SAAC3B,GACtEzC,EAAKiY,4BAOHrX,EAAAjC,UAAAsZ,sBAAV,WACI,IACMC,EAA0B,8HAChB,MAF+E,IAA/EhZ,KAAKF,UAAUe,EAAE,2CAA2CoY,GAAG,aAG3EjZ,KAAKF,UAAUe,EAAEmY,GAAyBjQ,KAAK,YAAY,GAE3D/I,KAAKF,UAAUe,EAAEmY,GAAyBE,WAAW,aAEjExX,EA7BA,CAHAjE,EAAA,GAGmCoC,gBAAtBlC,EAAA+D","file":"bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 2);\n","import {CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\n\n\nexport class AbstractModule {\n protected cashtippr: CashTippr;\n protected webHelpers: WebHelpers;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers = null) {\n this.cashtippr = cashtippr;\n this.webHelpers = webHelpers ? webHelpers : this.cashtippr.getWebHelpers();\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n}\n","import {Tooltips} from \"./admin/Tooltips\";\nimport {WebHelpers, WebHelpersConfig} from \"./WebHelpers\";\nimport {BlurryImage} from \"./BlurryImage\";\nimport {Shout} from \"./Shout\";\nimport {QrCode} from \"./QrCode\";\nimport {BadgerWallet} from \"./BadgerWallet\";\nimport {Woocommerce} from \"./Woocommerce\";\nimport {AdBlockDetect} from \"./AdBlockDetect\";\nimport {AdminControls} from \"./admin/AdminControls\";\n\nexport interface BitcoinCashConversionRate {\n [fiatCurrency: string]: number;\n}\nexport interface CashTipprConfig extends WebHelpersConfig {\n // same keys as in php\n show_search_engines: boolean;\n display_currency: string;\n rate: BitcoinCashConversionRate;\n ajaxConfirm?: boolean;\n keepTransaction?: boolean; // keep the transaction in mysql so that plugin addons can use them after payment\n paymentCommaDigits: number;\n\n detect_adblock: boolean;\n adblockDisable: boolean;\n adBlockScript: string;\n adblockNoConflict: boolean;\n adFrameBaitUrl: string;\n tipAmount: number;\n\n // present after order is placed\n orderID?: number;\n nonce?: string;\n checkPaymentIntervalSec: number;\n\n // localizations\n badgerLocked: string;\n paidTxt: string;\n}\n\nexport interface AbstractPayment {\n domID: string; // the full ID of the wrapper div for the payment control\n txid: string; // the blockchain transaction ID/hash\n amount: number; // the amount in the website's currency (USD,...)\n}\n\nexport interface CashtipprApiRes {\n error: boolean;\n errorMsg: string;\n data: any[];\n}\n\nexport class CashTippr {\n protected static readonly CONSENT_COOKIE_NAME = \"ct-ck\";\n protected static readonly CONFIRM_COOKIES_MSG = \"#ct-cookieMsg\";\n protected static readonly CONFIRM_COOKIES_BTN = \"#ct-confirmCookies\";\n // TODO separate entryPoints + classes for admin + public code? but tooltips and other admin stuff can be used publicly too (and is quite small)\n\n public readonly window: Window;\n public readonly $: JQueryStatic;\n public readonly badger: BadgerWallet;\n public readonly qr: QrCode;\n public readonly adBlockDetect: AdBlockDetect;\n public readonly blurryImage: BlurryImage;\n public readonly shout: Shout;\n public readonly woocommerce: Woocommerce;\n\n protected config: CashTipprConfig;\n protected webHelpers: WebHelpers;\n protected adminControls: AdminControls;\n protected tooltips: Tooltips;\n\n constructor(window: Window, $: JQueryStatic) {\n this.window = window;\n this.$ = $;\n this.config = this.window['cashtipprCfg'] || {};\n this.config.consentCookieName = CashTippr.CONSENT_COOKIE_NAME;\n this.config.confirmCookiesMsg = CashTippr.CONFIRM_COOKIES_MSG;\n this.config.confirmCookiesBtn = CashTippr.CONFIRM_COOKIES_BTN;\n\n this.webHelpers = new WebHelpers(this.window, this.$, this.config);\n this.tooltips = new Tooltips(this, this.webHelpers);\n this.adminControls = new AdminControls(this);\n this.badger = new BadgerWallet(this, this.webHelpers, true);\n this.qr = new QrCode(this, this.webHelpers);\n this.adBlockDetect = new AdBlockDetect(this, this.webHelpers);\n this.blurryImage = new BlurryImage(this, this.webHelpers);\n this.shout = new Shout(this, this.webHelpers);\n this.woocommerce = new Woocommerce(this, this.webHelpers);\n this.$(this.window.document).ready(($) => {\n this.adminControls.init();\n this.webHelpers.checkCookieConsent();\n });\n }\n\n public static toSatoshis(bch: number) {\n return Math.floor(bch * 100000000);\n }\n\n public getConfig() {\n return this.config;\n }\n\n public getTooltips() {\n return this.tooltips;\n }\n\n public getWebHelpers() {\n return this.webHelpers;\n }\n\n public getPluginPaymentID(paymentControlsWrapper: JQuery) {\n return paymentControlsWrapper.attr(\"id\").replace(/^ct-btn-wrap-/, \"\");\n }\n\n public addCopyInputListeners() {\n this.$(\".ct-copy-field\").click((event) => {\n event.preventDefault();\n const inputEl = this.$(event.target).parent().find(\"input[type='text']\");\n //let text = inputEl.val();\n inputEl.select();\n try {\n this.window.document.execCommand(\"copy\");\n }\n catch (err) { // try-catch shouldn't be needed except for some really old browsers\n }\n inputEl.select(); // ensure it's selected again for iOS devices to copy it manually. not working, remove?\n });\n this.$(\"#ct-qrcode-form input[type='text']\").click((event) => {\n this.$(event.target).select();\n });\n if (this.webHelpers.isAppleIOS() === true) // copy to clipboard button doesn't work there\n this.$(\"#ct-qrcode-form .ct-copy-field\").addClass(\"hidden\");\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n}\n","import {CashTippr} from \"./src/CashTippr\";\n\nlet cashtippr = new CashTippr(window, jQuery);\n(window as any).cashtippr = cashtippr;","import {CashTippr} from \"../CashTippr\";\nimport {AbstractModule} from \"../AbstractModule\";\nimport {WebHelpers} from \"../WebHelpers\";\n\nexport class Tooltips extends AbstractModule {\n protected cashtippr: CashTippr;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n }\n\n /**\n * Initializes status bar hover entries.\n */\n public initToolTips() {\n const window = this.cashtippr.window;\n const jQuery = this.cashtippr.$;\n const that = this;\n const tsfL10n = { // TODO localization\n states: {\n debug: false\n }\n }\n\n let touchBuffer = 0,\n inTouchBuffer = false;\n\n const setTouchBuffer = function() {\n inTouchBuffer = true;\n clearTimeout( touchBuffer );\n touchBuffer = setTimeout( function() {\n inTouchBuffer = false;\n }, 250 );\n }\n\n const setEvents = function( target, unset = false ) {\n\n unset = unset || false;\n\n let touchEvents = 'pointerdown.tsfTT touchstart.tsfTT click.tsfTT',\n $target = jQuery( target );\n\n if ( unset ) {\n $target.off( 'mousemove mouseleave mouseout ct-tooltip-update' );\n jQuery( document.body ).off( touchEvents );\n } else {\n $target.on( {\n 'mousemove' : mouseMove,\n 'mouseleave' : mouseLeave,\n 'mouseout' : mouseLeave,\n } );\n jQuery( document.body ).off( touchEvents ).on( touchEvents, touchRemove );\n }\n\n $target.on( 'ct-tooltip-update', updateDesc );\n }\n const unsetEvents = function( target ) {\n setEvents( target, true );\n }\n const updateDesc = function( event ) {\n if ( event.target.classList.contains( 'ct-tooltip-item' ) ) {\n let tooltipText = event.target.querySelector( '.ct-tooltip-text' );\n if ( tooltipText instanceof Element )\n tooltipText.innerHTML = event.target.dataset.desc;\n }\n }\n const mouseEnter = function( event ) {\n let $hoverItem = jQuery( event.target ),\n desc = event.target.dataset.desc;\n\n if ( desc && 0 === $hoverItem.find( 'div' ).length ) {\n //= Remove any titles attached.\n event.target.title = \"\";\n\n let $tooltip = jQuery(\n ''\n );\n $hoverItem.append( $tooltip );\n\n let $boundary = $hoverItem.closest( '.ct-tooltip-boundary' );\n $boundary = $boundary.length && $boundary || jQuery( document.body );\n\n //= 9 = arrow (8) + shadow (1)\n let tooltipHeight = $hoverItem.outerHeight() + 9,\n tooltipTop = $tooltip.offset().top - tooltipHeight,\n boundaryTop = $boundary.offset().top - ( $boundary.prop( 'scrolltop' ) || 0 );\n\n if ( boundaryTop > tooltipTop ) {\n $tooltip.addClass( 'ct-tooltip-down' );\n $tooltip.css( 'top', tooltipHeight + 'px' );\n } else {\n $tooltip.css( 'bottom', tooltipHeight + 'px' );\n }\n\n let $hoverItemWrap = $hoverItem.closest( '.ct-tooltip-wrap' ),\n $textWrap = $tooltip.find( '.ct-tooltip-text-wrap' ),\n $innerText = $textWrap.find( '.ct-tooltip-text' ),\n hoverItemWrapWidth = $hoverItemWrap.width(),\n textWrapWidth = $textWrap.outerWidth( true ),\n textWidth = $innerText.outerWidth( true ),\n textLeft = $textWrap.offset().left,\n textRight = textLeft + textWidth,\n boundaryLeft = $boundary.offset().left - ( $boundary.prop( 'scrollLeft' ) || 0 ),\n boundaryRight = boundaryLeft + $boundary.outerWidth();\n\n //= RTL and LTR are normalized to abide to left.\n let direction = 'left';\n\n if ( textLeft < boundaryLeft ) {\n //= Overflown over left boundary (likely window)\n //= Add indent relative to boundary. 24px width of arrow / 2 = 12 middle\n let horIndent = boundaryLeft - textLeft + 12,\n basis = parseInt( $textWrap.css( 'flex-basis' ), 10 );\n\n /**\n * If the overflow is greater than the tooltip flex basis,\n * the tooltip was grown. Shrink it back to basis and use that.\n */\n if ( horIndent < -basis )\n horIndent = -basis;\n\n $tooltip.css( direction, horIndent + 'px' );\n $tooltip.data( 'overflow', horIndent );\n $tooltip.data( 'overflowDir', direction );\n } else if ( textRight > boundaryRight ) {\n //= Overflown over right boundary (likely window)\n //= Add indent relative to boundary. Add 12px for visual appeal.\n let horIndent = boundaryRight - textRight - hoverItemWrapWidth - 12,\n basis = parseInt( $textWrap.css( 'flex-basis' ), 10 );\n\n /**\n * If the overflow is greater than the tooltip flex basis,\n * the tooltip was grown. Shrink it back to basis and use that.\n */\n if ( horIndent < -basis )\n horIndent = -basis;\n\n $tooltip.css( direction, horIndent + 'px' );\n $tooltip.data( 'overflow', horIndent );\n $tooltip.data( 'overflowDir', direction );\n } else if ( hoverItemWrapWidth < 42 ) {\n //= Small tooltip container. Add indent to make it visually appealing.\n let indent = -15;\n $tooltip.css( direction, indent + 'px' );\n $tooltip.data( 'overflow', indent );\n $tooltip.data( 'overflowDir', direction );\n } else if ( hoverItemWrapWidth > textWrapWidth ) {\n //= Wrap is bigger than tooltip. Adjust accordingly.\n let pagex = event.originalEvent && event.originalEvent.pageX || event.pageX, // iOS touch support,\n hoverItemLeft = $hoverItemWrap.offset().left,\n center = pagex - hoverItemLeft,\n left = center - textWrapWidth / 2,\n right = left + textWrapWidth;\n\n if ( left < 0 ) {\n //= Don't overflow left.\n left = 0;\n } else if ( right > hoverItemWrapWidth ) {\n //= Don't overflow right.\n //* Use textWidth instead of textWrapWidth as it gets squashed in flex.\n left = hoverItemWrapWidth - textWidth;\n }\n\n $tooltip.css( direction, left + 'px' );\n $tooltip.data( 'adjust', left );\n $tooltip.data( 'adjustDir', direction );\n }\n }\n }\n const mouseMove = function( event ) {\n let $target = jQuery( event.target ),\n $tooltip = $target.find( '.ct-tooltip' ),\n $arrow = $tooltip.find( '.ct-tooltip-arrow' ),\n overflow = $tooltip.data( 'overflow' ),\n overflowDir = $tooltip.data( 'overflowDir' );\n\n overflow = parseInt( overflow, 10 );\n overflow = isNaN( overflow ) ? 0 : - Math.round( overflow );\n\n if ( overflow ) {\n //= Static arrow based on static overflow.\n $arrow.css( overflowDir, overflow + \"px\" );\n } else {\n let pagex = event.originalEvent && event.originalEvent.pageX || event.pageX, // iOS touch support\n arrowBoundary = 7,\n arrowWidth = 16,\n $hoverItemWrap = $target.closest( '.ct-tooltip-wrap' ),\n mousex = pagex - $hoverItemWrap.offset().left - arrowWidth / 2,\n originalMousex = mousex,\n $textWrap = $tooltip.find( '.ct-tooltip-text-wrap' ),\n textWrapWidth = $textWrap.outerWidth( true ),\n adjust = $tooltip.data( 'adjust' ),\n adjustDir = $tooltip.data( 'adjustDir' ),\n boundaryRight = textWrapWidth - arrowWidth - arrowBoundary;\n\n //= mousex is skewed, adjust.\n adjust = parseInt( adjust, 10 );\n adjust = isNaN( adjust ) ? 0 : Math.round( adjust );\n if ( adjust ) {\n adjust = 'left' === adjustDir ? -adjust : adjust;\n mousex = mousex + adjust;\n\n //= Use textWidth for right boundary if adjustment exceeds.\n if ( boundaryRight - adjust > $hoverItemWrap.outerWidth( true ) ) {\n let $innerText = $textWrap.find( '.ct-tooltip-text' ),\n textWidth = $innerText.outerWidth( true );\n boundaryRight = textWidth - arrowWidth - arrowBoundary;\n }\n }\n\n if ( mousex <= arrowBoundary ) {\n //* Overflown left.\n $arrow.css( 'left', arrowBoundary + \"px\" );\n } else if ( mousex >= boundaryRight ) {\n //* Overflown right.\n $arrow.css( 'left', boundaryRight + \"px\" );\n } else {\n //= Somewhere in the middle.\n $arrow.css( 'left', mousex + \"px\" );\n }\n }\n }\n const mouseLeave = function( event ) {\n\n //* @see touchMove\n if ( inTouchBuffer )\n return;\n\n jQuery( event.target ).find( '.ct-tooltip' ).remove();\n unsetEvents( event.target );\n }\n /**\n * ^^^\n * These two methods conflict eachother in EdgeHTML.\n * Thusly, touch buffer.\n * vvv\n */\n const touchRemove = function( event ) {\n\n //* @see mouseLeave\n setTouchBuffer();\n\n let itemSelector = '.ct-tooltip-item',\n balloonSelector = '.ct-tooltip';\n\n let $target = jQuery( event.target ),\n $keepBalloon;\n\n if ( $target.hasClass( 'ct-tooltip-item' ) ) {\n $keepBalloon = $target.find( balloonSelector );\n }\n if ( ! $keepBalloon ) {\n let $children = $target.children( itemSelector );\n if ( $children.length ) {\n $keepBalloon = $children.find( balloonSelector );\n }\n }\n\n if ( $keepBalloon && $keepBalloon.length ) {\n //= Remove all but this.\n jQuery( balloonSelector ).not( $keepBalloon ).remove();\n } else {\n //= Remove all.\n jQuery( balloonSelector ).remove();\n }\n }\n\n /**\n * Loads tooltips within wrapper.\n * @function\n */\n const loadToolTip = function( event ) {\n\n if ( inTouchBuffer )\n return;\n\n let isTouch = false;\n\n switch ( event.type ) {\n case 'mouseenter' :\n //= Most likely, thus placed first.\n break;\n\n case 'pointerdown' :\n case 'touchstart' :\n isTouch = true;\n break;\n\n default :\n break;\n }\n\n if ( event.target.classList.contains( 'ct-tooltip-item' ) ) {\n //= Removes previous items and sets buffer.\n isTouch && touchRemove( event );\n\n mouseEnter( event );\n //= Initiate placement directly for Windows Touch or when overflown.\n mouseMove( event );\n\n setEvents( event.target );\n } else {\n //= Delegate or bubble, and go back to this method with the correct item.\n let item = event.target.querySelector( '.ct-tooltip-item:hover' ),\n _event = new jQuery.Event( event.type );\n\n _event.pageX = event.originalEvent && event.originalEvent.pageX || event.pageX;\n\n if ( item ) {\n if ( tsfL10n.states.debug ) console.log( 'Tooltip event warning: delegation' );\n jQuery( item ).trigger( _event );\n } else {\n if ( tsfL10n.states.debug ) console.log( 'Tooltip event warning: bubbling' );\n jQuery( event.target ).closest( '.ct-tooltip-wrap' ).find( '.ct-tooltip-item:hover' ).trigger( _event );\n }\n }\n\n //* Stop further propagation.\n event.stopPropagation();\n }\n\n /**\n * Initializes tooltips.\n * @function\n */\n const initTooltips = function() {\n let $wrap = jQuery( '.ct-tooltip-wrap' );\n\n $wrap.off( 'mouseenter pointerdown touchstart' );\n $wrap.on( 'mouseenter pointerdown touchstart', '.ct-tooltip-item', loadToolTip );\n }\n initTooltips();\n jQuery( window ).on( 'ct-reset-tooltips', initTooltips );\n\n (function() {\n let e = jQuery( '#wpcontent' );\n that.addTooltipBoundary( e );\n })();\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n /**\n * Adds tooltip boundaries.\n */\n protected addTooltipBoundary( e ) {\n jQuery( e ).addClass( 'ct-tooltip-boundary' );\n }\n\n /**\n * Triggers tooltip reset.\n */\n protected _triggerTooltipReset() { // not used yet\n jQuery( window ).trigger( 'ct-reset-tooltips' );\n }\n\n /**\n * Triggers active tooltip update.\n */\n protected _triggerTooltipUpdate(item) { // not used yet\n jQuery( item ).trigger( 'ct-tooltip-update' );\n }\n}\n","\nexport interface WebHelpersConfig {\n cookieLifeDays: number;\n cookiePath: string;\n siteUrl: string;\n\n // DOM ids of elements of cookie consent message\n consentCookieName: string;\n confirmCookiesMsg: string;\n confirmCookiesBtn: string;\n}\n\nexport class WebHelpers {\n public readonly window: Window;\n public readonly $: JQueryStatic;\n\n protected config: WebHelpersConfig;\n protected cssSelectors: string[] = [];\n\n constructor(window: Window, $: JQueryStatic, config: WebHelpersConfig) {\n this.window = window;\n this.$ = $;\n this.config = config;\n }\n\n public getBrowserLang() {\n return this.window.navigator.language.substr(0, 2).toLowerCase();\n }\n\n public getCookie(c_name: string) {\n let i, x, y;\n let ARRcookies = this.window.document.cookie.split(\";\");\n for (i = 0; i < ARRcookies.length; i++)\n {\n x = ARRcookies[i].substr(0, ARRcookies[i].indexOf(\"=\"));\n y = ARRcookies[i].substr(ARRcookies[i].indexOf(\"=\") + 1);\n x = x.replace(/^\\s+|\\s+$/g,\"\");\n if (x == c_name)\n return decodeURI(y);\n }\n return null;\n }\n\n public setCookie(name: string, value: any, expireDays: number) {\n let date = new Date();\n date = new Date(date.getTime()+1000*60*60*24* (expireDays ? expireDays : this.config.cookieLifeDays));\n //document.cookie = name + \"=\" + value + \"; expires=\" + date.toGMTString() + \"; path=\" + pageData.cookiePath + \"; domain=.\" + location.host;\n this.window.document.cookie = name + \"=\" + value + \"; expires=\" + date.toUTCString() + \"; path=\" + this.config.cookiePath;\n }\n\n public removeCookie(name: string) {\n //document.cookie = name + \"=; expires=Thu, 02 Jan 1970 00:00:00 UTC; path=\" + pageData.cookiePath + \"; domain=.\" + location.host;\n this.window.document.cookie = name + \"=; expires=Thu, 02 Jan 1970 00:00:00 UTC; path=\" + this.config.cookiePath;\n }\n\n public checkCookieConsent() {\n this.$(this.config.confirmCookiesBtn).click(() => {\n this.confirmCookies();\n });\n if (this.getCookie(this.config.consentCookieName) !== null)\n this.$(this.config.confirmCookiesMsg).remove(); // we recently showed the cookie confirm message. some pages might still be in browser cache\n }\n\n public fromBase64(data: string) {\n if (typeof this.window.atob !== \"function\") {\n this.window.console.error(\"Base64 decoding is not supported in your browser\");\n return \"\";\n }\n return this.window.atob(data);\n }\n\n public toBase64(data: string) {\n if (typeof this.window.btoa !== \"function\") {\n this.window.console.error(\"Base64 encoding is not supported in your browser\");\n return \"\";\n }\n return this.window.btoa(data);\n }\n\n /**\n * Populate a html template\n * @param text {String}: The html template (or just normal text with variables)\n * @param variables {Object}: the key-value pairs with variables names and their content to be set in text\n * @param safeHtml {boolean, default false}: don't escape html characters if set to true\n * @returns {String} the translated html\n */\n public translate(text: string, variables: any, safeHtml: boolean = false) {\n if (typeof text !== \"string\") {\n try {\n // @ts-ignore\n text = text.toString();\n }\n catch (e) {\n this.log(\"Text to translate is not a string\");\n return text;\n }\n }\n let start = 0, end = 0;\n while ((start = text.indexOf(\"{\", start)) !== -1)\n {\n if (start > 0 && text.charAt(start-1) === \"\\\\\") { // escaped javascript code beginning\n start++;\n continue;\n }\n end = text.indexOf(\"}\", start);\n if (end === -1) {\n this.log(\"Can not find end position while translating HTML\");\n break;\n }\n let placeHolder = text.substring(start+1, end);\n let translation = null;\n if (placeHolder.substring(0, 3) === \"tr:\") {\n let key = placeHolder.substring(3);\n //translation = this.tr(key.toUpperCase());\n translation = this.tr(key);\n }\n else if (typeof variables === \"object\") {\n let textPiece = variables[placeHolder];\n if (typeof textPiece !== \"undefined\") {\n if (typeof safeHtml === \"boolean\" && safeHtml)\n translation = textPiece;\n else\n translation = this.escapeOutput(textPiece);\n }\n }\n if (translation !== null) {\n let reg = new RegExp(\"\\\\{\" + placeHolder + \"\\\\}\", \"g\");\n text = text.replace(reg, translation);\n }\n else if (placeHolder.match(\"^[A-Za-z0-9_]+$\") !== null) {\n this.log(\"No translation found for place holder: \" + placeHolder);\n let reg = new RegExp(\"\\\\{\" + placeHolder + \"\\\\}\", \"g\");\n text = text.replace(reg, \"MISSING: \" + this.escapeOutput(placeHolder));\n }\n else\n start += placeHolder.length;\n }\n text = text.replace(/\\\\\\\\\\\\{/, \"{\");\n return text;\n }\n\n public escapeOutput(text: string, convertNewlines: boolean = true) {\n if (typeof text !== \"string\")\n return text;\n text = text.replace(/&/g, \"&\").replace(//g, \">\").replace(/\"/g, \""\").replace(/'/g, \"'\");\n if (typeof convertNewlines === \"undefined\" || convertNewlines === true)\n text = text.replace(/\\r?\\n/g, \"
\");\n return text;\n }\n\n public escapeRegex(str: string) {\n return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n }\n\n public tr(key: string) {\n //if (typeof language[key] === \"undefined\")\n //return \"MISSING: \" + key;\n //return language[key];\n //return i18next.t(key) // will just print the key if it doesn't exist and debug is disabled\n return key; // we don't have client-side translation support on this WP plugin yet. just return the key // TODO do we need this if we make our plugin use more ajax?\n }\n\n public log(args) {\n if (//typeof pageData.debugLog !== \"boolean\" || pageData.debugLog === false || // TODO add in CashTipprConfig\n typeof this.window.console !== \"object\" || typeof this.window.console.log !== \"function\")\n return;\n this.window.console.log(arguments);\n }\n\n public isAppleIOS() {\n // https://stackoverflow.com/questions/9038625/detect-if-device-is-ios\n return /iPad|iPhone|iPod/.test(this.window.navigator.userAgent) && !(this.window as any).MSStream;\n }\n\n public getAllCssSelectors(cached = true): string[] {\n if (cached === true && this.cssSelectors.length !== 0)\n return this.cssSelectors;\n\n this.cssSelectors = [];\n try {\n const originRegex = new RegExp(\"^\" + this.escapeRegex(this.window.document.location.origin), \"i\");\n for (let i = 0; i < this.window.document.styleSheets.length; i++)\n {\n const sheet: any = this.window.document.styleSheets[i];\n if (sheet.href && originRegex.test(sheet.href) === false)\n continue; // can't access it\n if (sheet.rules) {\n for (let u = 0; u < sheet.rules.length; u++)\n {\n if (sheet.rules[u].selectorText)\n this.cssSelectors.push(sheet.rules[u].selectorText);\n }\n }\n if (sheet.imports) {\n for (let x = 0; x < sheet.imports.length; x++)\n {\n for (let u = 0; u < sheet.imports[x].rules.length; u++)\n {\n if (sheet.imports[x].rules[u].selectorText)\n this.cssSelectors.push(sheet.imports[x].rules[u].selectorText);\n }\n }\n }\n }\n }\n catch (err) {\n this.window.console.error(\"Error getting CSS selectors\", err);\n }\n return this.cssSelectors;\n }\n\n public isExistingCssSelector(selector: string): boolean {\n const selectors = this.getAllCssSelectors();\n for (let i = 0; i < selectors.length; i++)\n {\n if (selectors[i] === selector) // css props case insensitive, class names in HTML case sensitive\n return true;\n }\n return false;\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected confirmCookies() {\n /* // no data stored in session\n this.getApi('/json/cookies', function(data) {\n if (data.error)\n //Hlp.showMsg(i18next.t('errorSending'), 'danger');\n console.error(\"Error sending data\");\n else {\n }\n })\n */\n this.$(this.config.confirmCookiesMsg).remove();\n this.setCookie(this.config.consentCookieName, \"1\", this.config.cookieLifeDays);\n }\n\n public getApi(path: string, data?: any, callback?: (data: any, textStatus: string, jqXHR: JQueryXHR) => any, dataType?: string) {\n if (typeof data === \"function\") {\n callback = data;\n data = null;\n }\n else if (data === undefined)\n data = null;\n let url = path;\n if (url.toLowerCase().indexOf(\"http\") !== 0)\n url = this.config.siteUrl + url;\n return this.$.get(url, data, (data, textStatus, jqXHR) => {\n callback(data, textStatus, jqXHR);\n }, dataType);\n }\n}\n","import {CashTippr} from \"./CashTippr\";\nimport {AbstractModule} from \"./AbstractModule\";\nimport {WebHelpers} from \"./WebHelpers\";\n\n/**\n * The class for displaying blurry images.\n * We bundle it together with all our JavaScript instead of with the addon because\n * a 2nd JS WebPack project would create unnecessary dependency + bootstrap overhead.\n */\nexport class BlurryImage extends AbstractModule {\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers)\n // TODO implement events this class (and other addons) can listen to so that we don't have to call functions in here directly\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n}\n","import {AbstractPayment, CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n/**\n * The class for displaying the shout addon.\n * We bundle it together with all our JavaScript instead of with the addon because\n * a 2nd JS WebPack project would create unnecessary dependency + bootstrap overhead.\n */\nexport class Shout extends AbstractModule {\n protected scheduleUpdateTimerID = 0;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n // TODO implement events this class (and other addons) can listen to so that we don't have to call functions in here directly\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n if (this.cashtippr.$(\".ct-message\").length !== 0) {\n this.updateRemainingChars();\n this.addEventListeners();\n }\n });\n\n // admin area\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.addConfirmDeleteMessages();\n })\n }\n\n public onPayment(payment: AbstractPayment) {\n setTimeout(() => { // shouldn't be needed, but BadgerWallet is really fast (running locally). just be sure the WP backend processed our payment\n this.cashtippr.$(\"#\" + payment.domID).parent().parent().submit();\n }, 500);\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected updateRemainingChars() {\n const forms = this.cashtippr.$(\".ct-message\").parent().parent();\n this.cashtippr.$.each(forms, (index, value) => {\n const formEl = this.cashtippr.$(value);\n let text = formEl.find(\".ct-message\").val();\n let maxChars = parseInt(formEl.find(\".ct-max-chars\").val());\n const remaining = maxChars - text.length;\n formEl.find(\".ct-chars-left\").text(remaining);\n if (remaining < 0) {\n formEl.find(\".ct-chars-left\").css(\"color\", \"red\");\n formEl.find(\".ct-shout\").prop(\"disabled\", true);\n formEl.find(\".ct-button\").fadeOut(\"slow\");\n }\n else {\n formEl.find(\".ct-chars-left\").css(\"color\", \"\");\n if (text.length === 0) { // don't let the user submit empty messages\n formEl.find(\".ct-shout\").prop(\"disabled\", true);\n formEl.find(\".ct-button\").fadeOut(\"slow\");\n }\n else {\n formEl.find(\".ct-shout\").prop(\"disabled\", false);\n formEl.find(\".ct-button\").fadeIn(\"slow\");\n }\n }\n });\n }\n\n protected addEventListeners() {\n this.cashtippr.$(\".ct-message\").keyup((event) => {\n this.scheduleCharsUpdate();\n });\n this.cashtippr.$(\".ct-message\").change((event) => {\n this.scheduleCharsUpdate();\n });\n this.cashtippr.$(\".ct-shout-form\").on(\"submit.cashtippr\", (event) => { // fix for badger wallet submitting form on click (before payment)\n event.preventDefault();\n this.cashtippr.$(event.target).off(\"submit.cashtippr\");\n });\n }\n\n protected addConfirmDeleteMessages() {\n this.cashtippr.$(\".ct-delete-shout-link\").on(\"click\", (event) => {\n const question = this.cashtippr.$(\"#ct-delete-shout-confirm\").text();\n if (this.cashtippr.window.confirm(question) === true)\n return;\n event.preventDefault();\n return false; // should't be needed anymore in 2018\n });\n }\n\n protected scheduleCharsUpdate() {\n if (this.scheduleUpdateTimerID !== 0)\n clearTimeout(this.scheduleUpdateTimerID);\n this.scheduleUpdateTimerID = setTimeout(() => {\n this.updateRemainingChars();\n }, 50);\n }\n}\n","import {AbstractPayment, CashTippr, CashtipprApiRes} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n\nexport class QrCode extends AbstractModule {\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.cashtippr.$(\".ct-qrcode-btn\").click((event) => {\n this.showQrDialog(event.target);\n });\n });\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected showQrDialog(target: Element) {\n const paymentButtonWrapper = this.cashtippr.$(target).parent().parent().parent().parent();\n const txid = this.cashtippr.getPluginPaymentID(paymentButtonWrapper);\n const paymentCtrlWrapper = paymentButtonWrapper.parent();\n let amount = 0.0;\n if (paymentCtrlWrapper.find(\"input[name='amount']\").length !== 0)\n amount = paymentCtrlWrapper.find(\"input[name='amount']\").val(); // custom editable amount by user\n let params = {\n txid: txid,\n am: amount\n }\n let dialog = this.webHelpers.translate(this.cashtippr.$(\"#ct-modal-qrcode-dialog-tpl\").html(), {\n dialog_class: \"dialog-\" + txid\n });\n this.cashtippr.$(\"body\").append(dialog); // its position is fixed relative to the viewport\n\n this.webHelpers.getApi(\"/wp-json/cashtippr/v1/qrcode\", params, (data) => {\n this.cashtippr.$(\".ct-loading\").remove();\n if (data.error === true) {\n this.cashtippr.window.console.error(\"Error starting QR code tip\");\n this.cashtippr.window.console.error(data.errorMsg);\n return;\n }\n this.cashtippr.$(\".ct-qr-code\").fadeIn(\"slow\").attr(\"src\", data.data[0]);\n });\n\n this.cashtippr.$(\".ct-close-dialog\").click((event) => {\n this.cashtippr.$(\".dialog-\" + txid).remove();\n });\n this.cashtippr.addCopyInputListeners();\n }\n}\n","import {AbstractPayment, CashTippr, CashtipprApiRes} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\nexport interface BadgerWalletPayment extends AbstractPayment {\n buttonId: string; // unique ID, tx ID in our case\n txid: string;\n amount: number;\n currency: string;\n buttonData: string; // JSON string \"{}\" or base64 data in our app\n buttonDataObj: any; // unserialized JS object from buttonData\n}\n\nexport class BadgerWallet extends AbstractModule {\n protected static readonly INSTALL_URL = \"https://badger.bitcoin.com/\";\n\n protected cashtippr: CashTippr;\n protected webHelpers: WebHelpers;\n protected globalCallbacks: boolean; // expose callback functions to window object because BadgerButton currently doesn't support functions on objects\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers, globalCallbacks = false) {\n super(cashtippr, webHelpers);\n this.globalCallbacks = globalCallbacks;\n\n if (this.globalCallbacks === true) {\n setTimeout(() => { // must be done after constructor or else functions are undefined\n this.cashtippr.window['onBadgerPayment'] = this.onBadgerPayment;\n this.cashtippr.window['onBadgerClientPayment'] = this.sendPaymentReceived;\n }, 0);\n }\n\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.cashtippr.$(\".ct-input-amount\").keyup((event) => {\n this.updateButtonAmount(event.target);\n });\n this.cashtippr.$(\".ct-input-amount\").change((event) => {\n this.updateButtonAmount(event.target);\n });\n this.addEventListeners();\n });\n }\n\n public isInstalled() {\n return (this.cashtippr.window as any).web4bch !== undefined;\n }\n\n public isLoggedIn() {\n const wnd: any = this.cashtippr.window;\n return typeof wnd.web4bch.bch.defaultAccount === \"string\" && wnd.web4bch.bch.defaultAccount !== \"\";\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected onBadgerPayment(payment: BadgerWalletPayment) {\n if (typeof payment.buttonData === \"string\" && payment.buttonData.length !== 0 && payment.buttonData[0] !== \"{\")\n payment.buttonDataObj = JSON.parse(this.cashtippr.getWebHelpers().fromBase64(payment.buttonData)) || {}; // this.webHelpers is undefined\n if (payment.domID === undefined)\n payment.domID = \"ct-btn-wrap-\" + payment.buttonId;\n //console.log(\"Badger Payment\", payment);\n\n // TODO make an ajax call to WP to check if the payment has actually been received (will an extension support some webhook callback? likely not)\n // then depending on if the content is hidden with CSS: modify style or reload page (server can tell this, or we add a variable)\n // simply always remove the style\n const config = this.cashtippr.getConfig();\n if (config.show_search_engines === true || config.ajaxConfirm === true) {\n //this.cashtippr.$(\".ct-hidden-text\").css(\"cssText\", \"display: inherit!important;\");\n // especially with editable + hidden button on same page\n\n if (!payment.buttonDataObj || payment.buttonDataObj.days !== 0) { // show everything for full passes\n this.cashtippr.$(\".ct-hidden-text\").fadeIn(\"slow\");\n this.cashtippr.$(\".ct-more, .ct-button-text, .ct-image-blurry\").fadeOut(\"slow\");\n }\n else { // only show the contents hidden in this button\n this.cashtippr.$(\"#ct-hidden-\" + payment.buttonId).fadeIn(\"slow\");\n this.cashtippr.$(\"#ct-button-text-\" + payment.buttonId + \", #ct-image-blurry-\" + payment.buttonId).fadeOut(\"slow\");\n if (payment.buttonDataObj.postHide === true) // auto hide of the full post. there can only be 1 such element\n this.cashtippr.$(\".ct-more\").fadeOut(\"slow\");\n }\n //this.sendPaymentReceived(payment);\n this.cashtippr.window['onBadgerClientPayment'].call(this.cashtippr.badger, payment, (res: CashtipprApiRes) => {\n if (payment.buttonDataObj && payment.buttonDataObj.shout === true)\n this.cashtippr.shout.onPayment(payment);\n if (payment.buttonDataObj && payment.buttonDataObj.woocommerce === true)\n this.cashtippr.woocommerce.onPayment(payment);\n this.cashtippr.adBlockDetect.onPayment(payment);\n });\n // TODO increment tips received and donation goal progress with JS\n if (typeof this.cashtippr.window['onCashtipprPayment'] === \"function\")\n this.cashtippr.window['onCashtipprPayment'].call(this.cashtippr.window, {badger: payment});\n return;\n }\n\n this.cashtippr.window['onBadgerClientPayment'].call(this.cashtippr.badger, payment, (res: CashtipprApiRes) => {\n if (payment.buttonDataObj && payment.buttonDataObj.shout === true) {\n this.cashtippr.shout.onPayment(payment);\n return; // this will already reload the page\n }\n // TODO add random query param to bypass caching? look at different WP caching plugins first\n // some might ignore query strings\n // better way would be to implement WP hooks to bypass cache for paid users (if provided by cache plugins)\n // to make it work with full-page caching we have to fetch params such as TXID via ajax either way\n this.cashtippr.window.location.reload(true);\n });\n }\n\n protected addEventListeners() {\n this.cashtippr.$(\".ct-badger-button\").click((event) => {\n if (this.isInstalled() === false)\n this.cashtippr.window.open(BadgerWallet.INSTALL_URL, \"\", \"\");\n else if (this.isLoggedIn() === false) {\n event.preventDefault();\n this.cashtippr.window.alert(this.cashtippr.getConfig().badgerLocked);\n }\n else\n this.sendPayment(event.target);\n });\n }\n\n protected sendPayment(button: Element) {\n const wnd: any = this.cashtippr.window;\n let web4bch = wnd.web4bch;\n web4bch = new wnd.Web4Bch(web4bch.currentProvider);\n\n const btn = this.cashtippr.$(button);\n let txParams: any = {\n to: btn.attr(\"data-to\"),\n from: web4bch.bch.defaultAccount,\n value: btn.attr(\"data-satoshis\")\n }\n\n web4bch.bch.sendTransaction(txParams, (err, res) => {\n if (err) {\n this.cashtippr.window.console.log(\"Error sending payment\", err);\n return;\n }\n // call the corresponding inline-javascript for this button\n let callback = btn.attr(\"data-success-callback\");\n if (callback && typeof this.cashtippr.window[callback] === \"function\")\n this.cashtippr.window[callback](res); // res is just the txid as string\n });\n }\n\n protected sendPaymentReceived(payment: BadgerWalletPayment, callback?: (res: CashtipprApiRes) => void) {\n let params = {\n txid: payment.buttonId,\n am: payment.amount,\n keep: this.cashtippr.getConfig().keepTransaction === true\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr/v1/mb-client\", params, (data) => {\n callback && callback(data);\n });\n }\n\n protected updateButtonAmount(target: Element) {\n const btnContainer = this.cashtippr.$(target).parent().parent();\n const btn = btnContainer.find(\".badger-button\");\n if (!btn) {\n this.cashtippr.window.console.error(\"Unable to find Badger button\", btnContainer);\n return;\n }\n const amountNewUserCurrency = parseFloat(this.cashtippr.$(target).val());\n if (amountNewUserCurrency === 0.0 || amountNewUserCurrency === Number.NaN)\n return;\n const currency = this.cashtippr.getConfig().display_currency;\n const amountSats = CashTippr.toSatoshis(amountNewUserCurrency / this.cashtippr.getConfig().rate[currency]);\n btn.attr(\"data-satoshis\", amountSats);\n btn.find(\".ct-btn-display-amount\").text(amountNewUserCurrency);\n }\n}\n","import {AbstractPayment, CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {Order} from \"./structs/Order\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n/**\n * Class to interact with the Woocommerce store of a WordPress installation.\n */\nexport class Woocommerce extends AbstractModule {\n protected fullyPaid: boolean = false;\n protected checkServerPaymentTimerID: number = 0;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n const config = this.cashtippr.getConfig();\n this.addButtonLinkClass();\n // check payment stastus sooner on 1st page load to update remaining amount\n if (config.checkPaymentIntervalSec > 0)\n setTimeout(this.checkPaymentStatus.bind(this, true), /*config.checkPaymentIntervalSec*/1*1000);\n //this.addPayButtonListener();\n\n if (this.cashtippr.$(\"#ct-qrcode-form\").length !== 0)\n this.addPaymentFormEvents(this.cashtippr.$(\"#ct-qrcode-form\").eq(0)); // the form after the order has been placed\n });\n }\n\n public onPayment(payment: AbstractPayment) {\n this.sendPaymentForValidation(payment);\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected sendPaymentForValidation(payment: AbstractPayment) {\n const firstButton = this.cashtippr.$(\".ct-btn-wrap-top\"); // there can only be 1 Woocommerce payment button per payment method\n let params = {\n txid: payment.txid,\n dbtxid: this.cashtippr.getPluginPaymentID(firstButton),\n am: payment.amount\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr-wc/v1/validate\", params, (data) => {\n if (data.data.length === 1) {\n this.cashtippr.window.document.location.assign(data.data[0].url);\n }\n // don't show an error message otherwise, because we likely just wait for more confirmations\n });\n }\n\n protected addPaymentFormEvents(paymentFormEl: JQuery) {\n this.cashtippr.addCopyInputListeners();\n }\n\n protected checkPaymentStatus(repeat = true) {\n const config = this.cashtippr.getConfig();\n if (config.nonce === undefined || config.orderID <= 0)\n return;\n let params = {\n n: config.nonce,\n oid: config.orderID\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr-wc/v1/order-status\", params, (data) => {\n if (repeat === true && config.checkPaymentIntervalSec > 0) { // TODO abort checking after x minutes?\n clearTimeout(this.checkServerPaymentTimerID); // ensure we don't have multiple timers running\n this.checkServerPaymentTimerID = setTimeout(this.checkPaymentStatus.bind(this, true), config.checkPaymentIntervalSec * 1000); // always repeat the check even if there was an error\n }\n if (data.error === true) {\n this.cashtippr.window.console.error(\"Error checking BCH payment status: %s\", data.errorMsg);\n return;\n }\n if (data.data && data.data.length >= 1) {\n const order: Order = Object.assign(new Order(), data.data[0]);\n if (order.status === \"paid\") {\n this.showPaymentReceived();\n return;\n }\n else if (order.bchAmountReceived > 0.0) {\n this.showPartialPayment(order);\n return;\n }\n }\n });\n }\n\n protected showPartialPayment(order: Order) {\n const numDecimals = this.cashtippr.getConfig().paymentCommaDigits;\n const remainingAmount = order.calculateRemaningAmount().toFixed(numDecimals);\n if (this.cashtippr.$(\"#ct-pay-amount-txt\").text() === remainingAmount)\n return;\n this.cashtippr.$(\"#ct-pay-amount-txt\").text(remainingAmount);\n this.cashtippr.$(\"#ct-payment-remaining\").fadeIn(\"slow\");\n\n // update payment amount in URI and QR code\n this.cashtippr.$(\"#ct-qr-code-image\").attr(\"src\", order.qrcode);\n this.cashtippr.$(\"#ct-address\").val(order.uri);\n this.cashtippr.$(\"#ct-pay-app\").attr(\"href\", order.uri);\n this.cashtippr.$(\".ct-badger-button\").attr(\"data-satoshis\", order.calculateRemaningAmount());\n }\n\n protected showPaymentReceived() {\n if (this.fullyPaid === true)\n return; // already updated\n this.fullyPaid = true;\n clearTimeout(this.checkServerPaymentTimerID);\n this.cashtippr.$(\"#ct-payment-status\").text(this.cashtippr.getConfig().paidTxt);\n this.cashtippr.$(\"#ct-payment-pending, #ct-pay-instructions, .ct-payment-option\").fadeOut(\"slow\");\n }\n\n protected addButtonLinkClass() {\n const buttons = this.cashtippr.$(\"#ct-pay-app\");\n if (buttons.length === 0)\n return;\n // try to find a native WP theme button style first\n if (this.webHelpers.isExistingCssSelector(\"a.btn\") === true)\n buttons.addClass(\"btn\");\n else if (this.webHelpers.isExistingCssSelector(\"a.button\") === true)\n buttons.addClass(\"button\");\n else\n buttons.addClass(\"ct-button-link\");\n }\n}\n","\nexport type OrderStatus = \"pending\" | \"paid\";\n\n/**\n * Class representing properties to check if a WooCommerce order has been paid.\n */\nexport class Order {\n public readonly id: number; // the unique ID for this order\n public readonly nonce: string; // a nonce to authenticate REST API requests\n public readonly status: OrderStatus;\n public readonly bchAmount: number; // amount requested (total order value)\n public readonly bchAmountReceived: number;\n public readonly qrcode: string; // an image link to the QR code with the (remaining) amount to be paid\n public readonly uri: string; // the payment URI\n\n constructor() {\n }\n\n public calculateRemaningAmount(): number {\n return Math.max(0.0, this.bchAmount - this.bchAmountReceived);\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n}\n","import {AbstractPayment, CashTippr} from \"./CashTippr\";\nimport {WebHelpers} from \"./WebHelpers\";\nimport {AbstractModule} from \"./AbstractModule\";\n\n\nexport class AdBlockDetect extends AbstractModule {\n protected static loadedAdFrame = false;\n\n constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {\n super(cashtippr, webHelpers);\n\n // TODO add option to store and load adblock lib files from /uploads/{random-filename}.js (created by PHP)\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n if (this.cashtippr.$(\"body\").hasClass(\"wp-admin\") === true)\n return; // don't run in admin panel\n else if (this.cashtippr.getConfig().detect_adblock === false || this.cashtippr.getConfig().tipAmount > 0.0)\n return;\n this.loadLib();\n });\n }\n\n protected loadLib() {\n // We look at whether FuckAdBlock already exists.\n const wnd: any = this.cashtippr.window;\n if(this.cashtippr.getConfig().adblockNoConflict !== true && (typeof wnd.fuckAdBlock !== 'undefined' || typeof wnd.FuckAdBlock !== 'undefined')) {\n // If this is the case, it means that something tries to usurp are identity\n // So, considering that it is a detection\n this.onAdBlockDetected();\n }\n else {\n wnd.fuckAdBlock = null; // prevent automatic instantiation\n const importFAB = this.cashtippr.window.document.createElement('script');\n importFAB.onload = () => {\n wnd.fuckAdBlock = new wnd.FuckAdBlock({\n checkOnLoad: true, // At launch, check if AdBlock is enabled // Uses the method fuckAdBlock.check()\n resetOnEnd: true, // At the end of the check, is that it removes all events added ?\n loopCheckTime: 55, // The number of milliseconds between each check\n loopMaxNumber: 6, // The number of negative checks after which there is considered that AdBlock is not enabled // Time (ms) = 50*(5-1) = 200ms (per default)\n baitClass: 'pub_300x250 pub_300x250m pub_728x90 text-ad textAd banner_ad text_ad text_ads text-ads text-ad-links', // CSS class used by the bait caught AdBlock\n baitStyle: 'width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important;', // CSS style used to hide the bait of the users\n debug: false, // Displays the debug in the console (available only from version 3.2 and more)\n });\n\n // If all goes well, we configure FuckAdBlock\n wnd.fuckAdBlock.onDetected(this.onAdBlockDetected.bind(this));\n wnd.fuckAdBlock.onNotDetected(this.onAdBlockNotDetected.bind(this));\n };\n importFAB.onerror = () => {\n // If the script does not load (blocked, integrity error, ...)\n // Then a detection is triggered\n this.onAdBlockDetected();\n };\n importFAB.integrity = 'sha256-f5s2H2XgAi/4M/ipOOw8pxmim1o7cTOWL72QbKu0lSc=';\n importFAB.crossOrigin = 'anonymous';\n importFAB.src = this.cashtippr.getConfig().adBlockScript;\n this.cashtippr.window.document.head.appendChild(importFAB);\n }\n }\n\n public onPayment(payment: AbstractPayment) {\n //this.cashtippr.$(\".dialog-adbl\").remove(); // better reload the page because we don't know if the webmaster modified it more with our JS callback\n this.cashtippr.window.document.location.reload();\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected onAdBlockNotDetected(secondTry: boolean = false) {\n //console.log('AdBlock is not enabled');\n if (secondTry === false)\n this.loadAdFrame();\n }\n\n protected onAdBlockDetected(secondTry: boolean = false) {\n //console.log('AdBlock is enabled');\n const wnd: any = this.cashtippr.window;\n if (typeof wnd === \"function\")\n wnd.ctipAdblockDetected();\n // blank out the page immediately, even if a version of adblock tries to block the AJAX request below\n const disablePage = this.cashtippr.getConfig().adblockDisable === true;\n if (disablePage === true) {\n let dialog = this.webHelpers.translate(this.cashtippr.$(\"#ct-modal-adblock-dialog-tpl\").html(), {\n dialog_class: \"dialog-adbl\",\n title: \"\",\n text: \"\"\n });\n this.cashtippr.$(\"body\").append(dialog); // its position is fixed relative to the viewport\n }\n let data = {\n msg: disablePage === true ? \"1\" : \"0\"\n }\n this.webHelpers.getApi(\"/wp-json/cashtippr/v1/get-post-notice\", data, (data) => { // always call this to fire PHP adblock detection hook\n this.cashtippr.$(\".dialog-adbl\").remove(); // we have to add it with content or else it doesn't resize properly\n if (disablePage !== true)\n return;\n if (data.error === true) {\n this.cashtippr.$(\"#ct-adbl-title\").text(data.errorMsg);\n //this.cashtippr.$(\"#ct-adbl-content\").html();\n return;\n }\n const postTitle = data.data[0].post.title;\n const postContent = data.data[0].post.content;\n let dialog = this.webHelpers.translate(this.cashtippr.$(\"#ct-modal-adblock-dialog-tpl\").html(), {\n dialog_class: \"dialog-adbl\",\n title: postTitle,\n text: postContent\n }, true);\n this.cashtippr.$(\"body\").append(dialog);\n // TODO generate 1-time addresses and enable qr-code. then check with WP cron for payment and store in session\n this.cashtippr.$(\"#ct-modal-adblock-dialog .ct-qrcode-wrap\").css(\"display\", \"none\");\n });\n }\n\n protected loadAdFrame() {\n if (AdBlockDetect.loadedAdFrame === true)\n return;\n AdBlockDetect.loadedAdFrame = true;\n const importScript = this.cashtippr.window.document.createElement('script');\n const wnd: any = this.cashtippr.window;\n importScript.onload = () => {\n setTimeout(() => { // delay check to be sure it's evaluated\n if (wnd.ctipAdblockOk !== true)\n this.onAdBlockDetected(true);\n else\n this.onAdBlockNotDetected(true);\n }, 100);\n };\n importScript.onerror = () => {\n this.onAdBlockDetected(true);\n };\n importScript.integrity = 'sha256-YrKAEKiVnq8uOpnEBYck9fbjgMBcJgjFcltgKGhtpkA=';\n importScript.crossOrigin = 'anonymous'; // not really needed here\n importScript.src = this.cashtippr.getConfig().adFrameBaitUrl;\n this.cashtippr.window.document.head.appendChild(importScript);\n }\n}\n","import {AbstractModule} from \"../AbstractModule\";\nimport {CashTippr} from \"../CashTippr\";\n\nexport class AdminControls extends AbstractModule {\n constructor(cashtippr: CashTippr) {\n super(cashtippr);\n }\n\n public init() {\n if (this.cashtippr.$(\"body\").attr(\"class\").indexOf(\"cashtippr\") === -1)\n return; // not our plugin settings page\n\n this.cashtippr.getTooltips().initToolTips();\n this.cashtippr.$(this.cashtippr.window.document).ready(($) => {\n this.enableAdblockSettings();\n });\n this.cashtippr.$(\"#cashtippr_settings\\\\[detect_adblock\\\\]\").on(\"change\", (event) => {\n this.enableAdblockSettings();\n });\n }\n\n // ################################################################\n // ###################### PRIVATE FUNCTIONS #######################\n\n protected enableAdblockSettings() {\n const enabled = this.cashtippr.$(\"#cashtippr_settings\\\\[detect_adblock\\\\]\").is(\":checked\") === true;\n const adblockSettingsSelector = \"#cashtippr_settings\\\\[adblockDisable\\\\], #cashtippr_settings\\\\[adblock_page\\\\], #cashtippr_settings\\\\[adblockNoConflict\\\\]\";\n if (enabled === false)\n this.cashtippr.$(adblockSettingsSelector).prop(\"disabled\", true);\n else\n this.cashtippr.$(adblockSettingsSelector).removeProp(\"disabled\");\n }\n}\n"],"sourceRoot":""}
\ No newline at end of file
diff --git a/tpl/js/src/QrCode.ts b/tpl/js/src/QrCode.ts
index e2fea2d..4cc6e02 100644
--- a/tpl/js/src/QrCode.ts
+++ b/tpl/js/src/QrCode.ts
@@ -19,7 +19,7 @@ export class QrCode extends AbstractModule {
// ###################### PRIVATE FUNCTIONS #######################
protected showQrDialog(target: Element) {
- const paymentButtonWrapper = this.cashtippr.$(target).parent().parent().parent();
+ const paymentButtonWrapper = this.cashtippr.$(target).parent().parent().parent().parent();
const txid = this.cashtippr.getPluginPaymentID(paymentButtonWrapper);
const paymentCtrlWrapper = paymentButtonWrapper.parent();
let amount = 0.0;
diff --git a/tpl/js/src/Woocommerce.ts b/tpl/js/src/Woocommerce.ts
index f736769..88d49a1 100644
--- a/tpl/js/src/Woocommerce.ts
+++ b/tpl/js/src/Woocommerce.ts
@@ -7,6 +7,8 @@ import {AbstractModule} from "./AbstractModule";
* Class to interact with the Woocommerce store of a WordPress installation.
*/
export class Woocommerce extends AbstractModule {
+ protected fullyPaid: boolean = false;
+ protected checkServerPaymentTimerID: number = 0;
constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {
super(cashtippr, webHelpers);
@@ -58,8 +60,10 @@ export class Woocommerce extends AbstractModule {
oid: config.orderID
}
this.webHelpers.getApi("/wp-json/cashtippr-wc/v1/order-status", params, (data) => {
- if (config.checkPaymentIntervalSec > 0) // TODO abort checking after x minutes?
- setTimeout(this.checkPaymentStatus.bind(this, true), config.checkPaymentIntervalSec*1000); // always repeat the check even if there was an error
+ if (repeat === true && config.checkPaymentIntervalSec > 0) { // TODO abort checking after x minutes?
+ clearTimeout(this.checkServerPaymentTimerID); // ensure we don't have multiple timers running
+ this.checkServerPaymentTimerID = setTimeout(this.checkPaymentStatus.bind(this, true), config.checkPaymentIntervalSec * 1000); // always repeat the check even if there was an error
+ }
if (data.error === true) {
this.cashtippr.window.console.error("Error checking BCH payment status: %s", data.errorMsg);
return;
@@ -94,6 +98,10 @@ export class Woocommerce extends AbstractModule {
}
protected showPaymentReceived() {
+ if (this.fullyPaid === true)
+ return; // already updated
+ this.fullyPaid = true;
+ clearTimeout(this.checkServerPaymentTimerID);
this.cashtippr.$("#ct-payment-status").text(this.cashtippr.getConfig().paidTxt);
this.cashtippr.$("#ct-payment-pending, #ct-pay-instructions, .ct-payment-option").fadeOut("slow");
}
diff --git a/tpl/js/src/admin/Tooltips.ts b/tpl/js/src/admin/Tooltips.ts
index 13c4b54..f5b6914 100644
--- a/tpl/js/src/admin/Tooltips.ts
+++ b/tpl/js/src/admin/Tooltips.ts
@@ -3,7 +3,6 @@ import {AbstractModule} from "../AbstractModule";
import {WebHelpers} from "../WebHelpers";
export class Tooltips extends AbstractModule {
- protected cashtippr: CashTippr;
constructor(cashtippr: CashTippr, webHelpers: WebHelpers) {
super(cashtippr, webHelpers);
diff --git a/tpl/moneybuttonCode.php b/tpl/moneybuttonCode.php
index 6b514e5..ab918e1 100644
--- a/tpl/moneybuttonCode.php
+++ b/tpl/moneybuttonCode.php
@@ -6,7 +6,10 @@
@@ -19,10 +22,10 @@ class="ct-badger-button button"
>
+
+
+
-
-
-