Skip to content

Instantly share code, notes, and snippets.

@emailrhoads
Last active September 16, 2022 16:13
Show Gist options
  • Save emailrhoads/f8a9a0c6baece7ae3b97fbaca01736ee to your computer and use it in GitHub Desktop.
Save emailrhoads/f8a9a0c6baece7ae3b97fbaca01736ee to your computer and use it in GitHub Desktop.
youtube creator gifting
<!DOCTYPE html>
<html lang="{{ locale }}" dir="{{ direction }}" class="{{ checkout_html_classes }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, height=device-height, minimum-scale=1.0, user-scalable=0">
<meta name="referrer" content="origin">
<title>{{ page_title }}</title>
{% comment %}{{ checkout.attributes }}{% endcomment %}
{{ content_for_header }}
{{ checkout_stylesheets }}
{{ checkout_scripts }}
{% style %}
/*
custom tweaks for checkout ... should be done through theme?
*/
:root {
/* checkout branding/coloring */
--header_bg_color: #232122;
--youtube_red: rgba(244, 1, 2, 1);
--youtube_red_hover: rgba(244, 1, 2, .85);
--checkout_text_color: white;
}
div.order-summary__section.order-summary__section--product-list { display: none; }
div.sidebar__content { display: none; }
div.section.section--remember-me { display: none; }
span.logo__text.heading-1 { display: none;}
table.product-table { display: none; }
div.map.default-background { display: none; }
div.box__row.text-container { display: none; }
div.section__content > div.section__content__column:nth-child(2) { display: none; }
div.content-box[data-order-updates=true] { display: none;}
a.step__footer__continue-btn.btn { display: none; }
.section--payment-method { display: none;}
aside[role=complementary] { visibility: hidden; }
/* header bg coloring */
body { background: var(--header_bg_color);}
.content { background-color: var(--header_bg_color);}
.order-summary-toggle { background-color: var(--header_bg_color);}
/* text coloring */
.main h2 {color: var(--checkout_text_color);}
body { color: var(--checkout_text_color);}
.sidebar .order-summary__emphasis { color: var(--checkout_text_color);}
.sidebar { color: var(--checkout_text_color) !important;}
.sidebar .payment-due__price { color: var(--checkout_text_color);}
.sidebar .payment-due-label__total { color: var(--checkout_text_color);}
.btn--subdued { color: var(--checkout_text_color); }
/* -- mobile aside */
.order-summary-toggle .order-summary-toggle__text { color: var(--checkout_text_color); }
.order-summary-toggle:hover .order-summary-toggle__text { color: var(--checkout_text_color); }
.order-summary-toggle .order-summary-toggle__text { color: var(--checkout_text_color); }
.order-summary-toggle:hover .order-summary-toggle__text { color: var(--checkout_text_color); }
.order-summary-toggle .order-summary-toggle__dropdown{ fill: var(--checkout_text_color); }
.order-summary-toggle:hover .order-summary-toggle__dropdown{ fill: var(--checkout_text_color); }
.order-summary-toggle .order-summary-toggle__icon, .order-summary-toggle:focus .order-summary-toggle__icon { fill: var(--checkout_text_color); }
.order-summary-toggle:hover .order-summary-toggle__icon, .order-summary-toggle:focus .order-summary-toggle__icon { fill: var(--checkout_text_color); }
.total-recap__final-price { color: var(--checkout_text_color); }
/* set reds */
.btn, .sp-modal-toggle { background-color: var(--youtube_red);}
.btn:hover, .sp-modal-toggle:hover { background-color: var(--youtube_red_hover); }
.icon-svg--color-accent { color: var(--youtube_red);}
a, .link { color: var(--youtube_red); }
{% endstyle %}
<script
srcx="https://cdn.lob.com/lob/address-elements/2.2.1/address-elements.min.js"
comment="LOB has an issue with our custom fields in the param, overridedn in the code below"
data-lob-key="live_pub_5a257e5925bb1468133c03efaf9875e"
data-lob-verify-value="strict"
data-lob-primary-value="true"
data-lob-err-bgcolor="#006eff"
data-lob-err-color="#ffffff"
data-lob-primary-id="checkout_shipping_address_address1"
data-lob-secondary-id="checkout_shipping_address_address2"
data-lob-city-id="checkout_shipping_address_city"
data-lob-state-id="checkout_shipping_address_province"
data-lob-zip-id="checkout_shipping_address_zip"
data-lob-country-id="checkout_shipping_address_country"
></script>
<script>
/* from https://shopify.dev/themes/architecture/layouts/checkout-liquid/customize-checkout */
(function($) {
$(document).on("page:load page:change", function() {
console.log( {{ checkout.attributes | json }} );
/* Need to preserve checkout attributes */
{% for attribute in checkout.attributes %}
Checkout.$('form.edit_checkout').append(
'<input type=hidden name="checkout[attributes][{{ attribute.first }}]" value="{{ attribute.last }}">'
)
{% endfor %}
/* parse URL for params*/
url = location.search;
var query = url.substr(1);
var result = {};
query.split("&").forEach(function(part) {
var item = part.split("=");
result[item[0]] = decodeURIComponent(item[1]);
});
if (Shopify.Checkout.step === "contact_information") {
{% comment %}
https://help.lob.com/print_mail/mail-send-settings#us-mail-strictness-settings
Here is some custom LOB code that was hacked up to allow URL params
{% endcomment %}
(()=>{
var e = {
787: e=>{
var t = function() {
"use strict";
var e = 0;
function t(e) {
var t = []
, i = 0
, n = 0;
this.push = function(s) {
e <= i - n && e <= ++n && (n = 0,
i = e - 1),
t[i % e] = s,
i++
}
,
this.asArray = function() {
var s = t.slice(n, Math.min(i, e))
, a = t.slice(0, Math.max(i - e, 0));
return s.concat(a)
}
,
this.list = t
}
function i(t, i) {
for (var n = i, s = 0; s < t.length; s++) {
var a = t[s]
, r = n.r;
r[a] || (r[a] = {
w: a,
r: {},
i: e++
}),
n = r[a]
}
return n
}
function n(e, t, i) {
var n;
return i[e] ? n = i[e] : (n = function(e, t) {
for (var i = [[t, 0]], n = {}, s = []; i.length; ) {
var a = i.shift()
, r = a[0]
, o = a[1]
, l = r.r
, c = e[o];
if (void 0 === c && r.fn && !n[r.i] ? (n[r.i] = 1,
s.push(r.fn)) : l[c] && i.push([l[c], o + 1]),
l["#"])
for (var u = o; u <= e.length; u++)
i.push([l["#"], u]);
c && l["*"] && i.push([l["*"], o + 1])
}
return s
}(e.split("."), t),
i[e] = n),
n
}
function s() {
var s = {
w: "",
r: {},
i: e++
}
, a = {}
, r = new t(9999);
this.emit = function e(t, i) {
var o = Date.now();
r.push([t, o]);
for (var l = n(t, s, a), c = [], u = {
topic: t,
ts: o
}, d = 0; d < l.length; d++)
for (var m = l[d], p = 0; p < m.length; p++)
try {
c.push(m[p](i, u))
} catch (t) {
if (!(0 < n("error", s, a).length))
throw t;
e("error", t)
}
return c
}
,
this.on = function(e, t) {
var n = i(e.split("."), s)
, r = n.fn || [];
return r.push(t),
n.fn = r,
a = {},
function() {
var e = r.indexOf(t);
-1 < e && r.splice(e, 1)
}
}
,
this.history = function(t) {
var s = {
w: "",
r: {},
i: e++
};
i(t.split("."), s).fn = 1;
for (var a = [], o = {}, l = r.asArray(), c = 0; c < l.length; c++) {
var u = l[c];
n(u[0], s, o).length && a.push(u)
}
return a
}
}
return s.Ring = t,
s
}();
e.exports = t
}
}
, t = {};
function i(n) {
var s = t[n];
if (void 0 !== s)
return s.exports;
var a = t[n] = {
exports: {}
};
return e[n](a, a.exports, i),
a.exports
}
i.n = e=>{
var t = e && e.__esModule ? ()=>e.default : ()=>e;
return i.d(t, {
a: t
}),
t
}
,
i.d = (e,t)=>{
for (var n in t)
i.o(t, n) && !i.o(e, n) && Object.defineProperty(e, n, {
enumerable: !0,
get: t[n]
})
}
,
i.o = (e,t)=>Object.prototype.hasOwnProperty.call(e, t);
var n = {};
(()=>{
"use strict";
i.d(n, {
J: ()=>A
});
const e = ["united states", "united states of america", "us", "u.s", "u.s.", "usa", "u.s.a", "u.s.a"]
, t = t=>t && t.length && !e.includes(t.val().toLowerCase())
, s = {
afghanistan: "AF",
"aland islands": "AX",
albania: "AL",
algeria: "DZ",
"american samoa": "AS",
andorra: "AD",
angola: "AO",
anguilla: "AI",
antarctica: "AQ",
"antigua and barbuda": "AG",
argentina: "AR",
armenia: "AM",
aruba: "AW",
australia: "AU",
austria: "AT",
azerbaijan: "AZ",
bahamas: "BS",
bahrain: "BH",
bangladesh: "BD",
barbados: "BB",
belarus: "BY",
belgium: "BE",
belize: "BZ",
benin: "BJ",
bermuda: "BM",
bhutan: "BT",
bolivia: "BO",
"bonaire, saint eustatius and saba": "BQ",
"bosnia and herzegovina": "BA",
botswana: "BW",
"bouvet island": "BV",
brazil: "BR",
"british indian ocean territory": "IO",
"british virgin islands": "VG",
brunei: "BN",
bulgaria: "BG",
"burkina faso": "BF",
burundi: "BI",
cambodia: "KH",
cameroon: "CM",
canada: "CA",
"cape verde": "CV",
"cayman islands": "KY",
"central african republic": "CF",
chad: "TD",
chile: "CL",
china: "CN",
"christmas island": "CX",
"cocos islands": "CC",
colombia: "CO",
comoros: "KM",
"cook islands": "CK",
"costa rica": "CR",
croatia: "HR",
cuba: "CU",
curacao: "CW",
cyprus: "CY",
"czech republic": "CZ",
"democratic republic of the congo": "CD",
denmark: "DK",
djibouti: "DJ",
dominica: "DM",
"dominican republic": "DO",
"east timor": "TL",
ecuador: "EC",
egypt: "EG",
"el salvador": "SV",
"equatorial guinea": "GQ",
eritrea: "ER",
estonia: "EE",
ethiopia: "ET",
"falkland islands": "FK",
"faroe islands": "FO",
fiji: "FJ",
finland: "FI",
france: "FR",
"french guiana": "GF",
"french polynesia": "PF",
"french southern territories": "TF",
gabon: "GA",
gambia: "GM",
georgia: "GE",
germany: "DE",
ghana: "GH",
gibraltar: "GI",
greece: "GR",
greenland: "GL",
grenada: "GD",
guadeloupe: "GP",
guam: "GU",
guatemala: "GT",
guernsey: "GG",
guinea: "GN",
"guinea-bissau": "GW",
guyana: "GY",
haiti: "HT",
"heard island and mcdonald islands": "HM",
honduras: "HN",
"hong kong": "HK",
hungary: "HU",
iceland: "IS",
india: "IN",
indonesia: "ID",
iran: "IR",
iraq: "IQ",
ireland: "IE",
"isle of man": "IM",
israel: "IL",
italy: "IT",
"ivory coast": "CI",
jamaica: "JM",
japan: "JP",
jersey: "JE",
jordan: "JO",
kazakhstan: "KZ",
kenya: "KE",
kiribati: "KI",
kosovo: "XK",
kuwait: "KW",
kyrgyzstan: "KG",
laos: "LA",
latvia: "LV",
lebanon: "LB",
lesotho: "LS",
liberia: "LR",
libya: "LY",
liechtenstein: "LI",
lithuania: "LT",
luxembourg: "LU",
macao: "MO",
macedonia: "MK",
madagascar: "MG",
malawi: "MW",
malaysia: "MY",
maldives: "MV",
mali: "ML",
malta: "MT",
"marshall islands": "MH",
martinique: "MQ",
mauritania: "MR",
mauritius: "MU",
mayotte: "YT",
mexico: "MX",
micronesia: "FM",
moldova: "MD",
monaco: "MC",
mongolia: "MN",
montenegro: "ME",
montserrat: "MS",
morocco: "MA",
mozambique: "MZ",
myanmar: "MM",
namibia: "NA",
nauru: "NR",
nepal: "NP",
netherlands: "NL",
"netherlands antilles": "AN",
"new caledonia": "NC",
"new zealand": "NZ",
nicaragua: "NI",
niger: "NE",
nigeria: "NG",
niue: "NU",
"norfolk island": "NF",
"north korea": "KP",
"northern mariana islands": "MP",
norway: "NO",
oman: "OM",
pakistan: "PK",
palau: "PW",
"palestinian territory": "PS",
panama: "PA",
"papua new guinea": "PG",
paraguay: "PY",
peru: "PE",
philippines: "PH",
pitcairn: "PN",
poland: "PL",
portugal: "PT",
"puerto rico": "PR",
qatar: "QA",
"republic of the congo": "CG",
reunion: "RE",
romania: "RO",
russia: "RU",
rwanda: "RW",
"saint barthelemy": "BL",
"saint helena": "SH",
"saint kitts and nevis": "KN",
"saint lucia": "LC",
"saint martin": "MF",
"saint pierre and miquelon": "PM",
"saint vincent and the grenadines": "VC",
samoa: "WS",
"san marino": "SM",
"sao tome and principe": "ST",
"saudi arabia": "SA",
senegal: "SN",
serbia: "RS",
"serbia and montenegro": "CS",
seychelles: "SC",
"sierra leone": "SL",
singapore: "SG",
"sint maarten": "SX",
slovakia: "SK",
slovenia: "SI",
"solomon islands": "SB",
somalia: "SO",
"south africa": "ZA",
"south georgia and the south sandwich islands": "GS",
"south korea": "KR",
"south sudan": "SS",
spain: "ES",
"sri lanka": "LK",
sudan: "SD",
suriname: "SR",
"svalbard and jan mayen": "SJ",
swaziland: "SZ",
sweden: "SE",
switzerland: "CH",
syria: "SY",
taiwan: "TW",
tajikistan: "TJ",
tanzania: "TZ",
thailand: "TH",
togo: "TG",
tokelau: "TK",
tonga: "TO",
"trinidad and tobago": "TT",
tunisia: "TN",
turkey: "TR",
turkmenistan: "TM",
"turks and caicos islands": "TC",
tuvalu: "TV",
"u.s. virgin islands": "VI",
uganda: "UG",
ukraine: "UA",
"united arab emirates": "AE",
"united kingdom": "GB",
"united states": "US",
"united states minor outlying islands": "UM",
uruguay: "UY",
uzbekistan: "UZ",
vanuatu: "VU",
vatican: "VA",
venezuela: "VE",
vietnam: "VN",
"wallis and futuna": "WF",
"western sahara": "EH",
yemen: "YE",
zambia: "ZM",
zimbabwe: "ZW"
}
, a = (e,t)=>{
if (t && t.length && e && e.length) {
let i;
return e.each((function(e, n) {
t.is(n.closest("form")) && (i = $(n))
}
)),
i || e
}
return e
}
, r = (e,t=null)=>{
let i;
const n = $("*[data-lob-" + e + "-id]").attr("data-lob-" + e + "-id");
if (n)
i = $("*[id=" + n + "]");
else {
const t = $("*[data-lob-" + e + "-name]").attr("data-lob-" + e + "-name")
, n = $("*[data-lob-" + e + "-class]").attr("data-lob-" + e + "-class");
i = t ? $("*[name=" + t + "]") : n ? $("." + n) : $("*[data-lob-" + e + "]")
}
return a(i, t)
}
, o = (e,t)=>{
const i = r(e, t);
return i.length && i.attr("data-lob-" + e) || $("*[data-lob-" + e + "-value]").attr("data-lob-" + e + "-value")
}
, l = e=>e.reduce(((e,t)=>{
return [...e, t, (i = t,
i.charAt(0).toUpperCase() + i.slice(1)), t.toUpperCase()];
var i
}
), [])
, c = {
primary: l(["primary", "address", "address1", "street"]),
secondary: l(["address 2", "address2", "street 2", "secondary", "apartment", "suite", "building", "unit", "apt", "ste", "bldg"]),
city: l(["city", "town"]),
state: l(["state", "province", "county", "district", "municipality"]),
zip: l(["zip", "postal", "postcode"]),
country: l(["country"])
}
, u = (e,t)=>{
const i = r(e, t);
return i.length ? i : null
}
, d = (e,t)=>{
const i = c[e].map((e=>`:contains('${e}')`)).join(", ");
let n = $(i);
if ("primary" === e && (n = n.filter(((e,t)=>!/(address|street)\s?2/i.test($(t).text())))),
!n.length)
return null;
const s = n.filter("label");
let r = $();
return s.each(((e,t)=>{
const i = (e=>{
const t = e.htmlFor;
if (t)
return $(`*[id=${t}]`);
const i = $(e).siblings("input");
if (i.length)
return i;
const n = $(e).children("input");
if (n.length)
return n;
const s = $(e).parentsUntil("form", "input");
return s.length ? s : $()
}
)(t);
r = r.add(i)
}
)),
r.length ? a(r, t) : null
}
, m = e=>{
const t = {
...c
};
"secondary" === e && (t.secondary = t.secondary.concat(l(["address"])));
const i = t[e].map((e=>`input[id*='${e}'], select[id*='${e}']`)).join(", ");
let n = $(i);
return "primary" === e ? n = n.filter(":not(input[name*='2']):not(input[for*='2']):not(input[id*='2'])") : "secondary" === e && (n = n.filter(":not(input[name*='1']):not(input[for*='1']):not(input[id*='1'])")),
n.length ? n : null
}
, p = e=>{
let i = "";
const n = t(e.country)
, s = Object.keys(e).filter((t=>{
if ("country" === t)
return !1;
if ("state" === t && n)
return !1;
const i = e[t];
return null === i || i && 0 === i.length
}
))
, a = Object.keys(e).filter((t=>{
const i = e[t];
return i && i.filter(":visible").length > 1
}
));
if (s.length) {
const e = s.length > 1 ? `${s.slice(0, -1).join(", ")}, and ${s.slice(-1)}` : s[0].toString()
, t = s.map((e=>`data-lob-${e}-id`)).join(", ")
, n = `[Lob AV Elements Error]:\tMissing form elements\nCould not find inputs for ${e}.\nPlease add the following attributes to the AV elements script: ${t}\nFor more information visit: https://www.lob.com/guides#av-elements-troubleshooting`
, a = `<p style="text-align: left">[Lob AV Elements Error] Missing form elements<br/>Could not find inputs for ${e}. Please add the following attributes to the AV elements script: <strong>${t}</strong>.<br/>For more information visit <a href="https://www.lob.com/guides#av-elements-troubleshooting">https://www.lob.com/guides#av-elements-troubleshooting</a></p>`;
console.error(n),
i = a
}
if (a.length) {
const e = a.length > 1 ? `${a.slice(0, -1).join(", ")}, and ${a.slice(-1)}` : a[0].toString()
, t = a.map((e=>`data-lob-${e}-id`)).join(", ")
, n = `[Lob AV Elements Error]:\tDuplicate form elements\nMultiple form elements were found for ${e}.\nPlease specify them by adding the following attributes to the AV elements script: ${t}\nFor more information visit: https://www.lob.com/guides#av-elements-troubleshooting`
, s = `<p style="text-align: left">[Lob AV Elements Error] Duplicate form elements<br/>Multiple form elements were found for ${e}. Please specify them by adding the following attributes to the AV elements script: <strong>${t}</strong>.<br/>For more information visit <a href="https://www.lob.com/guides#av-elements-troubleshooting">https://www.lob.com/guides#av-elements-troubleshooting</a></p>`;
console.error(n),
i += s
}
return i
}
, g = e=>{
const t = {
errorAnchorElement: r("verify-message-anchor", e),
primaryMsg: r("primary-message", e).hide(),
secondaryMsg: r("secondary-message", e).hide(),
cityMsg: r("city-message", e).hide(),
stateMsg: r("state-message", e).hide(),
zipMsg: r("zip-message", e).hide(),
countryMsg: r("country-message", e).hide(),
message: r("verify-message", e).hide()
}
, i = {};
console.log(t);
return ["primary", "secondary", "city", "state", "zip", "country"].forEach((t=>{
i[t] = u(t, e),
i[t] || (i[t] = d(t, e)),
(!i[t] || i[t] && i[t].length > 1) && (i[t] = m(t))
}
)),
{
...t,
...i,
parseResultError: p(i),
form: e
}
}
;
function h(e, t, i) {
return o(t + "-" + i) || e.styles[t + "-" + i]
}
const f = (e,t)=>{
const i = Object.keys(e).length <= 1 && e.constructor === Object;
return void 0 === e || i ? r("suggestion-stylesheet", t).length > 0 : !!e
}
;
let y = !1
, b = !1;
class v {
constructor(e, t, i) {
this.pageState = i || A()[0],
this.config = {
channel: t.channel,
api_key: t.api_key || o("key"),
autosubmit: i.autosubmit,
strictness: this.pageState.strictness,
denormalize: "false" !== o("secondary"),
suppress_stylesheet: f(t),
styles: t.styles || {
"err-color": "#117ab8",
"err-bgcolor": "#eeeeee",
"suggestion-color": "#666666",
"suggestion-bgcolor": "#fefefe",
"suggestion-bordercolor": "#a8a8a8",
"suggestion-activecolor": "#117ab8",
"suggestion-activebgcolor": "#eeeeee"
},
elements: t.elements || g(this.pageState.form),
messages: t.messages || {
primary_line: o("err-primary-line") || "Enter the Primary address.",
city_state_zip: o("err-city-state-zip") || "Enter City and State (or Zip).",
country: o("err-country") || "Enter a country",
zip: o("err-zip") || "Enter a valid Zip.",
undeliverable: o("err-undeliverable") || "The address could not be verified.",
deliverable_missing_unit: o("err-missing-unit") || "Enter a Suite or Unit.",
deliverable_unnecessary_unit: o("err-unnecessary-unit") || "Suite or Unit unnecessary.",
deliverable_incorrect_unit: o("err-incorrect-unit") || "Incorrect Unit. Please confirm.",
confirm: o("err-confirm") || "Did you mean",
DEFAULT: o("err-default") || "Unknown Error. The address could not be verified."
},
do: {
init: function() {
v(e, t, this.pageState)
}
}
};
console.log(this.pageState.autocomplete);
const n = "staging" === o("env") ? "https://api.lob-staging.com" : "https://api.lob.com";
this.config.apis = t.apis || {
autocomplete: n + "/v1/us_autocompletions",
intl_verify: n + "/v1/intl_verifications",
us_verify: n + "/v1/us_verifications"
},
this.pageState.autocomplete && this.configureAutocompletion(),
this.pageState.verify && this.configureVerification(),
this.config.channel.emit("elements.enriched", {
config: this.config,
form: this.config.elements.form[0]
})
}
hideMessages() {
const {elements: e} = this.config;
e.message.hide(),
e.primaryMsg.hide(),
e.secondaryMsg.hide(),
e.cityMsg.hide(),
e.stateMsg.hide(),
e.zipMsg.hide()
}
showMessage(e) {
const {channel: t, elements: {message: i, primaryMsg: n, secondaryMsg: s, cityMsg: a, stateMsg: r, zipMsg: o, form: l}, messages: c, denormalize: u} = this.config
, d = {
primary_line: e=>{
n.text(e).show("slow")
}
,
city_state_zip: e=>{
a.text(e).show("slow"),
r.text(e).show("slow"),
o.text(e).show("slow")
}
,
zip: e=>{
o.text(e).show("slow")
}
,
deliverable_missing_unit: e=>{
!u && n.text(e).show("slow") || s.text(e).show("slow")
}
,
deliverable_unnecessary_unit: e=>{
!u && n.text(e).show("slow") || s.text(e).show("slow")
}
,
deliverable_incorrect_unit: e=>{
!u && n.text(e).show("slow") || s.text(e).show("slow")
}
};
e && ("confirm" === e.type || "form_detection" === e.type ? i.html(e.msg).show("slow") : i.text(e.msg).show("slow"),
d[e.type] && d[e.type](c[e.type]),
t.emit("elements.us_verification.alert", {
error: e,
type: e.type,
form: l[0]
}))
}
autocomplete(e, i) {
console.log(this.config.international);
const {apis: n, api_key: s, channel: a, elements: r} = this.config;
if (this.config.international = t(r.country),
this.config.international)
return !1;
if (e.match(/[A-Za-z0-9]/)) {
const t = new XMLHttpRequest
, o = `${n.autocomplete}?av_integration_origin=${window.location.origin + window.location.pathname}&integration=av-elements`;
t.open("POST", o, !0),
t.setRequestHeader("Content-Type", "application/json"),
s && t.setRequestHeader("Authorization", "Basic " + btoa(s + ":")),
t.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE)
if (200 === this.status)
try {
const e = JSON.parse(t.responseText);
a.emit("elements.us_autocompletion.suggestion", {
suggestions: e.suggestions,
form: r.form[0]
}),
i(e.suggestions)
} catch (e) {
i(null)
}
else
401 === this.status ? (console.log("Please sign up on lob.com to get a valid api key."),
a.emit("elements.us_autocompletion.error", {
code: 401,
message: "Please sign up on lob.com to get a valid api key.",
form: r.form[0]
}),
i(null)) : (a.emit("elements.us_autocompletion.error", {
code: 500,
message: "Unknown error.",
form: r.form[0]
}),
i(null))
}
,
t.send(JSON.stringify({
address_prefix: e,
city: r.city.val(),
zip_code: r.zip.val(),
state: r.state.val(),
geo_ip_sort: !0
}))
}
return !1
}
applySuggestion(e) {
const {elements: t} = this.config;
"function" == typeof t.primary.autocomplete ? t.primary.autocomplete("val", e.primary_line) : t.primary.val(e.primary_line),
t.secondary.val(""),
t.city.val(e.city),
t.state.val(e.state),
t.zip.val(e.zip_code)
}
configureAutocompletion() {
const {elements: e, channel: t, suppress_stylesheet: i} = this.config;
var n;
i || y || (y = !0,
$("<style>").prop("type", "text/css").html((n = this.config,
`.algolia-autocomplete {\n display: ${(e=>"block" === e.elements.primary.css("display").toLowerCase() ? "block" : "")(n)};\n width: ${(e=>"block" === e.elements.primary.css("display").toLowerCase() ? "100%" : e.elements.primary.css("width") || e.elements.primary.outerWidth() + "px")(n)};\n vertical-align: middle;\n }\n .aa-dropdown-menu {\n width: 100%;\n border: 1px solid ${h(n, "suggestion", "bordercolor")};\n border-top: 0;\n background-color: ${h(n, "suggestion", "bgcolor")};\n overflow: hidden;\n border-radius: 0 0 .25rem .25rem;\n margin-top:-5px;\n }\n .aa-suggestion {\n cursor: pointer;\n padding: 6px 12px;\n color: ${h(n, "suggestion", "color")};\n }\n .aa-suggestion:hover,\n .aa-suggestion:active,\n .aa-suggestion.aa-cursor {\n color: ${h(n, "suggestion", "activecolor")};\n background-color: ${h(n, "suggestion", "activebgcolor")};\n }\n .aa-suggestion div {\n white-space: nowrap !important;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .aa-suggestion span {\n font-size: .8em;\n }`)).appendTo("head"));
"function" == typeof e.primary.autocomplete && e.primary.autocomplete({
hint: !1
}, {
source: this.autocomplete.bind(this),
templates: {
suggestion: ({primary_line: e, city: t, state: i, zip_code: n})=>$(`<div>${e} <span>${t}, ${i} ${n}</span></div>`)
},
cache: !1
}).on("autocomplete:selected", ((i,n)=>{
this.applySuggestion(n),
t.emit("elements.us_autocompletion.selection", {
selection: n,
form: e.form[0]
})
}
))
}
parseJSON(e) {
try {
return JSON.parse(e)
} catch (e) {
return console.log("Error parsing json", e),
{
error: {
message: "DEFAULT"
}
}
}
}
plus4(e) {
const t = [];
return e.zip_code && t.push(e.zip_code),
e.zip_code_plus_4 && t.push(e.zip_code_plus_4),
t.length ? t.join("-") : ""
}
denormalizeParts(e, t) {
const i = e.components && e.components.secondary_designator || "";
if (e.secondary_line || !this.config.denormalize)
return {
secondary_line: e.secondary_line,
primary_line: e.primary_line
};
if (i && t) {
const t = e.primary_line.split(i);
return {
secondary_line: `${i} ${t[1].trim()}`,
primary_line: t[0].trim()
}
}
return {
secondary_line: e.secondary_line,
primary_line: e.primary_line
}
}
formatAddressFromResponseData(e) {
const {components: t} = e
, i = this.denormalizeParts(e, !!this.config.elements.secondary.val());
return {
primary: i.primary_line,
secondary: i.secondary_line,
city: t && t.city || "",
state: t && t.state || "",
zip: this.config.international ? t.postal_code : this.plus4(t)
}
}
fixAndSave(e, t=!0) {
const {elements: i, international: n} = this.config;
let s = !1;
const a = this.config.address = this.formatAddressFromResponseData(e);
for (let e in a)
if (a.hasOwnProperty(e)) {
const r = i[e].val()
, o = a[e].toUpperCase() !== r.toUpperCase()
, l = !("zip" === e && 5 === r.length && 0 === a[e].indexOf(r));
o && !n && l && (s = !0),
t && i[e].val(a[e])
}
return s
}
resolveErrorType(e) {
return "primary_line is required or address is required" === e ? "primary_line" : "zip_code is required or both city and state are required" === e ? "city_state_zip" : "zip_code must be in a valid zip or zip+4 format" === e ? "zip" : "country is required" === e ? "country" : e in this.config.messages ? e : "DEFAULT"
}
isConfirmation() {
const {address: e, elements: t, strictness: i} = this.config;
if ("passthrough" !== i && e) {
for (let i in e)
if (e.hasOwnProperty(i) && t[i].val().toUpperCase() !== e[i].toUpperCase())
return !1;
return !0
}
return !1
}
isVerified(e, t) {
const {confirmed: i, strictness: n} = this.config
, s = this.fixAndSave(e, !1);
return !t || "deliverable" === e.deliverability && !s || "undeliverable" === e.deliverability && i && "passthrough" === n || "deliverable_missing_unit" === e.deliverability && i && "strict" !== n || "deliverable_unnecessary_unit" === e.deliverability && i && "strict" !== n || "deliverable_incorrect_unit" === e.deliverability && i && "strict" !== n
}
format(e, t) {
for (let i in t)
e = e.replace("{" + i + "}", t[i]);
return e
}
createDidYouMeanMessage(e) {
const {primary: t, secondary: i, city: n, state: s, zip: a} = this.formatAddressFromResponseData(e);
return `\n <span style="cursor: pointer">\n ${this.config.messages.confirm} <span style="text-decoration: underline">${`${t} ${i} ${n} ${s} ${a}`}</span>?\n </span>\n `
}
verify(e) {
const {apis: i, api_key: n, channel: a, elements: {primary: r, secondary: o, city: l, state: c, zip: u, country: d, message: m, form: p}, messages: g} = this.config;
this.config.international = t(d),
this.config.submit = "passthrough" === this.config.strictness,
this.config.confirmed = this.isConfirmation();
const h = {
primary_line: r.val(),
secondary_line: o.val(),
city: l.val(),
state: c.val()
};
if (this.config.international) {
const e = d.val().toLowerCase();
h.country = 2 === d.length ? e : s[e],
h.postal_code = u.val()
} else
h.zip_code = u.val();
const f = `${this.config.international ? i.intl_verify : i.us_verify}?av_integration_origin=${window.location.origin + window.location.pathname}&integration=av-elements`
, y = new XMLHttpRequest;
y.open("POST", f, !0),
y.setRequestHeader("Content-Type", "application/json"),
n && y.setRequestHeader("Authorization", "Basic " + btoa(n + ":"));
const b = this;
return y.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE) {
let t, i = b.parseJSON(y.responseText);
if (this.status && 200 !== this.status || i.statusCode && 200 !== i.statusCode)
401 === this.status ? (console.log("Please sign up on lob.com to get a valid api key."),
a.emit("elements.us_verification.error", {
code: 401,
type: "authorization",
data: i,
form: p[0]
}),
e(null, !0)) : (i = i && i.body || i,
t = b.resolveErrorType(i.error.message),
a.emit("elements.us_verification.error", {
code: i.error.code || 0,
type: t,
data: i,
form: p[0]
}),
e({
msg: g[t],
type: t
}));
else if (i = i && i.body || i,
b.isVerified(i, this.status))
a.emit("elements.us_verification.verification", {
code: 200,
data: i,
form: p[0]
}),
e(null, !0, i);
else if ("deliverable" === i.deliverability) {
const t = b.createDidYouMeanMessage(i);
m.click((()=>{
b.fixAndSave(i),
b.hideMessages(),
m.off("click"),
a.emit("elements.us_verification.improvement", {
data: i,
form: p[0]
})
}
)),
e({
msg: t,
type: "confirm"
})
} else
t = b.resolveErrorType(i.deliverability),
a.emit("elements.us_verification.error", {
code: 200,
type: "verification",
data: i,
form: p[0]
}),
e({
msg: g[t],
type: t
})
}
}
,
y.send(JSON.stringify(h)),
!1
}
prioritizeHandler(e, t) {
const i = $._data(e.get(0), "events");
i[t].unshift(i[t].pop())
}
verifyCallback(e, t, i={}) {
const {autosubmit: n, channel: s, elements: a, override: r, strictness: o, submit: l} = this.config;
return l || r ? (this.showMessage(e),
s.emit("elements.us_verification.verification", {
code: 200,
data: i,
form: a.form[0]
}),
this.config.submitted = !0,
this.config.override = !1,
a.form.off(".avSubmit", this.preFlight.bind(this)),
a.form.unbind(".avSubmit"),
n && (a.form.trigger("submit"),
a.form.get(0).submit()),
a.form.on("submit.avSubmit", this.preFlight.bind(this)),
void this.prioritizeHandler(a.form, "submit")) : t ? (this.config.submitted = !0,
this.config.override = !1,
a.form.off(".avSubmit", this.preFlight.bind(this)),
a.form.unbind(".avSubmit"),
void (n && (a.form.trigger("submit"),
a.form.get(0).submit()))) : (this.showMessage(e),
void (this.config.override = "passthrough" === o || ("undeliverable" === e.type ? "relaxed" === o : "DEFAULT" !== e.type && "strict" !== this.config.strictness)))
}
preFlight = e=>(e.stopImmediatePropagation(),
e.preventDefault(),
this.hideMessages(),
this.config.elements.message.off("click"),
this.verify(this.verifyCallback.bind(this)));
configureVerification() {
const {elements: e} = this.config;
if (this.pageState.create_message) {
const i = $('<div class="lob-verify-message"></div>')
, n = e.errorAnchorElement;
n.length ? i.insertBefore(n) : e.form.prepend(i),
e.message = i,
b || (b = !0,
$("<style>").prop("type", "text/css").html((t = this.config,
`\n .lob-verify-message {\n background-color: ${h(t, "err", "bgcolor")};\n border-radius: .25rem;\n color: ${h(t, "err", "color")};\n display: none;\n left: 50%;\n margin-bottom: 1.5rem;\n margin-right: -50%;\n margin-top: 1.5rem;\n max-width: 100%;\n padding: .5rem;\n position: relative;\n text-align: center;\n transform: translate(-50%, 0%);\n width: 100%;\n }`)).appendTo("head"))
}
var t;
"" !== e.parseResultError && this.showMessage({
type: "form_detection",
msg: e.parseResultError
}),
e.form.on("submit.avSubmit", this.preFlight.bind(this)),
this.prioritizeHandler(e.form, "submit")
}
}
var w = i(787)
, _ = i.n(w);
const M = ()=>{
const e = new (_())("lob-address-elements");
return {
channel: e,
instances: [],
on: e.on
}
}
, A = e=>{
const t = (()=>{
const e = u("primary") || $()
, t = d("primary") || $()
, i = m("primary") || $();
return e.add(t).add(i)
}
)()
, i = [];
return t.each(((t,n)=>{
const s = (n = $(n)).closest("form")
, a = ((e,t)=>{
const i = ["false", "strict", "normal", "relaxed", "passthrough"];
if (e && i.indexOf(e) > -1)
return e;
{
const e = o("verify", t);
return e && i.indexOf(e) > -1 ? e : "relaxed"
}
}
)(e ? e.strictness : null, s)
, l = "true" === o("verify-message", s) || s.length && !r("verify-message", s).length
, c = n.length && "false" !== o("primary", s)
, u = o("autosubmit", s) || !0
, d = "false" !== a && s.length && ("passthrough" === a || r("verify-message", s).length || l);
i.push({
autocomplete: c,
autosubmit: u,
create_message: l,
enrich: d || c,
form: s,
primary: n,
strictness: a,
verify: d
})
}
)),
i
}
;
!function() {
const e = (e,t)=>{
window.LobAddressElements || (window.LobAddressElements = M()),
t.channel = window.LobAddressElements.channel;
const i = i=>{
const {enrich: n, form: s} = i
, a = s && s.attr("data-lob-state") || "untouched";
"untouched" === a && n ? (s.attr("data-lob-state", "enriched"),
setTimeout((()=>{
const n = new v(e,t,i);
window.LobAddressElements || (window.LobAddressElements = M()),
window.LobAddressElements.instances.push(n)
}
), 0)) : "enriched" !== a || n || s.attr("data-lob-state", "untouched")
}
;
if ((e=>{
const n = ()=>{
A(t).forEach(i)
}
, s = window.MutationObserver || window.WebKitMutationObserver;
if (s) {
new s(n).observe(window.document.body, {
subtree: !0,
attributes: !0,
childList: !0
})
}
n()
}
)(),
!A().length)
return {
do: {
init: ()=>new v(e,t)
}
}
}
, t = "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"
, i = "https://cdnjs.cloudflare.com/ajax/libs/autocomplete.js/0.37.0/autocomplete.jquery.min.js"
, n = {
load: function() {
const e = Array.prototype.slice.call(arguments[0])
, t = n[e.shift()];
t && t.apply(this, e)
},
jquery: function() {
if (window.jQuery)
n.load(arguments);
else {
const e = arguments
, i = document.createElement("script");
i.onload = function() {
n.load(e)
}
,
i.src = t,
document.getElementsByTagName("body")[0].appendChild(i)
}
},
jquery_autocomplete: function() {
if (window.jQuery.fn.autocomplete)
n.load(arguments);
else {
const e = document.createElement("script")
, t = arguments;
e.onload = function() {
n.load(t)
}
,
e.src = i,
document.getElementsByTagName("body")[0].appendChild(e)
}
},
address_elements: function() {
if (window.LobAddressElements)
n.load(arguments);
else {
const t = window.LobAddressElementsConfig || {};
window.LobAddressElements = M();
const i = e(window.jQuery, t);
i && window.LobAddressElements.instances.push(i),
n.load(arguments)
}
}
};
n.load(["jquery", "jquery_autocomplete", "address_elements"])
}()
}
)()
}
)();
if (result?.emailaddress && Checkout.$('#checkout_email').val() == '' ){
Checkout.$('#checkout_email').val(result.emailaddress)
}
// this is where the LOB error messages should pop up
Checkout.$('#section-delivery-title').attr('data-lob-verify-message-anchor','');
Checkout.$('a.step__footer__previous-link').hide(); // do not link out to cart
Checkout.$('tr.total-line.total-line--shipping').hide(); // just hide shipping
Checkout.$('input[name=step]').val('payment_method')
Checkout.$('span.btn__content').text("{{ 'customer.login_page.guest_continue' | t }}"); // hacky way to avoid translating
var company = {% if checkout.attributes["youtube-channel"] %} '{{ checkout.attributes["youtube-channel"] }}' {% else %} {{ false }} {% endif %} || result['youtube-channel'];
Checkout.$('#checkout_shipping_address_company').val(company);
/* hack in shipping election on first page so we can skip it later */
Checkout.$('div.section--contact-information').append(
`
<input autocomplete="off" size="30" type="hidden" name="checkout[attributes][internal-id]" value="${result['internal-id']}">
<input autocomplete="off" size="30" type="hidden" name="checkout[attributes][youtube-channel]" value="${company}">
<!--
<input hidden=true class="input-radio" data-checkout-total-shipping="Free" data-checkout-total-shipping-cents="0" data-checkout-discounted-shipping-price="0.00" data-checkout-shipping-rate="Free" data-checkout-original-shipping-rate="Free" data-checkout-total-price="Free" data-checkout-total-price-cents="0" data-checkout-payment-due="$0.00" data-checkout-payment-due-cents="0" data-checkout-payment-subform="free" data-checkout-subtotal-price="$0.00" data-checkout-subtotal-price-cents="0" data-checkout-total-taxes="$0.00" data-checkout-total-taxes-cents="0" data-checkout-multiple-shipping-rates-group="false" data-backup="shopify-Economy-0.00" type="radio" value="shopify-Economy-0.00" name="checkout[shipping_rate][id]" id="checkout_shipping_rate_id_shopify-economy-0_00" checked="checked">
<input hidden=true class="input-radio" data-checkout-total-shipping="Free" data-checkout-total-shipping-cents="0" data-checkout-discounted-shipping-price="0.00" data-checkout-shipping-rate="Free" data-checkout-original-shipping-rate="Free" data-checkout-total-price="Free" data-checkout-total-price-cents="0" data-checkout-payment-due="$0.00" data-checkout-payment-due-cents="0" data-checkout-payment-subform="free" data-checkout-subtotal-price="$0.00" data-checkout-subtotal-price-cents="0" data-checkout-total-taxes="$0.00" data-checkout-total-taxes-cents="0" data-checkout-multiple-shipping-rates-group="false" data-backup="shopify-Economy%20International%20(6%20to%2010%20business%20days)-0.00" type="radio" value="shopify-Economy%20International%20(6%20to%2010%20business%20days)-0.00" name="checkout[shipping_rate][id]" id="checkout_shipping_rate_id_shopify-economy20international20620to201020business20days-0_00" checked="checked">
-->
<input hidden=true class="input-radio" data-checkout-total-shipping="Free" data-checkout-total-shipping-cents="0" data-checkout-discounted-shipping-price="0.00" data-checkout-shipping-rate="Free" data-checkout-original-shipping-rate="Free" data-checkout-total-price="Free" data-checkout-total-price-cents="0" data-checkout-payment-due="$0.00" data-checkout-payment-due-cents="0" data-checkout-payment-subform="free" data-checkout-subtotal-price="$0.00" data-checkout-subtotal-price-cents="0" data-checkout-total-taxes="$0.00" data-checkout-total-taxes-cents="0" data-checkout-multiple-shipping-rates-group="false" data-backup="shopify-Economy-0.00" type="radio" value="shopify-Economy-0.00" name="checkout[shipping_rate][id]" id="checkout_shipping_rate_id_shopify-economy-0_00" checked="checked">
`
);
Checkout.$(
`
<div class="section section--marketing-opt-in">
<div class="section__header">
<div class="layout-flex layout-flex--tight-vertical layout-flex--loose-horizontal layout-flex--wrap">
<h2 class="section__title layout-flex__item layout-flex__item--stretch" id="main-header" tabindex="-1">
Marketing Opt-In
</h2>
</div>
</div>
<div class="section__content" data-section="customer-information" data-shopify-pay-validate-on-load="false">
<div class="fieldset">
<div class="field field--show-floating-label opt-in" style="padding: 6px 0px;">
<input type=hidden id="marketing-opt-in-field" name="checkout[attributes][marketing-opt-in]" value="Yes">
<select id="marketing-opt-in-field-select" class="field__input field__input--select">
<option value="--" selected="selected">Please select an option</option>
<option value="Yes">Yes, I would like to receive a gift</option>
<option value="No">No, please opt out blah blah</option>
</select>
</div>
</div>
</div>
</div>
`
).insertBefore(Checkout.$('div.section.section--contact-information'));
/* hide the inputs until a marketing election is made */
{% unless checkout.attributes['marketing-opt-in'] == 'Yes' %}
Checkout.$('div.section--contact-information').hide();
Checkout.$('div.section--shipping-address').hide();
{% endunless %}
/* show hide fields based on marketing opt-in */
$('#marketing-opt-in-field-select').on('change', function(){
var electionVal = $('#marketing-opt-in-field-select').val();
if (electionVal == 'Yes'){
// show the email section
Checkout.$('div.section--contact-information').show();
Checkout.$('div.section--shipping-address').show();
// refill fields
Checkout.$('#checkout_shipping_address_last_name').val('');
// todo set checkout attribute field value
} else {
// hide sections
Checkout.$('div.section--contact-information').hide();
Checkout.$('div.section--shipping-address').hide();
// prefill the address
Checkout.$('#checkout_shipping_address_last_name').val('Opted Out');
// todo set checkout attribute field value
}
});
/* setup fields for LOB */
$('checkout_shipping_address_address1').attr('data-lob-primary');
}
if (Shopify.Checkout.step === "payment_method") {
Checkout.$('span.btn__content').text("{{ 'customer.login_page.submit' | t }}"); // hacky way to avoid translating
Checkout.$('input[name=previous_step]').val('contact_information');
var prevLink = Checkout.$('a.step__footer__previous-link')[0];
var oldPreviousUrl = prevLink.href
var newPreviousUrl = oldPreviousUrl.replace('shipping_method', 'contact_information');
prevLink.href = newPreviousUrl;
Checkout.$('span.step__footer__previous-link-content').text(" {{ 'customer.addresses.edit_address' | t }}");
Checkout.$('div.section--billing-address').hide();
Checkout.$('div[data-review-section=shipping-cost]').text(' {{ checkout.attributes["youtube-channel"] }}');
Checkout.$('div[data-review-section=shipping-cost]').prev('div.review-block__label').text('Channel');
if ( 'todo' == 'No' ) {
// submit the form?
}
}
console.log(Shopify.Checkout.step);
if (true){ // change to only be on order confirmation page
/* too hard/DOM dependent with CSS */
Checkout.$('h3:contains("Shipping method")').text('Channel');
Checkout.$('span.os-order-number').text('Order #{{ checkout.attributes["internal-id"] }}')
}
});
})(Checkout.$);
</script>
</head>
<body>
{{ skip_to_content_link }}
<header class="banner" data-header role="banner">
<div class="wrap">
{{ content_for_logo }}
</div>
</header>
{{ order_summary_toggle }}
<div class="content" data-content>
<div class="wrap">
<div class="main">
<header class="main__header" role="banner">
{{ content_for_logo }}
{% comment %} {{ breadcrumb }} {% endcomment %}
{% comment %} {{ alternative_payment_methods }} {% endcomment %}
</header>
<main class="main__content" role="main">
{{ content_for_layout }}
</main>
<footer class="main__footer" role="contentinfo">
{{ content_for_footer }}
</footer>
</div>
<aside class="sidebar" role="complementary">
<div class="sidebar__header">
{{ content_for_logo }}
</div>
<div class="sidebar__content">
{{ content_for_order_summary }}
</div>
</aside>
</div>
</div>
{{ tracking_code }}
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment