From df4b95dff094109fe3339665577dbf5916bae010 Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Wed, 25 Apr 2018 15:37:59 +0200 Subject: [PATCH 1/7] Add promotion case for redemption, change version, add doc --- README.md | 94 ++++++++++++++++++++++++++++++++++++++++++++--- lib/voucherify.js | 28 +++++++++++--- package.json | 2 +- 3 files changed, 113 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 834b093..ce84416 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Contents: * [1](https://github.com/rspective/voucherify.js#initialize-settings) - Installation and client-side authentication * [2](https://github.com/rspective/voucherify.js#validation) - How to validate [vouchers](https://docs.voucherify.io/reference/#vouchers-validate) and [promotions](https://docs.voucherify.io/reference/#validate-promotions-1) -* [3](https://github.com/rspective/voucherify.js#redeem-vouchers) - How to call [redemption](https://docs.voucherify.io/reference/#redeem-voucher-client-side) +* [3](https://github.com/rspective/voucherify.js#redemption) - How to call [redemption](https://docs.voucherify.io/reference/#redeem-voucher-client-side) * [4](https://github.com/rspective/voucherify.js#publish-vouchers) - How to call [publish](https://docs.voucherify.io/reference/#publish-voucher) coupons * [5](https://github.com/rspective/voucherify.js#list-vouchers) - How to call [list](https://docs.voucherify.io/reference/#list-vouchers) coupons * [6](https://github.com/rspective/voucherify.js#validation-widget) - Configuring validation widget @@ -307,16 +307,16 @@ Voucherify.validate("VOUCHER-CODE") There are several reasons why validation may fail (`valid: false` response). You'll find the actual cause in the `reason` field. For more details, visit [error reference](https://docs.voucherify.io/reference#errors) section. -### Redeem vouchers +### Redemption -Next to validation, the library allows you to [redeem](https://docs.voucherify.io/reference/#redeem-voucher-client-side) vouchers. +Next to validation, the library allows you to redeem [vouchers](https://docs.voucherify.io/reference/#redeem-voucher-client-side) and [promotions](https://docs.voucherify.io/reference/#redeem-promotion). Note: you have to enable **client-side redemptions** in your project's configuration. Reference: [redemption object](http://docs.voucherify.io/reference#the-redemption-object), [client-side redeem](https://docs.voucherify.io/reference/#redeem-voucher-client-side) How to use it: - +#### Vouchers `Voucherify.redeem("VOUCHER-CODE", payload, function callback (response) { })` where `payload` is an object which can include: @@ -325,12 +325,12 @@ where `payload` is an object which can include: - `source_id` - if not set, `tracking_id` will be used (if `tracking_id` is set) - `order` - with at least - `amount` +- `metadata` Example: `Voucherify.redeem("gfct5ZWI1nL", { order: { amount: 5000 } }, function callback (response) { })` - Success response ```javascript @@ -381,6 +381,89 @@ Success response } ``` +#### Promotion + +`Voucherify.redeem(null, payload, function callback (response) { })` + +where `payload` is an object which can include: + +- `tier` - promotion tier ID +- `customer` - voucher customer object + - `source_id` - if not set, `tracking_id` will be used (if `tracking_id` is set) +- `order` - with at least + - `amount` +- `metadata` + +Example: + +`Voucherify.redeem(null, { tier: 'promo_yourpromotiontierid', order: { amount: 5000 } }, function callback (response) { })` + +Success response + +```javascript +{ + "object": "redemption", + "customer_id": "cust_vAZ0M5nQUDv3zDoAcT6QSYhb", + "tracking_id": "(tracking_id not set)" + "result": "SUCCESS", + "amount": 30, + "order": { + "amount": 30, + "discount_amount": 30, + "items": null, + "customer": { + "id": "cust_vAZ0M5nQUDv3zDoAcT6QSYhb", + "object": "customer" + }, + "referrer": null, + "status": "CREATED", + "metadata": null + }, + "promotion_tier":{ + "id":"promo_TvPlKsF2tNXh3GhKPh0JKtDa", + "object":"promotion_tier", + "name":"tier_2", + "banner":null, + "campaign":{ + "id":"camp_mFxeXvEj7VeugrmFGdUNmKEp", + "object":"campaign", + "start_date":"2018-04-18T00:00:00Z", + "expiration_date":"2023-07-02T00:00:00Z", + "active":true + }, + "condition":{ + "id":"val_TerxvCfNklYF", + "created_at":"2018-04-25T07:06:29Z", + "junction":"AND", + "orders":{ + "junction":"AND", + "any_order_item_price":{ + "$more_than":[ + 1000000 + ] + } + } + }, + "action":{ + "discount":{ + "type":"AMOUNT", + "amount_off":100000 + } + }, + "metadata":null, + "summary":{ + "redemptions":{ + "total_redeemed":1 + }, + "orders":{ + "total_amount":0, + "total_discount_amount":0 + } + } + } +} +``` + If you are using *jQuery* in version higher than *1.5*, you can use its implementation of promises (remember to load `voucherify.js` script after loading *jQuery*): ```javascript @@ -671,6 +754,7 @@ The widget is fully configurable. You can decide which fields are visible and re ### Changelog +- **2018-04-25** - `1.19.0` - Add client side method for promotion redemption - **2018-04-24** - `1.18.0` - Add client side method for promotion validation - **2017-12-12** - `1.17.0` - Add redeem iframe widget - **2017-10-23** - `1.16.1` - Fix tracking custom events diff --git a/lib/voucherify.js b/lib/voucherify.js index 9b6ec75..b66b554 100644 --- a/lib/voucherify.js +++ b/lib/voucherify.js @@ -9,7 +9,8 @@ window.Voucherify = (function (window, document, $) { publish: API_BASE + "/client/v1/publish", list: API_BASE + "/client/v1/vouchers", track: API_BASE + "/client/v1/events", - validatePromotion: API_BASE + "/client/v1/promotions/validation" + validatePromotion: API_BASE + "/client/v1/promotions/validation", + redeemPromotion: API_BASE + "/client/v1/promotions/tiers/" }; var OPTIONS = {}; @@ -285,23 +286,40 @@ window.Voucherify = (function (window, document, $) { }, redeem: function (code, payload, callback) { + var isPromotion = false; + var tier; + if (!isValidInit(OPTIONS)) { return null; } + // if (!code) { + // console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."); + // return null; + // } + if (!code) { - console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."); - return null; + if( !payload.tier ){ + console.error("Voucherify client could not redeem promotion without tier, because it is missing."); + return null; + } + isPromotion = true; + tier = payload.tier; + delete payload.tier } - var queryString = "?code=" + encodeURIComponent(code.replace(/[\s\r\n]/g, "")); + var queryString = "" + if(!isPromotion){ + queryString += "?code=" + encodeURIComponent(code.replace(/[\s\r\n]/g, "")); + } // -- Tracking ID fallback payload = payload || {}; payload.customer = payload.customer || {}; payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId; - return xhrImplementation("POST", API.redeem + queryString, payload, callback); + + return xhrImplementation("POST", (isPromotion ? API.redeemPromotion + tier + "/redemption" : API.redeem) + queryString, payload, callback); }, publish: function (campaign, payload, callback) { diff --git a/package.json b/package.json index e19660f..73bb6af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "voucherify.js", - "version": "1.17.0", + "version": "1.19.0", "homepage": "http://www.voucherify.io", "description": "Client-side SDK for Voucherify.", "author": "rspective", From 30338c6f7bc47b40fc524d5e6963d4811330f8b8 Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Wed, 25 Apr 2018 15:43:23 +0200 Subject: [PATCH 2/7] Build distribution --- dist/voucherify.js | 41 ++++++++++++++++++++++++++++---------- dist/voucherify.min.js | 2 +- dist/voucherify.min.js.map | 2 +- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/dist/voucherify.js b/dist/voucherify.js index b4a303b..b66b554 100644 --- a/dist/voucherify.js +++ b/dist/voucherify.js @@ -9,7 +9,8 @@ window.Voucherify = (function (window, document, $) { publish: API_BASE + "/client/v1/publish", list: API_BASE + "/client/v1/vouchers", track: API_BASE + "/client/v1/events", - validatePromotion: API_BASE + "/client/v1/promotions/validation" + validatePromotion: API_BASE + "/client/v1/promotions/validation", + redeemPromotion: API_BASE + "/client/v1/promotions/tiers/" }; var OPTIONS = {}; @@ -267,13 +268,14 @@ window.Voucherify = (function (window, document, $) { } if (customer) { - if(typeof(code) === "object") { - queryString += "&" + Object.keys(customer).map(function (key) { - return encodeURIComponent("customer[" + key + "]") + "=" + encodeURIComponent(customer[ key ]); - }).join("&"); - } else { - queryString += "&customer=" + customer + if(typeof(customer) !== "object") { + console.error("Customer must be an object - please use instead { source_id: 'your_user' }"); + return null; } + + queryString += "&" + Object.keys(customer).map(function (key) { + return encodeURIComponent("customer[" + key + "]") + "=" + encodeURIComponent(customer[ key ]); + }).join("&"); } if (OPTIONS.trackingId) { @@ -284,23 +286,40 @@ window.Voucherify = (function (window, document, $) { }, redeem: function (code, payload, callback) { + var isPromotion = false; + var tier; + if (!isValidInit(OPTIONS)) { return null; } + // if (!code) { + // console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."); + // return null; + // } + if (!code) { - console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."); - return null; + if( !payload.tier ){ + console.error("Voucherify client could not redeem promotion without tier, because it is missing."); + return null; + } + isPromotion = true; + tier = payload.tier; + delete payload.tier } - var queryString = "?code=" + encodeURIComponent(code.replace(/[\s\r\n]/g, "")); + var queryString = "" + if(!isPromotion){ + queryString += "?code=" + encodeURIComponent(code.replace(/[\s\r\n]/g, "")); + } // -- Tracking ID fallback payload = payload || {}; payload.customer = payload.customer || {}; payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId; - return xhrImplementation("POST", API.redeem + queryString, payload, callback); + + return xhrImplementation("POST", (isPromotion ? API.redeemPromotion + tier + "/redemption" : API.redeem) + queryString, payload, callback); }, publish: function (campaign, payload, callback) { diff --git a/dist/voucherify.min.js b/dist/voucherify.min.js index 7be839e..d63d765 100644 --- a/dist/voucherify.min.js +++ b/dist/voucherify.min.js @@ -1,2 +1,2 @@ -window.Voucherify=function(e,t,n){"use strict";function o(e){return e&&("boolean"==typeof e.valid||"string"==typeof e.result||"object"==typeof e.voucher||"object"==typeof e.vouchers||"event"===e.object&&"string"==typeof e.type)}function i(e){return Math.round(100.001*e)/100}function r(e){if(!e||0>e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function c(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var d="https://api.voucherify.io",u={validate:d+"/client/v1/validate",redeem:d+"/client/v1/redeem",publish:d+"/client/v1/publish",list:d+"/client/v1/vouchers",track:d+"/client/v1/events",validatePromotion:d+"/client/v1/promotions/validation"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";return e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r&&(l+="object"==typeof e?"&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&"):"&customer="+r),f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validateVoucher)+l,void 0,t)},redeem:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."),null;var o="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""));return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",u.redeem+o,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?d:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=e-n*o;return i(d>0?d:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/s);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=n*o;return i(c>e?e:c)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",c,{type:"hidden",configurable:!0}),v=l("input","percentOff",c,{type:"hidden",configurable:!0}),y=l("input","amountOff",c,{type:"hidden",configurable:!0}),b=l("input","unitOff",c,{type:"hidden",configurable:!0}),C=l("input","tracking",c,{type:"hidden",configurable:!0}),x=l("button","validate",c,{}),_=(l("span","validateText",x,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),x.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),x.toggleClass(w,!1),x.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};_.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};x.toggleClass(w,!0),x.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),x.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),x.toggleClass(I,!0),x.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",c,{type:"hidden",configurable:!0}),v=l("button","redeem",c,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",x="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",_="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(x,!1)}),f.on("keyup",function(e){f.toggleClass(x,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(x,!0).delay(1e3).queue(function(){u.toggleClass(x,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(x,!0).delay(1e3).queue(function(){e.toggleClass(x,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(_,!0),f.toggleClass(_,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function c(e,t){return o[s(e,t)]}function d(e,o,i,r){r=r||{};var a=null,l=c("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var d in r)"configurable"!==d&&r.hasOwnProperty(d)&&a.attr(d,r[d]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof c("class",o)?c("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(O,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(O,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=d("div","container",f);p.addClass("wide");{var m=d("figure","logo",p),g=(d("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&d("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=d("div","row",p),b=r("email")&&d("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&d("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),x=r("line_1")&&d("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),_=r("line_2")&&d("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=d("div","row",p),I=r("postal_code")&&d("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&d("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=d("div","row",p),k=r("state")&&d("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&d("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=d("input","tracking",p,{type:"hidden",configurable:!0}),A=d("input","publishStatus",p,{type:"text"}),j=d("button","publish",p,{});d("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,O="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(O,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!x.val()&&a("line_1"))return u(x);t.customer.address.line_1=x.val()}if(r("line_2")){if(!_.val()&&a("line_2"))return u(_);t.customer.address.line_2=_.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}V.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),x&&x.hide(),_&&_.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(O,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;te||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function c(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var d="https://api.voucherify.io",u={validate:d+"/client/v1/validate",redeem:d+"/client/v1/redeem",publish:d+"/client/v1/publish",list:d+"/client/v1/vouchers",track:d+"/client/v1/events",validatePromotion:d+"/client/v1/promotions/validation",redeemPromotion:d+"/client/v1/promotions/tiers/"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validateVoucher)+l,void 0,t)},redeem:function(e,t,n){var o,i=!1;if(!s(f))return null;if(!e){if(!t.tier)return console.error("Voucherify client could not redeem promotion without tier, because it is missing."),null;i=!0,o=t.tier,delete t.tier}var r="";return i||(r+="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""))),t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",(i?u.redeemPromotion+o+"/redemption":u.redeem)+r,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?d:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=e-n*o;return i(d>0?d:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/s);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=n*o;return i(c>e?e:c)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",c,{type:"hidden",configurable:!0}),v=l("input","percentOff",c,{type:"hidden",configurable:!0}),y=l("input","amountOff",c,{type:"hidden",configurable:!0}),b=l("input","unitOff",c,{type:"hidden",configurable:!0}),C=l("input","tracking",c,{type:"hidden",configurable:!0}),_=l("button","validate",c,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",c,{type:"hidden",configurable:!0}),v=l("button","redeem",c,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function c(e,t){return o[s(e,t)]}function d(e,o,i,r){r=r||{};var a=null,l=c("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var d in r)"configurable"!==d&&r.hasOwnProperty(d)&&a.attr(d,r[d]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof c("class",o)?c("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(O,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(O,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=d("div","container",f);p.addClass("wide");{var m=d("figure","logo",p),g=(d("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&d("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=d("div","row",p),b=r("email")&&d("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&d("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&d("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&d("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=d("div","row",p),I=r("postal_code")&&d("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&d("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=d("div","row",p),k=r("state")&&d("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&d("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=d("input","tracking",p,{type:"hidden",configurable:!0}),A=d("input","publishStatus",p,{type:"text"}),j=d("button","publish",p,{});d("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,O="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(O,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}V.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(O,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;t()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(code) === \"object\") {\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n } else {\n queryString += \"&customer=\" + customer\n }\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!code) {\n console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n return null;\n }\n\n var queryString = \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.redeem + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","validateVoucher","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file From 6a1883942ebc3ac624e3421cb573dfa87cba8967 Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Fri, 27 Apr 2018 07:18:04 +0200 Subject: [PATCH 3/7] WIP --- dist/voucherify.min.js | 4 ---- dist/voucherify.min.js.map | 6 +----- lib/voucherify.js | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/dist/voucherify.min.js b/dist/voucherify.min.js index cfc3564..d63d765 100644 --- a/dist/voucherify.min.js +++ b/dist/voucherify.min.js @@ -1,6 +1,2 @@ -<<<<<<< HEAD window.Voucherify=function(e,t,n){"use strict";function o(e){return e&&("boolean"==typeof e.valid||"string"==typeof e.result||"object"==typeof e.voucher||"object"==typeof e.vouchers||"event"===e.object&&"string"==typeof e.type)}function i(e){return Math.round(100.001*e)/100}function r(e){if(!e||0>e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function c(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var d="https://api.voucherify.io",u={validate:d+"/client/v1/validate",redeem:d+"/client/v1/redeem",publish:d+"/client/v1/publish",list:d+"/client/v1/vouchers",track:d+"/client/v1/events",validatePromotion:d+"/client/v1/promotions/validation",redeemPromotion:d+"/client/v1/promotions/tiers/"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validateVoucher)+l,void 0,t)},redeem:function(e,t,n){var o,i=!1;if(!s(f))return null;if(!e){if(!t.tier)return console.error("Voucherify client could not redeem promotion without tier, because it is missing."),null;i=!0,o=t.tier,delete t.tier}var r="";return i||(r+="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""))),t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",(i?u.redeemPromotion+o+"/redemption":u.redeem)+r,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?d:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=e-n*o;return i(d>0?d:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/s);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=n*o;return i(c>e?e:c)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",c,{type:"hidden",configurable:!0}),v=l("input","percentOff",c,{type:"hidden",configurable:!0}),y=l("input","amountOff",c,{type:"hidden",configurable:!0}),b=l("input","unitOff",c,{type:"hidden",configurable:!0}),C=l("input","tracking",c,{type:"hidden",configurable:!0}),_=l("button","validate",c,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",c,{type:"hidden",configurable:!0}),v=l("button","redeem",c,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function c(e,t){return o[s(e,t)]}function d(e,o,i,r){r=r||{};var a=null,l=c("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var d in r)"configurable"!==d&&r.hasOwnProperty(d)&&a.attr(d,r[d]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof c("class",o)?c("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(O,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(O,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=d("div","container",f);p.addClass("wide");{var m=d("figure","logo",p),g=(d("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&d("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=d("div","row",p),b=r("email")&&d("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&d("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&d("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&d("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=d("div","row",p),I=r("postal_code")&&d("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&d("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=d("div","row",p),k=r("state")&&d("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&d("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=d("input","tracking",p,{type:"hidden",configurable:!0}),A=d("input","publishStatus",p,{type:"text"}),j=d("button","publish",p,{});d("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,O="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(O,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}V.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(O,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;te||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function c(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var d="https://api.voucherify.io",u={validate:d+"/client/v1/validate",redeem:d+"/client/v1/redeem",publish:d+"/client/v1/publish",list:d+"/client/v1/vouchers",track:d+"/client/v1/events",validatePromotion:d+"/client/v1/promotions/validation"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validateVoucher)+l,void 0,t)},redeem:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."),null;var o="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""));return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",u.redeem+o,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?d:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=e-n*o;return i(d>0?d:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/s);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=n*o;return i(c>e?e:c)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",c,{type:"hidden",configurable:!0}),v=l("input","percentOff",c,{type:"hidden",configurable:!0}),y=l("input","amountOff",c,{type:"hidden",configurable:!0}),b=l("input","unitOff",c,{type:"hidden",configurable:!0}),C=l("input","tracking",c,{type:"hidden",configurable:!0}),_=l("button","validate",c,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",c,{type:"hidden",configurable:!0}),v=l("button","redeem",c,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function c(e,t){return o[s(e,t)]}function d(e,o,i,r){r=r||{};var a=null,l=c("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var d in r)"configurable"!==d&&r.hasOwnProperty(d)&&a.attr(d,r[d]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof c("class",o)?c("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(O,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(O,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=d("div","container",f);p.addClass("wide");{var m=d("figure","logo",p),g=(d("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&d("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=d("div","row",p),b=r("email")&&d("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&d("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&d("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&d("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=d("div","row",p),I=r("postal_code")&&d("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&d("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=d("div","row",p),k=r("state")&&d("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&d("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=d("input","tracking",p,{type:"hidden",configurable:!0}),A=d("input","publishStatus",p,{type:"text"}),j=d("button","publish",p,{});d("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,O="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(O,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}V.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(O,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;t>>>>>> 92791991d579dfab95272f67e632f0627c3b4970 //# sourceMappingURL=voucherify.min.js.map diff --git a/dist/voucherify.min.js.map b/dist/voucherify.min.js.map index 281d065..603c7e6 100644 --- a/dist/voucherify.min.js.map +++ b/dist/voucherify.min.js.map @@ -1,5 +1 @@ -<<<<<<< HEAD -{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","validateVoucher","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} -======= -{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","validateVoucher","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"AAAAA,OAAOC,WAAc,SAAUD,EAAQE,EAAUC,GAC/C,YAuBA,SAASC,GAAyBC,GAChC,MAAOA,KAAgC,iBAAhBA,GAAU,OACH,gBAAjBA,GAAW,QACO,gBAAlBA,GAAY,SACO,gBAAnBA,GAAa,UACH,UAAhBA,EAAKC,QAA4C,gBAAfD,GAAS,MAgJpD,QAASE,GAAWC,GAClB,MAAOC,MAAKC,MAAc,QAARF,GAAyB,IAG7C,QAASG,GAAwBC,GAC/B,IAAKA,GAAuB,EAAXA,GAAgBA,EAAW,IAC1C,KAAM,IAAIC,OAAM,8DAIpB,QAASC,GAAuBF,GAC9B,IAAKA,GAAuB,EAAXA,EACf,KAAM,IAAIC,OAAM,8DAIpB,QAASE,GAAqBH,GAC5B,IAAKA,GAAuB,EAAXA,EACf,KAAM,IAAIC,OAAM,4DAIpB,QAASG,GAAYC,GACnB,MAAKA,GAAQC,cAIRD,EAAQC,eAIN,GAHLC,QAAQC,MAAM,4DACP,IALPD,QAAQC,MAAM,wDACP,GAo3BX,QAASC,KAyLP,QAASC,GAAaC,EAASN,GAC7B,GAAIO,GAAOC,IAUX,OARAD,GAAKE,SAAWH,EAEhBC,EAAKG,MAAQV,EAAQW,KAErBJ,EAAKK,SAAWC,EAAQC,YAAYP,EAAKE,SAAUM,EAAkBC,OAAOhB,EAAQiB,aAEpFV,EAAKW,QAAU,KAERV,KAAKW,eAnMd,GAAIC,GAAO,4BACPL,GACF,gBACA,eAEA,QAGEM,GACFC,kBACEX,KAAQ,kBACRM,YACE,aACA,sBACA,mBAEA,eACA,wBACA,qBAEA,aACA,sBACA,mBAEA,cACA,uBACA,oBAEA,cACA,uBACA,oBAEA,uBACA,gCACA,6BAEA,uBACA,gCACA,6BAEA,aACA,sBACA,mBAEA,oBACA,6BACA,0BAEA,cACA,uBACA,oBAEA,gBACA,yBACA,sBAEA,iBAGJM,eACEZ,KAAQ,mBACRM,YACE,WAEA,WACA,SAEA,aACA,sBACA,mBAEA,cACA,uBACA,oBAEA,cACA,uBACA,oBAEA,uBACA,gCACA,6BAEA,uBACA,gCACA,6BAEA,aACA,sBACA,mBAEA,oBACA,6BACA,0BAEA,cACA,uBACA,oBAEA,gBACA,yBACA,sBAEA,iBAGJO,WACEb,KAAQ,qBACRM,YACE,WACA,SAEA,aACA,sBACA,mBAEA,cACA,uBACA,oBAEA,cACA,uBACA,oBAEA,uBACA,gCACA,6BAEA,uBACA,gCACA,6BAEA,aACA,sBACA,mBAEA,oBACA,6BACA,0BAEA,cACA,uBACA,oBAEA,gBACA,yBACA,sBAEA,qBAKFJ,GACFY,KAAM,SAAUnB,EAASoB,EAAMC,GAC7B,MAAIrB,GAAQsB,iBACHtB,EAAQsB,iBAAiBF,EAAMC,GAAU,GAEzCrB,EAAQuB,YAAY,KAAOH,EAAMC,IAG5Cb,YAAa,SAAUR,EAASwB,GAC9B,MAAOC,OAAMC,UAAUC,OAAOC,KAAKJ,EAAiB,SAAU9B,EAASmC,GACrE,GAAIC,GAAe9B,EAAQ+B,aAAa,QAAUF,EAMlD,OAJIC,KACFpC,EAAQmC,GAAkBC,GAGrBpC,QAGXsC,cAAe,SAAUtC,GACvB,GAAIuC,KAMJ,OAJAC,QAAOC,KAAKzC,GAAS0C,QAAQ,SAASC,GACpCJ,EAAiBK,KAAK,aAAaD,EAAW,KAAKE,mBAAmB7C,EAAQ2C,OAGzE,IAAMJ,EAAiBO,KAAK,MAmBvCzC,GAAa2B,UAAUb,aAAe,WACpC,GAAIZ,GAAOC,IAEX,IAAID,EAAKW,QACP,MAAOX,EAGT,IAAIwC,IACF,eACA,gBACA,2BACA,gCACA,sBACA,oBACA,sBACA,aACA,cACA,4CACA,+BAgBF,OAbAxC,GAAKW,QAAUjC,EAAS+D,cAAc,UACtCzC,EAAKW,QAAQ+B,aAAa,cAAe,KACzC1C,EAAKW,QAAQ+B,aAAa,oBAAqB,QAC/C1C,EAAKW,QAAQgC,MAAMC,QAAUJ,EAAUD,KAAK,MAE5CjC,EAAQY,KAAKlB,EAAKW,QAAS,OAAQ,WACjC,MAAOX,GAAKW,QAAQgC,MAAME,WAAa,YAGzC7C,EAAKW,QAAQmC,IAAMjC,EAAOb,EAAKG,MAAQG,EAAQyB,cAAc/B,EAAKK,UAElEL,EAAKE,SAAS6C,YAAY/C,EAAKW,SAExBX,EAGT,IAAIgD,KAUJ,OARAf,QAAOC,KAAKpB,GAAiBqB,QAAQ,SAAUc,GAC7C,GAAIC,GAAW1E,EAAOE,SAASyE,iBAAiB,eAAiBF,EAEjEzB,OAAMC,UAAUU,QAAQR,KAAKuB,EAAU,SAAUnD,GAC/CiD,EAAQX,KAAK,GAAIvC,GAAaC,EAASe,EAAgBmC,SAIpDD,EA7yCT,GAAII,GAAW,4BAEXC,GACAC,SAAUF,EAAW,sBACrBG,OAAUH,EAAW,oBACrBI,QAAUJ,EAAW,qBACrBK,KAAUL,EAAW,sBACrBM,MAAUN,EAAW,oBACrBO,kBAAmBP,EAAW,oCAG9BQ,KAGAC,EAAiB,iBACjBC,EAAiB,iBACjBC,EAAiB,iBACjBC,EAAyB,yBAEzBC,EAAgB,yJAWhBC,EAAoB,IAGtBA,GADIvF,GAAwB,kBAAZA,GAAM,MAAsBA,EAAEwF,SAC1B,SAAUC,EAAQC,EAAKC,EAASlD,GAClD,GAAImD,GAAW,IAkEf,OAhEyB,kBAAf,KACRA,EAAW5F,EAAEwF,YAGfxF,EAAE6F,MACAC,KAAML,EAENC,IAAKA,EAELxF,KAAM6F,KAAKC,UAAUL,GAErBM,WACEC,iBAAiB,GAGnBC,SAAU,OACVC,SACEC,OAAU,mBACVC,eAAgB,mBAChBC,0BAA2BtB,EAAQlE,cACnCyF,iBAAkBvB,EAAQwB,MAC1BC,uBAAwB,iBAE1BC,QAAS1B,EAAQ0B,QAEjBC,QAAS,SAAU1G,GACjB,GAAI2G,GAAS,IAET5G,GAAyBC,GACF,kBAAf,GACRuC,EAASvC,GAET0F,EAASkB,QAAQ5G,IAGnB2G,GACEf,KAAM,QACNiB,QAAS,iCACTC,QAAS9G,GAGc,kBAAf,GACRuC,EAASoE,GAETjB,EAASqB,OAAOJ,KAKtB5F,MAAO,SAAUA,GACf,GAAI4F,IACFf,KAAM,QACNiB,QAAS,sBACTC,QAAS/F,EAGc,mBAAf,GACRwB,EAASoE,GAETjB,EAASqB,OAAOJ,MAKG,kBAAf,GACDjB,EAASsB,UAETC,QAIS,SAAU1B,EAAQC,EAAKC,EAASlD,GAClD,GAAI2E,GAAU,GAAIvH,GAAOwH,cAEzBD,GAAQlB,iBAAkB,EAC1BkB,EAAQE,KAAK7B,EAAQC,GAAK,GAC1B0B,EAAQT,QAAU1B,EAAQ0B,QAE1BS,EAAQG,iBAAiB,SAAU,oBACnCH,EAAQG,iBAAiB,eAAgB,oBACzCH,EAAQG,iBAAiB,0BAA2BtC,EAAQlE,eAC5DqG,EAAQG,iBAAiB,iBAAkBtC,EAAQwB,OACnDW,EAAQG,iBAAiB,uBAAwB,iBAEjDH,EAAQI,OAAS,WACf,GAAIX,GAAS,IAEb,IAAIO,EAAQK,QAAU,KAAOL,EAAQK,OAAS,IAAK,CACjD,GAAIvH,GAAO6F,KAAK2B,MAAMN,EAAQO,aAE1B1H,GAAyBC,GACF,kBAAf,IACRuC,EAASvC,IAGX2G,GACEf,KAAM,QACNiB,QAAS,iCACTC,QAAS9G,GAGc,kBAAf,IACRuC,EAASoE,QAIbA,IACEf,KAAM,QACNiB,QAAS,0BACTC,QAASI,EAAQK,QAGM,kBAAf,IACRhF,EAASoE,IAKfO,EAAQQ,QAAU,SAAU3G,GAC1B,GAAI4F,IACFf,KAAM,QACNiB,QAAS,sBACTC,QAAS/F,EAGc,mBAAf,IACRwB,EAASoE,IAIbO,EAAQS,KAAK9B,KAAKC,UAAUL,IAsChC,IAAImC,IACFC,WAAY,SAAUC,EAAavB,EAAOE,GACxC1B,EAAQlE,cAAgBiH,EACxB/C,EAAQwB,MAAQA,EAChBxB,EAAQ0B,QAAUA,GAAW,KAG/BsB,YAAa,SAAUC,GACrBjD,EAAQiD,WAAaA,GAGvBvD,SAAU,SAAUwD,EAAM1F,GACxB,IAAK5B,EAAYoE,GACf,MAAO,KAGT,IACImD,GACAC,EACAC,EACAC,EAJAC,GAAc,CAMG,iBAAX,KACRJ,EAASD,EAAKC,OACdC,EAAQF,EAAKE,MACbC,EAAWH,EAAKG,SAChBC,EAAWJ,EAAKI,SAChBJ,EAAOA,EAAKA,MAGRA,IACJA,EAAOA,EAAKM,QAAQ,YAAa,IAGnC,IAAIC,GAAc,GA2BlB,IA1BKP,GAMHO,EAAc,QAAU/E,mBAAmBwE,GACvCC,IACFM,GAAe,WAAaC,SAASP,MAPvCI,GAAc,EACXJ,IACDM,GAAe,UAAYC,SAASP,KASpCC,IACFK,GAAe,IAAML,EAAMO,IAAI,SAASC,EAAMC,GAC5C,MAAOxF,QAAOC,KAAKsF,GAAMD,IAAI,SAASG,GACpC,MAAOpF,oBAAmB,QAAUmF,EAAQ,KAAOC,EAAM,KAAO,IAAMpF,mBAAmBkF,EAAKE,MAC7FnF,KAAK,OACPA,KAAK,MAGN0E,IACFI,GAAe,IAAMpF,OAAOC,KAAK+E,GAAUM,IAAI,SAASG,GACtD,MAAOpF,oBAAmB,YAAcoF,EAAM,KAAO,IAAMpF,mBAAmB2E,EAASS,MACtFnF,KAAK,MAGN2E,EAAU,CACZ,GAAwB,gBAAf,GAEP,MADAvH,SAAQC,MAAM,8EACP,IAGTyH,IAAe,IAAMpF,OAAOC,KAAKgF,GAAUK,IAAI,SAAUG,GACvD,MAAOpF,oBAAmB,YAAcoF,EAAM,KAAO,IAAMpF,mBAAmB4E,EAAUQ,MACvFnF,KAAK,KAOV,MAJIqB,GAAQiD,aACVQ,GAAe,gBAAkB/E,mBAAmBsB,EAAQiD,aAGvD3C,EAAkB,OAAQiD,EAAc9D,EAAIM,kBAAoBN,EAAIsE,iBAAmBN,EAAavB,OAAW1E,IAGxHmC,OAAQ,SAAUuD,EAAMxC,EAASlD,GAC/B,IAAK5B,EAAYoE,GACf,MAAO,KAGT,KAAKkD,EAEH,MADAnH,SAAQC,MAAM,iGACP,IAGT,IAAIyH,GAAc,SAAW/E,mBAAmBwE,EAAKM,QAAQ,YAAa,IAO1E,OAJA9C,GAAUA,MACVA,EAAQ4C,SAAW5C,EAAQ4C,aAC3B5C,EAAQ4C,SAASU,UAAYtD,EAAQ4C,SAASU,WAAahE,EAAQiD,WAE5D3C,EAAkB,OAAQb,EAAIE,OAAS8D,EAAa/C,EAASlD,IAGtEoC,QAAS,SAAUqE,EAAUvD,EAASlD,GACpC,IAAK5B,EAAYoE,GACf,MAAO,KAGT,KAAKiE,EAEH,MADAlI,SAAQC,MAAM,mEACP,IAGT,IAAIyH,GAAc,aAAe/E,mBAAmBuF,EASpD,OANAvD,GAAUA,MACVA,EAAQ4C,SAAW5C,EAAQ4C,aAC3B5C,EAAQ4C,SAASU,UAAYtD,EAAQ4C,SAASU,WAAahE,EAAQiD,WAEnEvC,EAAQwD,QAAUxD,EAAQwD,SAAW,gBAE9B5D,EAAkB,OAAQb,EAAIG,QAAU6D,EAAa/C,EAASlD,IAGvE2G,aAAc,SAAUC,EAAS5G,GAC/B,IAAK5B,EAAYoE,GACf,MAAO,KAGc,mBAAZoE,IAA2B5G,IACpCA,EAAW4G,EACXA,KAGF,IAAIX,GAAc,IAAMpF,OAAOC,KAAK8F,GAC3BT,IAAI,SAASG,GACZ,MAAOpF,oBAAmBoF,GAAO,IAAMpF,mBAAmB0F,EAAQN,MAEnEnF,KAAK,IAEd,OAAO2B,GAAkB,MAAOb,EAAII,KAAO4D,EAAavB,OAAW1E,IAGrEsC,MAAO,SAAUuE,EAAYhB,EAAUC,EAAU9F,GAC/C,IAAK5B,EAAYoE,GACf,MAAO,KAGe,mBAAbsD,IAA4B9F,IACrCA,EAAW8F,EACXA,KAGF,IAAI5C,KAMJ,OALAA,GAAQ4D,MAAQD,EAChB3D,EAAQ2C,SAAWA,EACnB3C,EAAQ4C,SAAW5C,EAAQ4C,UAAYA,MACvC5C,EAAQ4C,SAASU,UAAYtD,EAAQ4C,SAASU,WAAahE,EAAQiD,WAE5D3C,EAAkB,OAAQb,EAAIK,MAAOY,EAASlD,IAGvD+G,OACEC,eAAgB,SAAUC,EAAWC,EAASC,GAC5C,GACInJ,GADAoJ,EAAI,GAGR,IAAIF,EAAQG,KAEV,MADArJ,GAAWH,KAAKyJ,IAAIJ,EAAQG,KAAKE,QAAUH,EAAGH,GACvCtJ,EAAWsJ,EAAYjJ,EAGhC,KAAKkJ,EAAQlJ,SACX,KAAM,IAAIC,OAAM,4BAGlB,IAA8B,YAA1BiJ,EAAQlJ,SAASqF,KAAoB,CACvCrF,EAAWkJ,EAAQlJ,SAASwJ,YAC5BzJ,EAAwBC,EACxB,IAAIyJ,GAAgBR,GAAajJ,EAAW,IAM5C,OAJIkJ,GAAQlJ,SAAS0J,eACnBD,EAAgB5J,KAAKyJ,IAAIJ,EAAQlJ,SAAS0J,aAAeN,EAAGK,IAGvD9J,EAAWsJ,EAAYQ,GAEzB,GAA8B,WAA1BP,EAAQlJ,SAASqF,KAAmB,CAC7CrF,EAAWkJ,EAAQlJ,SAAS2J,WAAaP,EACzClJ,EAAuBF,EACvB,IAAI4J,GAAWX,EAAYjJ,CAC3B,OAAOL,GAAWiK,EAAW,EAAIA,EAAW,GAEvC,GAA8B,SAA1BV,EAAQlJ,SAASqF,KAAiB,CAC3CrF,EAAWkJ,EAAQlJ,SAAS6J,SAC5B1J,EAAqBH,EACrB,IAAI4J,GAAWX,EAAYE,EAAYnJ,CACvC,OAAOL,GAAWiK,EAAW,EAAIA,EAAW,GAG5C,KAAM,IAAI3J,OAAM,+BAIpB6J,kBAAmB,SAASb,EAAWC,EAASC,GAC9C,GACInJ,GADAoJ,EAAI,GAGR,IAAIF,EAAQG,KAEV,MADArJ,GAAWH,KAAKyJ,IAAIJ,EAAQG,KAAKE,QAAUH,EAAGH,GACvCtJ,EAAWK,EAGpB,KAAKkJ,EAAQlJ,SACX,KAAM,IAAIC,OAAM,4BAGlB,IAA8B,YAA1BiJ,EAAQlJ,SAASqF,KAAoB,CACvCrF,EAAWkJ,EAAQlJ,SAASwJ,YAC5BzJ,EAAwBC,EACxB,IAAIyJ,GAAgBR,GAAajJ,EAAWoJ,EAM5C,OAJIF,GAAQlJ,SAAS0J,eACnBD,EAAgB5J,KAAKyJ,IAAIJ,EAAQlJ,SAAS0J,aAAeN,EAAGK,IAGvD9J,EAAW8J,GACb,GAA8B,WAA1BP,EAAQlJ,SAASqF,KAAmB,CAC7CrF,EAAWkJ,EAAQlJ,SAAS2J,WAAaP,EACzClJ,EAAuBF,EACvB,IAAI4J,GAAWX,EAAYjJ,CAC3B,OAAOL,GAAWiK,EAAW,EAAI5J,EAAWiJ,GAEvC,GAA8B,SAA1BC,EAAQlJ,SAASqF,KAAiB,CAC3CrF,EAAWkJ,EAAQlJ,SAAS6J,SAC5B1J,EAAqBH,EACrB,IAAIyJ,GAAgBN,EAAYnJ,CAChC,OAAOL,GAAW8J,EAAgBR,EAAYA,EAAYQ,GAG1D,KAAM,IAAIxJ,OAAM,gCAItB8J,OAAQ,SAASC,EAAU3J,GAOzB,QAAS4J,GAAmBlI,GAC1B,MAAOA,GAAKmI,OAAO,GAAGC,cAAgBpI,EAAKqI,MAAM,GAGnD,QAASC,GAAgBC,EAAQvI,GAC/B,MAAOuI,GAASL,EAAmBlI,GAGrC,QAASwI,GAAkBD,EAAQvI,GACjC,MAAO1B,GAAQgK,EAAgBC,EAAQvI,IAGzC,QAASyI,GAAenF,EAAMtD,EAAM0I,EAAYC,GAC9CA,EAASA,KACT,IAAIC,GAAW,KACXC,EAAqBL,EAAkB,WAAYxI,EAMvD,IAJI2I,EAAOG,cAAgBD,IACzBD,EAAWpL,EAAEqL,KAGVD,IAAaA,EAASG,OAAQ,CACjCH,EAAWpL,EAAED,EAAS+D,cAAcgC,IACpCoF,EAAWM,OAAOJ,EAElB,KAAK,GAAIK,KAAaN,GACF,iBAAdM,GAAgCN,EAAOO,eAAeD,IACxDL,EAASO,KAAKF,EAAWN,EAAOM,GAIvB,WAAT3F,GACFsF,EAASO,KAAK,OAAQb,EAAgB,aAActI,IAGzC,SAATsD,GAAmBqF,EAAOS,MAC5BR,EAASQ,KAAKT,EAAOS,MAKzB,MADAR,GAASS,SAAqD,gBAArCb,GAAkB,QAASxI,GAAqBwI,EAAkB,QAASxI,GAAQsI,EAAgB,aAActI,IACnI4I,EA/CT,GAAIU,GAAW9L,EAAEyK,EACjB,KAAKqB,IAAaA,EAASP,OACzB,KAAM,IAAI7K,OAAM,YAAc+J,EAAW,oBAE3C3J,GAAUA,KA8CV,IAAIoK,GAAiBD,EAAe,MAAO,YAAaa,GACpDC,EAAiBd,EAAe,SAAU,OAAQC,GAElDc,GADiBf,EAAe,MAAO,OAAQc,GAAkB5H,IAAgC,gBAApBrD,GAAQmL,QAAuBnL,EAAQmL,QAAU,iDAC7GhB,EAAe,QAAS,OAAQC,GAAcpF,KAAM,OAAQoG,YAAgD,gBAA5BpL,GAAQqL,gBAA+BrL,EAAQqL,gBAAkB,kBAClKC,EAAiBnB,EAAe,QAAS,SAAUC,GAAcpF,KAAMhF,EAAQsH,OAAS,OAAS,SAAU8D,YAAkD,gBAA9BpL,GAAQuL,kBAAiCvL,EAAQuL,kBAAoB,eACpMC,EAAiBrB,EAAe,QAAS,eAAgBC,GAAcpF,KAAM,SAAUwF,cAAc,IACrGiB,EAAiBtB,EAAe,QAAS,aAAcC,GAAcpF,KAAM,SAAUwF,cAAc,IACnGkB,EAAiBvB,EAAe,QAAS,YAAaC,GAAcpF,KAAM,SAAUwF,cAAc,IAClGmB,EAAiBxB,EAAe,QAAS,UAAWC,GAAcpF,KAAM,SAAUwF,cAAc,IAChGoB,EAAiBzB,EAAe,QAAS,WAAYC,GAAcpF,KAAM,SAAUwF,cAAc,IACjGqB,EAAiB1B,EAAe,SAAU,WAAYC,MAGtD7J,GAFiB4J,EAAe,OAAQ,eAAgB0B,GAAaf,KAAsC,gBAAzB9K,GAAQ8L,aAA4B9L,EAAQ8L,aAAe,aAEtItL,MACPuL,EAAwC,WAAzB/L,EAAQ+L,aAA4B/L,EAAQ+L,aAAe,oBAC1EC,EAA2C,gBAAvBhM,GAAQgM,WAA0BhM,EAAQgM,WAAa,kBAC3EC,EAA0D,WAAlCjM,EAAQiM,sBAAqCjM,EAAQiM,sBAAwB,2BACrGC,EAAsD,WAAhClM,EAAQkM,oBAAmClM,EAAQkM,oBAAsB,yBAEnGhB,GAAMiB,GAAG,QAAS,SAAS1D,GACzByC,EAAMkB,YAAYH,GAAuB,KAG3CX,EAAQa,GAAG,QAAS,SAAS1D,GAC3B6C,EAAQc,YAAYH,GAAuB,KAG7CJ,EAAUM,GAAG,QAAS,SAAS1D,GAU7B,GATA+C,EAAca,IAAI,IAClBX,EAAWW,IAAI,IACfV,EAASU,IAAI,IACbZ,EAAYY,IAAI,IAChBT,EAAUS,IAAI,IAEdR,EAAUO,YAAYL,GAAc,GACpCF,EAAUO,YAAYJ,GAAY,IAE7Bd,EAAMmB,MAOT,WANAnB,GAAMkB,YAAYH,GAAuB,GACtCK,MAAM,KACNC,MAAM,WACLrB,EAAMkB,YAAYH,GAAuB,GACzCf,EAAMsB,WAKZ,IAAI3H,IACFwC,KAAM6D,EAAMmB,MACZ/E,OAAQO,SAAwD,IAA/C4E,WAAWnB,EAAQe,MAAM1E,QAAQ,KAAM,OAG1DpH,GAAKsD,SAASgB,EAAS,SAAS6H,GAC9B,IAAKA,IAAaA,EAASC,MAAO,CAEhC,GAAIC,GAAkB,SAAUC,GAC9BA,EAAOT,YAAYL,GAAc,GACjCc,EAAOT,YAAYJ,GAAY,GAC/Ba,EAAOT,YAAYH,GAAuB,GACzCK,MAAM,KACNC,MAAM,WACLM,EAAOT,YAAYH,GAAuB,GAC1CY,EAAOL,YAIXX,GAAUO,YAAYL,GAAc,GACpCF,EAAUO,YAAYJ,GAAY,EAElC,IAAI9F,GAAkBwG,EAASxG,YAC3B4G,EAAkB5G,EAAQ4G,iBAC1BC,EAAkBD,EAAa7E,GAUnC,YAFE2E,IANE5M,EAAQsH,QACRyF,IAAc3I,GACd2I,IAAc1I,GACd0I,IAAczI,EAGA4G,EAFAI,GAOhBA,EAAQe,OAAS,EACnBf,EAAQe,IAAII,WAAWnB,EAAQe,MAAM1E,QAAQ,KAAM,OAEnD2D,EAAQ0B,KAAK,KAGf9B,EAAMkB,YAAYL,GAAc,GAChCT,EAAQc,YAAYL,GAAc,GAClCP,EAAca,IAAIK,EAAS/M,UAAY+M,EAAS/M,SAASqF,MAAQ,IACjE0G,EAAWW,IAAIK,EAAS/M,UAAY+M,EAAS/M,SAAS2J,YAAc,GACpEqC,EAASU,IAAIK,EAAS/M,UAAY+M,EAAS/M,SAAS6J,UAAY,GAChEiC,EAAYY,IAAIK,EAAS/M,UAAY+M,EAAS/M,SAASwJ,aAAe,GACtEyC,EAAUS,IAAIK,EAASO,aAAe,IAEtC/B,EAAMgC,KAAK,YAAY,GACvB5B,EAAQ4B,KAAK,YAAY,GACzBrB,EAAUqB,KAAK,YAAY,GAE3BhC,EAAMkB,YAAYJ,GAAY,GAC9BV,EAAQc,YAAYJ,GAAY,GAChCH,EAAUO,YAAYJ,GAAY,GAClCH,EAAUO,YAAYL,GAAc,GACpCb,EAAMkB,YAAYL,GAAc,GAEhCb,EAAMkB,YAAYF,GAAqB,GACvCZ,EAAQc,YAAYF,GAAqB,GAErClM,GAAWA,EAAQmN,aAA8C,kBAAxBnN,GAAQmN,aACnDnN,EAAQmN,YAAYT,QAM5BU,aAAc,SAASzD,EAAU3J,GAO/B,QAAS4J,GAAmBlI,GAC1B,MAAOA,GAAKmI,OAAO,GAAGC,cAAgBpI,EAAKqI,MAAM,GAGnD,QAASC,GAAgBC,EAAQvI,GAC/B,MAAOuI,GAASL,EAAmBlI,GAGrC,QAASwI,GAAkBD,EAAQvI,GACjC,MAAO1B,GAAQgK,EAAgBC,EAAQvI,IAGzC,QAASyI,GAAenF,EAAMtD,EAAM0I,EAAYC,GAC9CA,EAASA,KACT,IAAIC,GAAW,KACXC,EAAqBL,EAAkB,WAAYxI,EAMvD,IAJI2I,EAAOG,cAAgBD,IACzBD,EAAWpL,EAAEqL,KAGVD,IAAaA,EAASG,OAAQ,CACjCH,EAAWpL,EAAED,EAAS+D,cAAcgC,IACpCoF,EAAWM,OAAOJ,EAElB,KAAK,GAAIK,KAAaN,GACF,iBAAdM,GAAgCN,EAAOO,eAAeD,IACxDL,EAASO,KAAKF,EAAWN,EAAOM,GAIvB,WAAT3F,GACFsF,EAASO,KAAK,OAAQb,EAAgB,aAActI,IAGzC,SAATsD,GAAmBqF,EAAOS,MAC5BR,EAASQ,KAAKT,EAAOS,MAKzB,MADAR,GAASS,SAAqD,gBAArCb,GAAkB,QAASxI,GAAqBwI,EAAkB,QAASxI,GAAQsI,EAAgB,aAActI,IACnI4I,EA/CT,GAAIU,GAAW9L,EAAEyK,EACjB,KAAKqB,IAAaA,EAASP,OACzB,KAAM,IAAI7K,OAAM,YAAc+J,EAAW,oBAE3C3J,GAAUA,KA8CV,IAAIoK,GAAiBD,EAAe,MAAO,YAAaa,GACpDC,EAAiBd,EAAe,SAAU,OAAQC,GAElDc,GADiBf,EAAe,MAAO,OAAQc,GAAkB5H,IAAgC,gBAApBrD,GAAQmL,QAAuBnL,EAAQmL,QAAU,iDAC7GhB,EAAe,QAAS,OAAQC,GAAcpF,KAAM,OAAQoG,YAAgD,gBAA5BpL,GAAQqL,gBAA+BrL,EAAQqL,gBAAkB,kBAClKC,EAAiBnB,EAAe,QAAS,SAAUC,GAAcpF,KAAMhF,EAAQsH,OAAS,OAAS,SAAU8D,YAAkD,gBAA9BpL,GAAQuL,kBAAiCvL,EAAQuL,kBAAoB,eACpMK,EAAiBzB,EAAe,QAAS,WAAYC,GAAcpF,KAAM,SAAUwF,cAAc,IACjG6C,EAAelD,EAAe,SAAU,SAAUC,MAGlD7J,GAFe4J,EAAe,OAAQ,aAAckD,GAAWvC,KAAoC,gBAAvB9K,GAAQsN,WAA0BtN,EAAQsN,WAAa,WAE5H9M,MACPuL,EAAwC,WAAzB/L,EAAQ+L,aAA4B/L,EAAQ+L,aAAe,oBAC1EC,EAA2C,gBAAvBhM,GAAQgM,WAA0BhM,EAAQgM,WAAa,kBAC3EC,EAA0D,WAAlCjM,EAAQiM,sBAAqCjM,EAAQiM,sBAAwB,2BACrGC,EAAsD,WAAhClM,EAAQkM,oBAAmClM,EAAQkM,oBAAsB,yBAEnGhB,GAAMiB,GAAG,QAAS,SAAS1D,GACzByC,EAAMkB,YAAYH,GAAuB,KAG3CX,EAAQa,GAAG,QAAS,SAAS1D,GAC3B6C,EAAQc,YAAYH,GAAuB,KAG7CoB,EAAQlB,GAAG,QAAS,SAAS1D,GAM3B,GALAmD,EAAUS,IAAI,IAEdgB,EAAQjB,YAAYL,GAAc,GAClCsB,EAAQjB,YAAYJ,GAAY,IAE3Bd,EAAMmB,MAOT,WANAnB,GAAMkB,YAAYH,GAAuB,GACtCK,MAAM,KACNC,MAAM,WACLrB,EAAMkB,YAAYH,GAAuB,GACzCf,EAAMsB,WAKZ,IAAI3H,IACF0I,OACEjG,OAAQO,SAAwD,IAA/C4E,WAAWnB,EAAQe,MAAM1E,QAAQ,KAAM,QAI5DpH,GAAKuD,OAAOoH,EAAMmB,MAAOxH,EAAS,SAAS6H,GACzC,IAAKA,GAAgC,YAApBA,EAAS3G,OAAsB,CAE9C,GAAI6G,GAAkB,SAAUC,GAC9BA,EAAOT,YAAYL,GAAc,GACjCc,EAAOT,YAAYJ,GAAY,GAC/Ba,EAAOT,YAAYH,GAAuB,GACvCK,MAAM,KACNC,MAAM,WACLM,EAAOT,YAAYH,GAAuB,GAC1CY,EAAOL,YAIba,GAAQjB,YAAYL,GAAc,GAClCsB,EAAQjB,YAAYJ,GAAY,EAEhC,IAAI9F,GAAkBwG,EAASxG,YAC3B4G,EAAkB5G,EAAQ4G,iBAC1BC,EAAkBD,EAAa7E,GAUnC,YAFE2E,IANE5M,EAAQsH,QACRyF,IAAc3I,GACd2I,IAAc1I,GACd0I,IAAczI,EAGA4G,EAFAI,GAOhBA,EAAQe,OAAS,EACnBf,EAAQe,IAAII,WAAWnB,EAAQe,MAAM1E,QAAQ,KAAM,OAEnD2D,EAAQ0B,KAAK,KAGf9B,EAAMkB,YAAYL,GAAc,GAChCT,EAAQc,YAAYL,GAAc,GAClCH,EAAUS,IAAIK,EAASO,aAAe,IAEtC/B,EAAMgC,KAAK,YAAY,GACvB5B,EAAQ4B,KAAK,YAAY,GACzBG,EAAQH,KAAK,YAAY,GAEzBhC,EAAMkB,YAAYJ,GAAY,GAC9BV,EAAQc,YAAYJ,GAAY,GAChCqB,EAAQjB,YAAYJ,GAAY,GAChCqB,EAAQjB,YAAYL,GAAc,GAClCb,EAAMkB,YAAYL,GAAc,GAEhCb,EAAMkB,YAAYF,GAAqB,GACvCZ,EAAQc,YAAYF,GAAqB,GAErClM,GAAWA,EAAQwN,UAAwC,kBAArBxN,GAAQwN,UAChDxN,EAAQwN,SAASd,QAMzBe,cAAgB,SAAU9D,EAAU3J,GAYlC,QAAS0N,GAASC,EAAKT,GACrB,MAAOnL,OAAMC,UAAU4L,KAAK1L,KAAKyL,MAAW,SAAUE,GACpD,MAAOA,GAAMnM,OAASwL,IAI1B,QAASY,GAAiBZ,GACtB,MAAOQ,GAAS1N,EAAQ+N,eAAgBb,GAG5C,QAASc,GAAWd,GAChB,GAAIW,GAAQ9L,MAAMC,UAAUiM,KAAK/L,KAAKlC,EAAQ+N,mBAAsB,SAAUF,GAC1E,MAAOA,GAAMnM,OAASwL,GAG1B,OAAOW,IAASA,EAAMK,WAAY,EAGtC,QAAStE,GAAmBlI,GAC1B,MAAOA,GAAKmI,OAAO,GAAGC,cAAgBpI,EAAKqI,MAAM,GAGnD,QAASC,GAAgBC,EAAQvI,GAC/B,MAAOuI,GAASL,EAAmBlI,GAGrC,QAASwI,GAAkBD,EAAQvI,GACjC,MAAO1B,GAAQgK,EAAgBC,EAAQvI,IAGzC,QAASyI,GAAenF,EAAMtD,EAAM0I,EAAYC,GAC9CA,EAASA,KACT,IAAIC,GAAW,KACXC,EAAqBL,EAAkB,WAAYxI,EAMvD,IAJI2I,EAAOG,cAAgBD,IACzBD,EAAWpL,EAAEqL,KAGVD,IAAaA,EAASG,OAAQ,CACjCH,EAAWpL,EAAED,EAAS+D,cAAcgC,IACpCoF,EAAWM,OAAOJ,EAElB,KAAK,GAAIK,KAAaN,GACF,iBAAdM,GAAgCN,EAAOO,eAAeD,IACxDL,EAASO,KAAKF,EAAWN,EAAOM,GAIvB,WAAT3F,GACFsF,EAASO,KAAK,OAAQb,EAAgB,aAActI,IAGzC,SAATsD,GAAmBqF,EAAOS,MAC5BR,EAASQ,KAAKT,EAAOS,MAKzB,MADAR,GAASS,SAAqD,gBAArCb,GAAkB,QAASxI,GAAqBwI,EAAkB,QAASxI,GAAQsI,EAAgB,aAActI,IACnI4I,EAoCT,QAAS6D,GAAc7D,GACrBA,EAAS8B,YAAYL,GAAc,GACnCzB,EAAS8B,YAAYJ,GAAY,GACjC1B,EAAS8B,YAAYH,GAAuB,GACzCK,MAAM,KACNC,MAAM,WACLjC,EAAS8B,YAAYH,GAAuB,GAC5C3B,EAAS8B,YAAYL,GAAc,GACnCzB,EAAS8B,YAAYJ,GAAY,GACjC1B,EAASkC,YAnHf,GAAIxB,GAAW9L,EAAEyK,EACjB,KAAKqB,IAAaA,EAASP,OACzB,KAAM,IAAI7K,OAAM,YAAc+J,EAAW,oBAK3C,IAFA3J,EAAUA,OAELA,EAAQoO,aACX,KAAM,IAAIxO,OAAM,uCAiElB,IAAIwK,GAAiBD,EAAe,MAAO,YAAaa,EACxDZ,GAAWW,SAAS,OACpB,EAAA,GAAIE,GAAiBd,EAAe,SAAU,OAAQC,GAGlDiE,GAFiBlE,EAAe,MAAO,OAAQc,GAAkB5H,IAAgC,gBAApBrD,GAAQmL,QAAuBnL,EAAQmL,QAAU,iDAE7G2C,EAAiB,SAAW3D,EAAe,QAAS,eAAgBC,GAAcpF,KAAM,OAAQoG,YAAwD,gBAApCpL,GAAQsO,wBAAuCtO,EAAQsO,wBAA0B,UACtNC,EAAiBpE,EAAe,MAAO,MAAOC,GAC9CoE,EAAiBV,EAAiB,UAAY3D,EAAe,QAAS,gBAAiBoE,GAASvJ,KAAM,QAASoG,YAAyD,gBAArCpL,GAAQyO,yBAAwCzO,EAAQyO,yBAA2B,UACtNC,EAAiBZ,EAAiB,UAAY3D,EAAe,QAAS,gBAAiBoE,GAASvJ,KAAM,OAAQoG,YAAyD,gBAArCpL,GAAQ2O,yBAAwC3O,EAAQ2O,yBAA2B,UACrNC,EAAiBd,EAAiB,WAAa3D,EAAe,QAAS,gBAAiBC,GAAcpF,KAAM,OAAQoG,YAAyD,gBAArCpL,GAAQ6O,yBAAwC7O,EAAQ6O,yBAA2B,mBAC3NC,EAAiBhB,EAAiB,WAAa3D,EAAe,QAAS,gBAAiBC,GAAcpF,KAAM,OAAQoG,YAAyD,gBAArCpL,GAAQ+O,yBAAwC/O,EAAQ+O,yBAA2B,mBAC3NC,EAAiB7E,EAAe,MAAO,MAAOC,GAC9C6E,EAAsBnB,EAAiB,gBAAkB3D,EAAe,QAAS,qBAAsB6E,GAAShK,KAAM,OAAQoG,YAA8D,gBAA1CpL,GAAQkP,8BAA6ClP,EAAQkP,8BAAgC,gBAC/OC,EAAgBrB,EAAiB,SAAW3D,EAAe,QAAS,eAAgB6E,GAAShK,KAAM,OAAQoG,YAAwD,gBAApCpL,GAAQoP,wBAAuCpP,EAAQoP,wBAA0B,SAChNC,EAAiBlF,EAAe,MAAO,MAAOC,GAC9CkF,EAAiBxB,EAAiB,UAAY3D,EAAe,QAAS,gBAAiBkF,GAASrK,KAAM,OAAQoG,YAAyD,gBAArCpL,GAAQuP,yBAAwCvP,EAAQuP,yBAA2B,UACrNC,EAAmB1B,EAAiB,YAAc3D,EAAe,QAAS,kBAAmBkF,GAASrK,KAAM,OAAQoG,YAA2D,gBAAvCpL,GAAQyP,2BAA0CzP,EAAQyP,2BAA6B,YAE/N7D,EAAiBzB,EAAe,QAAS,WAAYC,GAAcpF,KAAM,SAAUwF,cAAc,IAEjGkF,EAAiBvF,EAAe,QAAS,gBAAiBC,GAAcpF,KAAM,SAE9E2K,EAAiBxF,EAAe,SAAU,UAAWC,KACpCD,GAAe,OAAQ,cAAewF,GAAY7E,KAAqC,gBAAxB9K,GAAQ4P,YAA2B5P,EAAQ4P,YAAc,gBAE7IF,EAAexC,KAAK,YAAY,GAAMF,MAEtC,IAAIzM,GAAOC,KACPuL,EAAwC,WAAzB/L,EAAQ+L,aAA4B/L,EAAQ+L,aAAe,oBAC1EC,EAA2C,gBAAvBhM,GAAQgM,WAA0BhM,EAAQgM,WAAa,kBAC3EC,EAA0D,WAAlCjM,EAAQiM,sBAAqCjM,EAAQiM,sBAAwB,2BACrGC,EAAsD,WAAhClM,EAAQkM,oBAAmClM,EAAQkM,oBAAsB,yBAenGyD,GAASxD,GAAG,QAAS,SAAS1D,GAC5BmD,EAAUS,IAAI,IAEdsD,EAASvD,YAAYL,GAAc,GACnC4D,EAASvD,YAAYJ,GAAY,EAEjC,IAAInH,IACF4C,YAGF,IAAIqG,EAAiB,QAAS,CAC5B,IAAKO,EAAchC,OAAS2B,EAAW,QACrC,MAAOG,GAAcE,EAEvBxJ,GAAQ4C,SAAe,KAAI4G,EAAchC,MAG3C,GAAIyB,EAAiB,SAAU,CAC7B,IAAKU,EAAenC,OAAS2B,EAAW,SACpC,MAAOG,GAAcK,EAEzB,IAAIA,EAAenC,QAAU7H,EAAcqL,KAAKrB,EAAenC,OAC3D,MAAO8B,GAAcK,EAEzB3J,GAAQ4C,SAAgB,MAAI+G,EAAenC,MAC3CxH,EAAQ4C,SAAoB,UAAI5C,EAAQ4C,SAAgB,MAG1D,GAAIqG,EAAiB,SAAW,CAC9B,IAAKY,EAAerC,OAAS2B,EAAW,SACpC,MAAOG,GAAcO,EAErBA,GAAerC,QACjBxH,EAAQ4C,SAAgB,MAAIiH,EAAerC,OAa/C,IATIyB,EAAiB,WACjBA,EAAiB,WACjBA,EAAiB,gBACjBA,EAAiB,SACjBA,EAAiB,UACjBA,EAAiB,cACnBjJ,EAAQ4C,SAAkB,YAGxBqG,EAAiB,UAAW,CAC9B,IAAKc,EAAevC,OAAS2B,EAAW,UACtC,MAAOG,GAAcS,EAEvB/J,GAAQ4C,SAAkB,QAAU,OAAImH,EAAevC,MAGzD,GAAIyB,EAAiB,UAAW,CAC9B,IAAKgB,EAAezC,OAAS2B,EAAW,UACtC,MAAOG,GAAcW,EAEvBjK,GAAQ4C,SAAkB,QAAU,OAAIqH,EAAezC,MAGzD,GAAIyB,EAAiB,eAAgB,CACnC,IAAKmB,EAAoB5C,OAAS2B,EAAW,eAC3C,MAAOG,GAAcc,EAEvBpK,GAAQ4C,SAAkB,QAAe,YAAIwH,EAAoB5C,MAGnE,GAAIyB,EAAiB,QAAS,CAC5B,IAAKqB,EAAc9C,OAAS2B,EAAW,QACrC,MAAOG,GAAcgB,EAEvBtK,GAAQ4C,SAAkB,QAAQ,KAAI0H,EAAc9C,MAGtD,GAAIyB,EAAiB,SAAU,CAC7B,IAAKwB,EAAejD,OAAS2B,EAAW,SACtC,MAAOG,GAAcmB,EAEvBzK,GAAQ4C,SAAkB,QAAS,MAAI6H,EAAejD,MAGxD,GAAIyB,EAAiB,WAAY,CAC/B,IAAK0B,EAAiBnD,OAAS2B,EAAW,WACxC,MAAOG,GAAcqB,EAEvB3K,GAAQ4C,SAAkB,QAAW,QAAI+H,EAAiBnD,MAG5D9L,EAAKwD,QAAQ/D,EAAQoO,aAAcvJ,EAAS,SAAS6H,GACnD,IAAKA,IAAaA,EAAS7D,UAAY6D,EAAS7D,QAAQxB,KAAM,CAC5D,GAAInB,GAAkBwG,EAASxG,YAC3B4G,EAAkB5G,EAAQ4G,iBAC1BC,EAAkBD,EAAa7E,GAQnC,OANAkG,GAAcwB,QAEV7B,EAAiB,UAAYf,IAAcxI,GAC7C4J,EAAcO,IAMlBL,GAAiBA,EAAcrB,OAC/BwB,GAAkBA,EAAexB,OACjC0B,GAAkBA,EAAe1B,OACjC4B,GAAkBA,EAAe5B,OACjC8B,GAAkBA,EAAe9B,OACjCiC,GAAuBA,EAAoBjC,OAC3CmC,GAAiBA,EAAcnC,OAC/BsC,GAAkBA,EAAetC,OACjCwC,GAAoBA,EAAiBxC,OAErC0C,EACKtD,YAAYF,GAAqB,GACjCG,IAAIK,EAAS7D,QAAQxB,MAAMyI,KAAK,KAErClE,EAAUS,IAAIK,EAASO,aAAe,IAEtC0C,EAASzC,KAAK,YAAY,GAE1ByC,EACKvD,YAAYL,GAAc,GAC1BiB,OAEDhN,GAAWA,EAAQ+P,aAA8C,kBAAxB/P,GAAQ+P,aACnD/P,EAAQ+P,YAAYrD,QAkU9B,OA3TA,UAAUsD,EAAUC,GAalB,QAASC,KACP,IAAKC,EAAY,CACfA,GAAa,CACb,KAAK,GAAIC,GAAI,EAAGA,EAAIC,EAAU5F,OAAQ2F,IACpCC,EAAUD,GAAGE,GAAGpO,KAAKnD,EAAQsR,EAAUD,GAAGG,IAE5CF,OAIJ,QAASG,KACsB,aAAxBvR,EAASwR,YACZP,IAtBJ,GAAKD,EAAL,CAIAD,EAAWA,GAAY,WACvBC,EAAUA,GAAWlR,CACrB,IAAIsR,MACAF,GAAa,EACbO,GAA8B,CAkBlCT,GAAQD,GAAY,SAASrO,EAAUuE,GACrC,GAAwB,kBAAbvE,GACT,KAAM,IAAIgP,WAAU,+CAEtB,OAAIR,OACFS,YAAW,WAAYjP,EAASuE,IAAY,IAG5CmK,EAAUzN,MAAM0N,GAAI3O,EAAU4O,IAAKrK,SAET,aAAxBjH,EAASwR,aAA+BxR,EAAS4C,aAAuC,gBAAxB5C,EAASwR,WAC3EG,WAAWV,EAAO,GACRQ,IACNzR,EAAS2C,kBACX3C,EAAS2C,iBAAiB,mBAAoBsO,GAAO,GACrDnR,EAAO6C,iBAAiB,OAAQsO,GAAO,KAEvCjR,EAAS4C,YAAY,qBAAsB2O,GAC3CzR,EAAO8C,YAAY,SAAUqO,IAE/BQ,GAA8B,QAGjC,WAAY3R,GA2PXA,GACFA,EAAO8R,SAAS,WACd3Q,QAAQ4Q,KAAK,8CACb1Q,MAKkB,mBAAX2Q,SAA0BA,OAAOC,UAC1CD,OAAOC,QAAUhK,GAGZA,GACNjI,OAAQA,OAAOE,SAAUF,OAAOkS","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!code) {\n console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n return null;\n }\n\n var queryString = \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.redeem + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} ->>>>>>> 92791991d579dfab95272f67e632f0627c3b4970 +{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","validateVoucher","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/lib/voucherify.js b/lib/voucherify.js index b66b554..5fd1d61 100644 --- a/lib/voucherify.js +++ b/lib/voucherify.js @@ -282,7 +282,7 @@ window.Voucherify = (function (window, document, $) { queryString += "&tracking_id=" + encodeURIComponent(OPTIONS.trackingId); } - return xhrImplementation("GET", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback); + return xhrImplementation("GET", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback); }, redeem: function (code, payload, callback) { From c816a6a68dbf4357ca8edae6707a5bf5a6f29a50 Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Fri, 27 Apr 2018 07:18:20 +0200 Subject: [PATCH 4/7] WIP --- dist/voucherify.js | 2 +- dist/voucherify.min.js | 2 +- dist/voucherify.min.js.map | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/voucherify.js b/dist/voucherify.js index b66b554..5fd1d61 100644 --- a/dist/voucherify.js +++ b/dist/voucherify.js @@ -282,7 +282,7 @@ window.Voucherify = (function (window, document, $) { queryString += "&tracking_id=" + encodeURIComponent(OPTIONS.trackingId); } - return xhrImplementation("GET", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback); + return xhrImplementation("GET", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback); }, redeem: function (code, payload, callback) { diff --git a/dist/voucherify.min.js b/dist/voucherify.min.js index d63d765..aa3659f 100644 --- a/dist/voucherify.min.js +++ b/dist/voucherify.min.js @@ -1,2 +1,2 @@ -window.Voucherify=function(e,t,n){"use strict";function o(e){return e&&("boolean"==typeof e.valid||"string"==typeof e.result||"object"==typeof e.voucher||"object"==typeof e.vouchers||"event"===e.object&&"string"==typeof e.type)}function i(e){return Math.round(100.001*e)/100}function r(e){if(!e||0>e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function c(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var d="https://api.voucherify.io",u={validate:d+"/client/v1/validate",redeem:d+"/client/v1/redeem",publish:d+"/client/v1/publish",list:d+"/client/v1/vouchers",track:d+"/client/v1/events",validatePromotion:d+"/client/v1/promotions/validation",redeemPromotion:d+"/client/v1/promotions/tiers/"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validateVoucher)+l,void 0,t)},redeem:function(e,t,n){var o,i=!1;if(!s(f))return null;if(!e){if(!t.tier)return console.error("Voucherify client could not redeem promotion without tier, because it is missing."),null;i=!0,o=t.tier,delete t.tier}var r="";return i||(r+="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""))),t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",(i?u.redeemPromotion+o+"/redemption":u.redeem)+r,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?d:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=e-n*o;return i(d>0?d:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/s);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=n*o;return i(c>e?e:c)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",c,{type:"hidden",configurable:!0}),v=l("input","percentOff",c,{type:"hidden",configurable:!0}),y=l("input","amountOff",c,{type:"hidden",configurable:!0}),b=l("input","unitOff",c,{type:"hidden",configurable:!0}),C=l("input","tracking",c,{type:"hidden",configurable:!0}),_=l("button","validate",c,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",c,{type:"hidden",configurable:!0}),v=l("button","redeem",c,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function c(e,t){return o[s(e,t)]}function d(e,o,i,r){r=r||{};var a=null,l=c("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var d in r)"configurable"!==d&&r.hasOwnProperty(d)&&a.attr(d,r[d]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof c("class",o)?c("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(O,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(O,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=d("div","container",f);p.addClass("wide");{var m=d("figure","logo",p),g=(d("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&d("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=d("div","row",p),b=r("email")&&d("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&d("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&d("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&d("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=d("div","row",p),I=r("postal_code")&&d("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&d("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=d("div","row",p),k=r("state")&&d("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&d("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=d("input","tracking",p,{type:"hidden",configurable:!0}),A=d("input","publishStatus",p,{type:"text"}),j=d("button","publish",p,{});d("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,O="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(O,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}V.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(O,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;te||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function d(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var c="https://api.voucherify.io",u={validate:c+"/client/v1/validate",redeem:c+"/client/v1/redeem",publish:c+"/client/v1/publish",list:c+"/client/v1/vouchers",track:c+"/client/v1/events",validatePromotion:c+"/client/v1/promotions/validation",redeemPromotion:c+"/client/v1/promotions/tiers/"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validate)+l,void 0,t)},redeem:function(e,t,n){var o,i=!1;if(!s(f))return null;if(!e){if(!t.tier)return console.error("Voucherify client could not redeem promotion without tier, because it is missing."),null;i=!0,o=t.tier,delete t.tier}var r="";return i||(r+="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""))),t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",(i?u.redeemPromotion+o+"/redemption":u.redeem)+r,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var d=e*(o/100);return t.discount.amount_limit&&(d=Math.min(t.discount.amount_limit/s,d)),i(e-d)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var c=e-o;return i(c>0?c:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=e-n*o;return i(c>0?c:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var d=e*(o/s);return t.discount.amount_limit&&(d=Math.min(t.discount.amount_limit/s,d)),i(d)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var c=e-o;return i(c>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=n*o;return i(d>e?e:d)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,d=a("selector",o);if(l.configurable&&d&&(s=n(d)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var c in l)"configurable"!==c&&l.hasOwnProperty(c)&&s.attr(c,l[c]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var d=l("div","container",s),c=l("figure","logo",d),u=(l("img","logo",c,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",d,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",d,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",d,{type:"hidden",configurable:!0}),v=l("input","percentOff",d,{type:"hidden",configurable:!0}),y=l("input","amountOff",d,{type:"hidden",configurable:!0}),b=l("input","unitOff",d,{type:"hidden",configurable:!0}),C=l("input","tracking",d,{type:"hidden",configurable:!0}),_=l("button","validate",d,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,d=a("selector",o);if(l.configurable&&d&&(s=n(d)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var c in l)"configurable"!==c&&l.hasOwnProperty(c)&&s.attr(c,l[c]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var d=l("div","container",s),c=l("figure","logo",d),u=(l("img","logo",c,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",d,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",d,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",d,{type:"hidden",configurable:!0}),v=l("button","redeem",d,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function d(e,t){return o[s(e,t)]}function c(e,o,i,r){r=r||{};var a=null,l=d("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var c in r)"configurable"!==c&&r.hasOwnProperty(c)&&a.attr(c,r[c]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof d("class",o)?d("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(V,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(V,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=c("div","container",f);p.addClass("wide");{var m=c("figure","logo",p),g=(c("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&c("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=c("div","row",p),b=r("email")&&c("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&c("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&c("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&c("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=c("div","row",p),I=r("postal_code")&&c("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&c("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=c("div","row",p),k=r("state")&&c("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&c("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=c("input","tracking",p,{type:"hidden",configurable:!0}),A=c("input","publishStatus",p,{type:"text"}),j=c("button","publish",p,{});c("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var O=this,V="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(V,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}O.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(V,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;t()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validateVoucher) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file From db256eebae1c0918973bf0deee851699d4adb5d3 Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Tue, 8 May 2018 08:22:22 +0200 Subject: [PATCH 5/7] Before merge commit --- dist/voucherify.min.js | 6 +----- dist/voucherify.min.js.map | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/dist/voucherify.min.js b/dist/voucherify.min.js index ba32b3f..ee41027 100644 --- a/dist/voucherify.min.js +++ b/dist/voucherify.min.js @@ -1,6 +1,2 @@ -<<<<<<< HEAD -window.Voucherify=function(e,t,n){"use strict";function o(e){return e&&("boolean"==typeof e.valid||"string"==typeof e.result||"object"==typeof e.voucher||"object"==typeof e.vouchers||"event"===e.object&&"string"==typeof e.type)}function i(e){return Math.round(100.001*e)/100}function r(e){if(!e||0>e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function d(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var c="https://api.voucherify.io",u={validate:c+"/client/v1/validate",redeem:c+"/client/v1/redeem",publish:c+"/client/v1/publish",list:c+"/client/v1/vouchers",track:c+"/client/v1/events",validatePromotion:c+"/client/v1/promotions/validation",redeemPromotion:c+"/client/v1/promotions/tiers/"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validate)+l,void 0,t)},redeem:function(e,t,n){var o,i=!1;if(!s(f))return null;if(!e){if(!t.tier)return console.error("Voucherify client could not redeem promotion without tier, because it is missing."),null;i=!0,o=t.tier,delete t.tier}var r="";return i||(r+="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""))),t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",(i?u.redeemPromotion+o+"/redemption":u.redeem)+r,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var d=e*(o/100);return t.discount.amount_limit&&(d=Math.min(t.discount.amount_limit/s,d)),i(e-d)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var c=e-o;return i(c>0?c:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=e-n*o;return i(c>0?c:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var d=e*(o/s);return t.discount.amount_limit&&(d=Math.min(t.discount.amount_limit/s,d)),i(d)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var c=e-o;return i(c>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=n*o;return i(d>e?e:d)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,d=a("selector",o);if(l.configurable&&d&&(s=n(d)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var c in l)"configurable"!==c&&l.hasOwnProperty(c)&&s.attr(c,l[c]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var d=l("div","container",s),c=l("figure","logo",d),u=(l("img","logo",c,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",d,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",d,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",d,{type:"hidden",configurable:!0}),v=l("input","percentOff",d,{type:"hidden",configurable:!0}),y=l("input","amountOff",d,{type:"hidden",configurable:!0}),b=l("input","unitOff",d,{type:"hidden",configurable:!0}),C=l("input","tracking",d,{type:"hidden",configurable:!0}),_=l("button","validate",d,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,d=a("selector",o);if(l.configurable&&d&&(s=n(d)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var c in l)"configurable"!==c&&l.hasOwnProperty(c)&&s.attr(c,l[c]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var d=l("div","container",s),c=l("figure","logo",d),u=(l("img","logo",c,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",d,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",d,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",d,{type:"hidden",configurable:!0}),v=l("button","redeem",d,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function d(e,t){return o[s(e,t)]}function c(e,o,i,r){r=r||{};var a=null,l=d("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var c in r)"configurable"!==c&&r.hasOwnProperty(c)&&a.attr(c,r[c]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof d("class",o)?d("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(V,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(V,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=c("div","container",f);p.addClass("wide");{var m=c("figure","logo",p),g=(c("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&c("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=c("div","row",p),b=r("email")&&c("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&c("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&c("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&c("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=c("div","row",p),I=r("postal_code")&&c("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&c("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=c("div","row",p),k=r("state")&&c("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&c("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=c("input","tracking",p,{type:"hidden",configurable:!0}),A=c("input","publishStatus",p,{type:"text"}),j=c("button","publish",p,{});c("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var O=this,V="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(V,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}O.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(V,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;te||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function c(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var d="https://api.voucherify.io",u={validate:d+"/client/v1/validate",redeem:d+"/client/v1/redeem",publish:d+"/client/v1/publish",list:d+"/client/v1/vouchers",track:d+"/client/v1/events",validatePromotion:d+"/client/v1/promotions/validation"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l+="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validate)+l,void 0,t)},redeem:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."),null;var o="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""));return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",u.redeem+o,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?d:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=e-n*o;return i(d>0?d:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var c=e*(o/s);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/s,c)),i(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var d=e-o;return i(d>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=n*o;return i(c>e?e:c)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",c,{type:"hidden",configurable:!0}),v=l("input","percentOff",c,{type:"hidden",configurable:!0}),y=l("input","amountOff",c,{type:"hidden",configurable:!0}),b=l("input","unitOff",c,{type:"hidden",configurable:!0}),C=l("input","tracking",c,{type:"hidden",configurable:!0}),_=l("button","validate",c,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,c=a("selector",o);if(l.configurable&&c&&(s=n(c)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var d in l)"configurable"!==d&&l.hasOwnProperty(d)&&s.attr(d,l[d]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var c=l("div","container",s),d=l("figure","logo",c),u=(l("img","logo",d,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",c,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",c,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",c,{type:"hidden",configurable:!0}),v=l("button","redeem",c,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function c(e,t){return o[s(e,t)]}function d(e,o,i,r){r=r||{};var a=null,l=c("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var d in r)"configurable"!==d&&r.hasOwnProperty(d)&&a.attr(d,r[d]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof c("class",o)?c("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(O,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(O,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=d("div","container",f);p.addClass("wide");{var m=d("figure","logo",p),g=(d("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&d("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=d("div","row",p),b=r("email")&&d("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&d("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&d("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&d("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=d("div","row",p),I=r("postal_code")&&d("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&d("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=d("div","row",p),k=r("state")&&d("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&d("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=d("input","tracking",p,{type:"hidden",configurable:!0}),A=d("input","publishStatus",p,{type:"text"}),j=d("button","publish",p,{});d("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,O="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(O,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}V.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(O,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;t>>>>>> f18b32142ad827d8ab1dd39798db665095ab1d07 +window.Voucherify=function(e,t,n){"use strict";function o(e){return e&&("boolean"==typeof e.valid||"string"==typeof e.result||"object"==typeof e.voucher||"object"==typeof e.vouchers||"event"===e.object&&"string"==typeof e.type)}function i(e){return Math.round(100.001*e)/100}function r(e){if(!e||0>e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function a(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function s(e){return e.applicationId?e.applicationId?!0:(console.error("Voucherify.js ERROR: Missing Client Token (Secret Key)."),!1):(console.error("Voucherify.js ERROR: Missing Client Application ID."),!1)}function d(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=a.readOptions(n._element,i.concat(t.attributes)),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo"],r={"voucher-redeem":{path:"/widgets/redeem",attributes:["code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},"get-voucher":{path:"/widgets/publish",attributes:["campaign","metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","button-label"]},subscribe:{path:"/widgets/subscribe",attributes:["metadata","source","name-field","name-field-required","name-field-label","email-field","email-field-required","email-field-label","phone-field","phone-field-required","phone-field-label","address-line-1-field","address-line-1-field-required","address-line-1-field-label","address-line-2-field","address-line-2-field-required","address-line-2-field-label","city-field","city-field-required","city-field-label","postal-code-field","postal-code-field-required","postal-code-field-label","state-field","state-field-required","state-field-label","country-field","country-field-required","country-field-label","subscribe-label"]}},a={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t){return Array.prototype.reduce.call(t,function(t,n){var o=e.getAttribute("data-"+n);return o&&(t[n]=o),t},{})},encodeOptions:function(e){var t=[];return Object.keys(e).forEach(function(n){t.push("[options]["+n+"]="+encodeURIComponent(e[n]))}),"?"+t.join("&")}};n.prototype.renderIframe=function(){var e=this;if(e._iframe)return e;var n=["width:400px;","height:475px;","background: transparent;","border: 0px none transparent;","overflow-x: hidden;","overflow-y: auto;","visibility: hidden;","margin: 0;","padding: 0;","-webkit-tap-highlight-color: transparent;","-webkit-touch-callout: none;"];return e._iframe=t.createElement("iframe"),e._iframe.setAttribute("frameBorder","0"),e._iframe.setAttribute("allowtransparency","true"),e._iframe.style.cssText=n.join("\n"),a.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+a.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var l=[];return Object.keys(r).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){l.push(new n(e,r[t]))})}),l}var c="https://api.voucherify.io",u={validate:c+"/client/v1/validate",redeem:c+"/client/v1/redeem",publish:c+"/client/v1/publish",list:c+"/client/v1/vouchers",track:c+"/client/v1/events",validatePromotion:c+"/client/v1/promotions/validation",redeemPromotion:c+"/client/v1/promotions/tiers/"},f={},p="invalid_amount",m="invalid_number",g="missing_amount",h="invalid_customer_phone",v=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,y=null;y=n&&"function"==typeof n.ajax&&n.Deferred?function(e,t,i,r){var a=null;return"function"!=typeof r&&(a=n.Deferred()),n.ajax({type:e,url:t,data:JSON.stringify(i),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":f.applicationId,"X-Client-Token":f.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:f.timeout,success:function(e){var t=null;o(e)?"function"==typeof r?r(e):a.resolve(e):(t={type:"error",message:"Unexpected response structure.",context:e},"function"==typeof r?r(t):a.reject(t))},error:function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r?r(t):a.reject(t)}}),"function"!=typeof r?a.promise():void 0}:function(t,n,i,r){var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=f.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",f.applicationId),a.setRequestHeader("X-Client-Token",f.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){var e=null;if(a.status>=200&&a.status<400){var t=JSON.parse(a.responseText);o(t)?"function"==typeof r&&r(t):(e={type:"error",message:"Unexpected response structure.",context:t},"function"==typeof r&&r(e))}else e={type:"error",message:"Unexpected status code.",context:a.status},"function"==typeof r&&r(e)},a.onerror=function(e){var t={type:"error",message:"XHR error happened.",context:e};"function"==typeof r&&r(t)},a.send(JSON.stringify(i))};var b={initialize:function(e,t,n){f.applicationId=e,f.token=t,f.timeout=n||5e3},setIdentity:function(e){f.trackingId=e},validate:function(e,t){if(!s(f))return null;var n,o,i,r,a=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var l="?";if(e?(l+="code="+encodeURIComponent(e),n&&(l+="&amount="+parseInt(n))):(a=!0,n&&(l+="amount="+parseInt(n))),o&&(l+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(l+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r){if("object"!=typeof r)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;l+="&"+Object.keys(r).map(function(e){return encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")}return f.trackingId&&(l+="&tracking_id="+encodeURIComponent(f.trackingId)),y("GET",(a?u.validatePromotion:u.validate)+l,void 0,t)},redeem:function(e,t,n){var o,i=!1;if(!s(f))return null;if(!e){if(!t.tier)return console.error("Voucherify client could not redeem promotion without tier, because it is missing."),null;i=!0,o=t.tier,delete t.tier}var r="";return i||(r+="?code="+encodeURIComponent(e.replace(/[\s\r\n]/g,""))),t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,y("POST",(i?u.redeemPromotion+o+"/redemption":u.redeem)+r,t,n)},publish:function(e,t,n){if(!s(f))return null;if(!e)return console.error("Voucherify.js ERROR: campaign is required to publish a voucher."),null;var o="?campaign="+encodeURIComponent(e);return t=t||{},t.customer=t.customer||{},t.customer.source_id=t.customer.source_id||f.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",u.publish+o,t,n)},listVouchers:function(e,t){if(!s(f))return null;"function"!=typeof e||t||(t=e,e={});var n="?"+Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return y("GET",u.list+n,void 0,t)},track:function(e,t,n,o){if(!s(f))return null;"function"!=typeof n||o||(o=n,n={});var i={};return i.event=e,i.metadata=t,i.customer=i.customer||n||{},i.customer.source_id=i.customer.source_id||f.trackingId,y("POST",u.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var d=e*(o/100);return t.discount.amount_limit&&(d=Math.min(t.discount.amount_limit/s,d)),i(e-d)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var c=e-o;return i(c>0?c:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var c=e-n*o;return i(c>0?c:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,s=100;if(t.gift)return o=Math.min(t.gift.balance/s,e),i(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,r(o);var d=e*(o/s);return t.discount.amount_limit&&(d=Math.min(t.discount.amount_limit/s,d)),i(d)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/s,a(o);var c=e-o;return i(c>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,l(o);var d=n*o;return i(d>e?e:d)}throw new Error("Unsupported discount type.")}},render:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,d=a("selector",o);if(l.configurable&&d&&(s=n(d)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var c in l)"configurable"!==c&&l.hasOwnProperty(c)&&s.attr(c,l[c]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var d=l("div","container",s),c=l("figure","logo",d),u=(l("img","logo",c,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",d,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",d,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","discountType",d,{type:"hidden",configurable:!0}),v=l("input","percentOff",d,{type:"hidden",configurable:!0}),y=l("input","amountOff",d,{type:"hidden",configurable:!0}),b=l("input","unitOff",d,{type:"hidden",configurable:!0}),C=l("input","tracking",d,{type:"hidden",configurable:!0}),_=l("button","validate",d,{}),x=(l("span","validateText",_,{text:"string"==typeof o.textValidate?o.textValidate:"Validate"}),this),w="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",I="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",q="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(P,!1)}),f.on("keyup",function(e){f.toggleClass(P,!1)}),_.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),_.toggleClass(w,!1),_.toggleClass(I,!1),!u.val())return void u.toggleClass(P,!0).delay(1e3).queue(function(){u.toggleClass(P,!1),u.dequeue()});var t={code:u.val(),amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))};x.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(w,!0),e.toggleClass(I,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};_.toggleClass(w,!0),_.toggleClass(I,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(w,!1),f.toggleClass(w,!1),h.val(e.discount&&e.discount.type||""),y.val(e.discount&&e.discount.amount_off||0),b.val(e.discount&&e.discount.unit_off||0),v.val(e.discount&&e.discount.percent_off||0),C.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),_.prop("disabled",!0),u.toggleClass(I,!0),f.toggleClass(I,!0),_.toggleClass(I,!0),_.toggleClass(w,!1),u.toggleClass(w,!1),u.toggleClass(q,!0),f.toggleClass(q,!0),o&&o.onValidated&&"function"==typeof o.onValidated&&o.onValidated(e)})})},renderRedeem:function(e,o){function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function r(e,t){return e+i(t)}function a(e,t){return o[r(e,t)]}function l(e,o,i,l){l=l||{};var s=null,d=a("selector",o);if(l.configurable&&d&&(s=n(d)),!s||!s.length){s=n(t.createElement(e)),i.append(s);for(var c in l)"configurable"!==c&&l.hasOwnProperty(c)&&s.attr(c,l[c]);"input"===e&&s.attr("name",r("voucherify",o)),"span"===e&&l.text&&s.text(l.text)}return s.addClass("string"==typeof a("class",o)?a("class",o):r("voucherify",o)),s}var s=n(e);if(!s||!s.length)throw new Error("Element '"+e+"' cannot be found");o=o||{};var d=l("div","container",s),c=l("figure","logo",d),u=(l("img","logo",c,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),l("input","code",d,{type:"text",placeholder:"string"==typeof o.textPlaceholder?o.textPlaceholder:"e.g. abc-123"})),f=l("input","amount",d,{type:o.amount?"text":"hidden",placeholder:"string"==typeof o.amountPlaceholder?o.amountPlaceholder:"e.g. 52.22"}),h=l("input","tracking",d,{type:"hidden",configurable:!0}),v=l("button","redeem",d,{}),y=(l("span","redeemText",v,{text:"string"==typeof o.textRedeem?o.textRedeem:"Redeem"}),this),b="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",C="string"==typeof o.classValid?o.classValid:"voucherifyValid",_="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",x="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";u.on("keyup",function(e){u.toggleClass(_,!1)}),f.on("keyup",function(e){f.toggleClass(_,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!u.val())return void u.toggleClass(_,!0).delay(1e3).queue(function(){u.toggleClass(_,!1),u.dequeue()});var t={order:{amount:parseInt(100*parseFloat(f.val().replace(/\,/,".")))}};y.redeem(u.val(),t,function(e){if(!e||"SUCCESS"!==e.result){var t=function(e){e.toggleClass(b,!0),e.toggleClass(C,!1),e.toggleClass(_,!0).delay(1e3).queue(function(){e.toggleClass(_,!1),e.dequeue()})};v.toggleClass(b,!0),v.toggleClass(C,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==p&&r!==m&&r!==g?u:f)}f.val()>=0?f.val(parseFloat(f.val().replace(/\,/,"."))):f.hide(100),u.toggleClass(b,!1),f.toggleClass(b,!1),h.val(e.tracking_id||""),u.prop("disabled",!0),f.prop("disabled",!0),v.prop("disabled",!0),u.toggleClass(C,!0),f.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),u.toggleClass(b,!1),u.toggleClass(x,!0),f.toggleClass(x,!0),o&&o.onRedeem&&"function"==typeof o.onRedeem&&o.onRedeem(e)})})},renderPublish:function(e,o){function i(e,t){return Array.prototype.some.call(e||[],function(e){return e.name===t})}function r(e){return i(o.customerFields,e)}function a(e){var t=Array.prototype.find.call(o.customerFields||[],function(t){return t.name===e});return t&&t.required||!1}function l(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(e,t){return e+l(t)}function d(e,t){return o[s(e,t)]}function c(e,o,i,r){r=r||{};var a=null,l=d("selector",o);if(r.configurable&&l&&(a=n(l)),!a||!a.length){a=n(t.createElement(e)),i.append(a);for(var c in r)"configurable"!==c&&r.hasOwnProperty(c)&&a.attr(c,r[c]);"input"===e&&a.attr("name",s("voucherify",o)),"span"===e&&r.text&&a.text(r.text)}return a.addClass("string"==typeof d("class",o)?d("class",o):s("voucherify",o)),a}function u(e){e.toggleClass(V,!0),e.toggleClass(S,!1),e.toggleClass(T,!0).delay(1e3).queue(function(){e.toggleClass(T,!1),e.toggleClass(V,!1),e.toggleClass(S,!1),e.dequeue()})}var f=n(e);if(!f||!f.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var p=c("div","container",f);p.addClass("wide");{var m=c("figure","logo",p),g=(c("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&c("input","customerName",p,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=c("div","row",p),b=r("email")&&c("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&c("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),_=r("line_1")&&c("input","customerLine1",p,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),x=r("line_2")&&c("input","customerLine2",p,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),w=c("div","row",p),I=r("postal_code")&&c("input","customerPostalCode",w,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&c("input","customerCity",w,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),q=c("div","row",p),k=r("state")&&c("input","customerState",q,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&c("input","customerCountry",q,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),R=c("input","tracking",p,{type:"hidden",configurable:!0}),A=c("input","publishStatus",p,{type:"text"}),j=c("button","publish",p,{});c("span","publishText",j,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var O=this,V="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",S="string"==typeof o.classValid?o.classValid:"voucherifyValid",T="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",U="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";j.on("click",function(e){R.val(""),j.toggleClass(V,!1),j.toggleClass(S,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return u(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return u(b);if(b.val()&&!v.test(b.val()))return u(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return u(C);C.val()&&(t.customer.phone=C.val())}if((r("line_1")||r("line_2")||r("postal_code")||r("city")||r("state")||r("country"))&&(t.customer.address={}),r("line_1")){if(!_.val()&&a("line_1"))return u(_);t.customer.address.line_1=_.val()}if(r("line_2")){if(!x.val()&&a("line_2"))return u(x);t.customer.address.line_2=x.val()}if(r("postal_code")){if(!I.val()&&a("postal_code"))return u(I);t.customer.address.postal_code=I.val()}if(r("city")){if(!P.val()&&a("city"))return u(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return u(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return u(E);t.customer.address.country=E.val()}O.publish(o.campaignName,t,function(e){if(!e||!e.voucher||!e.voucher.code){var t=e.context||{},n=t.responseJSON||{},i=n.key;return u(j),void(r("phone")&&i===h&&u(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),_&&_.hide(),x&&x.hide(),I&&I.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(U,!0).val(e.voucher.code).show(100),R.val(e.tracking_id||""),j.prop("disabled",!0),j.toggleClass(V,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})}};return function(n,o){function i(){if(!l){l=!0;for(var t=0;t()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString = \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} -======= -{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString += \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!code) {\n console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n return null;\n }\n\n var queryString = \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.redeem + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} ->>>>>>> f18b32142ad827d8ab1dd39798db665095ab1d07 +{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString += \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file From 590cc12c65ead97c97e3771ce73b758e495284ee Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Tue, 8 May 2018 08:23:16 +0200 Subject: [PATCH 6/7] Remove commented code --- lib/voucherify.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/voucherify.js b/lib/voucherify.js index 7556cfe..93019bd 100644 --- a/lib/voucherify.js +++ b/lib/voucherify.js @@ -293,11 +293,6 @@ window.Voucherify = (function (window, document, $) { return null; } - // if (!code) { - // console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."); - // return null; - // } - if (!code) { if( !payload.tier ){ console.error("Voucherify client could not redeem promotion without tier, because it is missing."); From a15e9ad7c76adedbb9c5ba549c6e342067172d7d Mon Sep 17 00:00:00 2001 From: Andrzej Szmajnta Date: Tue, 8 May 2018 08:27:58 +0200 Subject: [PATCH 7/7] no version changes --- dist/voucherify.js | 5 ----- dist/voucherify.min.js.map | 2 +- package.json | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/dist/voucherify.js b/dist/voucherify.js index 7556cfe..93019bd 100644 --- a/dist/voucherify.js +++ b/dist/voucherify.js @@ -293,11 +293,6 @@ window.Voucherify = (function (window, document, $) { return null; } - // if (!code) { - // console.error("Voucherify client could not verify code, because it is missing - please provide Voucher Code."); - // return null; - // } - if (!code) { if( !payload.tier ){ console.error("Voucherify client could not redeem promotion without tier, because it is missing."); diff --git a/dist/voucherify.min.js.map b/dist/voucherify.min.js.map index 381d27f..f6f693e 100644 --- a/dist/voucherify.min.js.map +++ b/dist/voucherify.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString += \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n // if (!code) {\n // console.error(\"Voucherify client could not verify code, because it is missing - please provide Voucher Code.\");\n // return null;\n // }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["voucherify.js"],"names":["window","Voucherify","document","$","isValidResponseStructure","data","object","roundMoney","value","Math","round","validatePercentDiscount","discount","Error","validateAmountDiscount","validateUnitDiscount","isValidInit","options","applicationId","console","error","renderIframes","RenderIframe","element","self","this","_element","_path","path","_options","helpers","readOptions","common_attributes","concat","attributes","_iframe","renderIframe","host","iframes_widgets","voucher-redeem","get-voucher","subscribe","bind","name","callback","addEventListener","attachEvent","allowed_options","Array","prototype","reduce","call","allowed_option","option_value","getAttribute","encodeOptions","query_parameters","Object","keys","forEach","option_key","push","encodeURIComponent","join","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API_BASE","API","validate","redeem","publish","list","track","validatePromotion","redeemPromotion","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","result","resolve","message","context","reject","promise","undefined","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","code","amount","items","metadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","tier","source_id","campaign","channel","listVouchers","filters","event_name","event","utils","calculatePrice","basePrice","voucher","unitPrice","e","gift","min","balance","percent_off","priceDiscount","amount_limit","amount_off","newPrice","unit_off","calculateDiscount","render","selector","getCapitalizedName","charAt","toUpperCase","slice","getPropertyName","prefix","getConfigProperty","create$control","$container","config","$control","configured$control","configurable","length","append","attribute","hasOwnProperty","attr","text","addClass","$element","$logoContainer","$code","logoSrc","placeholder","textPlaceholder","$amount","amountPlaceholder","$discountType","$percentOff","$amountOff","$unitOff","$tracking","$validate","textValidate","classInvalid","classValid","classInvalidAnimation","classValidAnimation","on","toggleClass","val","delay","queue","dequeue","parseFloat","response","valid","setFieldInvalid","$field","responseJSON","error_key","hide","tracking_id","prop","onValidated","renderRedeem","$redeem","textRedeem","order","onRedeem","renderPublish","contains","arr","some","field","containsCustomer","customerFields","isRequired","find","required","error$control","campaignName","$customerName","customerNamePlaceholder","$row1","$customerEmail","customerEmailPlaceholder","$customerPhone","customerPhonePlaceholder","$customerLine1","customerLine1Placeholder","$customerLine2","customerLine2Placeholder","$row3","$customerPostalCode","customerPostalCodePlaceholder","$customerCity","customerCityPlaceholder","$row4","$customerState","customerStatePlaceholder","$customerCountry","customerCountryPlaceholder","$publishStatus","$publish","textPublish","test","show","onPublished","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","docReady","info","module","exports","jQuery"],"mappings":"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","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API_BASE = \"https://api.voucherify.io\";\n\n var API = {\n validate: API_BASE + \"/client/v1/validate\",\n redeem: API_BASE + \"/client/v1/redeem\",\n publish: API_BASE + \"/client/v1/publish\",\n list: API_BASE + \"/client/v1/vouchers\",\n track: API_BASE + \"/client/v1/events\",\n validatePromotion: API_BASE + \"/client/v1/promotions/validation\",\n redeemPromotion: API_BASE + \"/client/v1/promotions/tiers/\"\n };\n\n var OPTIONS = {};\n\n // Error keys returned from voucherify API\n var INVALID_AMOUNT = \"invalid_amount\";\n var INVALID_NUMBER = \"invalid_number\";\n var MISSING_AMOUNT = \"missing_amount\";\n var INVALID_CUSTOMER_PHONE = \"invalid_customer_phone\";\n\n var EMAIL_PATTERN = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n function isValidResponseStructure(data) {\n return data && (typeof(data.valid) === \"boolean\" // validate\n || typeof(data.result) === \"string\" // redeem\n || typeof(data.voucher) === \"object\" // publish\n || typeof(data.vouchers) === \"object\" // list\n || (data.object === \"event\" && typeof(data.type) === \"string\") // track\n );\n }\n\n var xhrImplementation = null;\n\n if (!!$ && typeof($.ajax) === \"function\" && !!$.Deferred) {\n xhrImplementation = function (method, url, payload, callback) {\n var deferred = null;\n\n if (typeof(callback) !== \"function\") {\n deferred = $.Deferred();\n }\n\n $.ajax({\n type: method,\n\n url: url,\n\n data: JSON.stringify(payload),\n\n xhrFields: {\n withCredentials: true\n },\n\n dataType: \"json\",\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Client-Application-Id\": OPTIONS.applicationId,\n \"X-Client-Token\": OPTIONS.token,\n \"X-Voucherify-Channel\": \"Voucherify.js\"\n },\n timeout: OPTIONS.timeout,\n\n success: function (data) {\n var result = null;\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n } else {\n deferred.resolve(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n },\n\n error: function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n } else {\n deferred.reject(result);\n }\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n } else {\n return undefined;\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n var request = new window.XMLHttpRequest();\n\n request.withCredentials = true;\n request.open(method, url, true);\n request.timeout = OPTIONS.timeout;\n\n request.setRequestHeader(\"Accept\", \"application/json\");\n request.setRequestHeader(\"Content-Type\", \"application/json\");\n request.setRequestHeader(\"X-Client-Application-Id\", OPTIONS.applicationId);\n request.setRequestHeader(\"X-Client-Token\", OPTIONS.token);\n request.setRequestHeader(\"X-Voucherify-Channel\", \"Voucherify.js\");\n\n request.onload = function() {\n var result = null;\n\n if (request.status >= 200 && request.status < 400) {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n if (typeof(callback) === \"function\") {\n callback(data);\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n } else {\n result = {\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n }\n };\n\n request.onerror = function (error) {\n var result = {\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n };\n\n if (typeof(callback) === \"function\") {\n callback(result);\n }\n };\n\n request.send(JSON.stringify(payload));\n };\n }\n\n function roundMoney(value) {\n return Math.round(value * (100 + 0.001)) / 100;\n }\n\n function validatePercentDiscount(discount) {\n if (!discount || discount < 0 || discount > 100) {\n throw new Error('Invalid voucher, percent discount should be between 0-100.');\n }\n }\n\n function validateAmountDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, amount discount must be higher than zero.\");\n }\n }\n\n function validateUnitDiscount(discount) {\n if (!discount || discount < 0) {\n throw new Error(\"Invalid voucher, unit discount must be higher than zero.\");\n }\n }\n\n function isValidInit(options) {\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Application ID.\");\n return false;\n }\n if (!options.applicationId) {\n console.error(\"Voucherify.js ERROR: Missing Client Token (Secret Key).\");\n return false;\n }\n return true;\n }\n\n var voucherify = {\n initialize: function (clientAppId, token, timeout) {\n OPTIONS.applicationId = clientAppId;\n OPTIONS.token = token;\n OPTIONS.timeout = timeout || 5000;\n },\n\n setIdentity: function (trackingId) {\n OPTIONS.trackingId = trackingId;\n },\n\n validate: function (code, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n var isPromotion = false;\n var amount;\n var items;\n var metadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n customer = code.customer;\n code = code.code;\n }\n\n if (!!code) {\n code = code.replace(/[\\s\\r\\n]/g, \"\");\n }\n\n var queryString = \"?\";\n if (!code) {\n isPromotion = true;\n if(amount) {\n queryString += \"amount=\" + parseInt(amount);\n }\n } else {\n queryString += \"code=\" + encodeURIComponent(code);\n if (amount) {\n queryString += \"&amount=\" + parseInt(amount); // in cents, amount=1000 means $10\n }\n }\n\n if (items) {\n queryString += \"&\" + items.map(function(item, index) {\n return Object.keys(item).map(function(key) {\n return encodeURIComponent(\"item[\" + index + \"][\" + key + \"]\") + \"=\" + encodeURIComponent(item[key]);\n }).join(\"&\");\n }).join(\"&\");\n }\n\n if (metadata) {\n queryString += \"&\" + Object.keys(metadata).map(function(key) {\n return encodeURIComponent(\"metadata[\" + key + \"]\") + \"=\" + encodeURIComponent(metadata[key]);\n }).join(\"&\");\n }\n\n if (customer) {\n if(typeof(customer) !== \"object\") {\n console.error(\"Customer must be an object - please use instead { source_id: 'your_user' }\");\n return null;\n }\n\n queryString += \"&\" + Object.keys(customer).map(function (key) {\n return encodeURIComponent(\"customer[\" + key + \"]\") + \"=\" + encodeURIComponent(customer[ key ]);\n }).join(\"&\");\n }\n\n if (OPTIONS.trackingId) {\n queryString += \"&tracking_id=\" + encodeURIComponent(OPTIONS.trackingId);\n }\n\n return xhrImplementation(\"GET\", (isPromotion ? API.validatePromotion : API.validate) + queryString, undefined, callback);\n },\n\n redeem: function (code, payload, callback) {\n var isPromotion = false;\n var tier;\n\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!code) {\n if( !payload.tier ){\n console.error(\"Voucherify client could not redeem promotion without tier, because it is missing.\");\n return null;\n }\n isPromotion = true;\n tier = payload.tier;\n delete payload.tier\n }\n\n var queryString = \"\"\n if(!isPromotion){\n queryString += \"?code=\" + encodeURIComponent(code.replace(/[\\s\\r\\n]/g, \"\"));\n }\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n\n return xhrImplementation(\"POST\", (isPromotion ? API.redeemPromotion + tier + \"/redemption\" : API.redeem) + queryString, payload, callback);\n },\n\n publish: function (campaign, payload, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (!campaign) {\n console.error(\"Voucherify.js ERROR: campaign is required to publish a voucher.\");\n return null;\n }\n\n var queryString = \"?campaign=\" + encodeURIComponent(campaign);\n\n // -- Tracking ID fallback\n payload = payload || {};\n payload.customer = payload.customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n // -- Default channel\n payload.channel = payload.channel || \"Voucherify.js\";\n\n return xhrImplementation(\"POST\", API.publish + queryString, payload, callback);\n },\n\n listVouchers: function (filters, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof filters === \"function\" && !callback) {\n callback = filters;\n filters = {};\n }\n\n var queryString = \"?\" + Object.keys(filters)\n .map(function(key) {\n return encodeURIComponent(key) + \"=\" + encodeURIComponent(filters[key])\n })\n .join(\"&\");\n\n return xhrImplementation(\"GET\", API.list + queryString, undefined, callback);\n },\n\n track: function (event_name, metadata, customer, callback) {\n if (!isValidInit(OPTIONS)) {\n return null;\n }\n\n if (typeof customer === \"function\" && !callback) {\n callback = customer;\n customer = {};\n }\n\n var payload = {};\n payload.event = event_name;\n payload.metadata = metadata;\n payload.customer = payload.customer || customer || {};\n payload.customer.source_id = payload.customer.source_id || OPTIONS.trackingId;\n\n return xhrImplementation(\"POST\", API.track, payload, callback);\n },\n\n utils: {\n calculatePrice: function (basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(basePrice - discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / 100);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(basePrice - priceDiscount);\n\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var newPrice = basePrice - unitPrice * discount;\n return roundMoney(newPrice > 0 ? newPrice : 0);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n },\n\n calculateDiscount: function(basePrice, voucher, unitPrice) {\n var e = 100; // Number of digits after the decimal separator.\n var discount;\n\n if (voucher.gift) {\n discount = Math.min(voucher.gift.balance / e, basePrice);\n return roundMoney(discount);\n }\n\n if (!voucher.discount) {\n throw new Error(\"Unsupported voucher type.\");\n }\n\n if (voucher.discount.type === 'PERCENT') {\n discount = voucher.discount.percent_off;\n validatePercentDiscount(discount);\n var priceDiscount = basePrice * (discount / e);\n\n if (voucher.discount.amount_limit) {\n priceDiscount = Math.min(voucher.discount.amount_limit / e, priceDiscount);\n }\n\n return roundMoney(priceDiscount);\n } else if (voucher.discount.type === 'AMOUNT') {\n discount = voucher.discount.amount_off / e;\n validateAmountDiscount(discount);\n var newPrice = basePrice - discount;\n return roundMoney(newPrice > 0 ? discount : basePrice);\n\n } else if (voucher.discount.type === 'UNIT') {\n discount = voucher.discount.unit_off;\n validateUnitDiscount(discount);\n var priceDiscount = unitPrice * discount;\n return roundMoney(priceDiscount > basePrice ? basePrice : priceDiscount);\n\n } else {\n throw new Error(\"Unsupported discount type.\");\n }\n }\n },\n render: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $discountType = create$control(\"input\", \"discountType\", $container, { type: \"hidden\", configurable: true });\n var $percentOff = create$control(\"input\", \"percentOff\", $container, { type: \"hidden\", configurable: true });\n var $amountOff = create$control(\"input\", \"amountOff\", $container, { type: \"hidden\", configurable: true });\n var $unitOff = create$control(\"input\", \"unitOff\", $container, { type: \"hidden\", configurable: true });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $validate = create$control(\"button\", \"validate\", $container, {});\n var $validateText = create$control(\"span\", \"validateText\", $validate, { text: typeof options.textValidate === \"string\" ? options.textValidate : \"Validate\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $validate.on(\"click\", function(event) {\n $discountType.val(\"\");\n $amountOff.val(\"\");\n $unitOff.val(\"\");\n $percentOff.val(\"\");\n $tracking.val(\"\");\n\n $validate.toggleClass(classInvalid, false);\n $validate.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n code: $code.val(),\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n };\n\n self.validate(payload, function(response) {\n if (!response || !response.valid) {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $validate.toggleClass(classInvalid, true);\n $validate.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $discountType.val(response.discount && response.discount.type || \"\");\n $amountOff.val(response.discount && response.discount.amount_off || 0);\n $unitOff.val(response.discount && response.discount.unit_off || 0);\n $percentOff.val(response.discount && response.discount.percent_off || 0);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $validate.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $validate.toggleClass(classValid, true);\n $validate.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onValidated && typeof options.onValidated === \"function\") {\n options.onValidated(response);\n }\n });\n });\n },\n\n renderRedeem: function(selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n options = options || {};\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n var $code = create$control(\"input\", \"code\", $container, { type: \"text\", placeholder: typeof options.textPlaceholder === \"string\" ? options.textPlaceholder : \"e.g. abc-123\" });\n var $amount = create$control(\"input\", \"amount\", $container, { type: options.amount ? \"text\" : \"hidden\", placeholder: typeof options.amountPlaceholder === \"string\" ? options.amountPlaceholder : \"e.g. 52.22\" });\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n var $redeem = create$control(\"button\", \"redeem\", $container, {});\n var $redeemText = create$control(\"span\", \"redeemText\", $redeem, { text: typeof options.textRedeem === \"string\" ? options.textRedeem : \"Redeem\" });\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n $code.on(\"keyup\", function(event) {\n $code.toggleClass(classInvalidAnimation, false);\n });\n\n $amount.on(\"keyup\", function(event) {\n $amount.toggleClass(classInvalidAnimation, false);\n });\n\n $redeem.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $redeem.toggleClass(classInvalid, false);\n $redeem.toggleClass(classValid, false);\n\n if (!$code.val()) {\n $code.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $code.toggleClass(classInvalidAnimation, false);\n $code.dequeue();\n });\n return;\n }\n\n var payload = {\n order: {\n amount: parseInt(parseFloat($amount.val().replace(/\\,/, \".\")) * 100)\n }\n };\n\n self.redeem($code.val(), payload, function(response) {\n if (!response || response.result !== 'SUCCESS') {\n\n var setFieldInvalid = function ($field) {\n $field.toggleClass(classInvalid, true);\n $field.toggleClass(classValid, false);\n $field.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $field.toggleClass(classInvalidAnimation, false);\n $field.dequeue();\n });\n };\n\n $redeem.toggleClass(classInvalid, true);\n $redeem.toggleClass(classValid, false);\n\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n if (options.amount && (\n error_key === INVALID_AMOUNT ||\n error_key === INVALID_NUMBER ||\n error_key === MISSING_AMOUNT)) {\n setFieldInvalid($amount);\n } else {\n setFieldInvalid($code);\n }\n return;\n }\n\n if ($amount.val() >= 0) {\n $amount.val(parseFloat($amount.val().replace(/\\,/, \".\")))\n } else {\n $amount.hide(100);\n }\n\n $code.toggleClass(classInvalid, false);\n $amount.toggleClass(classInvalid, false);\n $tracking.val(response.tracking_id || \"\");\n\n $code.prop(\"disabled\", true);\n $amount.prop(\"disabled\", true);\n $redeem.prop(\"disabled\", true);\n\n $code.toggleClass(classValid, true);\n $amount.toggleClass(classValid, true);\n $redeem.toggleClass(classValid, true);\n $redeem.toggleClass(classInvalid, false);\n $code.toggleClass(classInvalid, false);\n\n $code.toggleClass(classValidAnimation, true);\n $amount.toggleClass(classValidAnimation, true);\n\n if (options && options.onRedeem && typeof options.onRedeem === \"function\") {\n options.onRedeem(response);\n }\n });\n });\n },\n\n renderPublish : function (selector, options) {\n var $element = $(selector);\n if (!$element || !$element.length) {\n throw new Error(\"Element '\" + selector + \"' cannot be found\");\n }\n\n options = options || {};\n\n if (!options.campaignName) {\n throw new Error(\"Option campaignName is not specified\");\n }\n\n function contains(arr, prop) {\n return Array.prototype.some.call(arr || [], function (field) {\n return field.name === prop;\n });\n }\n\n function containsCustomer(prop) {\n return contains(options.customerFields, prop);\n }\n\n function isRequired(prop) {\n var field = Array.prototype.find.call(options.customerFields || [], function (field) {\n return field.name === prop;\n });\n\n return field && field.required || false;\n }\n\n function getCapitalizedName(name) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n function getPropertyName(prefix, name) {\n return prefix + getCapitalizedName(name);\n }\n\n function getConfigProperty(prefix, name) {\n return options[getPropertyName(prefix, name)];\n }\n\n function create$control(type, name, $container, config) {\n config = config || {};\n var $control = null;\n var configured$control = getConfigProperty(\"selector\", name);\n\n if (config.configurable && configured$control) {\n $control = $(configured$control);\n }\n\n if (!$control || !$control.length) {\n $control = $(document.createElement(type));\n $container.append($control);\n\n for (var attribute in config) {\n if (attribute !== \"configurable\" && config.hasOwnProperty(attribute)) {\n $control.attr(attribute, config[attribute]);\n }\n }\n\n if (type === \"input\") {\n $control.attr(\"name\", getPropertyName(\"voucherify\", name));\n }\n\n if (type === \"span\" && config.text) {\n $control.text(config.text);\n }\n }\n\n $control.addClass(typeof getConfigProperty(\"class\", name) === \"string\" ? getConfigProperty(\"class\", name) : getPropertyName(\"voucherify\", name));\n return $control;\n }\n\n var $container = create$control(\"div\", \"container\", $element);\n $container.addClass(\"wide\");\n var $logoContainer = create$control(\"figure\", \"logo\", $container);\n var $logo = create$control(\"img\", \"logo\", $logoContainer, { src: typeof options.logoSrc === \"string\" ? options.logoSrc : \"https://app.voucherify.io/images/favicon.png\" });\n\n var $customerName = containsCustomer(\"name\") && create$control(\"input\", \"customerName\", $container, { type: \"text\", placeholder: typeof options.customerNamePlaceholder === \"string\" ? options.customerNamePlaceholder : \"Name\" });\n var $row1 = create$control(\"div\", \"row\", $container);\n var $customerEmail = containsCustomer(\"email\") && create$control(\"input\", \"customerEmail\", $row1, { type: \"email\", placeholder: typeof options.customerEmailPlaceholder === \"string\" ? options.customerEmailPlaceholder : \"Email\" });\n var $customerPhone = containsCustomer(\"phone\") && create$control(\"input\", \"customerPhone\", $row1, { type: \"text\", placeholder: typeof options.customerPhonePlaceholder === \"string\" ? options.customerPhonePlaceholder : \"Phone\" });\n var $customerLine1 = containsCustomer(\"line_1\") && create$control(\"input\", \"customerLine1\", $container, { type: \"text\", placeholder: typeof options.customerLine1Placeholder === \"string\" ? options.customerLine1Placeholder : \"Address line 1\" });\n var $customerLine2 = containsCustomer(\"line_2\") && create$control(\"input\", \"customerLine2\", $container, { type: \"text\", placeholder: typeof options.customerLine2Placeholder === \"string\" ? options.customerLine2Placeholder : \"Address line 2\" });\n var $row3 = create$control(\"div\", \"row\", $container);\n var $customerPostalCode = containsCustomer(\"postal_code\") && create$control(\"input\", \"customerPostalCode\", $row3, { type: \"text\", placeholder: typeof options.customerPostalCodePlaceholder === \"string\" ? options.customerPostalCodePlaceholder : \"Postal Code\" });\n var $customerCity = containsCustomer(\"city\") && create$control(\"input\", \"customerCity\", $row3, { type: \"text\", placeholder: typeof options.customerCityPlaceholder === \"string\" ? options.customerCityPlaceholder : \"City\" });\n var $row4 = create$control(\"div\", \"row\", $container);\n var $customerState = containsCustomer(\"state\") && create$control(\"input\", \"customerState\", $row4, { type: \"text\", placeholder: typeof options.customerStatePlaceholder === \"string\" ? options.customerStatePlaceholder : \"State\" });\n var $customerCountry = containsCustomer(\"country\") && create$control(\"input\", \"customerCountry\", $row4, { type: \"text\", placeholder: typeof options.customerCountryPlaceholder === \"string\" ? options.customerCountryPlaceholder : \"Country\" });\n\n var $tracking = create$control(\"input\", \"tracking\", $container, { type: \"hidden\", configurable: true });\n\n var $publishStatus = create$control(\"input\", \"publishStatus\", $container, { type: \"text\" });\n\n var $publish = create$control(\"button\", \"publish\", $container, {});\n var $publishText = create$control(\"span\", \"publishText\", $publish, { text: typeof options.textPublish === \"string\" ? options.textPublish : \"Get voucher\" });\n\n $publishStatus.prop(\"readonly\", true).hide();\n\n var self = this;\n var classInvalid = options.classInvalid === \"string\" ? options.classInvalid : \"voucherifyInvalid\";\n var classValid = typeof options.classValid === \"string\" ? options.classValid : \"voucherifyValid\";\n var classInvalidAnimation = options.classInvalidAnimation === \"string\" ? options.classInvalidAnimation : \"voucherifyAnimationShake\";\n var classValidAnimation = options.classValidAnimation === \"string\" ? options.classValidAnimation : \"voucherifyAnimationTada\";\n\n function error$control($control) {\n $control.toggleClass(classInvalid, true);\n $control.toggleClass(classValid, false);\n $control.toggleClass(classInvalidAnimation, true)\n .delay(1000)\n .queue(function(){\n $control.toggleClass(classInvalidAnimation, false);\n $control.toggleClass(classInvalid, false);\n $control.toggleClass(classValid, false);\n $control.dequeue();\n });\n }\n\n $publish.on(\"click\", function(event) {\n $tracking.val(\"\");\n\n $publish.toggleClass(classInvalid, false);\n $publish.toggleClass(classValid, false);\n\n var payload = {\n customer: {}\n };\n\n if (containsCustomer(\"name\")) {\n if (!$customerName.val() && isRequired(\"name\")) {\n return error$control($customerName);\n }\n payload.customer[\"name\"] = $customerName.val();\n }\n\n if (containsCustomer(\"email\")) {\n if (!$customerEmail.val() && isRequired(\"email\")) {\n return error$control($customerEmail);\n }\n if ($customerEmail.val() && !EMAIL_PATTERN.test($customerEmail.val())) {\n return error$control($customerEmail);\n }\n payload.customer[\"email\"] = $customerEmail.val();\n payload.customer[\"source_id\"] = payload.customer[\"email\"];\n }\n\n if (containsCustomer(\"phone\") ) {\n if (!$customerPhone.val() && isRequired(\"phone\")) {\n return error$control($customerPhone);\n }\n if ($customerPhone.val()) {\n payload.customer[\"phone\"] = $customerPhone.val();\n }\n }\n\n if (containsCustomer(\"line_1\") ||\n containsCustomer(\"line_2\") ||\n containsCustomer(\"postal_code\") ||\n containsCustomer(\"city\") ||\n containsCustomer(\"state\") ||\n containsCustomer(\"country\")) {\n payload.customer[\"address\"] = {};\n }\n\n if (containsCustomer(\"line_1\")) {\n if (!$customerLine1.val() && isRequired(\"line_1\")) {\n return error$control($customerLine1);\n }\n payload.customer[\"address\"][\"line_1\"] = $customerLine1.val();\n }\n\n if (containsCustomer(\"line_2\")) {\n if (!$customerLine2.val() && isRequired(\"line_2\")) {\n return error$control($customerLine2);\n }\n payload.customer[\"address\"][\"line_2\"] = $customerLine2.val();\n }\n\n if (containsCustomer(\"postal_code\")) {\n if (!$customerPostalCode.val() && isRequired(\"postal_code\")) {\n return error$control($customerPostalCode);\n }\n payload.customer[\"address\"][\"postal_code\"] = $customerPostalCode.val();\n }\n\n if (containsCustomer(\"city\")) {\n if (!$customerCity.val() && isRequired(\"city\")) {\n return error$control($customerCity);\n }\n payload.customer[\"address\"][\"city\"] = $customerCity.val();\n }\n\n if (containsCustomer(\"state\")) {\n if (!$customerState.val() && isRequired(\"state\")) {\n return error$control($customerState);\n }\n payload.customer[\"address\"][\"state\"] = $customerState.val();\n }\n\n if (containsCustomer(\"country\")) {\n if (!$customerCountry.val() && isRequired(\"country\")) {\n return error$control($customerCountry);\n }\n payload.customer[\"address\"][\"country\"] = $customerCountry.val()\n }\n\n self.publish(options.campaignName, payload, function(response) {\n if (!response || !response.voucher || !response.voucher.code) {\n var context = response.context || {};\n var responseJSON = context.responseJSON || {};\n var error_key = responseJSON.key;\n\n error$control($publish);\n\n if (containsCustomer(\"phone\") && error_key === INVALID_CUSTOMER_PHONE) {\n error$control($customerPhone);\n }\n\n return;\n }\n\n $customerName && $customerName.hide();\n $customerEmail && $customerEmail.hide();\n $customerPhone && $customerPhone.hide();\n $customerLine1 && $customerLine1.hide();\n $customerLine2 && $customerLine2.hide();\n $customerPostalCode && $customerPostalCode.hide();\n $customerCity && $customerCity.hide();\n $customerState && $customerState.hide();\n $customerCountry && $customerCountry.hide();\n\n $publishStatus\n .toggleClass(classValidAnimation, true)\n .val(response.voucher.code).show(100);\n\n $tracking.val(response.tracking_id || \"\");\n\n $publish.prop(\"disabled\", true);\n\n $publish\n .toggleClass(classInvalid, false)\n .hide();\n\n if (options && options.onPublished && typeof options.onPublished === \"function\") {\n options.onPublished(response);\n }\n });\n });\n }\n };\n\n (function(funcName, baseObj) {\n \"use strict\";\n\n if (!baseObj) {\n return;\n }\n\n funcName = funcName || \"docReady\";\n baseObj = baseObj || window;\n var readyList = [];\n var readyFired = false;\n var readyEventHandlersInstalled = false;\n\n function ready() {\n if (!readyFired) {\n readyFired = true;\n for (var i = 0; i < readyList.length; i++) {\n readyList[i].fn.call(window, readyList[i].ctx);\n }\n readyList = [];\n }\n }\n\n function readyStateChange() {\n if ( document.readyState === \"complete\" ) {\n ready();\n }\n }\n\n baseObj[funcName] = function(callback, context) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback for docReady(fn) must be a function\");\n }\n if (readyFired) {\n setTimeout(function() {callback(context);}, 1);\n return;\n } else {\n readyList.push({fn: callback, ctx: context});\n }\n if (document.readyState === \"complete\" || (!document.attachEvent && document.readyState === \"interactive\")) {\n setTimeout(ready, 1);\n } else if (!readyEventHandlersInstalled) {\n if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", ready, false);\n window.addEventListener(\"load\", ready, false);\n } else {\n document.attachEvent(\"onreadystatechange\", readyStateChange);\n window.attachEvent(\"onload\", ready);\n }\n readyEventHandlersInstalled = true;\n }\n }\n })(\"docReady\", window);\n\n function renderIframes() {\n var host = \"https://app.voucherify.io\";\n var common_attributes = [\n \"client-app-id\",\n \"client-token\",\n\n \"logo\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"attributes\": [\n \"code-field\",\n \"code-field-required\",\n \"code-field-label\",\n\n \"amount-field\",\n \"amount-field-required\",\n \"amount-field-label\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"name-field\",\n \"name-field-required\",\n \"name-field-label\",\n\n \"email-field\",\n \"email-field-required\",\n \"email-field-label\",\n\n \"phone-field\",\n \"phone-field-required\",\n \"phone-field-label\",\n\n \"address-line-1-field\",\n \"address-line-1-field-required\",\n \"address-line-1-field-label\",\n\n \"address-line-2-field\",\n \"address-line-2-field-required\",\n \"address-line-2-field-label\",\n\n \"city-field\",\n \"city-field-required\",\n \"city-field-label\",\n\n \"postal-code-field\",\n \"postal-code-field-required\",\n \"postal-code-field-label\",\n\n \"state-field\",\n \"state-field-required\",\n \"state-field-label\",\n\n \"country-field\",\n \"country-field-required\",\n \"country-field-label\",\n\n \"subscribe-label\"\n ]\n }\n };\n\n var helpers = {\n bind: function (element, name, callback) {\n if (element.addEventListener) {\n return element.addEventListener(name, callback, false)\n } else {\n return element.attachEvent(\"on\" + name, callback)\n }\n },\n readOptions: function (element, allowed_options) {\n return Array.prototype.reduce.call(allowed_options, function (options, allowed_option) {\n var option_value = element.getAttribute(\"data-\" + allowed_option);\n\n if (option_value) {\n options[allowed_option] = option_value;\n }\n\n return options;\n }, {});\n },\n encodeOptions: function (options) {\n var query_parameters = [];\n\n Object.keys(options).forEach(function(option_key) {\n query_parameters.push(\"[options][\"+option_key+\"]=\"+encodeURIComponent(options[option_key]));\n });\n\n return \"?\" + query_parameters.join(\"&\");\n }\n };\n\n\n function RenderIframe(element, options) {\n var self = this;\n\n self._element = element;\n\n self._path = options.path;\n\n self._options = helpers.readOptions(self._element, common_attributes.concat(options.attributes));\n\n self._iframe = null;\n\n return this.renderIframe();\n }\n\n RenderIframe.prototype.renderIframe = function () {\n var self = this;\n\n if (self._iframe) {\n return self;\n }\n\n var css_props = [\n \"width:400px;\",\n \"height:475px;\",\n \"background: transparent;\",\n \"border: 0px none transparent;\",\n \"overflow-x: hidden;\",\n \"overflow-y: auto;\",\n \"visibility: hidden;\",\n \"margin: 0;\",\n \"padding: 0;\",\n \"-webkit-tap-highlight-color: transparent;\",\n \"-webkit-touch-callout: none;\"\n ];\n\n self._iframe = document.createElement(\"iframe\");\n self._iframe.setAttribute(\"frameBorder\", \"0\");\n self._iframe.setAttribute(\"allowtransparency\", \"true\");\n self._iframe.style.cssText = css_props.join(\"\\n\");\n\n helpers.bind(self._iframe, \"load\", function () {\n return self._iframe.style.visibility = \"visible\"\n });\n\n self._iframe.src = host + self._path + helpers.encodeOptions(self._options);\n\n self._element.appendChild(self._iframe);\n\n return self;\n };\n\n var widgets = [];\n\n Object.keys(iframes_widgets).forEach(function (widget_name) {\n var elements = window.document.querySelectorAll(\".voucherify-\" + widget_name);\n\n Array.prototype.forEach.call(elements, function (element) {\n widgets.push(new RenderIframe(element, iframes_widgets[widget_name]));\n })\n });\n\n return widgets;\n }\n\n if (window) {\n window.docReady(function () {\n console.info(\"Document ready. Render voucherify iframes.\");\n renderIframes();\n });\n }\n\n\n if (typeof module !== \"undefined\" && module.exports) {\n module.exports = voucherify;\n }\n\n return voucherify;\n} (window, window.document, window.jQuery));\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/package.json b/package.json index e19660f..81e746e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "voucherify.js", - "version": "1.17.0", + "version": "1.18.0", "homepage": "http://www.voucherify.io", "description": "Client-side SDK for Voucherify.", "author": "rspective",