Created
May 9, 2016 23:50
-
-
Save frankiefu/7d331126726fe4e33ee3daad8284fffa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
@license | |
Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | |
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt | |
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | |
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt | |
Code distributed by Google as part of the polymer project is also | |
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt | |
--> | |
<link rel="import" href="../bower_components/polymer/polymer.html"> | |
<link rel="import" href="../bower_components/carbon-route/carbon-route.html"> | |
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html"> | |
<link rel="import" href="kart-button.html"> | |
<link rel="import" href="kart-common-styles.html"> | |
<link rel="import" href="kart-form-styles.html"> | |
<link rel="import" href="kart-input.html"> | |
<link rel="import" href="kart-select.html"> | |
<link rel="import" href="kart-switch.html"> | |
<!-- resources loaded by lazy-resources.html --> | |
<!-- | |
<link rel="prefetch" href="../bower_components/iron-form/iron-form.html"> | |
<link rel="prefetch" href="../bower_components/iron-icon/iron-icon.html"> | |
<link rel="prefetch" href="../bower_components/paper-spinner/paper-spinner-lite.html"> | |
<link rel="prefetch" href="kart-icons.html"> | |
--> | |
<dom-module id="kart-checkout"> | |
<template> | |
<style include="kart-common-styles kart-button kart-form-styles kart-input kart-select kart-switch"> | |
.main-frame { | |
transition: opacity 0.5s; | |
} | |
:host([waiting]) .main-frame { | |
opacity: 0.1; | |
} | |
kart-input, kart-select { | |
font-size: 16px; | |
color: var(--app-accent-color); | |
} | |
kart-select { | |
margin-bottom: 20px; | |
} | |
paper-spinner-lite { | |
position: fixed; | |
top: calc(50% - 14px); | |
left: calc(50% - 14px); | |
} | |
.billing-address-picker { | |
margin: 30px 0; | |
} | |
.billing-address-picker > label { | |
margin-left: 10px; | |
vertical-align: middle; | |
} | |
.grid { | |
margin-top: 40px; | |
@apply(--layout-horizontal); | |
} | |
.grid > section { | |
@apply(--layout-flex); | |
} | |
.grid > section:not(:first-child) { | |
margin-left: 80px; | |
} | |
.row { | |
@apply(--layout-horizontal); | |
} | |
.column { | |
@apply(--layout-vertical); | |
} | |
.row > .flex, | |
.input-row > * { | |
@apply(--layout-flex); | |
} | |
.input-row > *:not(:first-child) { | |
margin-left: 8px; | |
} | |
.order-summary-row { | |
line-height: 24px; | |
} | |
.total-row { | |
font-weight: 500; | |
margin: 30px 0; | |
} | |
@media (max-width: 767px) { | |
:host { | |
margin-bottom: 64px; | |
} | |
.grid { | |
display: block; | |
margin-top: 0; | |
} | |
.grid > section:not(:first-child) { | |
margin-left: 0; | |
} | |
} | |
</style> | |
<div class="main-frame"> | |
<iron-pages selected="[[state]]" attr-for-selected="state"> | |
<div state="init"> | |
<form action="/shop.axd/UpdateBillingAddress" method="post" name="frmBillingAddress"> | |
<div class="theLeft"> | |
<label>Name <span class="required">*</span></label> | |
<input class="input-medium" type="text" name="first_name" size="16" maxlength="16" value="" placeholder="First"> | |
<input class="input-itty" type="text" name="middle_initial" size="1" maxlength="1" value="" placeholder="MI"> | |
<input class="input-medium" type="text" name="last_name" size="16" maxlength="16" value="" placeholder="Last"> | |
<label>Address <span class="required">*</span></label> | |
<input class="input-xlarge" type="text" name="street" size="40" maxlength="30" value=""> | |
<label>Apt./Suite</label> | |
<input class="input-xlarge" type="text" name="address_ref1" size="40" maxlength="30" value=""> | |
<label>City <span class="required">*</span></label> | |
<input class="input-xlarge" type="text" name="city" size="40" maxlength="30" value=""> | |
<label>State <span class="required">*</span></label> | |
<div class="billing-address"> | |
<select name="state"> | |
<option value="" selected>State</option> | |
<option value="AK" > | |
AK: Alaska | |
<option value="AL" > | |
AL: Alabama | |
<option value="AR" > | |
AR: Arkansas | |
<option value="AZ" > | |
AZ: Arizona | |
<option value="CA" > | |
CA: California | |
<option value="CO" > | |
CO: Colorado | |
<option value="CT" > | |
CT: Connecticut | |
<option value="DC" > | |
DC: District of Columbia | |
<option value="DE" > | |
DE: Delaware | |
<option value="FL" > | |
FL: Florida | |
<option value="GA" > | |
GA: Georgia | |
<option value="GU" > | |
GU: Guam | |
<option value="HI" > | |
HI: Hawaii | |
<option value="IA" > | |
IA: Iowa | |
<option value="ID" > | |
ID: Idaho | |
<option value="IL" > | |
IL: Illinois | |
<option value="IN" > | |
IN: Indiana | |
<option value="KS" > | |
KS: Kansas | |
<option value="KY" > | |
KY: Kentucky | |
<option value="LA" > | |
LA: Louisiana | |
<option value="MA" > | |
MA: Massachusetts | |
<option value="MD" > | |
MD: Maryland | |
<option value="ME" > | |
ME: Maine | |
<option value="MI" > | |
MI: Michigan | |
<option value="MN" > | |
MN: Minnesota | |
<option value="MO" > | |
MO: Missouri | |
<option value="MS" > | |
MS: Mississippi | |
<option value="MT" > | |
MT: Montana | |
<option value="NC" > | |
NC: North Carolina | |
<option value="ND" > | |
ND: North Dakota | |
<option value="NE" > | |
NE: Nebraska | |
<option value="NH" > | |
NH: New Hampshire | |
<option value="NJ" > | |
NJ: New Jersey | |
<option value="NM" > | |
NM: New Mexico | |
<option value="NV" > | |
NV: Nevada | |
<option value="NY" > | |
NY: New York | |
<option value="OH" > | |
OH: Ohio | |
<option value="OK" > | |
OK: Oklahoma | |
<option value="OR" > | |
OR: Oregon | |
<option value="PA" > | |
PA: Pennsylvania | |
<option value="PR" > | |
PR: Puerto Rico | |
<option value="PW" > | |
PW: Palau | |
<option value="RI" > | |
RI: Rhode Island | |
<option value="SC" > | |
SC: South Carolina | |
<option value="SD" > | |
SD: South Dakota | |
<option value="TN" > | |
TN: Tennessee | |
<option value="TX" > | |
TX: Texas | |
<option value="UT" > | |
UT: Utah | |
<option value="VA" > | |
VA: Virginia | |
<option value="VT" > | |
VT: Vermont | |
<option value="WA" > | |
WA: Washington | |
<option value="WI" > | |
WI: Wisconsin | |
<option value="WV" > | |
WV: West Virginia | |
<option value="WY" > | |
WY: Wyoming | |
<option value=" " > | |
------- Canada -------- | |
<option value="AB" > | |
AB: Alberta | |
<option value="BC" > | |
BC: British Columbia | |
<option value="MB" > | |
MB: Manitoba | |
<option value="NB" > | |
NB: New Brunswick | |
<option value="NF" > | |
NF: Newfoundland | |
<option value="NS" > | |
NS: Nova Scotia | |
<option value="NT" > | |
NT: Northwest Territory | |
<option value="NU" > | |
NU: Nunavut | |
<option value="ON" > | |
ON: Ontario | |
<option value="PE" > | |
PE: Prince Edward Island | |
<option value="PQ" > | |
PQ: Quebec | |
<option value="SK" > | |
SK: Saskatchewan | |
<option value="YT" > | |
YT: Yukon Territory | |
<option value=" " > | |
----------------------- | |
<option value="FN" > | |
Foreign (non-US/Canada) | |
</select> | |
</div> | |
<label>Zip Code <span class="required">*</span></label> | |
<input class="input-small" type="text" name="zip_code" size="12" maxlength="7" value=""> | |
<input class="input-ext" type="text" name="zip_code_4" size="5" maxlength="4" value=""> | |
</div> | |
<!-- pull-left --> | |
<div class="theRight"> | |
<label>Country</label> | |
<div class="billing-address"> | |
<select name="country_code"> | |
<option value="0000" > | |
USA | |
<option value="0001" > | |
CANADA | |
</select> | |
</div> | |
<label>Phone <span class="required">*</span></label> | |
<input class="input-mini" type="text" name="day_phone_1" size="4" onkeyup="autotab(this, document.frmBillingAddress.day_phone_2)" maxlength="3" value=""> | |
<input class="input-mini" type="text" name="day_phone_2" size="4" onkeyup="autotab(this, document.frmBillingAddress.day_phone_3)" maxlength="3" value=""> | |
<input class="input-ext" type="text" name="day_phone_3" size="6" onkeyup="autotab(this, document.frmBillingAddress.day_phone_4)" maxlength="4" value=""> | |
Ext: | |
<input class="input-ext" type="text" name="day_phone_4" size="4" maxlength="4" value=""> | |
<label>Night Phone</label> | |
<input class="input-mini" type="text" name="night_phone_1" size="4" onkeyup="autotab(this, document.frmBillingAddress.night_phone_2)" maxlength="3" value=""> | |
<input class="input-mini" type="text" name="night_phone_2" size="4" onkeyup="autotab(this, document.frmBillingAddress.night_phone_3)" maxlength="3" value=""> | |
<input class="input-ext" type="text" name="night_phone_3" size="6" onkeyup="autotab(this, document.frmBillingAddress.night_phone_4)" maxlength="4" value=""> | |
Ext: | |
<input class="input-ext" type="text" name="night_phone_4" size="4" maxlength="4" value=""> | |
<label>Email Address <span class="required">*</span></label> | |
<input type="text" name="email" size="40" maxlength="50" value=""> | |
<label>Shipping Options</label> | |
<div class="well"> | |
<label class="radio"> | |
<input type="radio" name="ship_to_flag" value="B" checked> | |
Ship entire order to my billing address | |
</label> | |
<label class="radio"> | |
<input type="radio" name="ship_to_flag" value="C" > | |
Ship entire order to an address other than my billing address | |
</label> | |
</div> | |
<!-- /well --> | |
</div> | |
</form> | |
</div> | |
<!-- Success message UI --> | |
<header state="success"> | |
<h1>Thanks for your purchase!</h1> | |
<p>[[response.successMessage]]</p> | |
<kart-button class="action-btn"> | |
<a href="/">Finish</a> | |
</kart-button> | |
</header> | |
<!-- Error message UI --> | |
<header state="error"> | |
<h1>We couldn´t process your order</h1> | |
<p id="errorMessage">[[response.errorMessage]]</p> | |
<kart-button class="action-btn"> | |
<a href="/checkout">Try again</a> | |
</kart-button> | |
</header> | |
</iron-pages> | |
</div> | |
<!-- Handles the routing for the success and error subroutes --> | |
<carbon-route | |
route="[[route]]" | |
pattern="/:state" | |
on-active-changed="_activeRouteHandler"> | |
</carbon-route> | |
<!-- Show spinner when waiting for the server to repond --> | |
<paper-spinner-lite active="[[waiting]]"></paper-spinner-lite> | |
</template> | |
<script> | |
Polymer({ | |
is: 'kart-checkout', | |
properties: { | |
/** | |
* The route for the state. e.g. `success` and `error` are mounted in the | |
* `checkout/` route. | |
*/ | |
route: { | |
type: Object, | |
notify: true | |
}, | |
/** | |
* The total price of the contents in the user's cart. | |
*/ | |
total: Number, | |
/** | |
* The state of the form. Valid values are: | |
* `init`, `success` and `error`. | |
*/ | |
state: { | |
type: String, | |
value: 'init' | |
}, | |
/** | |
* An array containing the items in the cart. | |
*/ | |
cart: Array, | |
/** | |
* The server's response. | |
*/ | |
response: Object, | |
/** | |
* If true, the user must enter a billing address. | |
*/ | |
hasBillingAddress: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* If true, kart-checkout is currently visible on the screen. | |
*/ | |
visible: { | |
type: Boolean, | |
observer: '_visibleChanged' | |
}, | |
/** | |
* True when waiting for the server to repond. | |
*/ | |
waiting: { | |
type: Boolean, | |
readOnly: true, | |
reflectToAttribute: true | |
}, | |
/** | |
* True when waiting for the server to repond. | |
*/ | |
_hasItems: { | |
type: Boolean, | |
computed: '_computeHasItem(cart.length)' | |
} | |
}, | |
_submit: function(e) { | |
if (this._validateForm()) { | |
this.$.checkoutForm.submit(); | |
} | |
}, | |
/** | |
* Sets the valid state and updates the location. | |
*/ | |
_pushState: function(state) { | |
this._validState = state; | |
this.set('route.path', state); | |
}, | |
/** | |
* Checks that the `:state` subroute is correct. That is, the state has been pushed | |
* after receiving response from the server. e.g. Users can only go to `/checkout/success` | |
* if the server responsed with a success message. | |
*/ | |
_activeRouteHandler: function(e) { | |
var route = e.target; | |
if (e.detail.value) { | |
var state = route.data.state; | |
if (this._validState === state) { | |
this.state = state; | |
this._validState = ''; | |
return; | |
} | |
} | |
this.state = 'init'; | |
}, | |
/** | |
* Sets the initial state. | |
*/ | |
_reset: function() { | |
return; | |
var form = this.$.checkoutForm; | |
this._setWaiting(false); | |
form.reset(); | |
// Remove the `aria-invalid` attribute from the form inputs. | |
for (var el, i = 0; el = form.elements[i], i < form.elements.length; i++) { | |
el.removeAttribute('aria-invalid'); | |
} | |
}, | |
/** | |
* Validates the form's inputs and adds the `aria-invalid` attribute to the inputs | |
* that don't match the pattern specified in the markup. | |
*/ | |
_validateForm: function() { | |
var form = this.$.checkoutForm; | |
var firstInvalid = false; | |
for (var el, i = 0; el = form.elements[i], i < form.elements.length; i++) { | |
if (el.checkValidity()) { | |
el.removeAttribute('aria-invalid'); | |
} else { | |
if (!firstInvalid) { | |
// announce error message | |
if (el.nextElementSibling) { | |
this.fire('announce', el.nextElementSibling.getAttribute('error-message')); | |
} | |
if (el.scrollIntoViewIfNeeded) { | |
// safari, chrome | |
el.scrollIntoViewIfNeeded(); | |
} else { | |
// firefox, edge, ie | |
el.scrollIntoView(false); | |
} | |
el.focus(); | |
firstInvalid = true; | |
} | |
el.setAttribute('aria-invalid', 'true'); | |
} | |
} | |
return !firstInvalid; | |
}, | |
/** | |
* Adds the cart data to the payload that will be sent to the server | |
* and updates the UI to reflect the waiting state. | |
*/ | |
_willSendRequest: function(e) { | |
var form = e.target; | |
var rqBody = form.request.body; | |
// Populate the request body where `cartItemsId[i]` is the ID and `cartItemsQuantity[i]` | |
// is the quantity for some item `i`. | |
rqBody.cartItemsId = []; | |
rqBody.cartItemsQuantity = []; | |
this.cart.forEach(function(cartItem) { | |
rqBody.cartItemsId.push(cartItem.item.itemId); | |
rqBody.cartItemsQuantity.push(cartItem.quantity); | |
}); | |
this._setWaiting(true); | |
}, | |
/** | |
* Handles the response from the server by checking the response status | |
* and transitioning to the success or error UI. | |
*/ | |
_didReceiveResponse: function(e) { | |
var response = e.detail.response; | |
this.response = response; | |
this._setWaiting(true); | |
if (response.success) { | |
this._pushState('success'); | |
this._reset(); | |
this.fire('clear-cart'); | |
} else { | |
this._pushState('error'); | |
} | |
}, | |
_toggleBillingAddress: function(e) { | |
this.hasBillingAddress = e.target.checked; | |
if (this.hasBillingAddress) { | |
this.$.frmAddressB.focus(); | |
} | |
}, | |
_computeHasItem: function(cartLength) { | |
return cartLength > 0; | |
}, | |
_formatPrice: function(total) { | |
return isNaN(total) ? '' : '$' + total.toFixed(2); | |
}, | |
_getEntryTotal: function(entry) { | |
return this._formatPrice(entry.quantity * entry.item.price); | |
}, | |
_visibleChanged: function(visible) { | |
if (!visible) { | |
return; | |
} | |
// Reset the UI states | |
this._reset(); | |
// Notify the page's title | |
this.fire('change-section', { title: 'Checkout' }); | |
} | |
}); | |
</script> | |
</dom-module> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment