From 0be2ad7930ba219497b8e18531acabdec77f2963 Mon Sep 17 00:00:00 2001 From: pannga Date: Thu, 17 Jun 2021 12:20:34 +0200 Subject: [PATCH 1/3] Add iframe app-url option --- README.md | 6 +- dist/voucherify.js | 6 +- dist/voucherify.min.js | 2 +- dist/voucherify.min.js.map | 2 +- lib/voucherify.js | 6 +- package-lock.json | 870 ++++++++++++++++++------------------- package.json | 2 +- 7 files changed, 451 insertions(+), 443 deletions(-) diff --git a/README.md b/README.md index c0356e4..e637955 100644 --- a/README.md +++ b/README.md @@ -514,6 +514,7 @@ The iframe renders the redeem widget
e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function s(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function c(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 u(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=s.readOptions(n._element,i.concat(r).concat(t.attributes),t.defaults),n._iframe=null,this.renderIframe()}var o="https://app.voucherify.io",i=["client-app-id","client-token","logo","widget-id","height","success-message","failure-message"],r=["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","customer-metadata"],a=["consent-label","consent-description","consent-options","consent-options-required","consent-legal","consent-voucherify-note-visible"],l={"voucher-redeem":{path:"/widgets/redeem",defaults:{height:"480px"},attributes:["metadata","redemption-metadata","metadata-fields","code","code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","button-label"].concat(a)},"get-voucher":{path:"/widgets/publish",defaults:{height:"430px"},attributes:["campaign","metadata","source","button-label"]},subscribe:{path:"/widgets/subscribe",defaults:{height:"220px"},attributes:["metadata","source","subscribe-label"].concat(a)}},s={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t,n){return Array.prototype.reduce.call(t,function(t,o){var i=e.getAttribute("data-"+o);return i?t[o]=i:n[o]&&(t[o]=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=e._options.height;e._options.height=void 0;var i=["width:400px;","height:"+n+";","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=i.join("\n"),s.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=o+e._path+s.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var c=[];return Object.keys(l).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){c.push(new n(e,l[t]))})}),c}var d=o("https://api.voucherify.io"),p={},f="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,o,r){var a="function"==typeof r?{resolve:r,reject:r}:n.Deferred();return n.ajax({type:e,url:t,data:JSON.stringify(o),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":p.applicationId,"X-Client-Token":p.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:p.timeout,success:function(e){return i(e)?void a.resolve(e):void a.reject({type:"error",message:"Unexpected response structure.",context:e})},error:function(e){a.reject({type:"error",message:"XHR error happened.",context:e})}}),"function"!=typeof r?a.promise():void 0}:function(t,n,o,r){r="function"==typeof r?r:function(){};var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=p.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",p.applicationId),a.setRequestHeader("X-Client-Token",p.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){if(a.status>=200&&a.status<400)try{var e=JSON.parse(a.responseText);if(i(e))return void r(e);r({type:"error",message:"Unexpected response structure.",context:e})}catch(t){r({type:"error",message:"Unparsable response.",context:t})}else r({type:"error",message:"Unexpected status code.",context:a.status})},a.onerror=function(e){r({type:"error",message:"XHR error happened.",context:e})},a.send(JSON.stringify(o))};var b={initialize:function(e,t,n){p.applicationId=e,p.token=t,p.timeout=n||5e3},setIdentity:function(e){p.trackingId=e},setBaseUrl:function(e){e=e||"",0!==e.indexOf("https://")&&0!==e.indexOf("http://")&&(e="https://"+e),d=o(e)},validate:function(e,t){if(!c(p))return null;var n,o,i,r,a,l=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.orderMetadata,a=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var s="?";if(e?(s+="code="+encodeURIComponent(e),n&&(s+="&amount="+parseInt(n))):(l=!0,n&&(s+="amount="+parseInt(n))),o&&(s+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(s+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r&&(s+="&"+Object.keys(r).map(function(e){return encodeURIComponent("order[metadata]["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")),a){if("object"!=typeof a)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;s+="&"+Object.keys(a).map(function(e){return"metadata"===e?"object"!=typeof a.metadata?(console.error("Customer's metadata must be an object - please use instead { property: 'value' }"),null):Object.keys(a.metadata).map(function(e){return encodeURIComponent("customer[metadata]["+e+"]")+"="+encodeURIComponent(a.metadata[e])}).join("&"):encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(a[e])}).join("&")}return p.trackingId&&(s+="&tracking_id="+encodeURIComponent(p.trackingId)),y("GET",(l?d.validatePromotion:d.validate)+s,void 0,t)},redeem:function(e,t,n){if(!c(p))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||p.trackingId,y("POST",d.redeem+o,t,n)},publish:function(e,t,n){if(!c(p))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||p.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",d.publish+o,t,n)},listVouchers:function(e,t){if(!c(p))return null;"function"!=typeof e||t||(t=e,e={});var o="?"+n.param(e);return y("GET",d.list+o,void 0,t)},track:function(e,t,n,o){if(!c(p))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||p.trackingId,y("POST",d.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?u:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var u=e-n*o;return r(u>0?u:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/i);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var c=n*o;return r(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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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),I="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",w="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",R="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";d.on("keyup",function(e){d.toggleClass(P,!1)}),p.on("keyup",function(e){p.toggleClass(P,!1)}),x.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),x.toggleClass(I,!1),x.toggleClass(w,!1),!d.val())return void d.toggleClass(P,!0).delay(1e3).queue(function(){d.toggleClass(P,!1),d.dequeue()});var t={code:d.val(),amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))};_.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(I,!0),e.toggleClass(w,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};x.toggleClass(I,!0),x.toggleClass(w,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(I,!1),p.toggleClass(I,!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||""),d.prop("disabled",!0),p.prop("disabled",!0),x.prop("disabled",!0),d.toggleClass(w,!0),p.toggleClass(w,!0),x.toggleClass(w,!0),x.toggleClass(I,!1),d.toggleClass(I,!1),d.toggleClass(R,!0),p.toggleClass(R,!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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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";d.on("keyup",function(e){d.toggleClass(x,!1)}),p.on("keyup",function(e){p.toggleClass(x,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!d.val())return void d.toggleClass(x,!0).delay(1e3).queue(function(){d.toggleClass(x,!1),d.dequeue()});var t={order:{amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))}};y.redeem(d.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!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(b,!1),p.toggleClass(b,!1),h.val(e.tracking_id||""),d.prop("disabled",!0),p.prop("disabled",!0),v.prop("disabled",!0),d.toggleClass(C,!0),p.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),d.toggleClass(b,!1),d.toggleClass(_,!0),p.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 u(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 u in r)"configurable"!==u&&r.hasOwnProperty(u)&&a.attr(u,r[u]);"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 d(e){e.toggleClass(U,!0),e.toggleClass(q,!1),e.toggleClass(S,!0).delay(1e3).queue(function(){e.toggleClass(S,!1),e.toggleClass(U,!1),e.toggleClass(q,!1),e.dequeue()})}var p=n(e);if(!p||!p.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var f=u("div","container",p);f.addClass("wide");{var m=u("figure","logo",f),g=(u("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&u("input","customerName",f,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=u("div","row",f),b=r("email")&&u("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&u("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),x=r("line_1")&&u("input","customerLine1",f,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),_=r("line_2")&&u("input","customerLine2",f,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),I=u("div","row",f),w=r("postal_code")&&u("input","customerPostalCode",I,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&u("input","customerCity",I,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),R=u("div","row",f),k=r("state")&&u("input","customerState",R,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&u("input","customerCountry",R,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),j=u("input","tracking",f,{type:"hidden",configurable:!0}),A=u("input","publishStatus",f,{type:"text"}),O=u("button","publish",f,{});u("span","publishText",O,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,U="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",q="string"==typeof o.classValid?o.classValid:"voucherifyValid",S="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",T="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";O.on("click",function(e){j.val(""),O.toggleClass(U,!1),O.toggleClass(q,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return d(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return d(b);if(b.val()&&!v.test(b.val()))return d(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return d(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 d(x);t.customer.address.line_1=x.val()}if(r("line_2")){if(!_.val()&&a("line_2"))return d(_);t.customer.address.line_2=_.val()}if(r("postal_code")){if(!w.val()&&a("postal_code"))return d(w);t.customer.address.postal_code=w.val()}if(r("city")){if(!P.val()&&a("city"))return d(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return d(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return d(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 d(O),void(r("phone")&&i===h&&d(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),x&&x.hide(),_&&_.hide(),w&&w.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(T,!0).val(e.voucher.code).show(100),j.val(e.tracking_id||""),O.prop("disabled",!0),O.toggleClass(U,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})},refreshIframes:function(){e.docReady(function(){console.info("Re-render voucherify iframes."),u()})}};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 l(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function s(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function c(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 u(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=l.readOptions(n._element,o.concat(i).concat(t.attributes),t.defaults),n._iframe=null,this.renderIframe()}var o=["client-app-id","client-token","client-app-url","logo","widget-id","height","success-message","failure-message"],i=["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","customer-metadata"],r=["consent-label","consent-description","consent-options","consent-options-required","consent-legal","consent-voucherify-note-visible"],a={"voucher-redeem":{path:"/widgets/redeem",defaults:{height:"480px"},attributes:["metadata","redemption-metadata","metadata-fields","code","code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","button-label"].concat(r)},"get-voucher":{path:"/widgets/publish",defaults:{height:"430px"},attributes:["campaign","metadata","source","button-label"]},subscribe:{path:"/widgets/subscribe",defaults:{height:"220px"},attributes:["metadata","source","subscribe-label"].concat(r)}},l={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t,n){return Array.prototype.reduce.call(t,function(t,o){var i=e.getAttribute("data-"+o);return i?t[o]=i:n[o]&&(t[o]=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=e._options["client-app-url"]?e._options["client-app-url"]:"https://app.voucherify.io",o=e._options.height;e._options.height=void 0;var i=["width:400px;","height:"+o+";","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=i.join("\n"),l.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=n+e._path+l.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var s=[];return Object.keys(a).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){s.push(new n(e,a[t]))})}),s}var d=o("localhost:8000"),p={},f="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,o,r){var a="function"==typeof r?{resolve:r,reject:r}:n.Deferred();return n.ajax({type:e,url:t,data:JSON.stringify(o),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":p.applicationId,"X-Client-Token":p.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:p.timeout,success:function(e){return i(e)?void a.resolve(e):void a.reject({type:"error",message:"Unexpected response structure.",context:e})},error:function(e){a.reject({type:"error",message:"XHR error happened.",context:e})}}),"function"!=typeof r?a.promise():void 0}:function(t,n,o,r){r="function"==typeof r?r:function(){};var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=p.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",p.applicationId),a.setRequestHeader("X-Client-Token",p.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){if(a.status>=200&&a.status<400)try{var e=JSON.parse(a.responseText);if(i(e))return void r(e);r({type:"error",message:"Unexpected response structure.",context:e})}catch(t){r({type:"error",message:"Unparsable response.",context:t})}else r({type:"error",message:"Unexpected status code.",context:a.status})},a.onerror=function(e){r({type:"error",message:"XHR error happened.",context:e})},a.send(JSON.stringify(o))};var b={initialize:function(e,t,n){p.applicationId=e,p.token=t,p.timeout=n||5e3},setIdentity:function(e){p.trackingId=e},setBaseUrl:function(e){e=e||"",0!==e.indexOf("https://")&&0!==e.indexOf("http://")&&(e="https://"+e),d=o(e)},validate:function(e,t){if(!c(p))return null;var n,o,i,r,a,l=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.orderMetadata,a=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var s="?";if(e?(s+="code="+encodeURIComponent(e),n&&(s+="&amount="+parseInt(n))):(l=!0,n&&(s+="amount="+parseInt(n))),o&&(s+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(s+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r&&(s+="&"+Object.keys(r).map(function(e){return encodeURIComponent("order[metadata]["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")),a){if("object"!=typeof a)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;s+="&"+Object.keys(a).map(function(e){return"metadata"===e?"object"!=typeof a.metadata?(console.error("Customer's metadata must be an object - please use instead { property: 'value' }"),null):Object.keys(a.metadata).map(function(e){return encodeURIComponent("customer[metadata]["+e+"]")+"="+encodeURIComponent(a.metadata[e])}).join("&"):encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(a[e])}).join("&")}return p.trackingId&&(s+="&tracking_id="+encodeURIComponent(p.trackingId)),y("GET",(l?d.validatePromotion:d.validate)+s,void 0,t)},redeem:function(e,t,n){if(!c(p))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||p.trackingId,y("POST",d.redeem+o,t,n)},publish:function(e,t,n){if(!c(p))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||p.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",d.publish+o,t,n)},listVouchers:function(e,t){if(!c(p))return null;"function"!=typeof e||t||(t=e,e={});var o="?"+n.param(e);return y("GET",d.list+o,void 0,t)},track:function(e,t,n,o){if(!c(p))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||p.trackingId,y("POST",d.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?u:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var u=e-n*o;return r(u>0?u:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/i);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var c=n*o;return r(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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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),I="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",w="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",R="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";d.on("keyup",function(e){d.toggleClass(P,!1)}),p.on("keyup",function(e){p.toggleClass(P,!1)}),x.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),x.toggleClass(I,!1),x.toggleClass(w,!1),!d.val())return void d.toggleClass(P,!0).delay(1e3).queue(function(){d.toggleClass(P,!1),d.dequeue()});var t={code:d.val(),amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))};_.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(I,!0),e.toggleClass(w,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};x.toggleClass(I,!0),x.toggleClass(w,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(I,!1),p.toggleClass(I,!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||""),d.prop("disabled",!0),p.prop("disabled",!0),x.prop("disabled",!0),d.toggleClass(w,!0),p.toggleClass(w,!0),x.toggleClass(w,!0),x.toggleClass(I,!1),d.toggleClass(I,!1),d.toggleClass(R,!0),p.toggleClass(R,!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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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";d.on("keyup",function(e){d.toggleClass(x,!1)}),p.on("keyup",function(e){p.toggleClass(x,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!d.val())return void d.toggleClass(x,!0).delay(1e3).queue(function(){d.toggleClass(x,!1),d.dequeue()});var t={order:{amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))}};y.redeem(d.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!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(b,!1),p.toggleClass(b,!1),h.val(e.tracking_id||""),d.prop("disabled",!0),p.prop("disabled",!0),v.prop("disabled",!0),d.toggleClass(C,!0),p.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),d.toggleClass(b,!1),d.toggleClass(_,!0),p.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 u(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 u in r)"configurable"!==u&&r.hasOwnProperty(u)&&a.attr(u,r[u]);"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 d(e){e.toggleClass(U,!0),e.toggleClass(q,!1),e.toggleClass(S,!0).delay(1e3).queue(function(){e.toggleClass(S,!1),e.toggleClass(U,!1),e.toggleClass(q,!1),e.dequeue()})}var p=n(e);if(!p||!p.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var f=u("div","container",p);f.addClass("wide");{var m=u("figure","logo",f),g=(u("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&u("input","customerName",f,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=u("div","row",f),b=r("email")&&u("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&u("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),x=r("line_1")&&u("input","customerLine1",f,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),_=r("line_2")&&u("input","customerLine2",f,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),I=u("div","row",f),w=r("postal_code")&&u("input","customerPostalCode",I,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&u("input","customerCity",I,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),R=u("div","row",f),k=r("state")&&u("input","customerState",R,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&u("input","customerCountry",R,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),j=u("input","tracking",f,{type:"hidden",configurable:!0}),A=u("input","publishStatus",f,{type:"text"}),O=u("button","publish",f,{});u("span","publishText",O,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,U="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",q="string"==typeof o.classValid?o.classValid:"voucherifyValid",S="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",T="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";O.on("click",function(e){j.val(""),O.toggleClass(U,!1),O.toggleClass(q,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return d(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return d(b);if(b.val()&&!v.test(b.val()))return d(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return d(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 d(x);t.customer.address.line_1=x.val()}if(r("line_2")){if(!_.val()&&a("line_2"))return d(_);t.customer.address.line_2=_.val()}if(r("postal_code")){if(!w.val()&&a("postal_code"))return d(w);t.customer.address.postal_code=w.val()}if(r("city")){if(!P.val()&&a("city"))return d(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return d(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return d(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 d(O),void(r("phone")&&i===h&&d(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),x&&x.hide(),_&&_.hide(),w&&w.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(T,!0).val(e.voucher.code).show(100),j.val(e.tracking_id||""),O.prop("disabled",!0),O.toggleClass(U,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})},refreshIframes:function(){e.docReady(function(){console.info("Re-render voucherify iframes."),u()})}};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 = typeof(callback) === \"function\" ? { resolve: callback, reject: callback } : $.Deferred();\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 if (isValidResponseStructure(data)) {\n deferred.resolve(data);\n return;\n }\n\n deferred.reject({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n },\n\n error: function (error) {\n deferred.reject({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n });\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n callback = typeof(callback) === \"function\" ? callback : function () {\n };\n\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 if (request.status >= 200 && request.status < 400) {\n try {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n callback(data);\n return;\n }\n\n callback({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n } catch (error) {\n callback({\n type: \"error\",\n message: \"Unparsable response.\",\n context: error\n });\n }\n } else {\n callback({\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n });\n }\n };\n\n request.onerror = function (error) {\n callback({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\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 setBaseUrl: function (baseUrl) {\n baseUrl = baseUrl || \"\";\n\n if (baseUrl.indexOf(\"https://\") !== 0 && baseUrl.indexOf(\"http://\") !== 0) {\n baseUrl = \"https://\" + baseUrl;\n }\n\n API = buildAPI(baseUrl);\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 orderMetadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n orderMetadata = code.orderMetadata;\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 (orderMetadata) {\n queryString += \"&\" + Object.keys(orderMetadata).map(function (key) {\n return encodeURIComponent(\"order[metadata][\" + key + \"]\") + \"=\" + encodeURIComponent(orderMetadata[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 if (key === \"metadata\") {\n if (typeof(customer.metadata) !== \"object\") {\n console.error(\"Customer's metadata must be an object - please use instead { property: 'value' }\");\n return null;\n }\n\n return Object.keys(customer.metadata).map(function (metadataKey) {\n return encodeURIComponent(\"customer[metadata][\" + metadataKey + \"]\") + \"=\" + encodeURIComponent(customer.metadata[metadataKey]);\n }).join(\"&\");\n }\n\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 = \"?\" + $.param(filters);\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 refreshIframes: function () {\n window.docReady(function () {\n console.info(\"Re-render voucherify iframes.\");\n renderIframes();\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 () {\n callback(context);\n }, 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 \"widget-id\",\n \"height\",\n\n \"success-message\",\n \"failure-message\"\n ];\n\n var customer_attributes = [\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 \"customer-metadata\"\n ];\n\n var consent_fields = [\n \"consent-label\",\n \"consent-description\",\n \"consent-options\",\n \"consent-options-required\",\n \"consent-legal\",\n \"consent-voucherify-note-visible\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"defaults\": {\n \"height\": \"480px\"\n },\n \"attributes\": [\n \"metadata\",\n \"redemption-metadata\",\n\n \"metadata-fields\",\n\n \"code\",\n\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 \"button-label\"\n ].concat(consent_fields)\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"defaults\": {\n \"height\": \"430px\"\n },\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"defaults\": {\n \"height\": \"220px\"\n },\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"subscribe-label\"\n ].concat(consent_fields)\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, defaults) {\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 } else if (defaults[allowed_option]) { // check if the default value is provided\n options[allowed_option] = defaults[allowed_option];\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(customer_attributes).concat(options.attributes), options.defaults);\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 // -- set custom height or fallback\n var widget_height = self._options.height;\n // -- remove custom height from options to prevent before sending it\n self._options.height = undefined;\n\n var css_props = [\n \"width:400px;\",\n \"height:\" + widget_height + \";\",\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","$","buildAPI","baseUrl","validate","redeem","publish","list","track","validatePromotion","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","customer_attributes","attributes","defaults","_iframe","renderIframe","consent_fields","iframes_widgets","voucher-redeem","height","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","host","widget_height","undefined","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","resolve","reject","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","message","context","promise","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","setBaseUrl","indexOf","code","amount","items","metadata","orderMetadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","metadataKey","source_id","campaign","channel","listVouchers","filters","param","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","result","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","refreshIframes","docReady","info","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","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 = buildAPI(\"localhost:8000\");\n\n function buildAPI(baseUrl) {\n return {\n validate: baseUrl + \"/client/v1/validate\",\n redeem: baseUrl + \"/client/v1/redeem\",\n publish: baseUrl + \"/client/v1/publish\",\n list: baseUrl + \"/client/v1/vouchers\",\n track: baseUrl + \"/client/v1/events\",\n validatePromotion: baseUrl + \"/client/v1/promotions/validation\"\n };\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 = typeof(callback) === \"function\" ? { resolve: callback, reject: callback } : $.Deferred();\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 if (isValidResponseStructure(data)) {\n deferred.resolve(data);\n return;\n }\n\n deferred.reject({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n },\n\n error: function (error) {\n deferred.reject({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n });\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n callback = typeof(callback) === \"function\" ? callback : function () {\n };\n\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 if (request.status >= 200 && request.status < 400) {\n try {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n callback(data);\n return;\n }\n\n callback({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n } catch (error) {\n callback({\n type: \"error\",\n message: \"Unparsable response.\",\n context: error\n });\n }\n } else {\n callback({\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n });\n }\n };\n\n request.onerror = function (error) {\n callback({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\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 setBaseUrl: function (baseUrl) {\n baseUrl = baseUrl || \"\";\n\n if (baseUrl.indexOf(\"https://\") !== 0 && baseUrl.indexOf(\"http://\") !== 0) {\n baseUrl = \"https://\" + baseUrl;\n }\n\n API = buildAPI(baseUrl);\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 orderMetadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n orderMetadata = code.orderMetadata;\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 (orderMetadata) {\n queryString += \"&\" + Object.keys(orderMetadata).map(function (key) {\n return encodeURIComponent(\"order[metadata][\" + key + \"]\") + \"=\" + encodeURIComponent(orderMetadata[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 if (key === \"metadata\") {\n if (typeof(customer.metadata) !== \"object\") {\n console.error(\"Customer's metadata must be an object - please use instead { property: 'value' }\");\n return null;\n }\n\n return Object.keys(customer.metadata).map(function (metadataKey) {\n return encodeURIComponent(\"customer[metadata][\" + metadataKey + \"]\") + \"=\" + encodeURIComponent(customer.metadata[metadataKey]);\n }).join(\"&\");\n }\n\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 = \"?\" + $.param(filters);\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 refreshIframes: function () {\n window.docReady(function () {\n console.info(\"Re-render voucherify iframes.\");\n renderIframes();\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 () {\n callback(context);\n }, 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 common_attributes = [\n \"client-app-id\",\n \"client-token\",\n \"client-app-url\",\n\n \"logo\",\n\n \"widget-id\",\n \"height\",\n\n \"success-message\",\n \"failure-message\"\n ];\n\n var customer_attributes = [\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 \"customer-metadata\"\n ];\n\n var consent_fields = [\n \"consent-label\",\n \"consent-description\",\n \"consent-options\",\n \"consent-options-required\",\n \"consent-legal\",\n \"consent-voucherify-note-visible\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"defaults\": {\n \"height\": \"480px\"\n },\n \"attributes\": [\n \"metadata\",\n \"redemption-metadata\",\n\n \"metadata-fields\",\n\n \"code\",\n\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 \"button-label\"\n ].concat(consent_fields)\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"defaults\": {\n \"height\": \"430px\"\n },\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"defaults\": {\n \"height\": \"220px\"\n },\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"subscribe-label\"\n ].concat(consent_fields)\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, defaults) {\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 } else if (defaults[allowed_option]) { // check if the default value is provided\n options[allowed_option] = defaults[allowed_option];\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(customer_attributes).concat(options.attributes), options.defaults);\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 host = self._options[\"client-app-url\"] ? self._options[\"client-app-url\"] : \"https://app.voucherify.io\";\n\n // -- set custom height or fallback\n var widget_height = self._options.height;\n // -- remove custom height from options to prevent before sending it\n self._options.height = undefined;\n\n var css_props = [\n \"width:400px;\",\n \"height:\" + widget_height + \";\",\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 d93d08f..ead45ec 100644 --- a/lib/voucherify.js +++ b/lib/voucherify.js @@ -1,7 +1,7 @@ window.Voucherify = (function (window, document, $) { "use strict"; - var API = buildAPI("https://api.voucherify.io"); + var API = buildAPI("localhost:8000"); function buildAPI(baseUrl) { return { @@ -1089,10 +1089,10 @@ window.Voucherify = (function (window, document, $) { })("docReady", window); function renderIframes() { - var host = "https://app.voucherify.io"; var common_attributes = [ "client-app-id", "client-token", + "client-app-url", "logo", @@ -1259,6 +1259,8 @@ window.Voucherify = (function (window, document, $) { return self; } + var host = self._options["client-app-url"] ? self._options["client-app-url"] : "https://app.voucherify.io"; + // -- set custom height or fallback var widget_height = self._options.height; // -- remove custom height from options to prevent before sending it diff --git a/package-lock.json b/package-lock.json index 708ee58..ca5eb81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,19 +10,19 @@ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.0.3", - "liftoff": "2.3.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" }, "dependencies": { "archy": { @@ -37,11 +37,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "dependencies": { "ansi-styles": { @@ -62,7 +62,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -79,7 +79,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -110,24 +110,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "array-differ": { @@ -160,8 +160,8 @@ "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", "dev": true, "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" + "chalk": "^1.1.1", + "time-stamp": "^1.0.0" }, "dependencies": { "time-stamp": { @@ -178,7 +178,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.0" + "glogg": "^1.0.0" }, "dependencies": { "glogg": { @@ -187,7 +187,7 @@ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -206,7 +206,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -241,15 +241,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" }, "dependencies": { "lodash._basecopy": { @@ -282,7 +282,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" }, "dependencies": { "lodash._root": { @@ -299,9 +299,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" }, "dependencies": { "lodash._getnative": { @@ -336,8 +336,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } } } @@ -357,7 +357,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.9" }, "dependencies": { "readable-stream": { @@ -366,10 +366,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" }, "dependencies": { "core-util-is": { @@ -420,8 +420,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.2.11", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "readable-stream": { @@ -430,13 +430,13 @@ "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.0.1", - "string_decoder": "1.0.2", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.0.1", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" }, "dependencies": { "core-util-is": { @@ -475,7 +475,7 @@ "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "~5.0.1" } }, "util-deprecate": { @@ -500,8 +500,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -533,15 +533,15 @@ "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", "dev": true, "requires": { - "extend": "3.0.1", - "findup-sync": "0.4.3", - "fined": "1.0.2", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", - "rechoir": "0.6.2", - "resolve": "1.3.3" + "extend": "^3.0.0", + "findup-sync": "^0.4.2", + "fined": "^1.0.1", + "flagged-respawn": "^0.3.2", + "lodash.isplainobject": "^4.0.4", + "lodash.isstring": "^4.0.1", + "lodash.mapvalues": "^4.4.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" }, "dependencies": { "extend": { @@ -556,10 +556,10 @@ "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", "dev": true, "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" + "detect-file": "^0.1.0", + "is-glob": "^2.0.1", + "micromatch": "^2.3.7", + "resolve-dir": "^0.1.0" }, "dependencies": { "detect-file": { @@ -568,7 +568,7 @@ "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", "dev": true, "requires": { - "fs-exists-sync": "0.1.0" + "fs-exists-sync": "^0.1.0" }, "dependencies": { "fs-exists-sync": { @@ -585,7 +585,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" }, "dependencies": { "is-extglob": { @@ -602,19 +602,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.3" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" }, "dependencies": { "arr-diff": { @@ -623,7 +623,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.0.3" + "arr-flatten": "^1.0.1" }, "dependencies": { "arr-flatten": { @@ -646,9 +646,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" }, "dependencies": { "expand-range": { @@ -657,7 +657,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "2.2.3" + "fill-range": "^2.1.0" }, "dependencies": { "fill-range": { @@ -666,11 +666,11 @@ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^1.1.3", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" }, "dependencies": { "is-number": { @@ -679,7 +679,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "isobject": { @@ -705,8 +705,8 @@ "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "is-number": { @@ -715,7 +715,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -724,7 +724,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" }, "dependencies": { "is-buffer": { @@ -743,7 +743,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" }, "dependencies": { "is-buffer": { @@ -786,7 +786,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" }, "dependencies": { "is-posix-bracket": { @@ -803,7 +803,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "filename-regex": { @@ -824,7 +824,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" }, "dependencies": { "is-buffer": { @@ -841,7 +841,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.0.2" + "remove-trailing-separator": "^1.0.1" }, "dependencies": { "remove-trailing-separator": { @@ -858,8 +858,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" }, "dependencies": { "for-own": { @@ -868,7 +868,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" }, "dependencies": { "for-in": { @@ -893,10 +893,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "glob-base": { @@ -905,8 +905,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "glob-parent": { @@ -915,7 +915,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } } } @@ -934,8 +934,8 @@ "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", "dev": true, "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" + "is-equal-shallow": "^0.1.3", + "is-primitive": "^2.0.0" }, "dependencies": { "is-equal-shallow": { @@ -944,7 +944,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-primitive": { @@ -963,8 +963,8 @@ "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", "dev": true, "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" + "expand-tilde": "^1.2.2", + "global-modules": "^0.2.3" }, "dependencies": { "expand-tilde": { @@ -973,7 +973,7 @@ "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.1" }, "dependencies": { "os-homedir": { @@ -990,8 +990,8 @@ "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", "dev": true, "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" + "global-prefix": "^0.1.4", + "is-windows": "^0.2.0" }, "dependencies": { "global-prefix": { @@ -1000,10 +1000,10 @@ "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.4", - "is-windows": "0.2.0", - "which": "1.2.14" + "homedir-polyfill": "^1.0.0", + "ini": "^1.3.4", + "is-windows": "^0.2.0", + "which": "^1.2.12" }, "dependencies": { "homedir-polyfill": { @@ -1012,7 +1012,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "^1.0.0" }, "dependencies": { "parse-passwd": { @@ -1035,7 +1035,7 @@ "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" }, "dependencies": { "isexe": { @@ -1066,13 +1066,13 @@ "integrity": "sha1-WyhCS3YNdZiWC374SA3/itNmDpc=", "dev": true, "requires": { - "expand-tilde": "1.2.2", - "lodash.assignwith": "4.2.0", - "lodash.isempty": "4.4.0", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.pick": "4.4.0", - "parse-filepath": "1.0.1" + "expand-tilde": "^1.2.1", + "lodash.assignwith": "^4.0.7", + "lodash.isempty": "^4.2.1", + "lodash.isplainobject": "^4.0.4", + "lodash.isstring": "^4.0.1", + "lodash.pick": "^4.2.1", + "parse-filepath": "^1.0.1" }, "dependencies": { "expand-tilde": { @@ -1081,7 +1081,7 @@ "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.1" }, "dependencies": { "os-homedir": { @@ -1116,9 +1116,9 @@ "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", "dev": true, "requires": { - "is-absolute": "0.2.6", - "map-cache": "0.2.2", - "path-root": "0.1.1" + "is-absolute": "^0.2.3", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" }, "dependencies": { "is-absolute": { @@ -1127,8 +1127,8 @@ "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", "dev": true, "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" + "is-relative": "^0.2.1", + "is-windows": "^0.2.0" }, "dependencies": { "is-relative": { @@ -1137,7 +1137,7 @@ "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", "dev": true, "requires": { - "is-unc-path": "0.1.2" + "is-unc-path": "^0.1.1" }, "dependencies": { "is-unc-path": { @@ -1146,7 +1146,7 @@ "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", "dev": true, "requires": { - "unc-path-regex": "0.1.2" + "unc-path-regex": "^0.1.0" }, "dependencies": { "unc-path-regex": { @@ -1179,7 +1179,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "path-root-regex": "^0.1.0" }, "dependencies": { "path-root-regex": { @@ -1224,7 +1224,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.3.3" + "resolve": "^1.1.6" } }, "resolve": { @@ -1233,7 +1233,7 @@ "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" }, "dependencies": { "path-parse": { @@ -1258,9 +1258,9 @@ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.0" + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" }, "dependencies": { "end-of-stream": { @@ -1269,7 +1269,7 @@ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "1.3.3" + "once": "~1.3.0" }, "dependencies": { "once": { @@ -1278,7 +1278,7 @@ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" }, "dependencies": { "wrappy": { @@ -1323,7 +1323,7 @@ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" }, "dependencies": { "os-homedir": { @@ -1340,7 +1340,7 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "1.1.1" + "user-home": "^1.1.1" }, "dependencies": { "user-home": { @@ -1357,14 +1357,14 @@ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" }, "dependencies": { "defaults": { @@ -1373,7 +1373,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.2" + "clone": "^1.0.2" }, "dependencies": { "clone": { @@ -1390,12 +1390,12 @@ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" }, "dependencies": { "glob": { @@ -1404,10 +1404,10 @@ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" }, "dependencies": { "inflight": { @@ -1416,8 +1416,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" }, "dependencies": { "wrappy": { @@ -1440,7 +1440,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" }, "dependencies": { "wrappy": { @@ -1459,7 +1459,7 @@ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "0.1.1" + "find-index": "^0.1.1" }, "dependencies": { "find-index": { @@ -1476,7 +1476,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.0.0" }, "dependencies": { "brace-expansion": { @@ -1485,7 +1485,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" }, "dependencies": { @@ -1525,7 +1525,7 @@ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "0.5.2" + "gaze": "^0.5.1" }, "dependencies": { "gaze": { @@ -1534,7 +1534,7 @@ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "0.1.0" + "globule": "~0.1.0" }, "dependencies": { "globule": { @@ -1543,9 +1543,9 @@ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" }, "dependencies": { "glob": { @@ -1554,9 +1554,9 @@ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" }, "dependencies": { "graceful-fs": { @@ -1585,8 +1585,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" }, "dependencies": { "lru-cache": { @@ -1615,7 +1615,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.0" + "natives": "^1.1.0" }, "dependencies": { "natives": { @@ -1649,8 +1649,8 @@ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" }, "dependencies": { "first-chunk-stream": { @@ -1673,8 +1673,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" }, "dependencies": { "readable-stream": { @@ -1683,10 +1683,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" }, "dependencies": { "core-util-is": { @@ -1729,8 +1729,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" }, "dependencies": { "clone": { @@ -1763,8 +1763,8 @@ "integrity": "sha1-44jWQxEEbgVUevQwNTUtlJVQHFA=", "dev": true, "requires": { - "gulp-util": "3.0.8", - "thunks": "4.8.0" + "gulp-util": ">=3.0.0", + "thunks": "^4.5.1" }, "dependencies": { "gulp-util": { @@ -1773,24 +1773,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "array-differ": { @@ -1817,11 +1817,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "dependencies": { "ansi-styles": { @@ -1842,7 +1842,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -1859,7 +1859,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -1890,8 +1890,8 @@ "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", "dev": true, "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" + "chalk": "^1.1.1", + "time-stamp": "^1.0.0" }, "dependencies": { "time-stamp": { @@ -1908,7 +1908,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.0" + "glogg": "^1.0.0" }, "dependencies": { "glogg": { @@ -1917,7 +1917,7 @@ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -1936,7 +1936,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -1971,15 +1971,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" }, "dependencies": { "lodash._basecopy": { @@ -2012,7 +2012,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" }, "dependencies": { "lodash._root": { @@ -2029,9 +2029,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" }, "dependencies": { "lodash._getnative": { @@ -2066,8 +2066,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } } } @@ -2093,7 +2093,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.9" }, "dependencies": { "readable-stream": { @@ -2102,10 +2102,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" }, "dependencies": { "core-util-is": { @@ -2156,8 +2156,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.2.11", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "readable-stream": { @@ -2166,13 +2166,13 @@ "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.0.1", - "string_decoder": "1.0.2", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.0.1", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" }, "dependencies": { "core-util-is": { @@ -2211,7 +2211,7 @@ "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "~5.0.1" } }, "util-deprecate": { @@ -2236,8 +2236,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -2271,11 +2271,11 @@ "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", "dev": true, "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" + "convert-source-map": "^1.1.1", + "graceful-fs": "^4.1.2", + "strip-bom": "^2.0.0", + "through2": "^2.0.0", + "vinyl": "^1.0.0" }, "dependencies": { "convert-source-map": { @@ -2296,7 +2296,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" }, "dependencies": { "is-utf8": { @@ -2313,8 +2313,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.2.11", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "readable-stream": { @@ -2323,13 +2323,13 @@ "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.0.1", - "string_decoder": "1.0.2", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.0.1", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" }, "dependencies": { "core-util-is": { @@ -2368,7 +2368,7 @@ "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "~5.0.1" } }, "util-deprecate": { @@ -2393,8 +2393,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -2426,11 +2426,11 @@ "integrity": "sha1-dgqGpc9oRT4ANhMHY93ilSCT44s=", "dev": true, "requires": { - "deap": "1.0.0", - "gulp-util": "3.0.8", - "through2": "0.6.5", + "deap": ">=1.0.0 <2.0.0-0", + "gulp-util": ">=3.0.0 <4.0.0-0", + "through2": ">=0.6.1 <1.0.0-0", "uglify-js": "2.4.19", - "vinyl-sourcemaps-apply": "0.1.4" + "vinyl-sourcemaps-apply": ">=0.1.1 <0.2.0-0" }, "dependencies": { "deap": { @@ -2445,24 +2445,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "array-differ": { @@ -2489,11 +2489,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "dependencies": { "ansi-styles": { @@ -2514,7 +2514,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -2531,7 +2531,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -2562,8 +2562,8 @@ "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", "dev": true, "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" + "chalk": "^1.1.1", + "time-stamp": "^1.0.0" }, "dependencies": { "time-stamp": { @@ -2580,7 +2580,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.0" + "glogg": "^1.0.0" }, "dependencies": { "glogg": { @@ -2589,7 +2589,7 @@ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -2608,7 +2608,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -2643,15 +2643,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" }, "dependencies": { "lodash._basecopy": { @@ -2684,7 +2684,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" }, "dependencies": { "lodash._root": { @@ -2701,9 +2701,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" }, "dependencies": { "lodash._getnative": { @@ -2738,8 +2738,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } } } @@ -2765,7 +2765,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.9" }, "dependencies": { "readable-stream": { @@ -2774,10 +2774,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" }, "dependencies": { "core-util-is": { @@ -2828,8 +2828,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.2.11", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "readable-stream": { @@ -2838,13 +2838,13 @@ "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.0.1", - "string_decoder": "1.0.2", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.0.1", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" }, "dependencies": { "core-util-is": { @@ -2883,7 +2883,7 @@ "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "~5.0.1" } }, "util-deprecate": { @@ -2908,8 +2908,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -2935,8 +2935,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" }, "dependencies": { "readable-stream": { @@ -2945,10 +2945,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" }, "dependencies": { "core-util-is": { @@ -2991,10 +2991,10 @@ "integrity": "sha1-pD14KPMuzsf8OhTfwPlGb+2k384=", "dev": true, "requires": { - "async": "0.2.10", + "async": "~0.2.6", "source-map": "0.1.34", - "uglify-to-browserify": "1.0.2", - "yargs": "3.5.4" + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.5.4" }, "dependencies": { "async": { @@ -3009,7 +3009,7 @@ "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" }, "dependencies": { "amdefine": { @@ -3032,8 +3032,8 @@ "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", "dev": true, "requires": { - "camelcase": "1.2.1", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "decamelize": "^1.0.0", "window-size": "0.1.0", "wordwrap": "0.0.2" }, @@ -3072,7 +3072,7 @@ "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", "dev": true, "requires": { - "source-map": "0.1.43" + "source-map": "^0.1.39" }, "dependencies": { "source-map": { @@ -3081,7 +3081,7 @@ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" }, "dependencies": { "amdefine": { @@ -3102,9 +3102,9 @@ "integrity": "sha1-oYlcVhS0hQ6kLekZn8XE+3XSPnw=", "dev": true, "requires": { - "gulp-util": "3.0.8", - "through2": "2.0.3", - "uglifycss": "0.0.25" + "gulp-util": "^3.0.8", + "through2": "^2.0.3", + "uglifycss": "^0.0.25" }, "dependencies": { "gulp-util": { @@ -3113,24 +3113,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "array-differ": { @@ -3157,11 +3157,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "dependencies": { "ansi-styles": { @@ -3182,7 +3182,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -3199,7 +3199,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -3230,8 +3230,8 @@ "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", "dev": true, "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" + "chalk": "^1.1.1", + "time-stamp": "^1.0.0" }, "dependencies": { "time-stamp": { @@ -3248,7 +3248,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.0" + "glogg": "^1.0.0" }, "dependencies": { "glogg": { @@ -3257,7 +3257,7 @@ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -3276,7 +3276,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" }, "dependencies": { "sparkles": { @@ -3311,15 +3311,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" }, "dependencies": { "lodash._basecopy": { @@ -3352,7 +3352,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" }, "dependencies": { "lodash._root": { @@ -3369,9 +3369,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" }, "dependencies": { "lodash._getnative": { @@ -3406,8 +3406,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } } } @@ -3433,7 +3433,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.9" }, "dependencies": { "readable-stream": { @@ -3442,10 +3442,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" }, "dependencies": { "core-util-is": { @@ -3496,8 +3496,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -3523,8 +3523,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.2.11", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "readable-stream": { @@ -3533,13 +3533,13 @@ "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.0.1", - "string_decoder": "1.0.2", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.0.1", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" }, "dependencies": { "core-util-is": { @@ -3578,7 +3578,7 @@ "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "~5.0.1" } }, "util-deprecate": { diff --git a/package.json b/package.json index 47c8d7d..980f50e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "voucherify.js", - "version": "1.32.0", + "version": "1.32.1", "homepage": "http://www.voucherify.io", "description": "Client-side SDK for Voucherify.", "author": "rspective", From 9b2a86eb92c57795d2f541b252c1cd62920b901b Mon Sep 17 00:00:00 2001 From: pannga Date: Thu, 17 Jun 2021 12:24:34 +0200 Subject: [PATCH 2/3] Fix broken url --- dist/voucherify.js | 2 +- dist/voucherify.min.js | 2 +- dist/voucherify.min.js.map | 2 +- lib/voucherify.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/voucherify.js b/dist/voucherify.js index ead45ec..c03dff2 100644 --- a/dist/voucherify.js +++ b/dist/voucherify.js @@ -1,7 +1,7 @@ window.Voucherify = (function (window, document, $) { "use strict"; - var API = buildAPI("localhost:8000"); + var API = buildAPI("https://api.voucherify.io"); function buildAPI(baseUrl) { return { diff --git a/dist/voucherify.min.js b/dist/voucherify.min.js index ddfabf4..30f8710 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{validate:e+"/client/v1/validate",redeem:e+"/client/v1/redeem",publish:e+"/client/v1/publish",list:e+"/client/v1/vouchers",track:e+"/client/v1/events",validatePromotion:e+"/client/v1/promotions/validation"}}function i(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 r(e){return Math.round(100.001*e)/100}function a(e){if(!e||0>e||e>100)throw new Error("Invalid voucher, percent discount should be between 0-100.")}function l(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function s(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function c(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 u(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=l.readOptions(n._element,o.concat(i).concat(t.attributes),t.defaults),n._iframe=null,this.renderIframe()}var o=["client-app-id","client-token","client-app-url","logo","widget-id","height","success-message","failure-message"],i=["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","customer-metadata"],r=["consent-label","consent-description","consent-options","consent-options-required","consent-legal","consent-voucherify-note-visible"],a={"voucher-redeem":{path:"/widgets/redeem",defaults:{height:"480px"},attributes:["metadata","redemption-metadata","metadata-fields","code","code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","button-label"].concat(r)},"get-voucher":{path:"/widgets/publish",defaults:{height:"430px"},attributes:["campaign","metadata","source","button-label"]},subscribe:{path:"/widgets/subscribe",defaults:{height:"220px"},attributes:["metadata","source","subscribe-label"].concat(r)}},l={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t,n){return Array.prototype.reduce.call(t,function(t,o){var i=e.getAttribute("data-"+o);return i?t[o]=i:n[o]&&(t[o]=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=e._options["client-app-url"]?e._options["client-app-url"]:"https://app.voucherify.io",o=e._options.height;e._options.height=void 0;var i=["width:400px;","height:"+o+";","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=i.join("\n"),l.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=n+e._path+l.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var s=[];return Object.keys(a).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){s.push(new n(e,a[t]))})}),s}var d=o("localhost:8000"),p={},f="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,o,r){var a="function"==typeof r?{resolve:r,reject:r}:n.Deferred();return n.ajax({type:e,url:t,data:JSON.stringify(o),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":p.applicationId,"X-Client-Token":p.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:p.timeout,success:function(e){return i(e)?void a.resolve(e):void a.reject({type:"error",message:"Unexpected response structure.",context:e})},error:function(e){a.reject({type:"error",message:"XHR error happened.",context:e})}}),"function"!=typeof r?a.promise():void 0}:function(t,n,o,r){r="function"==typeof r?r:function(){};var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=p.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",p.applicationId),a.setRequestHeader("X-Client-Token",p.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){if(a.status>=200&&a.status<400)try{var e=JSON.parse(a.responseText);if(i(e))return void r(e);r({type:"error",message:"Unexpected response structure.",context:e})}catch(t){r({type:"error",message:"Unparsable response.",context:t})}else r({type:"error",message:"Unexpected status code.",context:a.status})},a.onerror=function(e){r({type:"error",message:"XHR error happened.",context:e})},a.send(JSON.stringify(o))};var b={initialize:function(e,t,n){p.applicationId=e,p.token=t,p.timeout=n||5e3},setIdentity:function(e){p.trackingId=e},setBaseUrl:function(e){e=e||"",0!==e.indexOf("https://")&&0!==e.indexOf("http://")&&(e="https://"+e),d=o(e)},validate:function(e,t){if(!c(p))return null;var n,o,i,r,a,l=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.orderMetadata,a=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var s="?";if(e?(s+="code="+encodeURIComponent(e),n&&(s+="&amount="+parseInt(n))):(l=!0,n&&(s+="amount="+parseInt(n))),o&&(s+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(s+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r&&(s+="&"+Object.keys(r).map(function(e){return encodeURIComponent("order[metadata]["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")),a){if("object"!=typeof a)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;s+="&"+Object.keys(a).map(function(e){return"metadata"===e?"object"!=typeof a.metadata?(console.error("Customer's metadata must be an object - please use instead { property: 'value' }"),null):Object.keys(a.metadata).map(function(e){return encodeURIComponent("customer[metadata]["+e+"]")+"="+encodeURIComponent(a.metadata[e])}).join("&"):encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(a[e])}).join("&")}return p.trackingId&&(s+="&tracking_id="+encodeURIComponent(p.trackingId)),y("GET",(l?d.validatePromotion:d.validate)+s,void 0,t)},redeem:function(e,t,n){if(!c(p))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||p.trackingId,y("POST",d.redeem+o,t,n)},publish:function(e,t,n){if(!c(p))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||p.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",d.publish+o,t,n)},listVouchers:function(e,t){if(!c(p))return null;"function"!=typeof e||t||(t=e,e={});var o="?"+n.param(e);return y("GET",d.list+o,void 0,t)},track:function(e,t,n,o){if(!c(p))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||p.trackingId,y("POST",d.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?u:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var u=e-n*o;return r(u>0?u:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/i);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var c=n*o;return r(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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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),I="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",w="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",R="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";d.on("keyup",function(e){d.toggleClass(P,!1)}),p.on("keyup",function(e){p.toggleClass(P,!1)}),x.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),x.toggleClass(I,!1),x.toggleClass(w,!1),!d.val())return void d.toggleClass(P,!0).delay(1e3).queue(function(){d.toggleClass(P,!1),d.dequeue()});var t={code:d.val(),amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))};_.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(I,!0),e.toggleClass(w,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};x.toggleClass(I,!0),x.toggleClass(w,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(I,!1),p.toggleClass(I,!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||""),d.prop("disabled",!0),p.prop("disabled",!0),x.prop("disabled",!0),d.toggleClass(w,!0),p.toggleClass(w,!0),x.toggleClass(w,!0),x.toggleClass(I,!1),d.toggleClass(I,!1),d.toggleClass(R,!0),p.toggleClass(R,!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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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";d.on("keyup",function(e){d.toggleClass(x,!1)}),p.on("keyup",function(e){p.toggleClass(x,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!d.val())return void d.toggleClass(x,!0).delay(1e3).queue(function(){d.toggleClass(x,!1),d.dequeue()});var t={order:{amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))}};y.redeem(d.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!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(b,!1),p.toggleClass(b,!1),h.val(e.tracking_id||""),d.prop("disabled",!0),p.prop("disabled",!0),v.prop("disabled",!0),d.toggleClass(C,!0),p.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),d.toggleClass(b,!1),d.toggleClass(_,!0),p.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 u(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 u in r)"configurable"!==u&&r.hasOwnProperty(u)&&a.attr(u,r[u]);"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 d(e){e.toggleClass(U,!0),e.toggleClass(q,!1),e.toggleClass(S,!0).delay(1e3).queue(function(){e.toggleClass(S,!1),e.toggleClass(U,!1),e.toggleClass(q,!1),e.dequeue()})}var p=n(e);if(!p||!p.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var f=u("div","container",p);f.addClass("wide");{var m=u("figure","logo",f),g=(u("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&u("input","customerName",f,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=u("div","row",f),b=r("email")&&u("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&u("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),x=r("line_1")&&u("input","customerLine1",f,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),_=r("line_2")&&u("input","customerLine2",f,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),I=u("div","row",f),w=r("postal_code")&&u("input","customerPostalCode",I,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&u("input","customerCity",I,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),R=u("div","row",f),k=r("state")&&u("input","customerState",R,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&u("input","customerCountry",R,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),j=u("input","tracking",f,{type:"hidden",configurable:!0}),A=u("input","publishStatus",f,{type:"text"}),O=u("button","publish",f,{});u("span","publishText",O,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,U="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",q="string"==typeof o.classValid?o.classValid:"voucherifyValid",S="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",T="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";O.on("click",function(e){j.val(""),O.toggleClass(U,!1),O.toggleClass(q,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return d(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return d(b);if(b.val()&&!v.test(b.val()))return d(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return d(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 d(x);t.customer.address.line_1=x.val()}if(r("line_2")){if(!_.val()&&a("line_2"))return d(_);t.customer.address.line_2=_.val()}if(r("postal_code")){if(!w.val()&&a("postal_code"))return d(w);t.customer.address.postal_code=w.val()}if(r("city")){if(!P.val()&&a("city"))return d(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return d(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return d(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 d(O),void(r("phone")&&i===h&&d(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),x&&x.hide(),_&&_.hide(),w&&w.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(T,!0).val(e.voucher.code).show(100),j.val(e.tracking_id||""),O.prop("disabled",!0),O.toggleClass(U,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})},refreshIframes:function(){e.docReady(function(){console.info("Re-render voucherify iframes."),u()})}};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 l(e){if(!e||0>e)throw new Error("Invalid voucher, amount discount must be higher than zero.")}function s(e){if(!e||0>e)throw new Error("Invalid voucher, unit discount must be higher than zero.")}function c(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 u(){function n(e,t){var n=this;return n._element=e,n._path=t.path,n._options=l.readOptions(n._element,o.concat(i).concat(t.attributes),t.defaults),n._iframe=null,this.renderIframe()}var o=["client-app-id","client-token","client-app-url","logo","widget-id","height","success-message","failure-message"],i=["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","customer-metadata"],r=["consent-label","consent-description","consent-options","consent-options-required","consent-legal","consent-voucherify-note-visible"],a={"voucher-redeem":{path:"/widgets/redeem",defaults:{height:"480px"},attributes:["metadata","redemption-metadata","metadata-fields","code","code-field","code-field-required","code-field-label","amount-field","amount-field-required","amount-field-label","button-label"].concat(r)},"get-voucher":{path:"/widgets/publish",defaults:{height:"430px"},attributes:["campaign","metadata","source","button-label"]},subscribe:{path:"/widgets/subscribe",defaults:{height:"220px"},attributes:["metadata","source","subscribe-label"].concat(r)}},l={bind:function(e,t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},readOptions:function(e,t,n){return Array.prototype.reduce.call(t,function(t,o){var i=e.getAttribute("data-"+o);return i?t[o]=i:n[o]&&(t[o]=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=e._options["client-app-url"]?e._options["client-app-url"]:"https://app.voucherify.io",o=e._options.height;e._options.height=void 0;var i=["width:400px;","height:"+o+";","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=i.join("\n"),l.bind(e._iframe,"load",function(){return e._iframe.style.visibility="visible"}),e._iframe.src=n+e._path+l.encodeOptions(e._options),e._element.appendChild(e._iframe),e};var s=[];return Object.keys(a).forEach(function(t){var o=e.document.querySelectorAll(".voucherify-"+t);Array.prototype.forEach.call(o,function(e){s.push(new n(e,a[t]))})}),s}var d=o("https://api.voucherify.io"),p={},f="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,o,r){var a="function"==typeof r?{resolve:r,reject:r}:n.Deferred();return n.ajax({type:e,url:t,data:JSON.stringify(o),xhrFields:{withCredentials:!0},dataType:"json",headers:{Accept:"application/json","Content-Type":"application/json","X-Client-Application-Id":p.applicationId,"X-Client-Token":p.token,"X-Voucherify-Channel":"Voucherify.js"},timeout:p.timeout,success:function(e){return i(e)?void a.resolve(e):void a.reject({type:"error",message:"Unexpected response structure.",context:e})},error:function(e){a.reject({type:"error",message:"XHR error happened.",context:e})}}),"function"!=typeof r?a.promise():void 0}:function(t,n,o,r){r="function"==typeof r?r:function(){};var a=new e.XMLHttpRequest;a.withCredentials=!0,a.open(t,n,!0),a.timeout=p.timeout,a.setRequestHeader("Accept","application/json"),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("X-Client-Application-Id",p.applicationId),a.setRequestHeader("X-Client-Token",p.token),a.setRequestHeader("X-Voucherify-Channel","Voucherify.js"),a.onload=function(){if(a.status>=200&&a.status<400)try{var e=JSON.parse(a.responseText);if(i(e))return void r(e);r({type:"error",message:"Unexpected response structure.",context:e})}catch(t){r({type:"error",message:"Unparsable response.",context:t})}else r({type:"error",message:"Unexpected status code.",context:a.status})},a.onerror=function(e){r({type:"error",message:"XHR error happened.",context:e})},a.send(JSON.stringify(o))};var b={initialize:function(e,t,n){p.applicationId=e,p.token=t,p.timeout=n||5e3},setIdentity:function(e){p.trackingId=e},setBaseUrl:function(e){e=e||"",0!==e.indexOf("https://")&&0!==e.indexOf("http://")&&(e="https://"+e),d=o(e)},validate:function(e,t){if(!c(p))return null;var n,o,i,r,a,l=!1;"object"==typeof e&&(n=e.amount,o=e.items,i=e.metadata,r=e.orderMetadata,a=e.customer,e=e.code),e&&(e=e.replace(/[\s\r\n]/g,""));var s="?";if(e?(s+="code="+encodeURIComponent(e),n&&(s+="&amount="+parseInt(n))):(l=!0,n&&(s+="amount="+parseInt(n))),o&&(s+="&"+o.map(function(e,t){return Object.keys(e).map(function(n){return encodeURIComponent("item["+t+"]["+n+"]")+"="+encodeURIComponent(e[n])}).join("&")}).join("&")),i&&(s+="&"+Object.keys(i).map(function(e){return encodeURIComponent("metadata["+e+"]")+"="+encodeURIComponent(i[e])}).join("&")),r&&(s+="&"+Object.keys(r).map(function(e){return encodeURIComponent("order[metadata]["+e+"]")+"="+encodeURIComponent(r[e])}).join("&")),a){if("object"!=typeof a)return console.error("Customer must be an object - please use instead { source_id: 'your_user' }"),null;s+="&"+Object.keys(a).map(function(e){return"metadata"===e?"object"!=typeof a.metadata?(console.error("Customer's metadata must be an object - please use instead { property: 'value' }"),null):Object.keys(a.metadata).map(function(e){return encodeURIComponent("customer[metadata]["+e+"]")+"="+encodeURIComponent(a.metadata[e])}).join("&"):encodeURIComponent("customer["+e+"]")+"="+encodeURIComponent(a[e])}).join("&")}return p.trackingId&&(s+="&tracking_id="+encodeURIComponent(p.trackingId)),y("GET",(l?d.validatePromotion:d.validate)+s,void 0,t)},redeem:function(e,t,n){if(!c(p))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||p.trackingId,y("POST",d.redeem+o,t,n)},publish:function(e,t,n){if(!c(p))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||p.trackingId,t.channel=t.channel||"Voucherify.js",y("POST",d.publish+o,t,n)},listVouchers:function(e,t){if(!c(p))return null;"function"!=typeof e||t||(t=e,e={});var o="?"+n.param(e);return y("GET",d.list+o,void 0,t)},track:function(e,t,n,o){if(!c(p))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||p.trackingId,y("POST",d.track,i,o)},utils:{calculatePrice:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(e-o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/100);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(e-c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?u:0)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var u=e-n*o;return r(u>0?u:0)}throw new Error("Unsupported discount type.")},calculateDiscount:function(e,t,n){var o,i=100;if(t.gift)return o=Math.min(t.gift.balance/i,e),r(o);if(!t.discount)throw new Error("Unsupported voucher type.");if("PERCENT"===t.discount.type){o=t.discount.percent_off,a(o);var c=e*(o/i);return t.discount.amount_limit&&(c=Math.min(t.discount.amount_limit/i,c)),r(c)}if("AMOUNT"===t.discount.type){o=t.discount.amount_off/i,l(o);var u=e-o;return r(u>0?o:e)}if("UNIT"===t.discount.type){o=t.discount.unit_off,s(o);var c=n*o;return r(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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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),I="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",w="string"==typeof o.classValid?o.classValid:"voucherifyValid",P="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",R="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";d.on("keyup",function(e){d.toggleClass(P,!1)}),p.on("keyup",function(e){p.toggleClass(P,!1)}),x.on("click",function(e){if(h.val(""),y.val(""),b.val(""),v.val(""),C.val(""),x.toggleClass(I,!1),x.toggleClass(w,!1),!d.val())return void d.toggleClass(P,!0).delay(1e3).queue(function(){d.toggleClass(P,!1),d.dequeue()});var t={code:d.val(),amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))};_.validate(t,function(e){if(!e||!e.valid){var t=function(e){e.toggleClass(I,!0),e.toggleClass(w,!1),e.toggleClass(P,!0).delay(1e3).queue(function(){e.toggleClass(P,!1),e.dequeue()})};x.toggleClass(I,!0),x.toggleClass(w,!1);var n=e.context||{},i=n.responseJSON||{},r=i.key;return void t(!o.amount||r!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(I,!1),p.toggleClass(I,!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||""),d.prop("disabled",!0),p.prop("disabled",!0),x.prop("disabled",!0),d.toggleClass(w,!0),p.toggleClass(w,!0),x.toggleClass(w,!0),x.toggleClass(I,!1),d.toggleClass(I,!1),d.toggleClass(R,!0),p.toggleClass(R,!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 u in l)"configurable"!==u&&l.hasOwnProperty(u)&&s.attr(u,l[u]);"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),u=l("figure","logo",c),d=(l("img","logo",u,{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"})),p=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";d.on("keyup",function(e){d.toggleClass(x,!1)}),p.on("keyup",function(e){p.toggleClass(x,!1)}),v.on("click",function(e){if(h.val(""),v.toggleClass(b,!1),v.toggleClass(C,!1),!d.val())return void d.toggleClass(x,!0).delay(1e3).queue(function(){d.toggleClass(x,!1),d.dequeue()});var t={order:{amount:parseInt(100*parseFloat(p.val().replace(/\,/,".")))}};y.redeem(d.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!==f&&r!==m&&r!==g?d:p)}p.val()>=0?p.val(parseFloat(p.val().replace(/\,/,"."))):p.hide(100),d.toggleClass(b,!1),p.toggleClass(b,!1),h.val(e.tracking_id||""),d.prop("disabled",!0),p.prop("disabled",!0),v.prop("disabled",!0),d.toggleClass(C,!0),p.toggleClass(C,!0),v.toggleClass(C,!0),v.toggleClass(b,!1),d.toggleClass(b,!1),d.toggleClass(_,!0),p.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 u(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 u in r)"configurable"!==u&&r.hasOwnProperty(u)&&a.attr(u,r[u]);"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 d(e){e.toggleClass(U,!0),e.toggleClass(q,!1),e.toggleClass(S,!0).delay(1e3).queue(function(){e.toggleClass(S,!1),e.toggleClass(U,!1),e.toggleClass(q,!1),e.dequeue()})}var p=n(e);if(!p||!p.length)throw new Error("Element '"+e+"' cannot be found");if(o=o||{},!o.campaignName)throw new Error("Option campaignName is not specified");var f=u("div","container",p);f.addClass("wide");{var m=u("figure","logo",f),g=(u("img","logo",m,{src:"string"==typeof o.logoSrc?o.logoSrc:"https://app.voucherify.io/images/favicon.png"}),r("name")&&u("input","customerName",f,{type:"text",placeholder:"string"==typeof o.customerNamePlaceholder?o.customerNamePlaceholder:"Name"})),y=u("div","row",f),b=r("email")&&u("input","customerEmail",y,{type:"email",placeholder:"string"==typeof o.customerEmailPlaceholder?o.customerEmailPlaceholder:"Email"}),C=r("phone")&&u("input","customerPhone",y,{type:"text",placeholder:"string"==typeof o.customerPhonePlaceholder?o.customerPhonePlaceholder:"Phone"}),x=r("line_1")&&u("input","customerLine1",f,{type:"text",placeholder:"string"==typeof o.customerLine1Placeholder?o.customerLine1Placeholder:"Address line 1"}),_=r("line_2")&&u("input","customerLine2",f,{type:"text",placeholder:"string"==typeof o.customerLine2Placeholder?o.customerLine2Placeholder:"Address line 2"}),I=u("div","row",f),w=r("postal_code")&&u("input","customerPostalCode",I,{type:"text",placeholder:"string"==typeof o.customerPostalCodePlaceholder?o.customerPostalCodePlaceholder:"Postal Code"}),P=r("city")&&u("input","customerCity",I,{type:"text",placeholder:"string"==typeof o.customerCityPlaceholder?o.customerCityPlaceholder:"City"}),R=u("div","row",f),k=r("state")&&u("input","customerState",R,{type:"text",placeholder:"string"==typeof o.customerStatePlaceholder?o.customerStatePlaceholder:"State"}),E=r("country")&&u("input","customerCountry",R,{type:"text",placeholder:"string"==typeof o.customerCountryPlaceholder?o.customerCountryPlaceholder:"Country"}),j=u("input","tracking",f,{type:"hidden",configurable:!0}),A=u("input","publishStatus",f,{type:"text"}),O=u("button","publish",f,{});u("span","publishText",O,{text:"string"==typeof o.textPublish?o.textPublish:"Get voucher"})}A.prop("readonly",!0).hide();var V=this,U="string"===o.classInvalid?o.classInvalid:"voucherifyInvalid",q="string"==typeof o.classValid?o.classValid:"voucherifyValid",S="string"===o.classInvalidAnimation?o.classInvalidAnimation:"voucherifyAnimationShake",T="string"===o.classValidAnimation?o.classValidAnimation:"voucherifyAnimationTada";O.on("click",function(e){j.val(""),O.toggleClass(U,!1),O.toggleClass(q,!1);var t={customer:{}};if(r("name")){if(!g.val()&&a("name"))return d(g);t.customer.name=g.val()}if(r("email")){if(!b.val()&&a("email"))return d(b);if(b.val()&&!v.test(b.val()))return d(b);t.customer.email=b.val(),t.customer.source_id=t.customer.email}if(r("phone")){if(!C.val()&&a("phone"))return d(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 d(x);t.customer.address.line_1=x.val()}if(r("line_2")){if(!_.val()&&a("line_2"))return d(_);t.customer.address.line_2=_.val()}if(r("postal_code")){if(!w.val()&&a("postal_code"))return d(w);t.customer.address.postal_code=w.val()}if(r("city")){if(!P.val()&&a("city"))return d(P);t.customer.address.city=P.val()}if(r("state")){if(!k.val()&&a("state"))return d(k);t.customer.address.state=k.val()}if(r("country")){if(!E.val()&&a("country"))return d(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 d(O),void(r("phone")&&i===h&&d(C))}g&&g.hide(),b&&b.hide(),C&&C.hide(),x&&x.hide(),_&&_.hide(),w&&w.hide(),P&&P.hide(),k&&k.hide(),E&&E.hide(),A.toggleClass(T,!0).val(e.voucher.code).show(100),j.val(e.tracking_id||""),O.prop("disabled",!0),O.toggleClass(U,!1).hide(),o&&o.onPublished&&"function"==typeof o.onPublished&&o.onPublished(e)})})},refreshIframes:function(){e.docReady(function(){console.info("Re-render voucherify iframes."),u()})}};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 = typeof(callback) === \"function\" ? { resolve: callback, reject: callback } : $.Deferred();\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 if (isValidResponseStructure(data)) {\n deferred.resolve(data);\n return;\n }\n\n deferred.reject({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n },\n\n error: function (error) {\n deferred.reject({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n });\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n callback = typeof(callback) === \"function\" ? callback : function () {\n };\n\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 if (request.status >= 200 && request.status < 400) {\n try {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n callback(data);\n return;\n }\n\n callback({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n } catch (error) {\n callback({\n type: \"error\",\n message: \"Unparsable response.\",\n context: error\n });\n }\n } else {\n callback({\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n });\n }\n };\n\n request.onerror = function (error) {\n callback({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\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 setBaseUrl: function (baseUrl) {\n baseUrl = baseUrl || \"\";\n\n if (baseUrl.indexOf(\"https://\") !== 0 && baseUrl.indexOf(\"http://\") !== 0) {\n baseUrl = \"https://\" + baseUrl;\n }\n\n API = buildAPI(baseUrl);\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 orderMetadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n orderMetadata = code.orderMetadata;\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 (orderMetadata) {\n queryString += \"&\" + Object.keys(orderMetadata).map(function (key) {\n return encodeURIComponent(\"order[metadata][\" + key + \"]\") + \"=\" + encodeURIComponent(orderMetadata[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 if (key === \"metadata\") {\n if (typeof(customer.metadata) !== \"object\") {\n console.error(\"Customer's metadata must be an object - please use instead { property: 'value' }\");\n return null;\n }\n\n return Object.keys(customer.metadata).map(function (metadataKey) {\n return encodeURIComponent(\"customer[metadata][\" + metadataKey + \"]\") + \"=\" + encodeURIComponent(customer.metadata[metadataKey]);\n }).join(\"&\");\n }\n\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 = \"?\" + $.param(filters);\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 refreshIframes: function () {\n window.docReady(function () {\n console.info(\"Re-render voucherify iframes.\");\n renderIframes();\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 () {\n callback(context);\n }, 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 common_attributes = [\n \"client-app-id\",\n \"client-token\",\n \"client-app-url\",\n\n \"logo\",\n\n \"widget-id\",\n \"height\",\n\n \"success-message\",\n \"failure-message\"\n ];\n\n var customer_attributes = [\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 \"customer-metadata\"\n ];\n\n var consent_fields = [\n \"consent-label\",\n \"consent-description\",\n \"consent-options\",\n \"consent-options-required\",\n \"consent-legal\",\n \"consent-voucherify-note-visible\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"defaults\": {\n \"height\": \"480px\"\n },\n \"attributes\": [\n \"metadata\",\n \"redemption-metadata\",\n\n \"metadata-fields\",\n\n \"code\",\n\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 \"button-label\"\n ].concat(consent_fields)\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"defaults\": {\n \"height\": \"430px\"\n },\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"defaults\": {\n \"height\": \"220px\"\n },\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"subscribe-label\"\n ].concat(consent_fields)\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, defaults) {\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 } else if (defaults[allowed_option]) { // check if the default value is provided\n options[allowed_option] = defaults[allowed_option];\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(customer_attributes).concat(options.attributes), options.defaults);\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 host = self._options[\"client-app-url\"] ? self._options[\"client-app-url\"] : \"https://app.voucherify.io\";\n\n // -- set custom height or fallback\n var widget_height = self._options.height;\n // -- remove custom height from options to prevent before sending it\n self._options.height = undefined;\n\n var css_props = [\n \"width:400px;\",\n \"height:\" + widget_height + \";\",\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","$","buildAPI","baseUrl","validate","redeem","publish","list","track","validatePromotion","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","customer_attributes","attributes","defaults","_iframe","renderIframe","consent_fields","iframes_widgets","voucher-redeem","height","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","host","widget_height","undefined","css_props","createElement","setAttribute","style","cssText","visibility","src","appendChild","widgets","widget_name","elements","querySelectorAll","API","OPTIONS","INVALID_AMOUNT","INVALID_NUMBER","MISSING_AMOUNT","INVALID_CUSTOMER_PHONE","EMAIL_PATTERN","xhrImplementation","Deferred","method","url","payload","deferred","resolve","reject","ajax","type","JSON","stringify","xhrFields","withCredentials","dataType","headers","Accept","Content-Type","X-Client-Application-Id","X-Client-Token","token","X-Voucherify-Channel","timeout","success","message","context","promise","request","XMLHttpRequest","open","setRequestHeader","onload","status","parse","responseText","onerror","send","voucherify","initialize","clientAppId","setIdentity","trackingId","setBaseUrl","indexOf","code","amount","items","metadata","orderMetadata","customer","isPromotion","replace","queryString","parseInt","map","item","index","key","metadataKey","source_id","campaign","channel","listVouchers","filters","param","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","result","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","refreshIframes","docReady","info","funcName","baseObj","ready","readyFired","i","readyList","fn","ctx","readyStateChange","readyState","readyEventHandlersInstalled","TypeError","setTimeout","module","exports","jQuery"],"mappings":"AAAAA,OAAOC,WAAc,SAAUD,EAAQE,EAAUC,GAC/C,YAIA,SAASC,GAASC,GAChB,OACEC,SAAmBD,EAAU,sBAC7BE,OAAmBF,EAAU,oBAC7BG,QAAmBH,EAAU,qBAC7BI,KAAmBJ,EAAU,sBAC7BK,MAAmBL,EAAU,oBAC7BM,kBAAmBN,EAAU,oCAcjC,QAASO,GAAyBC,GAChC,MAAOA,KAAgC,iBAAhBA,GAAU,OACH,gBAAjBA,GAAW,QACO,gBAAlBA,GAAY,SACO,gBAAnBA,GAAa,UACH,UAAhBA,EAAKC,QAA4C,gBAAfD,GAAS,MAqHpD,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,GAq5BX,QAASC,KAsJP,QAASC,GAAaC,EAASN,GAC7B,GAAIO,GAAOC,IAUX,OARAD,GAAKE,SAAWH,EAEhBC,EAAKG,MAAQV,EAAQW,KAErBJ,EAAKK,SAAWC,EAAQC,YAAYP,EAAKE,SAAUM,EAAkBC,OAAOC,GAAqBD,OAAOhB,EAAQkB,YAAalB,EAAQmB,UAErIZ,EAAKa,QAAU,KAERZ,KAAKa,eAhKd,GAAIN,IACF,gBACA,eACA,iBAEA,OAEA,YACA,SAEA,kBACA,mBAGEE,GACF,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,qBAGEK,GACF,gBACA,sBACA,kBACA,2BACA,gBACA,mCAGEC,GACFC,kBACEb,KAAQ,kBACRQ,UACEM,OAAU,SAEZP,YACE,WACA,sBAEA,kBAEA,OAEA,aACA,sBACA,mBAEA,eACA,wBACA,qBAEA,gBACAF,OAAOM,IAEXI,eACEf,KAAQ,mBACRQ,UACEM,OAAU,SAEZP,YACE,WAEA,WACA,SAEA,iBAGJS,WACEhB,KAAQ,qBACRQ,UACEM,OAAU,SAEZP,YACE,WACA,SAEA,mBACAF,OAAOM,KAITT,GACFe,KAAM,SAAUtB,EAASuB,EAAMC,GAC7B,MAAIxB,GAAQyB,iBACHzB,EAAQyB,iBAAiBF,EAAMC,GAAU,GAEzCxB,EAAQ0B,YAAY,KAAOH,EAAMC,IAG5ChB,YAAa,SAAUR,EAAS2B,EAAiBd,GAC/C,MAAOe,OAAMC,UAAUC,OAAOC,KAAKJ,EAAiB,SAAUjC,EAASsC,GACrE,GAAIC,GAAejC,EAAQkC,aAAa,QAAUF,EAQlD,OANIC,GACFvC,EAAQsC,GAAkBC,EACjBpB,EAASmB,KAClBtC,EAAQsC,GAAkBnB,EAASmB,IAG9BtC,QAGXyC,cAAe,SAAUzC,GACvB,GAAI0C,KAMJ,OAJAC,QAAOC,KAAK5C,GAAS6C,QAAQ,SAAUC,GACrCJ,EAAiBK,KAAK,aAAeD,EAAa,KAAOE,mBAAmBhD,EAAQ8C,OAG/E,IAAMJ,EAAiBO,KAAK,MAmBvC5C,GAAa8B,UAAUd,aAAe,WACpC,GAAId,GAAOC,IAEX,IAAID,EAAKa,QACP,MAAOb,EAGT,IAAI2C,GAAO3C,EAAKK,SAAS,kBAAoBL,EAAKK,SAAS,kBAAoB,4BAG3EuC,EAAgB5C,EAAKK,SAASa,MAElClB,GAAKK,SAASa,OAAS2B,MAEvB,IAAIC,IACF,eACA,UAAYF,EAAgB,IAC5B,2BACA,gCACA,sBACA,oBACA,sBACA,aACA,cACA,4CACA,+BAgBF,OAbA5C,GAAKa,QAAU3C,EAAS6E,cAAc,UACtC/C,EAAKa,QAAQmC,aAAa,cAAe,KACzChD,EAAKa,QAAQmC,aAAa,oBAAqB,QAC/ChD,EAAKa,QAAQoC,MAAMC,QAAUJ,EAAUJ,KAAK,MAE5CpC,EAAQe,KAAKrB,EAAKa,QAAS,OAAQ,WACjC,MAAOb,GAAKa,QAAQoC,MAAME,WAAa,YAGzCnD,EAAKa,QAAQuC,IAAMT,EAAO3C,EAAKG,MAAQG,EAAQ4B,cAAclC,EAAKK,UAElEL,EAAKE,SAASmD,YAAYrD,EAAKa,SAExBb,EAGT,IAAIsD,KAUJ,OARAlB,QAAOC,KAAKrB,GAAiBsB,QAAQ,SAAUiB,GAC7C,GAAIC,GAAWxF,EAAOE,SAASuF,iBAAiB,eAAiBF,EAEjE5B,OAAMC,UAAUU,QAAQR,KAAK0B,EAAU,SAAUzD,GAC/CuD,EAAQd,KAAK,GAAI1C,GAAaC,EAASiB,EAAgBuC,SAIpDD,EAzxCT,GAAII,GAAMtF,EAAS,6BAafuF,KAGAC,EAAiB,iBACjBC,EAAiB,iBACjBC,EAAiB,iBACjBC,EAAyB,yBAEzBC,EAAgB,yJAWhBC,EAAoB,IAGtBA,GADE9F,GAAwB,kBAAZA,GAAM,MAAoBA,EAAE+F,SACtB,SAAUC,EAAQC,EAAKC,EAAS9C,GAClD,GAAI+C,GAAgC,kBAAf,IAA8BC,QAAShD,EAAUiD,OAAQjD,GAAapD,EAAE+F,UA6C7F,OA3CA/F,GAAEsG,MACAC,KAAMP,EAENC,IAAKA,EAELvF,KAAM8F,KAAKC,UAAUP,GAErBQ,WACEC,iBAAiB,GAGnBC,SAAU,OACVC,SACEC,OAAU,mBACVC,eAAgB,mBAChBC,0BAA2BxB,EAAQjE,cACnC0F,iBAAkBzB,EAAQ0B,MAC1BC,uBAAwB,iBAE1BC,QAAS5B,EAAQ4B,QAEjBC,QAAS,SAAU3G,GACjB,MAAID,GAAyBC,OAC3ByF,GAASC,QAAQ1F,OAInByF,GAASE,QACPE,KAAM,QACNe,QAAS,iCACTC,QAAS7G,KAIbe,MAAO,SAAUA,GACf0E,EAASE,QACPE,KAAM,QACNe,QAAS,sBACTC,QAAS9F,OAKU,kBAAf,GACD0E,EAASqB,UADlB,QAKkB,SAAUxB,EAAQC,EAAKC,EAAS9C,GAClDA,EAAgC,kBAAf,GAA4BA,EAAW,YAGxD,IAAIqE,GAAU,GAAI5H,GAAO6H,cAEzBD,GAAQd,iBAAkB,EAC1Bc,EAAQE,KAAK3B,EAAQC,GAAK,GAC1BwB,EAAQL,QAAU5B,EAAQ4B,QAE1BK,EAAQG,iBAAiB,SAAU,oBACnCH,EAAQG,iBAAiB,eAAgB,oBACzCH,EAAQG,iBAAiB,0BAA2BpC,EAAQjE,eAC5DkG,EAAQG,iBAAiB,iBAAkBpC,EAAQ0B,OACnDO,EAAQG,iBAAiB,uBAAwB,iBAEjDH,EAAQI,OAAS,WACf,GAAIJ,EAAQK,QAAU,KAAOL,EAAQK,OAAS,IAC5C,IACE,GAAIpH,GAAO8F,KAAKuB,MAAMN,EAAQO,aAE9B,IAAIvH,EAAyBC,GAE3B,WADA0C,GAAS1C,EAIX0C,IACEmD,KAAM,QACNe,QAAS,iCACTC,QAAS7G,IAEX,MAAOe,GACP2B,GACEmD,KAAM,QACNe,QAAS,uBACTC,QAAS9F,QAIb2B,IACEmD,KAAM,QACNe,QAAS,0BACTC,QAASE,EAAQK,UAKvBL,EAAQQ,QAAU,SAAUxG,GAC1B2B,GACEmD,KAAM,QACNe,QAAS,sBACTC,QAAS9F,KAIbgG,EAAQS,KAAK1B,KAAKC,UAAUP,IAsChC,IAAIiC,IACFC,WAAY,SAAUC,EAAanB,EAAOE,GACxC5B,EAAQjE,cAAgB8G,EACxB7C,EAAQ0B,MAAQA,EAChB1B,EAAQ4B,QAAUA,GAAW,KAG/BkB,YAAa,SAAUC,GACrB/C,EAAQ+C,WAAaA,GAGvBC,WAAY,SAAUtI,GACpBA,EAAUA,GAAW,GAEe,IAAhCA,EAAQuI,QAAQ,aAAoD,IAA/BvI,EAAQuI,QAAQ,aACvDvI,EAAU,WAAaA,GAGzBqF,EAAMtF,EAASC,IAGjBC,SAAU,SAAUuI,EAAMtF,GACxB,IAAK/B,EAAYmE,GACf,MAAO,KAGT,IACImD,GACAC,EACAC,EACAC,EACAC,EALAC,GAAc,CAOG,iBAAX,KACRL,EAASD,EAAKC,OACdC,EAAQF,EAAKE,MACbC,EAAWH,EAAKG,SAChBC,EAAgBJ,EAAKI,cACrBC,EAAWL,EAAKK,SAChBL,EAAOA,EAAKA,MAGRA,IACJA,EAAOA,EAAKO,QAAQ,YAAa,IAGnC,IAAIC,GAAc,GAiClB,IAhCKR,GAMHQ,GAAe,QAAU5E,mBAAmBoE,GACxCC,IACFO,GAAe,WAAaC,SAASR,MAPvCK,GAAc,EACVL,IACFO,GAAe,UAAYC,SAASR,KASpCC,IACFM,GAAe,IAAMN,EAAMQ,IAAI,SAAUC,EAAMC,GAC7C,MAAOrF,QAAOC,KAAKmF,GAAMD,IAAI,SAAUG,GACrC,MAAOjF,oBAAmB,QAAUgF,EAAQ,KAAOC,EAAM,KAAO,IAAMjF,mBAAmB+E,EAAKE,MAC7FhF,KAAK,OACPA,KAAK,MAGNsE,IACFK,GAAe,IAAMjF,OAAOC,KAAK2E,GAAUO,IAAI,SAAUG,GACvD,MAAOjF,oBAAmB,YAAciF,EAAM,KAAO,IAAMjF,mBAAmBuE,EAASU,MACtFhF,KAAK,MAGNuE,IACFI,GAAe,IAAMjF,OAAOC,KAAK4E,GAAeM,IAAI,SAAUG,GAC5D,MAAOjF,oBAAmB,mBAAqBiF,EAAM,KAAO,IAAMjF,mBAAmBwE,EAAcS,MAClGhF,KAAK,MAGNwE,EAAU,CACZ,GAAyB,gBAAf,GAER,MADAvH,SAAQC,MAAM,8EACP,IAGTyH,IAAe,IAAMjF,OAAOC,KAAK6E,GAAUK,IAAI,SAAUG,GACvD,MAAY,aAARA,EACgC,gBAAvBR,GAAiB,UAC1BvH,QAAQC,MAAM,oFACP,MAGFwC,OAAOC,KAAK6E,EAASF,UAAUO,IAAI,SAAUI,GAClD,MAAOlF,oBAAmB,sBAAwBkF,EAAc,KAAO,IAAMlF,mBAAmByE,EAASF,SAASW,MACjHjF,KAAK,KAGHD,mBAAmB,YAAciF,EAAM,KAAO,IAAMjF,mBAAmByE,EAASQ,MACtFhF,KAAK,KAOV,MAJIiB,GAAQ+C,aACVW,GAAe,gBAAkB5E,mBAAmBkB,EAAQ+C,aAGvDzC,EAAkB,OAAQkD,EAAczD,EAAI/E,kBAAoB+E,EAAIpF,UAAY+I,EAAaxE,OAAWtB,IAGjHhD,OAAQ,SAAUsI,EAAMxC,EAAS9C,GAC/B,IAAK/B,EAAYmE,GACf,MAAO,KAGT,KAAKkD,EAEH,MADAlH,SAAQC,MAAM,iGACP,IAGT,IAAIyH,GAAc,SAAW5E,mBAAmBoE,EAAKO,QAAQ,YAAa,IAO1E,OAJA/C,GAAUA,MACVA,EAAQ6C,SAAW7C,EAAQ6C,aAC3B7C,EAAQ6C,SAASU,UAAYvD,EAAQ6C,SAASU,WAAajE,EAAQ+C,WAE5DzC,EAAkB,OAAQP,EAAInF,OAAS8I,EAAahD,EAAS9C,IAGtE/C,QAAS,SAAUqJ,EAAUxD,EAAS9C,GACpC,IAAK/B,EAAYmE,GACf,MAAO,KAGT,KAAKkE,EAEH,MADAlI,SAAQC,MAAM,mEACP,IAGT,IAAIyH,GAAc,aAAe5E,mBAAmBoF,EASpD,OANAxD,GAAUA,MACVA,EAAQ6C,SAAW7C,EAAQ6C,aAC3B7C,EAAQ6C,SAASU,UAAYvD,EAAQ6C,SAASU,WAAajE,EAAQ+C,WAEnErC,EAAQyD,QAAUzD,EAAQyD,SAAW,gBAE9B7D,EAAkB,OAAQP,EAAIlF,QAAU6I,EAAahD,EAAS9C,IAGvEwG,aAAc,SAAUC,EAASzG,GAC/B,IAAK/B,EAAYmE,GACf,MAAO,KAGc,mBAAZqE,IAA2BzG,IACpCA,EAAWyG,EACXA,KAGF,IAAIX,GAAc,IAAMlJ,EAAE8J,MAAMD,EAEhC,OAAO/D,GAAkB,MAAOP,EAAIjF,KAAO4I,EAAaxE,OAAWtB,IAGrE7C,MAAO,SAAUwJ,EAAYlB,EAAUE,EAAU3F,GAC/C,IAAK/B,EAAYmE,GACf,MAAO,KAGe,mBAAbuD,IAA4B3F,IACrCA,EAAW2F,EACXA,KAGF,IAAI7C,KAMJ,OALAA,GAAQ8D,MAAQD,EAChB7D,EAAQ2C,SAAWA,EACnB3C,EAAQ6C,SAAW7C,EAAQ6C,UAAYA,MACvC7C,EAAQ6C,SAASU,UAAYvD,EAAQ6C,SAASU,WAAajE,EAAQ+C,WAE5DzC,EAAkB,OAAQP,EAAIhF,MAAO2F,EAAS9C,IAGvD6G,OACEC,eAAgB,SAAUC,EAAWC,EAASC,GAC5C,GACIpJ,GADAqJ,EAAI,GAGR,IAAIF,EAAQG,KAEV,MADAtJ,GAAWH,KAAK0J,IAAIJ,EAAQG,KAAKE,QAAUH,EAAGH,GACvCvJ,EAAWuJ,EAAYlJ,EAGhC,KAAKmJ,EAAQnJ,SACX,KAAM,IAAIC,OAAM,4BAGlB,IAA8B,YAA1BkJ,EAAQnJ,SAASsF,KAAoB,CACvCtF,EAAWmJ,EAAQnJ,SAASyJ,YAC5B1J,EAAwBC,EACxB,IAAI0J,GAAgBR,GAAalJ,EAAW,IAM5C,OAJImJ,GAAQnJ,SAAS2J,eACnBD,EAAgB7J,KAAK0J,IAAIJ,EAAQnJ,SAAS2J,aAAeN,EAAGK,IAGvD/J,EAAWuJ,EAAYQ,GAEzB,GAA8B,WAA1BP,EAAQnJ,SAASsF,KAAmB,CAC7CtF,EAAWmJ,EAAQnJ,SAAS4J,WAAaP,EACzCnJ,EAAuBF,EACvB,IAAI6J,GAAWX,EAAYlJ,CAC3B,OAAOL,GAAWkK,EAAW,EAAIA,EAAW,GAEvC,GAA8B,SAA1BV,EAAQnJ,SAASsF,KAAiB,CAC3CtF,EAAWmJ,EAAQnJ,SAAS8J,SAC5B3J,EAAqBH,EACrB,IAAI6J,GAAWX,EAAYE,EAAYpJ,CACvC,OAAOL,GAAWkK,EAAW,EAAIA,EAAW,GAG5C,KAAM,IAAI5J,OAAM,+BAIpB8J,kBAAmB,SAAUb,EAAWC,EAASC,GAC/C,GACIpJ,GADAqJ,EAAI,GAGR,IAAIF,EAAQG,KAEV,MADAtJ,GAAWH,KAAK0J,IAAIJ,EAAQG,KAAKE,QAAUH,EAAGH,GACvCvJ,EAAWK,EAGpB,KAAKmJ,EAAQnJ,SACX,KAAM,IAAIC,OAAM,4BAGlB,IAA8B,YAA1BkJ,EAAQnJ,SAASsF,KAAoB,CACvCtF,EAAWmJ,EAAQnJ,SAASyJ,YAC5B1J,EAAwBC,EACxB,IAAI0J,GAAgBR,GAAalJ,EAAWqJ,EAM5C,OAJIF,GAAQnJ,SAAS2J,eACnBD,EAAgB7J,KAAK0J,IAAIJ,EAAQnJ,SAAS2J,aAAeN,EAAGK,IAGvD/J,EAAW+J,GACb,GAA8B,WAA1BP,EAAQnJ,SAASsF,KAAmB,CAC7CtF,EAAWmJ,EAAQnJ,SAAS4J,WAAaP,EACzCnJ,EAAuBF,EACvB,IAAI6J,GAAWX,EAAYlJ,CAC3B,OAAOL,GAAWkK,EAAW,EAAI7J,EAAWkJ,GAEvC,GAA8B,SAA1BC,EAAQnJ,SAASsF,KAAiB,CAC3CtF,EAAWmJ,EAAQnJ,SAAS8J,SAC5B3J,EAAqBH,EACrB,IAAI0J,GAAgBN,EAAYpJ,CAChC,OAAOL,GAAW+J,EAAgBR,EAAYA,EAAYQ,GAG1D,KAAM,IAAIzJ,OAAM,gCAItB+J,OAAQ,SAAUC,EAAU5J,GAO1B,QAAS6J,GAAmBhI,GAC1B,MAAOA,GAAKiI,OAAO,GAAGC,cAAgBlI,EAAKmI,MAAM,GAGnD,QAASC,GAAgBC,EAAQrI,GAC/B,MAAOqI,GAASL,EAAmBhI,GAGrC,QAASsI,GAAkBD,EAAQrI,GACjC,MAAO7B,GAAQiK,EAAgBC,EAAQrI,IAGzC,QAASuI,GAAenF,EAAMpD,EAAMwI,EAAYC,GAC9CA,EAASA,KACT,IAAIC,GAAW,KACXC,EAAqBL,EAAkB,WAAYtI,EAMvD,IAJIyI,EAAOG,cAAgBD,IACzBD,EAAW7L,EAAE8L,KAGVD,IAAaA,EAASG,OAAQ,CACjCH,EAAW7L,EAAED,EAAS6E,cAAc2B,IACpCoF,EAAWM,OAAOJ,EAElB,KAAK,GAAIK,KAAaN,GACF,iBAAdM,GAAgCN,EAAOO,eAAeD,IACxDL,EAASO,KAAKF,EAAWN,EAAOM,GAIvB,WAAT3F,GACFsF,EAASO,KAAK,OAAQb,EAAgB,aAAcpI,IAGzC,SAAToD,GAAmBqF,EAAOS,MAC5BR,EAASQ,KAAKT,EAAOS,MAKzB,MADAR,GAASS,SAAqD,gBAArCb,GAAkB,QAAStI,GAAqBsI,EAAkB,QAAStI,GAAQoI,EAAgB,aAAcpI,IACnI0I,EA/CT,GAAIU,GAAWvM,EAAEkL,EACjB,KAAKqB,IAAaA,EAASP,OACzB,KAAM,IAAI9K,OAAM,YAAcgK,EAAW,oBAE3C5J,GAAUA,KA8CV,IAAIqK,GAAiBD,EAAe,MAAO,YAAaa,GACpDC,EAAiBd,EAAe,SAAU,OAAQC,GAElDc,GADiBf,EAAe,MAAO,OAAQc,GAAkBvH,IAAgC,gBAApB3D,GAAQoL,QAAuBpL,EAAQoL,QAAU,iDAC7GhB,EAAe,QAAS,OAAQC,GAAcpF,KAAM,OAAQoG,YAAgD,gBAA5BrL,GAAQsL,gBAA+BtL,EAAQsL,gBAAkB,kBAClKC,EAAiBnB,EAAe,QAAS,SAAUC,GAAcpF,KAAMjF,EAAQqH,OAAS,OAAS,SAAUgE,YAAkD,gBAA9BrL,GAAQwL,kBAAiCxL,EAAQwL,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,MAGtD9J,GAFiB6J,EAAe,OAAQ,eAAgB0B,GAAaf,KAAsC,gBAAzB/K,GAAQ+L,aAA4B/L,EAAQ+L,aAAe,aAEtIvL,MACPwL,EAAwC,WAAzBhM,EAAQgM,aAA4BhM,EAAQgM,aAAe,oBAC1EC,EAA2C,gBAAvBjM,GAAQiM,WAA0BjM,EAAQiM,WAAa,kBAC3EC,EAA0D,WAAlClM,EAAQkM,sBAAqClM,EAAQkM,sBAAwB,2BACrGC,EAAsD,WAAhCnM,EAAQmM,oBAAmCnM,EAAQmM,oBAAsB,yBAEnGhB,GAAMiB,GAAG,QAAS,SAAU1D,GAC1ByC,EAAMkB,YAAYH,GAAuB,KAG3CX,EAAQa,GAAG,QAAS,SAAU1D,GAC5B6C,EAAQc,YAAYH,GAAuB,KAG7CJ,EAAUM,GAAG,QAAS,SAAU1D,GAU9B,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,IAAI7H,IACFwC,KAAM+D,EAAMmB,MACZjF,OAAQQ,SAAwD,IAA/C6E,WAAWnB,EAAQe,MAAM3E,QAAQ,KAAM,OAG1DpH,GAAK1B,SAAS+F,EAAS,SAAU+H,GAC/B,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,IAAIhG,GAAe0G,EAAS1G,YACxB8G,EAAe9G,EAAQ8G,iBACvBC,EAAeD,EAAa9E,GAUhC,YAFE4E,IANE7M,EAAQqH,QACR2F,IAAc7I,GACd6I,IAAc5I,GACd4I,IAAc3I,EAGA8G,EAFAI,GAOhBA,EAAQe,OAAS,EACnBf,EAAQe,IAAII,WAAWnB,EAAQe,MAAM3E,QAAQ,KAAM,OAEnD4D,EAAQ0B,KAAK,KAGf9B,EAAMkB,YAAYL,GAAc,GAChCT,EAAQc,YAAYL,GAAc,GAClCP,EAAca,IAAIK,EAAShN,UAAYgN,EAAShN,SAASsF,MAAQ,IACjE0G,EAAWW,IAAIK,EAAShN,UAAYgN,EAAShN,SAAS4J,YAAc,GACpEqC,EAASU,IAAIK,EAAShN,UAAYgN,EAAShN,SAAS8J,UAAY,GAChEiC,EAAYY,IAAIK,EAAShN,UAAYgN,EAAShN,SAASyJ,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,GAErCnM,GAAWA,EAAQoN,aAA8C,kBAAxBpN,GAAQoN,aACnDpN,EAAQoN,YAAYT,QAM5BU,aAAc,SAAUzD,EAAU5J,GAOhC,QAAS6J,GAAmBhI,GAC1B,MAAOA,GAAKiI,OAAO,GAAGC,cAAgBlI,EAAKmI,MAAM,GAGnD,QAASC,GAAgBC,EAAQrI,GAC/B,MAAOqI,GAASL,EAAmBhI,GAGrC,QAASsI,GAAkBD,EAAQrI,GACjC,MAAO7B,GAAQiK,EAAgBC,EAAQrI,IAGzC,QAASuI,GAAenF,EAAMpD,EAAMwI,EAAYC,GAC9CA,EAASA,KACT,IAAIC,GAAW,KACXC,EAAqBL,EAAkB,WAAYtI,EAMvD,IAJIyI,EAAOG,cAAgBD,IACzBD,EAAW7L,EAAE8L,KAGVD,IAAaA,EAASG,OAAQ,CACjCH,EAAW7L,EAAED,EAAS6E,cAAc2B,IACpCoF,EAAWM,OAAOJ,EAElB,KAAK,GAAIK,KAAaN,GACF,iBAAdM,GAAgCN,EAAOO,eAAeD,IACxDL,EAASO,KAAKF,EAAWN,EAAOM,GAIvB,WAAT3F,GACFsF,EAASO,KAAK,OAAQb,EAAgB,aAAcpI,IAGzC,SAAToD,GAAmBqF,EAAOS,MAC5BR,EAASQ,KAAKT,EAAOS,MAKzB,MADAR,GAASS,SAAqD,gBAArCb,GAAkB,QAAStI,GAAqBsI,EAAkB,QAAStI,GAAQoI,EAAgB,aAAcpI,IACnI0I,EA/CT,GAAIU,GAAWvM,EAAEkL,EACjB,KAAKqB,IAAaA,EAASP,OACzB,KAAM,IAAI9K,OAAM,YAAcgK,EAAW,oBAE3C5J,GAAUA,KA8CV,IAAIqK,GAAiBD,EAAe,MAAO,YAAaa,GACpDC,EAAiBd,EAAe,SAAU,OAAQC,GAElDc,GADiBf,EAAe,MAAO,OAAQc,GAAkBvH,IAAgC,gBAApB3D,GAAQoL,QAAuBpL,EAAQoL,QAAU,iDAC7GhB,EAAe,QAAS,OAAQC,GAAcpF,KAAM,OAAQoG,YAAgD,gBAA5BrL,GAAQsL,gBAA+BtL,EAAQsL,gBAAkB,kBAClKC,EAAiBnB,EAAe,QAAS,SAAUC,GAAcpF,KAAMjF,EAAQqH,OAAS,OAAS,SAAUgE,YAAkD,gBAA9BrL,GAAQwL,kBAAiCxL,EAAQwL,kBAAoB,eACpMK,EAAiBzB,EAAe,QAAS,WAAYC,GAAcpF,KAAM,SAAUwF,cAAc,IACjG6C,EAAiBlD,EAAe,SAAU,SAAUC,MAGpD9J,GAFiB6J,EAAe,OAAQ,aAAckD,GAAWvC,KAAoC,gBAAvB/K,GAAQuN,WAA0BvN,EAAQuN,WAAa,WAE9H/M,MACPwL,EAAwC,WAAzBhM,EAAQgM,aAA4BhM,EAAQgM,aAAe,oBAC1EC,EAA2C,gBAAvBjM,GAAQiM,WAA0BjM,EAAQiM,WAAa,kBAC3EC,EAA0D,WAAlClM,EAAQkM,sBAAqClM,EAAQkM,sBAAwB,2BACrGC,EAAsD,WAAhCnM,EAAQmM,oBAAmCnM,EAAQmM,oBAAsB,yBAEnGhB,GAAMiB,GAAG,QAAS,SAAU1D,GAC1ByC,EAAMkB,YAAYH,GAAuB,KAG3CX,EAAQa,GAAG,QAAS,SAAU1D,GAC5B6C,EAAQc,YAAYH,GAAuB,KAG7CoB,EAAQlB,GAAG,QAAS,SAAU1D,GAM5B,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,IAAI7H,IACF4I,OACEnG,OAAQQ,SAAwD,IAA/C6E,WAAWnB,EAAQe,MAAM3E,QAAQ,KAAM,QAI5DpH,GAAKzB,OAAOqM,EAAMmB,MAAO1H,EAAS,SAAU+H,GAC1C,IAAKA,GAAgC,YAApBA,EAASc,OAAsB,CAE9C,GAAIZ,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,IAAIhG,GAAe0G,EAAS1G,YACxB8G,EAAe9G,EAAQ8G,iBACvBC,EAAeD,EAAa9E,GAUhC,YAFE4E,IANE7M,EAAQqH,QACR2F,IAAc7I,GACd6I,IAAc5I,GACd4I,IAAc3I,EAGA8G,EAFAI,GAOhBA,EAAQe,OAAS,EACnBf,EAAQe,IAAII,WAAWnB,EAAQe,MAAM3E,QAAQ,KAAM,OAEnD4D,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,GAErCnM,GAAWA,EAAQ0N,UAAwC,kBAArB1N,GAAQ0N,UAChD1N,EAAQ0N,SAASf,QAMzBgB,cAAe,SAAU/D,EAAU5J,GAYjC,QAAS4N,GAASC,EAAKV,GACrB,MAAOjL,OAAMC,UAAU2L,KAAKzL,KAAKwL,MAAW,SAAUE,GACpD,MAAOA,GAAMlM,OAASsL,IAI1B,QAASa,GAAiBb,GACxB,MAAOS,GAAS5N,EAAQiO,eAAgBd,GAG1C,QAASe,GAAWf,GAClB,GAAIY,GAAQ7L,MAAMC,UAAUgM,KAAK9L,KAAKrC,EAAQiO,mBAAsB,SAAUF,GAC5E,MAAOA,GAAMlM,OAASsL,GAGxB,OAAOY,IAASA,EAAMK,WAAY,EAGpC,QAASvE,GAAmBhI,GAC1B,MAAOA,GAAKiI,OAAO,GAAGC,cAAgBlI,EAAKmI,MAAM,GAGnD,QAASC,GAAgBC,EAAQrI,GAC/B,MAAOqI,GAASL,EAAmBhI,GAGrC,QAASsI,GAAkBD,EAAQrI,GACjC,MAAO7B,GAAQiK,EAAgBC,EAAQrI,IAGzC,QAASuI,GAAenF,EAAMpD,EAAMwI,EAAYC,GAC9CA,EAASA,KACT,IAAIC,GAAW,KACXC,EAAqBL,EAAkB,WAAYtI,EAMvD,IAJIyI,EAAOG,cAAgBD,IACzBD,EAAW7L,EAAE8L,KAGVD,IAAaA,EAASG,OAAQ,CACjCH,EAAW7L,EAAED,EAAS6E,cAAc2B,IACpCoF,EAAWM,OAAOJ,EAElB,KAAK,GAAIK,KAAaN,GACF,iBAAdM,GAAgCN,EAAOO,eAAeD,IACxDL,EAASO,KAAKF,EAAWN,EAAOM,GAIvB,WAAT3F,GACFsF,EAASO,KAAK,OAAQb,EAAgB,aAAcpI,IAGzC,SAAToD,GAAmBqF,EAAOS,MAC5BR,EAASQ,KAAKT,EAAOS,MAKzB,MADAR,GAASS,SAAqD,gBAArCb,GAAkB,QAAStI,GAAqBsI,EAAkB,QAAStI,GAAQoI,EAAgB,aAAcpI,IACnI0I,EAoCT,QAAS8D,GAAc9D,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,GAAWvM,EAAEkL,EACjB,KAAKqB,IAAaA,EAASP,OACzB,KAAM,IAAI9K,OAAM,YAAcgK,EAAW,oBAK3C,IAFA5J,EAAUA,OAELA,EAAQsO,aACX,KAAM,IAAI1O,OAAM,uCAiElB,IAAIyK,GAAsBD,EAAe,MAAO,YAAaa,EAC7DZ,GAAWW,SAAS,OACpB,EAAA,GAAIE,GAAsBd,EAAe,SAAU,OAAQC,GAGvDkE,GAFsBnE,EAAe,MAAO,OAAQc,GAAkBvH,IAAgC,gBAApB3D,GAAQoL,QAAuBpL,EAAQoL,QAAU,iDAE7G4C,EAAiB,SAAW5D,EAAe,QAAS,eAAgBC,GAAcpF,KAAM,OAAQoG,YAAwD,gBAApCrL,GAAQwO,wBAAuCxO,EAAQwO,wBAA0B,UAC3NC,EAAsBrE,EAAe,MAAO,MAAOC,GACnDqE,EAAsBV,EAAiB,UAAY5D,EAAe,QAAS,gBAAiBqE,GAASxJ,KAAM,QAASoG,YAAyD,gBAArCrL,GAAQ2O,yBAAwC3O,EAAQ2O,yBAA2B,UAC3NC,EAAsBZ,EAAiB,UAAY5D,EAAe,QAAS,gBAAiBqE,GAASxJ,KAAM,OAAQoG,YAAyD,gBAArCrL,GAAQ6O,yBAAwC7O,EAAQ6O,yBAA2B,UAC1NC,EAAsBd,EAAiB,WAAa5D,EAAe,QAAS,gBAAiBC,GAAcpF,KAAM,OAAQoG,YAAyD,gBAArCrL,GAAQ+O,yBAAwC/O,EAAQ+O,yBAA2B,mBAChOC,EAAsBhB,EAAiB,WAAa5D,EAAe,QAAS,gBAAiBC,GAAcpF,KAAM,OAAQoG,YAAyD,gBAArCrL,GAAQiP,yBAAwCjP,EAAQiP,yBAA2B,mBAChOC,EAAsB9E,EAAe,MAAO,MAAOC,GACnD8E,EAAsBnB,EAAiB,gBAAkB5D,EAAe,QAAS,qBAAsB8E,GAASjK,KAAM,OAAQoG,YAA8D,gBAA1CrL,GAAQoP,8BAA6CpP,EAAQoP,8BAAgC,gBAC/OC,EAAsBrB,EAAiB,SAAW5D,EAAe,QAAS,eAAgB8E,GAASjK,KAAM,OAAQoG,YAAwD,gBAApCrL,GAAQsP,wBAAuCtP,EAAQsP,wBAA0B,SACtNC,EAAsBnF,EAAe,MAAO,MAAOC,GACnDmF,EAAsBxB,EAAiB,UAAY5D,EAAe,QAAS,gBAAiBmF,GAAStK,KAAM,OAAQoG,YAAyD,gBAArCrL,GAAQyP,yBAAwCzP,EAAQyP,yBAA2B,UAC1NC,EAAsB1B,EAAiB,YAAc5D,EAAe,QAAS,kBAAmBmF,GAAStK,KAAM,OAAQoG,YAA2D,gBAAvCrL,GAAQ2P,2BAA0C3P,EAAQ2P,2BAA6B,YAElO9D,EAAsBzB,EAAe,QAAS,WAAYC,GAAcpF,KAAM,SAAUwF,cAAc,IAEtGmF,EAAsBxF,EAAe,QAAS,gBAAiBC,GAAcpF,KAAM,SAEnF4K,EAAsBzF,EAAe,SAAU,UAAWC,KACpCD,GAAe,OAAQ,cAAeyF,GAAY9E,KAAqC,gBAAxB/K,GAAQ8P,YAA2B9P,EAAQ8P,YAAc,gBAElJF,EAAezC,KAAK,YAAY,GAAMF,MAEtC,IAAI1M,GAAOC,KACPwL,EAAwC,WAAzBhM,EAAQgM,aAA4BhM,EAAQgM,aAAe,oBAC1EC,EAA2C,gBAAvBjM,GAAQiM,WAA0BjM,EAAQiM,WAAa,kBAC3EC,EAA0D,WAAlClM,EAAQkM,sBAAqClM,EAAQkM,sBAAwB,2BACrGC,EAAsD,WAAhCnM,EAAQmM,oBAAmCnM,EAAQmM,oBAAsB,yBAenG0D,GAASzD,GAAG,QAAS,SAAU1D,GAC7BmD,EAAUS,IAAI,IAEduD,EAASxD,YAAYL,GAAc,GACnC6D,EAASxD,YAAYJ,GAAY,EAEjC,IAAIrH,IACF6C,YAGF,IAAIuG,EAAiB,QAAS,CAC5B,IAAKO,EAAcjC,OAAS4B,EAAW,QACrC,MAAOG,GAAcE,EAEvB3J,GAAQ6C,SAAe,KAAI8G,EAAcjC,MAG3C,GAAI0B,EAAiB,SAAU,CAC7B,IAAKU,EAAepC,OAAS4B,EAAW,SACtC,MAAOG,GAAcK,EAEvB,IAAIA,EAAepC,QAAU/H,EAAcwL,KAAKrB,EAAepC,OAC7D,MAAO+B,GAAcK,EAEvB9J,GAAQ6C,SAAgB,MAAIiH,EAAepC,MAC3C1H,EAAQ6C,SAAoB,UAAI7C,EAAQ6C,SAAgB,MAG1D,GAAIuG,EAAiB,SAAU,CAC7B,IAAKY,EAAetC,OAAS4B,EAAW,SACtC,MAAOG,GAAcO,EAEnBA,GAAetC,QACjB1H,EAAQ6C,SAAgB,MAAImH,EAAetC,OAa/C,IATI0B,EAAiB,WACjBA,EAAiB,WACjBA,EAAiB,gBACjBA,EAAiB,SACjBA,EAAiB,UACjBA,EAAiB,cACnBpJ,EAAQ6C,SAAkB,YAGxBuG,EAAiB,UAAW,CAC9B,IAAKc,EAAexC,OAAS4B,EAAW,UACtC,MAAOG,GAAcS,EAEvBlK,GAAQ6C,SAAkB,QAAU,OAAIqH,EAAexC,MAGzD,GAAI0B,EAAiB,UAAW,CAC9B,IAAKgB,EAAe1C,OAAS4B,EAAW,UACtC,MAAOG,GAAcW,EAEvBpK,GAAQ6C,SAAkB,QAAU,OAAIuH,EAAe1C,MAGzD,GAAI0B,EAAiB,eAAgB,CACnC,IAAKmB,EAAoB7C,OAAS4B,EAAW,eAC3C,MAAOG,GAAcc,EAEvBvK,GAAQ6C,SAAkB,QAAe,YAAI0H,EAAoB7C,MAGnE,GAAI0B,EAAiB,QAAS,CAC5B,IAAKqB,EAAc/C,OAAS4B,EAAW,QACrC,MAAOG,GAAcgB,EAEvBzK,GAAQ6C,SAAkB,QAAQ,KAAI4H,EAAc/C,MAGtD,GAAI0B,EAAiB,SAAU,CAC7B,IAAKwB,EAAelD,OAAS4B,EAAW,SACtC,MAAOG,GAAcmB,EAEvB5K,GAAQ6C,SAAkB,QAAS,MAAI+H,EAAelD,MAGxD,GAAI0B,EAAiB,WAAY,CAC/B,IAAK0B,EAAiBpD,OAAS4B,EAAW,WACxC,MAAOG,GAAcqB,EAEvB9K,GAAQ6C,SAAkB,QAAW,QAAIiI,EAAiBpD,MAG5D/L,EAAKxB,QAAQiB,EAAQsO,aAAc1J,EAAS,SAAU+H,GACpD,IAAKA,IAAaA,EAAS7D,UAAY6D,EAAS7D,QAAQ1B,KAAM,CAC5D,GAAInB,GAAe0G,EAAS1G,YACxB8G,EAAe9G,EAAQ8G,iBACvBC,EAAeD,EAAa9E,GAQhC,OANAoG,GAAcwB,QAEV7B,EAAiB,UAAYhB,IAAc1I,GAC7C+J,EAAcO,IAMlBL,GAAiBA,EAActB,OAC/ByB,GAAkBA,EAAezB,OACjC2B,GAAkBA,EAAe3B,OACjC6B,GAAkBA,EAAe7B,OACjC+B,GAAkBA,EAAe/B,OACjCkC,GAAuBA,EAAoBlC,OAC3CoC,GAAiBA,EAAcpC,OAC/BuC,GAAkBA,EAAevC,OACjCyC,GAAoBA,EAAiBzC,OAErC2C,EACKvD,YAAYF,GAAqB,GACjCG,IAAIK,EAAS7D,QAAQ1B,MAAM4I,KAAK,KAErCnE,EAAUS,IAAIK,EAASO,aAAe,IAEtC2C,EAAS1C,KAAK,YAAY,GAE1B0C,EACKxD,YAAYL,GAAc,GAC1BiB,OAEDjN,GAAWA,EAAQiQ,aAA8C,kBAAxBjQ,GAAQiQ,aACnDjQ,EAAQiQ,YAAYtD,QAK5BuD,eAAgB,WACd3R,EAAO4R,SAAS,WACdjQ,QAAQkQ,KAAK,iCACbhQ,OAsSN,OAjSA,UAAWiQ,EAAUC,GAanB,QAASC,KACP,IAAKC,EAAY,CACfA,GAAa,CACb,KAAK,GAAIC,GAAI,EAAGA,EAAIC,EAAUhG,OAAQ+F,IACpCC,EAAUD,GAAGE,GAAGtO,KAAK9D,EAAQmS,EAAUD,GAAGG,IAE5CF,OAIJ,QAASG,KACqB,aAAxBpS,EAASqS,YACXP,IAtBJ,GAAKD,EAAL,CAIAD,EAAWA,GAAY,WACvBC,EAAUA,GAAW/R,CACrB,IAAImS,MACAF,GAAa,EACbO,GAA8B,CAkBlCT,GAAQD,GAAY,SAAUvO,EAAUmE,GACtC,GAAwB,kBAAbnE,GACT,KAAM,IAAIkP,WAAU,+CAEtB,OAAIR,OACFS,YAAW,WACTnP,EAASmE,IACR,IAGHyK,EAAU3N,MAAO4N,GAAI7O,EAAU8O,IAAK3K,SAEV,aAAxBxH,EAASqS,aAA+BrS,EAASuD,aAAuC,gBAAxBvD,EAASqS,WAC3EG,WAAWV,EAAO,GACRQ,IACNtS,EAASsD,kBACXtD,EAASsD,iBAAiB,mBAAoBwO,GAAO,GACrDhS,EAAOwD,iBAAiB,OAAQwO,GAAO,KAEvC9R,EAASuD,YAAY,qBAAsB6O,GAC3CtS,EAAOyD,YAAY,SAAUuO,IAE/BQ,GAA8B,QAGjC,WAAYxS,GA+NXA,GACFA,EAAO4R,SAAS,WACdjQ,QAAQkQ,KAAK,8CACbhQ,MAKkB,mBAAX8Q,SAA0BA,OAAOC,UAC1CD,OAAOC,QAAUtK,GAGZA,GACPtI,OAAQA,OAAOE,SAAUF,OAAO6S","file":"voucherify.min.js","sourcesContent":["window.Voucherify = (function (window, document, $) {\n \"use strict\";\n\n var API = buildAPI(\"https://api.voucherify.io\");\n\n function buildAPI(baseUrl) {\n return {\n validate: baseUrl + \"/client/v1/validate\",\n redeem: baseUrl + \"/client/v1/redeem\",\n publish: baseUrl + \"/client/v1/publish\",\n list: baseUrl + \"/client/v1/vouchers\",\n track: baseUrl + \"/client/v1/events\",\n validatePromotion: baseUrl + \"/client/v1/promotions/validation\"\n };\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 = typeof(callback) === \"function\" ? { resolve: callback, reject: callback } : $.Deferred();\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 if (isValidResponseStructure(data)) {\n deferred.resolve(data);\n return;\n }\n\n deferred.reject({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n },\n\n error: function (error) {\n deferred.reject({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\n });\n }\n });\n\n if (typeof(callback) !== \"function\") {\n return deferred.promise();\n }\n };\n } else {\n xhrImplementation = function (method, url, payload, callback) {\n callback = typeof(callback) === \"function\" ? callback : function () {\n };\n\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 if (request.status >= 200 && request.status < 400) {\n try {\n var data = JSON.parse(request.responseText);\n\n if (isValidResponseStructure(data)) {\n callback(data);\n return;\n }\n\n callback({\n type: \"error\",\n message: \"Unexpected response structure.\",\n context: data\n });\n } catch (error) {\n callback({\n type: \"error\",\n message: \"Unparsable response.\",\n context: error\n });\n }\n } else {\n callback({\n type: \"error\",\n message: \"Unexpected status code.\",\n context: request.status\n });\n }\n };\n\n request.onerror = function (error) {\n callback({\n type: \"error\",\n message: \"XHR error happened.\",\n context: error\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 setBaseUrl: function (baseUrl) {\n baseUrl = baseUrl || \"\";\n\n if (baseUrl.indexOf(\"https://\") !== 0 && baseUrl.indexOf(\"http://\") !== 0) {\n baseUrl = \"https://\" + baseUrl;\n }\n\n API = buildAPI(baseUrl);\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 orderMetadata;\n var customer;\n\n if (typeof(code) === \"object\") {\n amount = code.amount;\n items = code.items;\n metadata = code.metadata;\n orderMetadata = code.orderMetadata;\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 (orderMetadata) {\n queryString += \"&\" + Object.keys(orderMetadata).map(function (key) {\n return encodeURIComponent(\"order[metadata][\" + key + \"]\") + \"=\" + encodeURIComponent(orderMetadata[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 if (key === \"metadata\") {\n if (typeof(customer.metadata) !== \"object\") {\n console.error(\"Customer's metadata must be an object - please use instead { property: 'value' }\");\n return null;\n }\n\n return Object.keys(customer.metadata).map(function (metadataKey) {\n return encodeURIComponent(\"customer[metadata][\" + metadataKey + \"]\") + \"=\" + encodeURIComponent(customer.metadata[metadataKey]);\n }).join(\"&\");\n }\n\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 = \"?\" + $.param(filters);\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 refreshIframes: function () {\n window.docReady(function () {\n console.info(\"Re-render voucherify iframes.\");\n renderIframes();\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 () {\n callback(context);\n }, 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 common_attributes = [\n \"client-app-id\",\n \"client-token\",\n \"client-app-url\",\n\n \"logo\",\n\n \"widget-id\",\n \"height\",\n\n \"success-message\",\n \"failure-message\"\n ];\n\n var customer_attributes = [\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 \"customer-metadata\"\n ];\n\n var consent_fields = [\n \"consent-label\",\n \"consent-description\",\n \"consent-options\",\n \"consent-options-required\",\n \"consent-legal\",\n \"consent-voucherify-note-visible\"\n ];\n\n var iframes_widgets = {\n \"voucher-redeem\": {\n \"path\": \"/widgets/redeem\",\n \"defaults\": {\n \"height\": \"480px\"\n },\n \"attributes\": [\n \"metadata\",\n \"redemption-metadata\",\n\n \"metadata-fields\",\n\n \"code\",\n\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 \"button-label\"\n ].concat(consent_fields)\n },\n \"get-voucher\": {\n \"path\": \"/widgets/publish\",\n \"defaults\": {\n \"height\": \"430px\"\n },\n \"attributes\": [\n \"campaign\",\n\n \"metadata\",\n \"source\",\n\n \"button-label\"\n ]\n },\n \"subscribe\": {\n \"path\": \"/widgets/subscribe\",\n \"defaults\": {\n \"height\": \"220px\"\n },\n \"attributes\": [\n \"metadata\",\n \"source\",\n\n \"subscribe-label\"\n ].concat(consent_fields)\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, defaults) {\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 } else if (defaults[allowed_option]) { // check if the default value is provided\n options[allowed_option] = defaults[allowed_option];\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(customer_attributes).concat(options.attributes), options.defaults);\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 host = self._options[\"client-app-url\"] ? self._options[\"client-app-url\"] : \"https://app.voucherify.io\";\n\n // -- set custom height or fallback\n var widget_height = self._options.height;\n // -- remove custom height from options to prevent before sending it\n self._options.height = undefined;\n\n var css_props = [\n \"width:400px;\",\n \"height:\" + widget_height + \";\",\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 ead45ec..c03dff2 100644 --- a/lib/voucherify.js +++ b/lib/voucherify.js @@ -1,7 +1,7 @@ window.Voucherify = (function (window, document, $) { "use strict"; - var API = buildAPI("localhost:8000"); + var API = buildAPI("https://api.voucherify.io"); function buildAPI(baseUrl) { return { From da6575baf26e2029ba940a29c6fd62ff3796b728 Mon Sep 17 00:00:00 2001 From: pannga Date: Fri, 18 Jun 2021 09:07:29 +0200 Subject: [PATCH 3/3] Updated version --- README.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e637955..cff9a3d 100644 --- a/README.md +++ b/README.md @@ -739,7 +739,7 @@ Description and legal fields do support markdown syntax. It means that you can u ### Changelog -- **2021-06-20** - `1.32.1` - Add possibility of configuring API endpoint for iframe widgets +- **2021-06-20** - `1.33.0` - Add possibility of configuring API endpoint for iframe widgets - **2020-09-16** - `1.32.0` - Add possibility to send order metadata with validation request - **2019-12-23** - `1.31.0` - Add possibility to send customer metadata with validation request - **2019-02-05** - `1.30.0` - Add method for setting base app url diff --git a/package.json b/package.json index 980f50e..84c51af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "voucherify.js", - "version": "1.32.1", + "version": "1.33.0", "homepage": "http://www.voucherify.io", "description": "Client-side SDK for Voucherify.", "author": "rspective",