diff options
| author | Rene Ae <aehtyb@gmail.com> | 2015-12-04 20:32:44 -0600 |
|---|---|---|
| committer | Rene Ae <aehtyb@gmail.com> | 2015-12-04 20:32:44 -0600 |
| commit | 10efb0f7b426426057fed757fe3c851a249358dd (patch) | |
| tree | b80e285251d30fbca36220c932ef180c29c55dcf /StoneIsland/platforms/android/assets/www/js/lib | |
| parent | 015b58ff6845b5cb79b13fec109a37b4c10c7813 (diff) | |
android build
Diffstat (limited to 'StoneIsland/platforms/android/assets/www/js/lib')
43 files changed, 4082 insertions, 0 deletions
diff --git a/StoneIsland/platforms/android/assets/www/js/lib/_router.js b/StoneIsland/platforms/android/assets/www/js/lib/_router.js new file mode 100755 index 00000000..b1fa1c97 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/_router.js @@ -0,0 +1,105 @@ +var SiteRouter = Router.extend({ + + el: 'body', + routeByHash: true, + + routes: { + '/': 'intro', + '/intro': 'intro', + '/hub': 'hub', + '/story': 'story', + '/archive': 'archive', + + '/store': 'collection', + '/store/closed': 'closed', + '/store/:code': 'product', + + '/account/login': 'login', + '/account/logout': 'logout', + '/account/signup': 'signup', + '/account/profile': 'profile', + '/account/payment': 'payment', + '/account/shipping': 'shipping', + '/account/orders': 'orders', + '/account/settings': 'settings', + + '/page/terms': 'terms', + '/page/privacy': 'privacy', + '/page/returns': 'returns', + '/page/care': 'care', + + '/search': 'search', + + '/cart': 'cart.summary', + '/cart/summary': 'cart.summary', + '/cart/payment': 'cart.payment', + '/cart/shipping': 'cart.shipping', + '/cart/confirm': 'cart.confirm', + '/cart/thanks': 'cart.thanks', + '/cart/error': 'cart.error', + }, + + initialize: function(){ + var fn + for (var route in this.routes) { + fn = this.routes[route] + if (! this[fn]) { + this[fn] = this.default_view(fn) + } + } + }, + + initial_route: null, + launch: function(){ + if (this.initial_route) { + this.parseRoute( this.initial_route ) + } + else { + this.route() + } + this.initial_route = null + }, + + go: function(url){ + if (app.view && app.view.hide) { + app.view.hide() + } + window.location.href = "#/" + url + this.parseRoute(url) + }, + + default_view: function(name){ + var fn = function(){ + console.log(name) + if (app.view != app.login && app.view != app.signin) { + app.last_view = app.view + } + if (app.view && app.view.hide) { + app.view.hide() + } + if (name.match(/\./)) { + var n = name.split(".") + console.log(name, n) + app.view = app[n[0]][n[1]] + } + else { + app.view = app[name] + } + app.header.set_back( !! app.view.back ) + app.view.show() + }.bind(this) + return fn + }, + + product: function(code){ + if (app.view && app.view.hide) { + app.view.hide() + } + app.view = app.product + app.header.set_back( true ) + app.product.load(code) + app.product.show() + }, + +}) + diff --git a/StoneIsland/platforms/android/assets/www/js/lib/account/AccountView.js b/StoneIsland/platforms/android/assets/www/js/lib/account/AccountView.js new file mode 100755 index 00000000..1c5c9f16 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/account/AccountView.js @@ -0,0 +1,129 @@ +var AccountView = View.extend({ + + initialize: function(){ + }, + + connect: function(cb){ + auth.init(this.ready.bind(this, cb)) + }, + + ready: function(cb){ + if (auth.logged_in()) { + this.logged_in(cb) + } + else { + this.logged_out(cb) + } + }, + + addresses: [], + addressLookup: {}, + ccs: [], + ccLookup: {}, + + listAddresses: function(cb){ + sdk.address.list({ + success: function(data){ + this.populateAddresses(data, cb) + }.bind(this) + }) + }, + + populateAddresses: function(data, cb){ + console.log("populate addresses:", data.AddressBook.addressBookItem) + + if (! data.AddressBook) { + console.log("no addresses") + cb && cb() + return + } + + this.addresses = data.AddressBook.addressBookItem + this.addressLookup = {} + data.AddressBook.addressBookItem.forEach(function(item){ + this.addressLookup[ item.Id ] = item + if (item.IsDefault) { + console.log("SHIPPING ADDRESS", item) + app.shipping.populate(item) + } + if (item.IsBillingDefault) { + console.log("BILLING ADDRESS") + app.payment.populate(item) + } + }.bind(this)) + + app.cart.shipping.populate() + + cb && cb() + }, + + listCreditCards: function(cb){ + sdk.payment.list_credit_cards({ + success: function(data){ + this.populateCreditCards(data, cb) + }.bind(this) + }) + }, + + populateCreditCards: function(data, cb){ + console.log("populate ccs:", data.CreditCards) + this.ccs = data.CreditCards + this.ccLookup = {} + if (! data.CreditCards || ! data.CreditCards.length) { + } + else { + data.CreditCards.forEach(function(cc){ + this.ccLookup[cc.Id] = cc + }.bind(this)) + app.payment.populate( data.CreditCards[0] ) + app.cart.payment.populate() + } + cb && cb() + }, + + logged_in: function(cb){ + this.listAddresses() + this.listCreditCards() + $("#nav .login").hide() + $("#nav .account, #nav .logout").show() + if (! auth.deferred_product && app.last_view) { + if (app.last_view != app.login && app.last_view != app.signin && app.last_view != app.logout) { + app.view && app.view.hide && app.view.hide() + app.view = app.last_view + app.view.show() + } + } + else { + cb && cb() + } + if ( ! auth.has_cart() ) { + app.curtain.show("loading") + auth.create_cart(function(){ + auth.add_deferred_product_to_cart(function(){ + app.router.go("cart") + setTimeout(function(){ + app.curtain.hide("loading") + }, 500) + }) + }) + } + else { + if (auth.deferred_product) { + auth.add_deferred_product_to_cart(function(){ + app.router.go("cart") + }) + } + else { + app.cart.load() + } + } + }, + + logged_out: function(cb){ + $("#nav .login").show() + $("#nav .account, #nav .logout").hide() + $("#nav").removeClass("account") + cb && cb() + }, + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/account/OrdersView.js b/StoneIsland/platforms/android/assets/www/js/lib/account/OrdersView.js new file mode 100755 index 00000000..a1b83767 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/account/OrdersView.js @@ -0,0 +1,189 @@ +var OrdersView = ScrollableView.extend({ + + el: "#orders", + + loaded: false, + + list_template: $("#orders .list_template").html(), + item_template: $("#orders .item_template").html(), + + events: { + "click .back": "back", + "click .item": "load_single", + }, + + initialize: function(){ + this.$list = this.$(".list") + this.$empty = this.$(".empty") + this.$single_order = this.$("#single_order") + + this.$rows = this.$(".rows") + this.$subtotal = this.$(".subtotal") + this.$shipping = this.$(".shipping") + this.$tax = this.$(".tax") + this.$total = this.$(".total") + + this.$shipping_address = this.$(".shipping_address") + this.$shipping_method = this.$(".shipping_method") + + this.scroller = new IScroll('#orders', app.iscroll_options) + }, + + show: function(){ + if (! auth.logged_in()) { return app.router.go("intro") } + app.header.set_back(false) + app.footer.hide() + document.body.className = "orders" + this.deferScrollToTop() + this.el.className = "" + + if (this.loaded) { + this.populate() + } + else { + this.fetch() + } + }, + + orders: null, + orderLookup: {}, + + fetch: function(){ + this.$list.empty() + this.$empty.hide() + this.loader = new Loader(this.ready.bind(this)) + app.curtain.show("loading") + sdk.account.fetch_orders({ + success: function(data){ + this.loader.register("orders") + this.orders = data.OrderDetails + data.OrderDetails.forEach(function(row){ + this.loader.register(row.OrderNumber) + sdk.account.fetch_single_order({ + id: row.OrderNumber, + success: function(row_data){ + this.orderLookup[ row.OrderNumber ] = row_data.OrderFullDetails + this.loader.ready(row.OrderNumber) + }.bind(this), + error: function(){ + this.orderLookup[ row.OrderNumber ] = null + this.loader.ready(row.OrderNumber) + }.bind(this), + }) + }.bind(this)) + this.loader.ready("orders") + }.bind(this), + error: function(){ + console.log("error fetching orders") + }.bind(this), + }) + }, + + ready: function(){ + this.populate() + app.curtain.hide("loading") + }, + + populate: function(){ + this.$list.empty() + + if (! this.orders.length) { + this.$empty.show() + return + } + else { + this.$empty.hide() + } + this.orders.forEach(function(row){ + var order = this.orderLookup[ row.OrderNumber ] + if (! order) { return } + var t = this.list_template.replace(/{{date}}/g, moment(order['Date']).format("ddd MM/DD/YYYY").toUpperCase()) + .replace(/{{id}}/g, row.OrderNumber) + .replace(/{{total}}/g, as_cash( order.TotalAmount )) + var $t = $(t), $images = $t.find(".images") + order.Items.forEach(function(item){ + var img = new Image () + img.src = sdk.image(item['Code10'], "11_f") + $images.append(img) + }.bind(this)) + this.$list.append($t) + }.bind(this)) + + this.refreshScroller() + }, + + load_single: function(e){ + var id = $(e.currentTarget).data("id") + var order = this.orderLookup[ id ] + if (! order) { return } + + console.log(order) + + this.$rows.empty() + + order.Items.forEach(function(item){ + var $el = $("<div class='item'><img src='img/spinner.gif'></div>") + this.$rows.append($el) + var code_ten = item.Code10 + + var code = code_ten.substr(0, 8) + app.product.find(code, function(data, details){ + var descriptions = app.product.get_descriptions( details ) + + var name_partz = descriptions['ModelNames'].split(' ') + var num = name_partz.shift() + var title = name_partz.join(' ') + var type = title_case( descriptions['MicroCategory'] ) + + var color_name, size_name + + details.Item.ModelColors.some(function(color){ + if (color['Code10'] == code_ten) { + color_name = color['ColorDescription'] + return true + } + return false + }) + size_name = item.DefaultSize + " " + item.DefaultSizeClassFamily + + var t = this.item_template + .replace(/{{image}}/, sdk.image(item['Code10'], '11_f')) + .replace(/{{sku}}/, num) + .replace(/{{title}}/, title) + .replace(/{{type}}/, type) + .replace(/{{size}}/, size_name || "DEFAULT") + .replace(/{{color}}/, color_name || "DEFAULT") + .replace(/{{quantity}}/, 1) + .replace(/{{price}}/, as_cash(details.Item.Price.DiscountedPrice)) + $el.data("price", details.Item.Price.DiscountedPrice) + $el.html(t) + this.refreshScroller() + }.bind(this)) + }.bind(this)) + + var subtotal = order.ItemsTotalAmount + var shipping_cost = order.Delivery.Amount + var tax = order.SalesTaxAmount + var total = order.TotalToPay + + this.$subtotal.html( as_cash(subtotal) ) + this.$shipping.html( as_cash(shipping_cost) ) + this.$tax.html( as_cash(tax) ) + this.$total.html( as_cash(total) ) + + var street = order.Delivery.Address.replace(/\n$/,"").replace("\n","<br>") + var address = order.Delivery.Name + "<br>" + street + "<br>" + order.Delivery.City + " " + order.Delivery.ZipCode + this.$shipping_address.html(address) + this.$shipping_method.html(order.Delivery.Type + " - " + order.Delivery.Time) + + app.header.set_back(true) + this.$el.addClass("single") + }, + + back: function(){ + app.header.set_back(false) + this.el.className = "" + }, + +}) + diff --git a/StoneIsland/platforms/android/assets/www/js/lib/account/PaymentView.js b/StoneIsland/platforms/android/assets/www/js/lib/account/PaymentView.js new file mode 100755 index 00000000..03dc8cbf --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/account/PaymentView.js @@ -0,0 +1,115 @@ +var PaymentView = FormView.extend({ + + el: "#payment", + + action: sdk.payment.add_credit_card, + + events: { + }, + + test_data: { + "Name":"Name", + "Surname":"Surname", + "Address1":"address", + "Address2":"address2", + "City":"Ferrara", + "Province":"NY", + "HolderIsoCountry":"IT", + "CreditCardCountry": "US", + "ZipCode":"40200", + "Type":"Visa", + "Number":"4111111111111111", + "ExpirationMonth":"09", + "ExpirationYear":"2017", + "Cvv":"1233", + }, + + initialize: function(){ + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.address = new AddressView ({ parent: this, checkPhone: false }) + this.cc = new CreditCardView ({ parent: this }) + this.scroller = new IScroll('#payment', app.iscroll_options) + }, + + show: function(){ + if (! auth.logged_in()) { return app.router.go("intro") } + app.footer.show("SAVE", "CANCEL") + document.body.className = "payment" + this.deferScrollToTop() + // this.preload() + }, + + populate: function(data){ + this.data = data || this.data + this.address.populate(data) + this.cc.populate(data) + }, + + finalize: function(data){ + if (this.cc.data && this.cc.data.Guid) { + sdk.payment.delete_credit_card({ + guid: this.cc.data.Guid, + success: function(){}, + error: function(){}, + }) + } + + data.IsDefault = "true" // this.$isDefault.prop("checked") ? "true" : "false" + data.UserId = sdk.auth.user_id + data.HolderIsoCountry = "US" + data.CreditCardNumber = data.Number + data.IsPreferred = "true" + + console.log(data) + return data + }, + + success: function(data){ + app.curtain.show("loading") + app.account.listAddresses(function(){ + app.curtain.hide("loading") + }) + }, + + error: function(data){ + console.log(data) + }, + + cancel: function(){ + app.router.go("intro") + }, + +}) + +/* + var new_card = { + "Name":"Name", + "Surname":"Surname", + "Address":"address", + "City":"Ferrara", + "Province":"FE", + "HolderIsoCountry":"IT", + "ZipCode":"40200", + "Type":"Visa", + "Number":"0000567890124285", + "ExpirationMonth":"02", + "ExpirationYear":"2017", + } + promise(sdk.payment.add_credit_card, { data: new_card }).then(function(data){ + last_guid = data['CreditCard']['Guid'] + assert(data.Header.StatusCode == 201) + assert(!! last_guid) + done() + }) + + promise(sdk.payment.list_credit_cards, { data: {} }).then(function(data){ + assert(data.Header.StatusCode == 201) + console.log(data) + done() + }) + + promise(sdk.payment.delete_credit_card, { guid: last_guid }).then(function(data){ + assert(data.Header.StatusCode == 200) + done() +*/
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/account/ProfileView.js b/StoneIsland/platforms/android/assets/www/js/lib/account/ProfileView.js new file mode 100755 index 00000000..ed2f3536 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/account/ProfileView.js @@ -0,0 +1,82 @@ +var ProfileView = FormView.extend({ + + el: "#profile", + + events: { + }, + + action: sdk.account.update, + + initialize: function(){ + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.scroller = new IScroll('#profile', app.iscroll_options) + }, + + show: function(){ + if (! auth.logged_in()) { return app.router.go("intro") } + app.footer.show("SAVE", "CANCEL") + document.body.className = "profile" + this.preload(auth.user) + this.deferScrollToTop() + }, + + validate_presence: { + "Name": "Please enter your first name.", + "Surname": "Please enter your last name.", + "Email": "Please enter a valid email address.", + }, + + validate_fields: function(data, errors){ + if (! data.Email.match("@")) { errors.push([ "Email", "Email address is not valid." ]) } + if (! data.CurrentPassword && (data.NewPassword || data.Email !== auth.user.Email)) { errors.push([ "CurrentPassword", "Please enter your current password." ]) } + if (data.CurrentPassword && ! data.NewPassword) { errors.push([ "NewPassword", "Please enter your new password." ]) } + if (data.NewPassword && data.NewPassword.length < 7) { errors.push([ "CurrentPassword", "New password must be 7 characters or more." ]) } + // if (data.Gender === "NONE") { errors.push([ "Gender", "Please supply your gender." ]) } + }, + + finalize: function(data){ + if (data.CurrentPassword && (data.NewPassword || data.Email !== auth.user.Email)) { + data.NewPassword = data.NewPassword || data.CurrentPassword + data.NewEmail = data.NewEmail || auth.user.Email + + sdk.account.update_mail_and_password({ + data: { + Password: data.CurrentPassword, + NewPassword: data.NewPassword || data.CurrentPassword, + Email: auth.user, + NewEmail: data.NewEmail || auth.user.Email, + }, + success: function(){ console.log("updated password") }, + error: function(){ console.log("error updating password") }, + }) + } + + var submissible_data = _.pick(data, "Name Surname BirthDay YooxLetter".split(" ")) + submissible_data.Gender = "U" +// submissible_data.idUser = auth.user_id +// submissible_data.AccessToken = auth.access_token +// submissible_data.Premium = "false" +// submissible_data.LanguageId = "" +// submissible_data.SiteCode = "STONEISLAND_US" +// submissible_data.FuriganaName = "" +// submissible_data.FuriganaSurname = "" +// submissible_data.UserPromocode = "" + submissible_data.BirthDay += "T00:00:00Z" + submissible_data.YooxLetter = data.YooxLetter || "false" + submissible_data.DataProfiling = "true" + + return submissible_data + }, + + success: function(data){ + }, + + error: function(data){ + }, + + cancel: function(){ + app.router.go("intro") + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/account/SettingsView.js b/StoneIsland/platforms/android/assets/www/js/lib/account/SettingsView.js new file mode 100755 index 00000000..7f96bb88 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/account/SettingsView.js @@ -0,0 +1,24 @@ +var SettingsView = FormView.extend({ + + el: "#settings", + + events: { + }, + + initialize: function(){ + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.scroller = new IScroll('#settings', app.iscroll_options) + }, + + show: function(){ + if (! auth.logged_in()) { return app.router.go("intro") } + app.footer.show("SAVE", "CANCEL") + document.body.className = "settings" + this.deferScrollToTop() + }, + + save: function(){ + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/account/ShippingView.js b/StoneIsland/platforms/android/assets/www/js/lib/account/ShippingView.js new file mode 100755 index 00000000..39baf2aa --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/account/ShippingView.js @@ -0,0 +1,77 @@ +var ShippingView = FormView.extend({ + + el: "#shipping", + + action: sdk.address.add, + + events: { + }, + + test_data: { + "Name":"name", + "Surname":"surname", + "Address":"address1\naddress2", + "IsDefault":false, + "IsBillingDefault":false, + "IsOwner":false, + "ZipCode":"88040", + "City":"City", + "Province":"NY", + "Phone":"1234567890", + "Mobile":"Mobile", + "Mail":"Mail", + "UserId": sdk.auth.user_id, + }, + + initialize: function(){ + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.address = new AddressView ({ parent: this }) + this.scroller = new IScroll('#shipping', app.iscroll_options) + }, + + show: function(){ + if (! auth.logged_in()) { return app.router.go("intro") } +// this.preload( this.data || this.test_data ) + app.footer.show("SAVE", "CANCEL") + document.body.className = "shipping" + this.deferScrollToTop() + }, + + populate: function(data){ + this.data = data || this.data + this.address.populate(data) + }, + + finalize: function(data){ + if (this.address.data && this.address.data.Id) { + sdk.address.destroy({ + id: this.address.data.Id, + success: function(){}, + error: function(){}, + }) + } + + data.IsDefault = "true" // this.$isDefault.prop("checked") ? "true" : "false" + data.UserId = sdk.auth.user_id + + console.log(data) + return data + }, + + success: function(data){ + app.curtain.show("loading") + app.account.listAddresses(function(){ + app.curtain.hide("loading") + }) + }, + + error: function(data){ + console.log(data) + }, + + cancel: function(){ + app.router.go("intro") + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/auth/LoginView.js b/StoneIsland/platforms/android/assets/www/js/lib/auth/LoginView.js new file mode 100755 index 00000000..1f7438cc --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/auth/LoginView.js @@ -0,0 +1,53 @@ +var LoginView = FormView.extend({ + + el: "#login", + + action: sdk.account.login, + + events: { + "click .newuser": "new_user", + "submit form": "save", + }, + + initialize: function(){ + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.scroller = new IScroll('#login', app.iscroll_options) + }, + + show: function(){ + if (auth.logged_in()) { + app.router.go("intro") + return + } + var msg = "* Your personal and payment<br>information will always remain private" + app.footer.show("SUBMIT", "CANCEL") + this.$form.get(0).reset() + this.$msg.html(msg) + document.body.className = "login" + }, + + new_user: function(){ + app.router.go("account/signup") + }, + + validate_presence: { + "Email": "Please enter a valid email address.", + "Password": "Please enter your password.", + }, + + success: function(data){ + // console.log(data) + app.account.logged_in(function(){ app.router.go("store") }) + }, + + error: function(data){ + this.$msg.html("There was an error logging you in. Bad password?") + this.$msg.addClass('alert-notice') + }, + + cancel: function(){ + auth.deferred_product = null + }, + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/auth/LogoutView.js b/StoneIsland/platforms/android/assets/www/js/lib/auth/LogoutView.js new file mode 100755 index 00000000..481dcb8d --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/auth/LogoutView.js @@ -0,0 +1,16 @@ +var LogoutView = View.extend({ + + el: "#logout", + + events: { + }, + + show: function(){ + document.body.className = "logout" + app.header.set_cart_count(0) + app.footer.hide() + auth.log_out() + app.account.logged_out() + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/auth/SignupView.js b/StoneIsland/platforms/android/assets/www/js/lib/auth/SignupView.js new file mode 100755 index 00000000..afbb8877 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/auth/SignupView.js @@ -0,0 +1,117 @@ +var SignupView = FormView.extend({ + + el: "#signup", + + action: sdk.account.signup, + last_data: null, + +/* + test_data: { + "Email": "testit.account" + Math.floor(Math.random() * 10000000) + "@yoox.com", + "Password": "TestPassword", + "Password2": "TestPassword", + "Gender": "U", + "Name": "TestName", + "Surname": "TestSurname", + "BirthDay": "1978-11-12", + "DataProfiling": true, + "DataProfiling2": true, + }, +*/ + + events: { + "click .privacy-msg": "privacy_link", + "submit form": "save", + }, + + initialize: function(){ + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.scroller = new IScroll('#signup', app.iscroll_options) + }, + + show: function(){ + if (auth.logged_in()) { + app.router.go("intro") + return + } + var msg = "* Your personal and payment<br>information will always remain private" + app.footer.show("SUBMIT", "CANCEL") + this.$form.get(0).reset() + this.$msg.html(msg) + document.body.className = "signup" + + this.preload() + this.deferScrollToTop() + }, + + validate_presence: { + "Name": "Please enter your first name.", + "Surname": "Please enter your last name.", + "Email": "Please enter a valid email address.", + "ConfirmEmail": "Please enter a valid email address.", + "BirthDay": "Please enter your birthday.", + "Password": "Please enter your password.", + "Password2": "Please enter your password again.", + "DataProfiling": "You must agree to data profiling.", + }, + + validate_fields: function(data, errors){ + if (data.Password.length < 7) { errors.push([ "Password", "Password must be 7 characters or more." ]) } + if (data.Password !== data.Password2) { errors.push([ "Password2", "Passwords don't match." ]) } + if (! data.Email.match("@")) { errors.push([ "Email", "Email address is not valid." ]) } + if (data.Email.toLowerCase() !== data.ConfirmEmail.toLowerCase()) { errors.push([ "ConfirmEmail", "Email addresses don't match." ]) } + // if (data.Gender === "NONE") { errors.push([ "Gender", "Please supply your gender." ]) } + if (data.DataProfiling !== "true") { errors.push([ "DataProfiling", "You must consent to use this service." ]) } + if (data.DataProfiling2 !== "true") { errors.push([ "DataProfiling2", "You must consent to use this service." ]) } + if (! data.YooxLetter) { data.YooxLetter = false } + }, + + finalize: function(data){ + delete data.DataProfiling2 + delete data.ConfirmEmail + + data.Gender = "U" + data.BirthDay += "T00:00:00Z" + + this.last_data = data + console.log(data) + return data + }, + + privacy_link: function(){ + // rewrite app.privacy instance temporarily + app.privacy.back = function(){ + app.router.go("account/signup") + } + app.privacy.hide = function(){ + app.privacy.back = app.privacy.hide = null + } + app.router.go("page/privacy") + }, + + success: function(data){ + console.log('success', data) + auth.user = auth.user || {} + auth.user.Name = this.last_data.Name + auth.user.Surname = this.last_data.Surname + auth.user.Email = this.last_data.Email + auth.user.BirthDay = this.last_data.BirthDay + app.account.logged_in(function(){ app.router.go("store") }) + }, + + error: function(data){ + try { + data = JSON.parse(data.responseText) + app.signup.show_errors([[ 'Name', data['Error']['Description'] ]]) + } + catch (e) { + app.signup.show_errors([[ 'Name', "There was an unknown error." ]]) + } + }, + + cancel: function(){ + auth.deferred_product = null + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/blogs/ArchiveView.js b/StoneIsland/platforms/android/assets/www/js/lib/blogs/ArchiveView.js new file mode 100755 index 00000000..254df6d1 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/blogs/ArchiveView.js @@ -0,0 +1,228 @@ +var ArchiveView = ScrollableView.extend({ + + el: "#archive", + menu_template: $("#archive .menu .template").html(), + row_template: $("#archive .scroll .template").html(), + + events: { + "click .item": "pick", + "mousedown .row": "mousedown", + "touchstart .row": "touchstart", + "mousemove .row": "mousemove", + "touchmove .row": "touchmove", + "mouseup .row": "mouseup", + "touchend .row": "touchend", + }, + + initialize: function(){ + this.$menu_items = this.$(".menu .items") + this.$content = this.$(".content") + this.$loader = this.$(".loader") + this.scroller = new IScroll('#archive .scroll', app.iscroll_options) + this.$subtitle = this.$('.subtitle') + this.subtitle_html = this.$subtitle.html() + + }, + + back: function(){ + this.$el.addClass("menu") + app.header.set_back(false) + this.$subtitle.html( this.subtitle_html ) + }, + + pick: function(e){ + this.$el.removeClass("menu") + app.header.set_back(true) + var index = $(e.currentTarget).data("index") + this.$subtitle.html( $(e.currentTarget).text() ) + this.populateDecade(index) + }, + + show: function(){ + this.deferScrollToTop() + app.footer.hide() + this.back() + document.body.className = "archive" + }, + + populate: function(data){ + if (this.loaded) { return } + this.loaded = true + this.data = data + this.$loader.hide() + this.$content.empty() + + // id title images[ uri label code caption ] + this.data.forEach(function(row, index){ + + var t = this.menu_template.replace(/{{title}}/, row.title) + var $t = $(t) + $t.data("title", row.title) + $t.data("index", index) + this.$menu_items.append($t) + }.bind(this)) + + this.back() + this.deferScrollToTop() + + this.populateDecade(0, 3) + }, + + populateDecade: function(index, count){ + this.$content.empty() + + var loader = new Loader() + + var row = this.data[index] + + count = count || row.images.length + + row.images.forEach(function(cell, i){ + var $t = $("<div>") + $t.addClass("row").addClass("loading") + var t = this.row_template.replace(/{{image}}/, cell.uri) + .replace(/{{label}}/, cell.label) + .replace(/{{code}}/, cell.code) + .replace(/{{caption}}/, cell.caption) + $t.html(t) + $t.data("flipped", false) + this.$content.append($t) + + var item = $t[0] + var aa = this.build_aa_item( item ) + aa.q = 0 + this.render( aa, 0 ) + aa.flipped = true + this.fix_z_index( aa ) + + var $text = $t.find(".text") + if ( ($text.height() % 2) == 1) { + $text.css("margin-bottom", "1px") + } + + loader.preloadImage(cell.uri, function(){ + aa.flipped = false + this.fix_z_index( aa ) + $t.removeClass('loading') + }.bind(this)) + }.bind(this)) + }, + +// ['transformProp'] = "translateZ(0) translateX(-50%) translateY(-50%) "; +// .image, .text + + touchstart: function(e){ + app.archive.row = e.currentTarget + app.archive.mousedown(e.originalEvent.touches[0]) + }, + touchmove: function(e){ + app.archive.mousemove(e.originalEvent.touches[0]) + }, + touchend: function(e){ + app.archive.mouseup() + }, + + row: null, + image: null, + text: null, + flipped: false, + q: 0, + + mousedown: function(e){ + var aa = app.archive.item = app.archive.build_aa_item( app.archive.row || e.currentTarget ) + aa.mouse_x = e.pageX + aa.mouse_y = e.pageY + }, + + build_aa_item: function(el){ + var aa = {} + aa.row = el + aa.flipped = $(aa.row).data('flipped') + aa.image = $(aa.row).find(".image")[0] + aa.text = $(aa.row).find(".text")[0] + aa.q = 0 + return aa + }, + + mousemove: function(e){ + if (! app.archive.item) return + aa = app.archive.item + var dx = ( aa.mouse_x - e.pageX ) / window.innerWidth + var dy = ( aa.mouse_y - e.pageY ) / window.innerWidth + + var gray, opacity, q + + dx = Math.abs(dx) + dx *= 2 + q = clamp( dx, 0, 1 ) + + this.render(aa, q) + + aa.q = q +/* + aa.row.style['transformProp'] = [ + "translateZ(0)", + "translateX(-50%)", + "translateY(-50%)", + "rotateY(" + dx + "deg)", + ].join(" ") +*/ + }, + + render: function(aa, q){ + if ( aa.flipped ) { + gray = Math.round( (1-q) * 100 ) + opacity = lerp(q, 0.2, 1) + text_opacity = lerp(q, 1, 0.3) +// console.log("<", gray, opacity) + } + else { + gray = Math.round( q * 100 ) + opacity = lerp(q, 1, 0.2) + text_opacity = lerp(q, 0.3, 1) +// console.log(">", gray, opacity) + } + aa.image.style.WebkitFilter = "grayscale(" + gray + "%)" + aa.image.style.opacity = opacity + aa.text.style.opacity = text_opacity + }, + + margin: 0.3, + + mouseup: function(e){ + aa = app.archive.item + app.archive.row = null + app.archive.item = null + var was_flipped = aa.flipped + var flipped = aa.flipped ? (aa.q < app.archive.margin) : (aa.q > app.archive.margin) + var dest = was_flipped == flipped ? 0 : 1 + $(aa.row).data('flipped', flipped) + + oktween.add({ + obj: {q: aa.q}, + to: {q: dest}, + duration: 200 * Math.abs(aa.q-dest), + update: function(o, dt){ + app.archive.render(aa, o.q) + }, + }) + + this.fix_z_index(aa) + }, + + fix_z_index: function (aa) { + if ( aa.flipped ) { + console.log(aa.q) + z = aa.q > app.archive.margin ? 2 : 1 + zz = aa.q > app.archive.margin ? 1 : 2 + } + else { + z = aa.q < app.archive.margin ? 2 : 1 + zz = aa.q < app.archive.margin ? 1 : 2 + } + aa.image.style.zIndex = z + aa.text.style.zIndex = zz + + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/blogs/BlogView.js b/StoneIsland/platforms/android/assets/www/js/lib/blogs/BlogView.js new file mode 100755 index 00000000..9b49abbd --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/blogs/BlogView.js @@ -0,0 +1,70 @@ +var BlogView = View.extend({ + + data: null, + loaded: false, + initialize: function(){ + this.loader = new Loader () + this.fetch() + }, + + fetch: function(){ + $.ajax({ + method: "GET", +// url: sdk.env == 'test' ? '/db.json' : "http://stone.sup.land/db.json", + url: "http://stone.sup.land/db.json", + success: this.success.bind(this), + cache: true, + }) + }, + + success: function(data){ + + if (this.loaded) return + + this.loaded = true + this.data = data = typeof data == "string" ? JSON.parse(data) : data + + app.archive.populate(data.archive) + this.loader.preloadImage(data.hub[0].image[0].uri, function(img){ + app.hub.populate(data.hub) + }) + this.loader.preloadImage(data.story[0].image.uri, function(img){ + app.story.populate(data.story) + }) + data.page.forEach(function(page){ + app[page.tag].populate(page) + + }) + app.collection.setCollectionName( data.store[0].collection ) + + app.closed.populate(data.store[0].ClosedStoreImages) + switch (data.store[0].StoreStatus) { + case "open": + app.closed.storeIsClosed = false + break + case "closed": + app.closed.storeIsClosed = true + app.closed.storeOpenDate = null + break + case "openson": + app.closed.storeIsClosed = true + app.closed.storeOpenDate = moment(data.store[0].OpensOn) + break + } + console.log(data.store[0].StoreStatus) + + var fits_large = (data.store[0].FitsLarge === "true") + app.product.$fit.toggle( fits_large ) + app.product.$sizing.toggle( fits_large ) + + if (data.store[0].BackgroundIsGray === "true") { + app.collection.$el.addClass("gray") + app.product.gallery.$el.addClass("gray") + } + + app.gallery_id = data.store[0].CollectionId + + app.collection.fetch() + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/blogs/HubView.js b/StoneIsland/platforms/android/assets/www/js/lib/blogs/HubView.js new file mode 100755 index 00000000..49c05ff6 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/blogs/HubView.js @@ -0,0 +1,113 @@ +var HubView = ScrollableView.extend({ + + el: "#hub", + template: $("#hub .template").html(), + + events: { + "click .share": "content-share", + "click .store": "store_link", + "click .gallery-left": "gallery_left", + "click .gallery-right": "gallery_right", + "click .play": "play_video", + }, + + initialize: function(){ + this.$content = this.$(".content") + this.$loader = this.$(".loader") + this.scroller = new IScroll('#hub', app.iscroll_options) + }, + + show: function(){ + this.deferScrollToTop() + app.footer.hide() + document.body.className = "hub" + }, + + galleries: {}, + populate: function(data){ + this.data = data + this.$loader.hide() + this.$content.empty() + this.galleries = {} + // id date subtitle body link store image[uri caption] + this.data.forEach(function(row){ + // console.log(row) + var t = this.template.replace(/{{id}}/g, row.id) + .replace(/{{date}}/, moment(row.date).format("MM.DD.YYYY")) + .replace(/{{title}}/, row.title) + .replace(/{{subtitle}}/, row.subtitle) + .replace(/{{link}}/, row.link) + .replace(/{{body}}/, row.body.replace(/\n/g, "<br>")) + var $t = $(t) + if (row.store != "true") { + $t.find(".store").remove() + } + this.$content.append($t) + + if (row.image.length > 1) { + // image gallery + var $gallery = $(".gallery-" + row.id) + row.image.forEach(function(img){ + var el = document.createElement("div") + el.style.backgroundImage = "url(" + img.uri + ")" + el.className = "item" + $gallery.append(el) + }) + this.galleries[row.id] = new Flickity( ".gallery-" + row.id, { + selector: '.item', + cellAlign: 'center', + autoPlay: false, + freeScroll: false, + wrapAround: true, + imagesLoaded: true, + prevNextButtons: false, + pageDots: false, + contain: true, + draggable: true, + }) + } + else { + // single image + var el = document.createElement("div") + el.style.backgroundImage = "url(" + row.image[0].uri + ")" + el.className = "item" + $(".gallery-" + row.id).append(el) + $(".gallery-" + row.id).data("row", row) + + // video, append play button + if (row.link.match(/youtube|youtu.be|vimeo/)) { + var play = document.createElement("div") + play.className = "play" + $(".gallery-" + row.id).append(play) + } + $t.find(".gallery-left").remove() + $t.find(".gallery-right").remove() + } + + }.bind(this)) + + this.deferScrollToTop() + }, + + store_link: function(){ + app.router.go("store") + }, + play_video: function(e){ + var row = $(e.currentTarget).closest('.gallery-video-post').data("row") + window.open(row.link, '_system') + }, + + gallery_left: function(e){ + var id = $(e.currentTarget).closest(".hub_item").data('id') + this.galleries[id].previous() + }, + gallery_right: function(e){ + var id = $(e.currentTarget).closest(".hub_item").data('id') + this.galleries[id].next() + }, + + share: function(){ + window.plugins.socialsharing.share( this.item['ModelNames'], null, null, "http://stoneisland.com/") + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/blogs/PageView.js b/StoneIsland/platforms/android/assets/www/js/lib/blogs/PageView.js new file mode 100755 index 00000000..4bf05430 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/blogs/PageView.js @@ -0,0 +1,24 @@ +var PageView = ScrollableView.extend({ + + events: { + }, + + initialize: function(opt){ + this.page = opt.page + this.setElement("#" + opt.page) + this.$content = this.$(".content") + this.$loader = this.$(".loader") + this.scroller = new IScroll('#' + this.page, app.iscroll_options) + }, + + show: function(){ + this.deferScrollToTop() + app.footer.hide() + document.body.className = this.page + }, + + populate: function(data){ + this.$content.html(data.body.replace(/\n/g, "<br>")) + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/blogs/StoryView.js b/StoneIsland/platforms/android/assets/www/js/lib/blogs/StoryView.js new file mode 100755 index 00000000..84684ff7 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/blogs/StoryView.js @@ -0,0 +1,65 @@ +var StoryView = ScrollableView.extend({ + + loaded: false, + + el: "#story", + template: $("#story .template").html(), + + events: { + "click .links li": "pick", + }, + + initialize: function(){ + this.sections = {} + this.$img = this.$("img") + this.$content = this.$(".content") + this.$links = this.$(".links") + this.$loader = this.$(".loader") + this.scroller = new IScroll('#story', app.iscroll_options) + }, + + show: function(){ + this.deferScrollToTop() + app.footer.hide() + document.body.className = "story" + }, + + populate: function(data){ + if (this.loaded) { console.warn("populate called twice"); return } + this.loaded = true + this.data = data + this.$loader.hide() + this.$content.empty() + // id title image[uri caption] body + this.data.forEach(function(row){ + var t = this.template.replace(/{{id}}/, row.id) + .replace(/{{body}}/, row.body.replace(/\n/g, "<br>")) + var li = document.createElement("li") + li.dataset.id = row.id + li.innerHTML = row.title + this.sections[row.id] = row + this.$links.append(li) + this.$content.append(t) + }.bind(this)) + + this.set_active( this.data[0].id ) + }, + + pick: function(e){ + var id = e.currentTarget.dataset.id + this.set_active(id) + }, + + set_active: function(id){ + this.$links.find(".active").removeClass("active") + this.$links.find("[data-id=" + id + "]").addClass("active") + + this.$content.find(".active").removeClass("active") + this.$content.find("[data-id=" + id + "]").addClass("active") + + var section = this.sections[id] + this.$img.attr("src", section.image.uri) + this.deferScrollToTop() + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartConfirm.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartConfirm.js new file mode 100755 index 00000000..f6c7f1f5 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartConfirm.js @@ -0,0 +1,174 @@ +var CartConfirm = FormView.extend({ + + el: "#cart_confirm", + + template: $("#cart_confirm .template").html(), + + events: { + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$rows = this.$(".rows") + this.$subtotal = this.$(".subtotal") + this.$shipping = this.$(".shipping") + this.$tax = this.$(".tax") + this.$total = this.$(".total") + + this.$shipping_address = this.$(".shipping_address") + this.$shipping_method = this.$(".shipping_method") + + this.$payment_name = this.$(".payment_name") + this.$payment_method = this.$(".payment_method") + this.$payment_address = this.$(".payment_address") + + this.scroller = new IScroll('#cart_confirm', app.iscroll_options) + }, + + show: function(){ + document.body.className = "cart" + app.cart.el.className = "confirm" + app.footer.show("PLACE ORDER", "CANCEL") + window.location.hash = "#/cart/confirm" + this.deferScrollToTop() + + app.curtain.show("loading") + promise(sdk.cart.get_status).then( this.populate.bind(this) ) + }, + + populate: function(data){ + console.log(data) + + data = data.Cart + + this.$rows.empty() + + data.Items.forEach(function(item){ + var $el = $("<div class='item'><img src='img/spinner.gif'></div>") + this.$rows.append($el) + var code_ten = item.Code10 + var size_id = item.Size + + var code = code_ten.substr(0, 8) + app.product.find(code, function(data, details){ + var descriptions = app.product.get_descriptions( details ) + + var name_partz = descriptions['ModelNames'].split(' ') + var num = name_partz.shift() + var title = name_partz.join(' ') + var type = title_case( descriptions['MicroCategory'] ) + + var color_name, size_name + + details.Item.ModelColors.some(function(color){ + if (color['Code10'] == code_ten) { + color_name = color['ColorDescription'] + return true + } + return false + }) + + details.Item.ModelSizes.some(function(size){ + if (size['SizeId'] == size_id) { + // console.log(size) + size_name = size['Default']['Text'] + size_name = SIZE_LOOKUP[ size_name ] || size_name + if (! size_name && ! size['Default']['Labeled']) { + size_name = size['Default']['Text'] + " " + size['Default']['ClassFamily'] + } + + return true + } + return false + }) + +// size_name = item.DefaultSize + " " + item.DefaultSizeClassFamily + + var t = this.template + .replace(/{{image}}/, sdk.image(item['Code10'], '11_f')) + .replace(/{{sku}}/, num) + .replace(/{{title}}/, title) + .replace(/{{type}}/, type) + .replace(/{{size}}/, size_name || "DEFAULT") + .replace(/{{color}}/, color_name || "DEFAULT") + .replace(/{{quantity}}/, 1) + .replace(/{{price}}/, as_cash(details.Item.Price.DiscountedPrice)) + $el.data("price", details.Item.Price.DiscountedPrice) + $el.html(t) + this.refreshScroller() + }.bind(this)) + }.bind(this)) + + var subtotal = data.Totals.TotalWithoutPromotions + var shipping_cost = data.DeliveryMethod.Selected.Amount.Total + var tax = data.Totals.TotalSalesTax + var total = data.Totals.TotalToPay + + this.$subtotal.html( as_cash(subtotal) ) + this.$shipping.html( as_cash(shipping_cost) ) + this.$tax.html( as_cash(tax) ) + this.$total.html( as_cash(total) ) + + var street = data.Receiver.StreetWithNumber.replace(/\n$/,"").replace("\n", ", ") + var address = data.Receiver.Name.toUpperCase() + " " + data.Receiver.Surname.toUpperCase() + "<br>" + street + ", " + address += data.Receiver.City + ", " + data.Receiver.Region + " " + data.Receiver.PostalCode + + this.$shipping_address.html(address) + this.$shipping_method.html(data.DeliveryMethod.Selected.Type == 1 ? "* STANDARD SHIPPING" : "* EXPRESS SHIPPING") + + var cc = data.Payment.CreditCard + var cc_street = cc.HolderAddress.replace(/\n$/,"").replace("\n", ", ") + var cc_type = cc.Type == "AmericanExpress" ? "American Express" : cc.Type + + this.$payment_name.html( cc.HolderName.toUpperCase() + " " + cc.HolderSurname.toUpperCase() ) + this.$payment_method.html( cc_type.toUpperCase() + " XXXX-XXXX-XXXX-" + cc.Last4 ) + + app.curtain.hide("loading") + }, + + save: function(){ + promise(sdk.cart.finalize, {}).then(function(){ + app.router.go('cart/thanks') + }.bind(this)).error(function(data){ + // {"Header":{"StatusCode":403,"Description":"403 Forbidden"},"Error":{"Description":"GenericApiError:CartAlreadyClosed"}} + // {"Header":{"StatusCode":409,"Description":"304 NotModified"},"Error":{"Description":"FinalizationError:\\"Item has been removed from cart because it is no longer available.\\"\\n235"}}' + // {"Header":{"StatusCode":409,"Description":"304 NotModified"},"Error":{"Description":"FinalizationError:\"The cart cannot be empty.\"\n233"}} + // {"Header":{"StatusCode":409,"Description":"304 NotModified"},"Error":{"Description":"FinalizationError:\"The reciever validation fails."}} + // {"Header":{"StatusCode":440,"Description":"304 NotModified"},"Error":{"Description":"GenericApiError:CartFinalizationNotYetCompleted"}} + // {"Header":{"StatusCode":441,"Description":"304 NotModified"},"Error":{"Description":"GenericApiError:EmptyCreditCard"}} + switch (data.StatusCode) { + case 403: // cart already closed + auth.clear_cart(auth.create_cart) + app.router.go('thanks') + break + case 409: // finalization error + this.finalization_error(data) + break + case 440: // genericapierror (credit card error!) + case 441: // genericapierror (credit card empty) + app.router.go('cart/payment') + app.cart.payment.show_errors([["Number","There was a problem with your credit card."]]) + break + } + }.bind(this)) + }, + + finalization_error: function(data){ + if (data['Error']['Description'].match(/receiver validation fails/)) { + app.router.go('cart/shipping') + app.cart.payment.show_errors([["Number","There was a problem with your credit card."]]) + } + else if (data['Error']['Description'].match(/cart cannot be empty/)) { + app.router.go('cart/summary') + } + else if (data['Error']['Description'].match(/Item has been removed/)) { + app.router.go('cart/error') + app.cart.error.show_error("We're sorry, but one or more items was out of stock. Please check your cart and try again.") + } + }, + + cancel: function(){ + app.router.go('cart/payment') + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartError.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartError.js new file mode 100755 index 00000000..f9a1963e --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartError.js @@ -0,0 +1,28 @@ +var CartError = View.extend({ + + el: "#cart_error", + + events: { + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$error = this.$(".errrrrrrrrrrrrrrr") + }, + + show: function(){ + document.body.className = "cart" + app.cart.el.className = "error" + app.footer.show("< BACK TO CART") + app.footer.hide() + }, + + show_error: function(msg){ + this.$error.html(msg) + }, + + ok: function(){ + app.router.go("cart/summary") + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartPayment.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartPayment.js new file mode 100755 index 00000000..f3c54d55 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartPayment.js @@ -0,0 +1,185 @@ +var CartPayment = FormView.extend({ + + el: "#cart_payment", + + address_template: $("#cart_payment .address_row_template").html(), + cc_template: $("#cart_payment .cc_template").html(), + + action: sdk.cart.set_credit_card, + + address_list_mode: false, + cc_list_mode: false, + data: {}, + + events: { + "change [name=SameAsShipping]": "toggle_shipping", + "click .address_dropdown": "toggle_address", + "click .cc_dropdown": "toggle_cc", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$form = this.$("form") + this.$msg = this.$(".msg") + this.$same_as_shipping = this.$("[name=SameAsShipping]") + this.$billing_address_rapper = this.$(".billing_address_rapper") + this.$address_list = this.$(".address_list") + this.$address_form = this.$(".address") + this.$address_dropdown = this.$(".address_dropdown") + this.$cc_list = this.$(".cc_list") + this.$cc_form = this.$(".cc") + this.$cc_dropdown = this.$(".cc_dropdown") + this.$cc_confirm = this.$(".cc_confirm") + + this.address = new AddressView ({ parent: this, checkPhone: false }) + this.cc = new CreditCardView ({ parent: this }) + this.scroller = new IScroll('#cart_payment', app.iscroll_options) + this.address.disabled = true + this.cc.disabled = true + }, + + show: function(){ + document.body.className = "cart" + app.cart.el.className = "payment" + app.footer.show("CONFIRM >", "CANCEL") + window.location.hash = "#/cart/payment" + + this.populate() + this.deferScrollToTop() + }, + + toggle_shipping: function(){ + setTimeout(function(){ + var state = this.$same_as_shipping.prop("checked") + this.$billing_address_rapper.toggle( ! state ) + this.address.disabled = state + }.bind(this)) + }, + + toggle_address: function(state){ + if (! app.account.ccs.length) { + state = false + } + // this.$address_dropdown.toggle( !! app.account.ccs.length ) + + this.address_list_mode = typeof state == "boolean" ? state : ! this.list_mode + this.address.disabled = this.address_list_mode + this.$address_form.toggle(! this.address_list_mode) + this.$address_list.toggle(this.address_list_mode) + }, + + toggle_cc: function(state){ + if (! app.account.ccs.length) { + state = false + } + // this.$cc_dropdown.toggle( !! app.account.ccs.length ) + + this.cc_list_mode = typeof state == "boolean" ? state : ! this.cc_list_mode + this.cc.disabled = this.cc_list_mode + this.$cc_form.toggle(! this.cc_list_mode) + this.$cc_list.toggle(this.cc_list_mode) + this.$cc_confirm.toggle(this.cc_list_mode) + }, + + populate: function(){ + this.$(".save_as_default").show() + this.$address_list.empty() + this.$cc_list.empty() + this.toggle_address( !! app.account.ccs.length ) + this.toggle_cc( !! app.account.ccs.length ) + + app.account.ccs.forEach(function(cc){ + var address_t = this.address_template.replace(/{{id}}/g, cc.Id) + .replace(/{{checked}}/g, cc.IsDefault ? "checked" : "") + .replace(/{{name}}/g, (cc.Name + " " + cc.Surname).toUpperCase()) + .replace(/{{address}}/g, cc.Address.replace(/\n$/,"").replace("\n", ", ")) + .replace(/{{city}}/g, cc.City) + .replace(/{{state}}/g, cc.Province) + .replace(/{{zip}}/g, cc.ZipCode) + + var cc_t = this.cc_template.replace(/{{id}}/g, cc.Id) + .replace(/{{checked}}/g, cc.IsDefault ? "checked" : "") + .replace(/{{number}}/g, cc['Number']) + .replace(/{{type}}/g, cc.Type.toUpperCase()) + .replace(/{{exp}}/g, cc.ExpirationMonth + "/" + cc.ExpirationYear) + + this.$address_list.append(address_t) + this.$cc_list.append(cc_t) + }.bind(this)) + }, + + finalize: function(data){ + var shipping_info = {}, address_data, address_id, cc_info = {}, cc_data, cc_id + var shipping_type = $("[name=ShippingType]").filter(function(){ return $(this).prop("checked") }).val() + + if (this.$same_as_shipping.prop("checked")) { + address_data = app.cart.shipping.data + } + else if (this.address_list_mode) { + address_id = this.$("[name=AddressId]").filter(function(){ return $(this).prop("checked") }).val() + address_data = app.account.addressLookup[ address_id ] + } + else { + address_data = data + } + + if (this.cc_list_mode) { + cc_id = this.$("[name=CCId]").filter(function(){ return $(this).prop("checked") }).val() + cc_data = app.account.ccLookup[ cc_id ] + + var card_on_file = { + "guid": cc_data.Guid, + "cvv": this.$("[name=CvvConfirm]"), + } + + app.curtain.show("loading") + promise(sdk.cart.use_stored_credit_card, { data: card_on_file }).then(function(data){ + app.curtain.hide("loading") + this.success() + }.bind(this)).error(function(data){ + app.curtain.hide("loading") + console.log(data) + }.bind(this)) + + return + } + else { + cc_data = data + } + + var credit_info = { + "HolderName": address_data.Name, + "HolderSurname": address_data.Surname, + "HolderAddress": address_data.Address || address_data.StreetWithNumber, + "HolderCity": address_data.City, + "HolderProvince": address_data.Province, + "HolderZip": address_data.PostalCode || address_data.ZipCode, + "HolderISOCountry": CANADIAN_LOOKUP[ address_data.Province ] ? "CA" : "US", + "HolderEmail": auth.user.Email, + "CardNumber": cc_data['Number'], + "Type": cc_data.Type, + "ExpirationMonth": cc_data.ExpirationMonth, + "ExpirationYear": cc_data.ExpirationYear.substr(2,3), + "Cvv": cc_data.Cvv, + } + + console.log( credit_info ) + + return credit_info + }, + + success: function(){ + app.router.go('cart/confirm') + }, + + error: function(data){ + console.log(data) + app.cart.payment.show_errors([["Number","There was a problem with your credit card."]]) + }, + + cancel: function(){ + app.router.go('cart/shipping') + }, + + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartShipping.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartShipping.js new file mode 100755 index 00000000..f17d42d2 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartShipping.js @@ -0,0 +1,136 @@ +var CartShipping = FormView.extend({ + + el: "#cart_shipping", + + action: sdk.cart.set_shipping_address, + + list_mode: true, + data: {}, + + template: $("#cart_shipping .template").html(), + + events: { + "click .dropdown-wrapper": "toggle_dropdown", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$form = this.$("form") + this.$dropdown_wrapper = this.$(".dropdown-wrapper") + this.$address_list = this.$(".address_list") + this.$address_form = this.$(".address") + this.$msg = this.$(".msg") + this.address = new AddressView ({ parent: this }) + this.scroller = new IScroll('#cart_shipping', app.iscroll_options) + this.address.disabled = true + }, + + show: function(){ + document.body.className = "cart" + app.cart.el.className = "shipping" + app.footer.show("PAYMENT >", "CANCEL") + window.location.hash = "#/cart/shipping" + this.populate() + this.deferScrollToTop() + }, + + populate: function(){ + // id checked name address city state zip + this.$(".save_as_default").show() + this.$address_list.empty() + if (! app.account.addresses.length) { + this.toggle_dropdown(false) + return + } + app.account.addresses.forEach(function(address){ + var t = this.template.replace(/{{id}}/g, address.Id) + .replace(/{{checked}}/g, address.IsDefault ? "checked" : "") + .replace(/{{name}}/g, (address.Name + " " + address.Surname).toUpperCase()) + .replace(/{{address}}/g, address.Address.replace(/\n$/,"").replace("\n", ", ")) + .replace(/{{city}}/g, address.City) + .replace(/{{state}}/g, address.Province) + .replace(/{{zip}}/g, address.ZipCode) + this.$address_list.append(t) + }.bind(this)) + }, + + load_form: function(cart_data){ + var data = cart_data.Cart.Receiver + var addy = data.StreetWithNumber.split("\n") + data.Address1 = addy[0] || "" + data.Address2 = addy[1] || "" + data.ZipCode = data.PostalCode + data.Province = data.Region + this.load_data(data) + + this.data = data + if (cart_data.Cart.DeliveryMethod && cart_data.Cart.DeliveryMethod.Selected && cart_data.Cart.DeliveryMethod.Type) { + $("#standard-shipping").prop("checked", cart_data.Cart.DeliveryMethod.Type == 1) + $("#express-shipping").prop("checked", cart_data.Cart.DeliveryMethod.Type == 2) + } + }, + + toggle_dropdown: function(state){ + if (! app.account.addresses.length) { + state = false + } + this.list_mode = typeof state == "boolean" ? state : ! this.list_mode + this.$dropdown_wrapper.toggle( !! app.account.addresses.length ) + this.address.disabled = this.list_mode + this.$address_form.toggle(! this.list_mode) + this.$address_list.toggle(this.list_mode) + }, + + // sdk.cart.set_shipping_address + // sdk.shipping.get_delivery_types + // sdk.shipping.set_delivery_type + + shipping_types: { + Standard: 1, + Express: 2, + }, + + finalize: function(data){ + var shipping_info = {}, address_data, address_id + var shipping_type = $("[name=ShippingType]").filter(function(){ return $(this).prop("checked") }).val() + + sdk.shipping.set_delivery_type({ + id: this.shipping_types[shipping_type], + success: function(data){ console.log("set shipping type", data) }, + error: function(data){ console.log("didnt set shipping type", data) }, + }) + + if (this.list_mode) { + address_id = this.$("[name=AddressId]").filter(function(){ return $(this).prop("checked") }).val() + address_data = app.account.addressLookup[ address_id ] + } + else { + address_data = data + } + + shipping_info.Name = address_data.Name + shipping_info.Surname = address_data.Surname + shipping_info.Email = auth.user.Email + shipping_info.Phone = address_data.Phone + shipping_info.Mobile = address_data.Phone + shipping_info.StreetWithNumber = address_data.Address + shipping_info.PostalCode = address_data.ZipCode + shipping_info.City = address_data.City + shipping_info.Province = address_data.Province + shipping_info.Region = address_data.Province + shipping_info.CountryCode = CANADIAN_LOOKUP[ address_data.Province ] ? "CA" : "US" + + this.data = shipping_info + + return shipping_info + }, + + success: function(){ + app.router.go('cart/payment') + }, + + cancel: function(){ + app.router.go('cart/summary') + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartSummary.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartSummary.js new file mode 100755 index 00000000..ff1e001f --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartSummary.js @@ -0,0 +1,202 @@ +var CartSummary = ScrollableView.extend({ + + el: "#cart_summary", + + template: $("#cart_summary .template").html(), + + events: { + "click .remove": "remove_item", + }, + + data: null, + + initialize: function(opt){ + this.parent = opt.parent + this.$loader = this.$(".loader") + this.$cart_body = this.$(".cart_body") + this.$cart_empty = this.$(".cart_empty") + this.scroller = new IScroll('#cart_summary', app.iscroll_options) + + this.$rows = this.$(".rows") + this.$subtotal = this.$(".subtotal") + this.$shipping = this.$(".shipping") + this.$tax = this.$(".tax") + this.$total = this.$(".total") + }, + + show: function(){ + document.body.className = "cart" + app.cart.el.className = "summary" + window.location.hash = "#/cart/summary" + if (auth.has_cart()) { + this.load() + } + else { + this.empty() + } + }, + + load: function(){ + this.el.className = "loading" + app.footer.show("SHIPPING >", "CANCEL") + app.curtain.show("loading") + sdk.cart.get_status({ + success: this.populate.bind(this), + error: this.empty.bind(this), + }) + }, + + populate: function(data){ + this.data = data + + console.log("CART", data) + + if (! data.Cart.Items || data.Cart.Items.length == 0) { + return this.empty() + } + + this.parent.$steps.show() + this.updateCounts() + + this.$rows.empty() + + data.Cart.Items.forEach(function(item){ + var code_ten = item['Code10'] + var code = code_ten.substr(0, 8) + var size_id = item['Size'] + + var $el = $("<div>").addClass("cart_item_row") + $el.html("<img src='img/spinner.gif'>") + $el.data({ + code: code_ten, + size: size_id, + }) + this.$rows.append($el) + app.product.find(code, function(data, details){ + // console.log(data, details) + + var descriptions = app.product.get_descriptions( details ) + // console.log(descriptions) + + var name_partz = descriptions['ModelNames'].split(' ') + var num = name_partz.shift() + var title = name_partz.join(' ') + var type = title_case( descriptions['MicroCategory'] ) + + var color_name, size_name + // console.log(code) + details.Item.ModelColors.some(function(color){ + if (color['Code10'] == code_ten) { + color_name = color['ColorDescription'] + // console.log(color) + return true + } + return false + }) + details.Item.ModelSizes.some(function(size){ + if (size['SizeId'] == size_id) { + // console.log(size) + size_name = size['Default']['Text'] + size_name = SIZE_LOOKUP[ size_name ] || size_name + if (! size_name && ! size['Default']['Labeled']) { + size_name = size['Default']['Text'] + " " + size['Default']['ClassFamily'] + } + + return true + } + return false + }) + + var t = this.template + .replace(/{{image}}/, sdk.image(item['Code10'], '11_f')) + .replace(/{{sku}}/, num) + .replace(/{{title}}/, title) + .replace(/{{type}}/, type) + .replace(/{{size}}/, size_name) + .replace(/{{color}}/, color_name) + .replace(/{{quantity}}/, 1) + .replace(/{{price}}/, as_cash(details.Item.Price.DiscountedPrice)) + $el.html(t) + this.refreshScroller() + }.bind(this)) + }.bind(this)) + + if (data.Cart.Receiver && data.Cart.Receiver.City) { + app.cart.shipping.load_form( data ) + } + + this.updateTotals() + + this.el.className = "full" + this.refreshScroller() + app.curtain.hide("loading") + }, + + updateCounts: function(){ + app.header.set_cart_count( this.data.Cart.Items.length ) + this.parent.setHeaderCount( this.data.Cart.Items.length ) + }, + + updateTotals: function(){ + var subtotal = this.data.Cart.Totals.TotalWithoutPromotions + var shipping_cost = this.data.Cart.DeliveryMethod.Selected.Amount.Total + var tax = this.data.Cart.Totals.TotalSalesTax + var total = this.data.Cart.Totals.TotalToPay + + this.$subtotal.html( as_cash(subtotal) ) + this.$shipping.html( as_cash(shipping_cost) ) + this.$tax.html( as_cash(tax) ) + this.$total.html( as_cash(total) ) + }, + + empty: function(){ + app.footer.hide() + app.header.set_cart_count(0) + this.parent.setHeaderCount( 0 ) + this.parent.$itemcount.html("0 ITEMS") + this.el.className = "empty" + this.parent.$steps.hide() + }, + + save: function(){ + app.router.go('cart/shipping') + }, + + cancel: function(){ + app.router.go('intro') + }, + + remove_item: function(e){ + var $el = $( e.currentTarget ).closest(".cart_item_row") + var data = $el.data() + + console.log(this.data.Cart) + + this.data.Cart.Totals.TotalWithoutPromotions -= data.price + this.data.Cart.Totals.TotalToPay -= data.price + this.data.Cart.Items = this.data.Cart.Items.filter(function(item){ + return ( item['Code10'] !== data.code || item['Size'] !== data.size) + }) + + this.updateTotals() + this.updateCounts() + $el.remove() + this.refreshScroller() + + if (this.data.Cart.Items.length == 0) { + this.empty() + } + + app.curtain.show("loading") + sdk.cart.delete_item({ + data: { + Code10: data.code, + Size: data.size, + }, + success: function(){ + app.curtain.hide("loading") + }, + }) + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartThanks.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartThanks.js new file mode 100755 index 00000000..eb95197b --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartThanks.js @@ -0,0 +1,25 @@ +var CartThanks = View.extend({ + + el: "#cart_thanks", + + events: { + }, + + initialize: function(opt){ + this.parent = opt.parent + }, + + show: function(){ + document.body.className = "cart" + app.cart.el.className = "thanks" + app.footer.show("< BACK TO COLLECTION") + app.footer.hide() + + app.orders.loaded = false + }, + + ok: function(){ + app.router.go("store") + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/cart/CartView.js b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartView.js new file mode 100755 index 00000000..1b08e418 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/cart/CartView.js @@ -0,0 +1,66 @@ +var CartView = View.extend({ + + el: "#cart", + + events: { + "click .summary_step": "show_summary", + "click .shipping_step": "show_shipping", + "click .payment_step": "show_payment", + }, + + initialize: function(){ + this.summary = new CartSummary ({ parent: this }) + this.payment = new CartPayment ({ parent: this }) + this.shipping = new CartShipping ({ parent: this }) + this.confirm = new CartConfirm ({ parent: this }) + this.thanks = new CartThanks ({ parent: this }) + this.error = new CartError ({ parent: this }) + + this.$steps = this.$(".steps") + this.$full_msg = this.$(".full_msg") + this.$empty_msg = this.$(".empty_msg") + this.$itemcount = this.$(".itemcount") + }, + + load: function(){ + sdk.cart.get_status({ + success: function(data){ + this.summary.data = data + this.summary.updateCounts() + }.bind(this), + error: function(data){ + console.log(data) + }, + }) + }, + + show: function(){ + document.body.className = "cart" + this.show_summary() + }, + + show_summary: function(){ + this.summary.show() + }, + + show_shipping: function(){ + this.shipping.show() + }, + + show_payment: function(){ + this.payment.show() + }, + + setHeaderCount: function(n){ + if (n) { + this.$itemcount.html(pluralize(n, "ITEM", "S")) + this.$full_msg.show() + this.$empty_msg.hide() + } + else { + this.$full_msg.hide() + this.$empty_msg.show() + } + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/etc/deeplink.js b/StoneIsland/platforms/android/assets/www/js/lib/etc/deeplink.js new file mode 100755 index 00000000..648dd167 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/etc/deeplink.js @@ -0,0 +1,3 @@ +function handleOpenURL (url) { + app.router.initial_route = url +}
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/etc/geo.js b/StoneIsland/platforms/android/assets/www/js/lib/etc/geo.js new file mode 100755 index 00000000..fac34c1e --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/etc/geo.js @@ -0,0 +1,39 @@ +var geo = (function(){ + var geo = {} + + geo.fetch = function(){ + navigator.geolocation.getCurrentPosition(geo.success, geo.error, {timeout: 15000}) + } + + geo.success = function(position){ + var lat_str = as_degrees( position.coords.latitude || 40.99167 ) + var lng_str = as_degrees( position.coords.longitude || -74.07944 ) + $(".latlng").html( lat_str + " " + lng_str ) + } + + geo.error = function(error){ + $(".latlng").html( "+40° 58' 90\" -74° 04' 46\"" ) + } + + function as_degrees (n) { + var s = "" + if (n >= 0) s += "+" + s += Math.floor(n) + "° " + + n = Math.abs(n) + n %= 1 + n *= 60 + nn = Math.floor(n) + if (nn < 10) nn = "0" + nn + s += nn + "' " + + n %= 1 + n *= 60 + nn = Math.floor(n) + if (nn < 10) nn = "0" + nn + s += nn + '"' + return s + } + + return geo +})()
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/etc/push.js b/StoneIsland/platforms/android/assets/www/js/lib/etc/push.js new file mode 100755 index 00000000..ab0c0141 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/etc/push.js @@ -0,0 +1 @@ +//
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/AddressView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/AddressView.js new file mode 100755 index 00000000..ad5745fb --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/AddressView.js @@ -0,0 +1,267 @@ + +var AddressView = SerializableView.extend({ + + template: $("#address_template").html(), + + disabled: false, + + events: { + "change [name=Province]": 'update_country', + }, + + initialize: function(opt){ + this.parent = opt.parent + this.checkPhone = 'checkPhone' in opt ? opt.checkPhone : true + this.setElement( this.parent.$(".address") ) + this.$el.html(this.template) + }, + + populate: function(data){ + this.data = data + var address = data.Address.split("\n") + data.Address1 = address[0] + data.Address2 = address[1] + this.$(".address input").val("") + this.load_data(data) + this.update_country() + }, + + validate_presence: { + "Name": "Please enter your first name.", + "Surname": "Please enter your last name.", + "Address1": "Please enter your street address.", + "City": "Please enter your city.", + "ZipCode": "Please enter your zip code.", + }, + + validate_fields: function(data, errors){ + if (this.disabled) { return } + if (this.checkPhone && ! data.Phone) { errors.push([ "Phone", "Please enter your phone number." ]) } + if (this.checkPhone && data.Phone && data.Phone.replace(/[^0-9]/g, "").length < 10) { errors.push([ "Phone", "Phone numbers must be at least 10 digits." ]) } + if (! data.Province || data.Province == "NONE") { errors.push([ "Province", "Please choose your state." ]) } + data.Address = data.Address1 + "\n" + data.Address2 + data.UserId = auth.user_id + delete data.Address1 + delete data.Address2 + }, + + update_country: function(){ + var state = this.$("[name=Province]").val() + console.log(state) + if (CANADIAN_LOOKUP[state]) { + this.$(".country-label").html("CANADA") + } + else { + this.$(".country-label").html("UNITED STATES") + } + }, + +}) + +var CANADIAN_PROVINCES = "AB BC MB NB NL NS NT NU ON PE SK QC YT".split(" ") +var CANADIAN_LOOKUP = {} +CANADIAN_PROVINCES.forEach(function(k){ CANADIAN_LOOKUP[k] = true }) + +var COUNTRIES = [ + ['Country Name', 'NONE'], + ['United States', 'US'], + ['Abkhazia', 'GE'], + ['Afghanistan', 'AF'], + ['Albania', 'AL'], + ['Algeria', 'DZ'], + ['Andorra', 'AD'], + ['Angola', 'AO'], + ['Antigua and Barbuda', 'AG'], + ['Argentina', 'AR'], + ['Armenia', 'AM'], + ['Australia', 'AU'], + ['Austria', 'AT'], + ['Azerbaijan', 'AZ'], + ['Bahamas', 'BS'], + ['Bahrain', 'BH'], + ['Bangladesh', 'BD'], + ['Barbados', 'BB'], + ['Belarus', 'BY'], + ['Belgium', 'BE'], + ['Belize', 'BZ'], + ['Benin', 'BJ'], + ['Bhutan', 'BT'], + ['Bolivia', 'BO'], + ['Bosnia and Herzegovina', 'BA'], + ['Botswana', 'BW'], + ['Brazil', 'BR'], + ['Brunei', 'BN'], + ['Bulgaria', 'BG'], + ['Burkina Faso', 'BF'], + ['Burundi', 'BI'], + ['Cambodia', 'KH'], + ['Cameroon', 'CM'], + ['Canada', 'CA'], + ['Cape Verde', 'CV'], + ['Central African Republic', 'CF'], + ['Chad', 'TD'], + ['Chile', 'CL'], + ['China', 'CN'], + ['Colombia', 'CO'], + ['Comoros', 'KM'], + ['Congo', 'CD'], + ['Congo-Brazzaville', 'CG'], + ['Costa Rica', 'CR'], + ['Cote d\'Ivoire (Ivory Coast)', 'CI'], + ['Croatia', 'HR'], + ['Cuba', 'CU'], + ['Cyprus', 'CY'], + ['Czech Republic', 'CZ'], + ['Denmark', 'DK'], + ['Djibouti', 'DJ'], + ['Dominica', 'DM'], + ['Dominican Republic', 'DO'], + ['Ecuador', 'EC'], + ['Egypt', 'EG'], + ['El Salvador', 'SV'], + ['Equatorial Guinea', 'GQ'], + ['Eritrea', 'ER'], + ['Estonia', 'EE'], + ['Ethiopia', 'ET'], + ['Fiji', 'FJ'], + ['Finland', 'FI'], + ['France', 'FR'], + ['Gabon', 'GA'], + ['Gambia', '220'], + ['Georgia', 'GE'], + ['Germany', 'DE'], + ['Ghana', 'GH'], + ['Greece', 'GR'], + ['Grenada', 'GD'], + ['Guatemala', 'GT'], + ['Guinea', 'GN'], + ['Guinea-Bissau', 'GW'], + ['Guyana', 'GY'], + ['Haiti', 'HT'], + ['Honduras', 'HN'], + ['Hungary', 'HU'], + ['Iceland', 'IS'], + ['India', 'IN'], + ['Indonesia', 'ID'], + ['Iran', 'IR'], + ['Iraq', 'IQ'], + ['Ireland', 'IE'], + ['Israel', 'IL'], + ['Italy', 'IT'], + ['Jamaica', 'JM'], + ['Japan', 'JP'], + ['Jordan', 'JO'], + ['Kazakhstan', 'KZ'], + ['Kenya', 'KE'], + ['Kiribati', 'KI'], + ['Kuwait', 'KW'], + ['Kyrgyzstan', 'KG'], + ['Laos', 'LA'], + ['Latvia', 'LV'], + ['Lebanon', 'LB'], + ['Lesotho', 'LS'], + ['Liberia', 'LR'], + ['Libya', 'LY'], + ['Liechtenstein', 'LI'], + ['Lithuania', 'LT'], + ['Luxembourg', 'LU'], + ['Macedonia', 'MK'], + ['Madagascar', 'MG'], + ['Malawi', 'MW'], + ['Malaysia', 'MY'], + ['Maldives', 'MV'], + ['Mali', 'ML'], + ['Malta', 'MT'], + ['Marshall Islands', 'MH'], + ['Mauritania', 'MR'], + ['Mauritius', 'MU'], + ['Mexico', 'MX'], + ['Micronesia', 'FM'], + ['Moldova', 'MD'], + ['Monaco', 'MC'], + ['Mongolia', 'MN'], + ['Montenegro', 'ME'], + ['Morocco', 'MA'], + ['Mozambique', 'MZ'], + ['Myanmar', 'MM'], + ['Nagorno-Karabakh', 'AZ'], + ['Namibia', 'NA'], + ['Nauru', 'NR'], + ['Nepal', 'NP'], + ['Netherlands', 'NL'], + ['New Zealand', 'NZ'], + ['Nicaragua', 'NI'], + ['Niger', 'NE'], + ['Nigeria', 'NG'], + ['North Korea', 'KP'], + ['Northern Cyprus', 'CY'], + ['Norway', 'NO'], + ['Oman', 'OM'], + ['Pakistan', 'PK'], + ['Palau', 'PW'], + ['Panama', 'PA'], + ['Papua New Guinea', 'PG'], + ['Paraguay', 'PY'], + ['Peru', 'PE'], + ['Philippines', 'PH'], + ['Poland', 'PL'], + ['Portugal', 'PT'], + ['Qatar', 'QA'], + ['Romania', 'RO'], + ['Russia', 'RU'], + ['Rwanda', 'RW'], + ['Saint Kitts and Nevis', 'KN'], + ['Saint Lucia', 'LC'], + ['Saint Vincent and the Grenadines', 'VC'], + ['Samoa', 'WS'], + ['San Marino', 'SM'], + ['Sao Tome and Principe', 'ST'], + ['Saudi Arabia', 'SA'], + ['Senegal', 'SN'], + ['Serbia', 'RS'], + ['Seychelles', 'SC'], + ['Sierra Leone', 'SL'], + ['Singapore', 'SG'], + ['Slovakia', 'SK'], + ['Slovenia', 'SI'], + ['Solomon Islands', 'SB'], + ['Somalia', 'SO'], + ['Somaliland', 'SO'], + ['South Africa', 'Rand'], + ['South Korea', 'KR'], + ['South Ossetia', 'GE'], + ['Spain', 'ES'], + ['Sri Lanka', 'LK'], + ['Sudan', 'SD'], + ['Suriname', 'SR'], + ['Swaziland', 'SZ'], + ['Sweden', 'SE'], + ['Switzerland', 'CH'], + ['Syria', 'SY'], + ['Taiwan', 'TW'], + ['Tajikistan', 'TJ'], + ['Tanzania', 'TZ'], + ['Thailand', 'TH'], + ['Timor-Leste', 'TL'], + ['Togo', 'TG'], + ['Tonga', 'TO'], + ['Transnistria', 'MD'], + ['Trinidad and Tobago', 'TT'], + ['Tunisia', 'TN'], + ['Turkey', 'TR'], + ['Turkmenistan', 'TM'], + ['Tuvalu', 'TV'], + ['Uganda', 'UG'], + ['Ukraine', 'UA'], + ['United Arab Emirates', 'AE'], + ['United Kingdom', 'GB'], + ['Uruguay', 'UY'], + ['Uzbekistan', 'UZ'], + ['Vanuatu', 'VU'], + ['Vatican City', 'VA'], + ['Venezuela', 'VE'], + ['Vietnam', 'VN'], + ['Yemen', 'YE'], + ['Zambia', 'ZM'], + ['Zimbabwe', 'ZW'], +] diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/CreditCardView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/CreditCardView.js new file mode 100755 index 00000000..63784618 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/CreditCardView.js @@ -0,0 +1,61 @@ + +var CreditCardView = SerializableView.extend({ + + template: $("#creditcard_template").html(), + + cardOptions: { + accept: ['visa', 'mastercard', 'amex', 'jcb'], + }, + + events: { + }, + + initialize: function(opt){ + this.parent = opt.parent + this.setElement( this.parent.$(".cc") ) + this.$el.html(this.template) + + this.$number = this.$("[name=Number]") + this.$number.validateCreditCard(this.updateCard.bind(this), this.cardOptions) + }, + + populate: function(data){ + this.data = data + data.Number = "XXXX XXXX XXXX " + data.Number + this.$number.attr("type", "text") + this.parent.$(".cc input").val("") + this.$(".cc input").val("") + this.load_data(data) + }, + + updateCard: function(card){ + // console.log(card) + // card.card_type.name + // card.card_type.valid + }, + + validate_presence: { + 'Number': 'Please enter your credit card number.', + 'Cvv': 'Please enter your security code.', + }, + + validate_fields: function(data, errors){ + if (this.disabled) { return } + var card = this.$number.validateCreditCard(this.cardOptions) + if (! card.valid) { errors.push([ "Number", "Your card number is invalid." ]) } + if (! data.ExpirationMonth || data.ExpirationMonth == "NONE") { errors.push([ "ExpirationMonth", "Please enter the expiration month." ]) } + if (! data.ExpirationYear || data.ExpirationYear == "NONE") { errors.push([ "ExpirationYear", "Please select the expiration month." ]) } + data.UserId = auth.user_id + if (card.valid) { + data.Type = YOOX_CREDIT_CARD_NAME_LOOKUP[ card.card_type.name ] + } + }, + +}) + +var YOOX_CREDIT_CARD_NAME_LOOKUP = { + "visa": "Visa", + "mastercard": "Mastercard", + "amex": "AmericanExpress", + "jcb": "JCB", +} diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/CurtainView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/CurtainView.js new file mode 100755 index 00000000..d444fd60 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/CurtainView.js @@ -0,0 +1,39 @@ +var CurtainView = View.extend({ + + el: "#curtain", + + events: { + "click": "click", + }, + + initialize: function(){ + }, + + klass: null, + show: function(klass){ + this.$el.addClass("visible") + if (klass) { + this.klass = klass + this.$el.addClass(klass) + } + }, + + hide: function(k){ + this.$el.removeClass("visible") + if (this.klass) { + setTimeout( function(){ + this.$el.removeClass(this.klass) + }.bind(this), 200 ) + } + }, + + click: function(){ + if (document.body.classList.contains("nav")) { + app.nav.hide() + } + if (app.selector.visible) { + app.selector.hide() + } + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/FooterView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/FooterView.js new file mode 100755 index 00000000..74b249e6 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/FooterView.js @@ -0,0 +1,40 @@ +var FooterView = View.extend({ + + el: "#footer", + + events: { + "click .ok": "ok", + "click .cancel": "cancel", + }, + + initialize: function(){ + this.$ok = this.$(".ok") + this.$cancel = this.$(".cancel") + }, + + show: function(ok, cancel){ + if (cancel) { + this.$ok.removeClass("wide") + this.$cancel.show().html(cancel) + } + else { + this.$ok.addClass("wide") + this.$cancel.hide() + } + this.$ok.html(ok) + this.$el.show() + }, + + hide: function(){ + this.$el.hide() + }, + + ok: function(){ + (app.view.save || app.view.ok).bind(app.view)() + }, + + cancel: function(){ + app.view.cancel ? app.view.cancel() : app.intro.show() + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/HeaderView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/HeaderView.js new file mode 100755 index 00000000..b2f01208 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/HeaderView.js @@ -0,0 +1,57 @@ +var HeaderView = View.extend({ + + el: "#header", + + events: { + "click .burger": "nav", + "click .logo": "logo", + "click .cart": "cart", + }, + + initialize: function(){ + this.$burger = this.$(".burger") + this.$cart = this.$(".cart") + this.$cart_count = this.$(".cart_count") + }, + + back_state: false, + set_back: function(state){ + this.back_state = state + if (state) { + this.$burger[0].className = "burger ion-ios-arrow-left" + } + else { + this.$burger[0].className = "burger ion-android-menu" + } + }, + + nav: function(){ + if (this.back_state) { + app.view.back() + } + else { + app.nav.show() + } + }, + + logo: function(){ + app.router.go("intro") + }, + + cart: function(){ + app.router.go("cart") + }, + + count: 0, + set_cart_count: function(n){ + this.count = n + this.$cart_count.html(n || " ") + }, + increment_cart_count: function(){ + this.$cart_count.html( ++this.count ) + }, + decrement_cart_count: function(){ + this.$cart_count.html( --this.count ) + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/IntroView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/IntroView.js new file mode 100755 index 00000000..2d8dca43 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/IntroView.js @@ -0,0 +1,46 @@ +var IntroView = View.extend({ + + el: "#intro", + + events: { + "click .store": "store", + "click .hub": "hub", + "click .story": "story", + "click .archive": "archive", + }, + + initialize: function(){ + this.compass = this.$("#compass").get(0) + this.orient = this.deviceorientation.bind(this) + }, + + show: function(){ + document.body.className = "intro" + window.addEventListener("deviceorientation", this.orient) + app.footer.hide() + this.orient({ alpha: 0 }) + // get location.. + }, + + hide: function(){ + window.removeEventListener("deviceorientation", this.orient) + }, + + deviceorientation: function(e){ + var heading + if ('webkitCompassHeading' in e) { + heading = e.webkitCompassHeading || 0 + } + else { + heading = e.alpha || 0 + } + heading = - heading + this.compass.style[transformProp] = "translateZ(0) translateX(-50%) translateY(-50%) rotate(" + heading + "deg)" + }, + + store: function(){ app.router.go("store") }, + hub: function(){ app.router.go("hub") }, + story: function(){ app.router.go("story") }, + archive: function(){ app.router.go("archive") }, + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/NavView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/NavView.js new file mode 100755 index 00000000..704aaa34 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/NavView.js @@ -0,0 +1,157 @@ +var NavView = View.extend({ + + el: "#nav", + + events: { + "click .logo": "intro", + + "click .store": "store", + "click .hub": "hub", + "click .story": "story", + "click .archive": "archive", + + "click .login": "login", + "click .logout": "logout", + "click .account": "account", + "click .faq": "faq", + "click .search": "search", + + "click .main": "back", + "click .account_back": "back", + "click .profile": "profile", + "click .payment": "payment", + "click .shipping": "shipping", + "click .settings": "settings", + "click .orders": "orders", + "click .return_link": "return_link", + + "click .faq_back": "back", + "click .privacy": "privacy", + "click .returns": "returns", + "click .terms": "terms", + "click .care": "care", + + "click .fb": "fb", + "click .insta": "insta", + "click .tw": "tw", + }, + + initialize: function(){ + }, + + show: function(klass){ + $("body").addClass("nav") + app.curtain.show("dark") + if (klass) { + setTimeout(function(){ + this.addClass(klass) + }.bind(this), 500) + } + }, + + hide: function(){ + $("body").removeClass("nav") + app.curtain.hide("dark") + }, + + intro: function(){ + this.hide() + app.router.go("intro") + }, + store: function(){ + this.hide() + app.router.go("store") + }, + hub: function(){ + this.hide() + app.router.go("hub") + }, + story: function(){ + this.hide() + app.router.go("story") + }, + archive: function(){ + this.hide() + app.router.go("archive") + }, + + login: function(){ + this.hide() + auth.last_view = app.view + app.router.go("account/login") + }, + logout: function(){ + this.hide() + auth.last_view = app.view + app.router.go("account/logout") + }, + account: function(){ + this.el.className = "account" + }, + + back: function(){ + this.el.className = "" + }, + + profile: function(){ + this.hide() + app.router.go("account/profile") + }, + payment: function(){ + this.hide() + app.router.go("account/payment") + }, + shipping: function(){ + this.hide() + app.router.go("account/shipping") + }, + orders: function(){ + this.hide() + app.router.go("account/orders") + }, + settings: function(){ + this.hide() + app.router.go("account/settings") + }, + return_link: function(){ + window.open("http://www.stoneisland.com/", '_system') + }, + + + faq: function(){ + this.el.className = "faq" + }, + privacy: function(){ + this.hide() + app.router.go("page/privacy") + }, + returns: function(){ + this.hide() + app.router.go("page/returns") + }, + terms: function(){ + this.hide() + app.router.go("page/terms") + }, + care: function(){ + window.open("http://www.stoneisland.com/localize.asp?tskay=4036416C&page=help/return&deviceYeti=smartphone", '_system') + }, + + + search: function(){ + this.hide() + app.router.go("search") + }, + + + fb: function(){ + window.open("https://www.facebook.com/StoneIsland", '_system') + }, + insta: function(){ + window.open("https://instagram.com/stoneisland_official", '_system') + }, + tw: function(){ + window.open("https://twitter.com/stoneisland", '_system') + }, + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/nav/SearchView.js b/StoneIsland/platforms/android/assets/www/js/lib/nav/SearchView.js new file mode 100755 index 00000000..f21634a5 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/nav/SearchView.js @@ -0,0 +1,16 @@ +var SearchView = View.extend({ + + el: "#search", + + events: { + }, + + show: function(){ + app.footer.show("SEARCH", "CANCEL") + document.body.className = "search" + }, + + save: function(){ + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/products/ClosedStoreView.js b/StoneIsland/platforms/android/assets/www/js/lib/products/ClosedStoreView.js new file mode 100755 index 00000000..5f8c1e84 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/products/ClosedStoreView.js @@ -0,0 +1,56 @@ +var ClosedStoreView = View.extend({ + + el: "#closed", + + storeIsClosed: false, + + events: { + "click .website_link": "website_link", + }, + + delay: 8000, + + timeout: -1, + images: null, + + initialize: function(){ + this.loader = new Loader () + }, + + show: function(){ + document.body.className = "closed" + this.animate() + app.footer.hide() + console.log(this) + if (this.storeOpenDate) { + var date = moment(this.storeOpenDate).format("MM/DD") + console.log(date) + $(".closed_store_msg h3").html("THIS STORE WILL OPEN ON " + date) + } + else { + $(".closed_store_msg h3").html("THIS STORE IS CURRENTLY CLOSED") + } + }, + + hide: function(){ + clearTimeout(this.timeout) + }, + + animate: function(){ + this.timeout = setTimeout(this.animate.bind(this), this.delay) + if (! this.images) return + var url = choice(this.images) + this.loader.preloadImage(url, function(img){ + this.el.style.backgroundImage = 'url(' + img.src + ')' + }.bind(this)) + }, + + populate: function(data){ + this.images = data.map(function(img){ return img.uri }) + }, + + website_link: function(){ + window.open("http://www.stoneisland.com/", '_system') + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/products/CollectionView.js b/StoneIsland/platforms/android/assets/www/js/lib/products/CollectionView.js new file mode 100755 index 00000000..d4315514 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/products/CollectionView.js @@ -0,0 +1,114 @@ + +var CollectionView = ScrollableView.extend({ + + el: "#collection", + template: $("#collection .template").html(), + loaded: false, + data: null, + items: {}, + + events: { + "touchstart .item": "touchstart", + "touchmove .item": "touchmove", + "touchend .item": "touchend", + "mousedown .item": "touchstart", + "mousemove .item": "touchmove", + "mouseup .item": "touchend", + }, + + initialize: function(){ + this.$title = this.$("h1") + this.$content = this.$(".content") + this.$loader = this.$(".loader") + this.scroller = new IScroll('#collection', app.iscroll_options) + this.filterView = new CategoryFilter ({ parent: this }) + }, + + show: function(){ + if (app.closed.storeIsClosed) { + // (! this.storeOpenDate || moment().diff(this.storeOpenDate) > 0 ) ) { + return app.closed.show() + } + app.footer.show("FILTER") + document.body.className = "collection" + if (this.loaded) { + return this.populate(this.data) + } + // this.fetch() + }, + + save: function(){ + this.filterView.filter() + }, + + fetch: function(){ + if (this.loaded) return + this.$loader.show() + sdk.product.collection({ + gallery_id: app.gallery_id, + success: this.populate.bind(this) + }) + }, + + populate: function(data){ + if (this.loaded && ! data) { + data = this.data + } + else { + this.data = data + } + if (! this.loaded) { + this.loaded = true + this.$loader.hide() + this.$content.empty() + // DefaultCode10 + data.SearchResponseFull.Results.Items.forEach(this.append.bind(this)) + this.deferScrollToTop() + } + this.afterFetchCallback && this.afterFetchCallback() + app.collection.deferRefresh() + }, + + append: function(item){ + this.items[ item['Code8'] ] = item + var t = this.template.replace(/{{image}}/, sdk.image(item['DefaultCode10'], '11_f')) + .replace(/{{code8}}/, item['Code8']) + this.$content.append(t) + }, + + pick: function(e){ + var code = $(e.currentTarget).data("code") + var data = this.items[code] + app.product.load(code, data) + }, + + collectionName: "STONE ISLAND", + setCollectionName: function(name){ + this.collectionName = name + this.$title.html(this.collectionName) + }, + + firstTouch: { x: 0, y: 0, id: "" }, + lastTouch: { x: 0, y: 0, id: "" }, + touchstart: function(e){ + var p = e.originalEvent.touches ? e.originalEvent.touches[0] : e.originalEvent + this.firstTouch.x = this.lastTouch.x = p.pageX + this.firstTouch.y = this.lastTouch.y = p.pageY + this.firstTouch.id = e.currentTarget.dataset.id + }, + touchmove: function(e){ + var p = e.originalEvent.touches ? e.originalEvent.touches[0] : e.originalEvent + this.lastTouch.x = p.pageX + this.lastTouch.y = p.pageY + this.lastTouch.id = e.currentTarget.dataset.id + }, + touchend: function(e){ + var first = app.collection.firstTouch + var last = app.collection.lastTouch + var distance = Math.sqrt( Math.pow(first.x - last.x, 2) + Math.pow(first.y - last.y, 2) ) + if (distance < 20) { + this.pick(e) + } + }, + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/products/GalleryView.js b/StoneIsland/platforms/android/assets/www/js/lib/products/GalleryView.js new file mode 100755 index 00000000..02193f14 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/products/GalleryView.js @@ -0,0 +1,65 @@ +var GalleryView = View.extend({ + + el: "#gallery", + template: $("#gallery .template").html(), + + events: { +// "click .left": "prev", +// "click .right": "next", +// "touchstart .gallery": "touchstart", +// "touchmove .gallery": "touchmove", +// "touchend .gallery": "touchend", + }, + + initialize: function(){ + this.$(".template").remove() + }, + + reset: function(){ + this.gallery && this.gallery.destroy() + this.$el.empty() + }, + + populate: function(code, image_ids){ + var valid_styles = {} + image_ids.forEach(function(id){ + if (id.indexOf("_") == -1) return + var partz = id.split("_") + var size = parseInt(partz[0]), style = partz[1] + if (size > 13) return; + if (! valid_styles[style] || valid_styles[style] < size) { + valid_styles[style] = size + } + }) + Object.keys(valid_styles).sort(sort_image_styles).forEach(function(style){ + var id = valid_styles[style] + "_" + style + var t = this.template.replace(/{{image}}/, sdk.image(code, id)) + this.$el.append(t) + }.bind(this)) + + this.gallery = new Flickity( "#gallery", { + selector: '.item', + cellAlign: 'center', + autoPlay: false, + freeScroll: false, + wrapAround: true, + imagesLoaded: true, + prevNextButtons: false, + pageDots: false, + contain: true, + draggable: true, + }) + }, + + touchstart: function(e){ + }, + touchmove: function(e){ + }, + touchend: function(e){ + }, + +}) + +var YOOX_IMAGE_STYLE_ORDER = "ZZZ d f".split(" ") + +function sort_image_styles (b,a){ return (YOOX_IMAGE_STYLE_ORDER.indexOf(a)) - (YOOX_IMAGE_STYLE_ORDER.indexOf(b)) }
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/products/ProductView.js b/StoneIsland/platforms/android/assets/www/js/lib/products/ProductView.js new file mode 100755 index 00000000..4789850a --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/products/ProductView.js @@ -0,0 +1,397 @@ + +var ProductView = ScrollableView.extend({ + + el: "#product", + + events: { + "click .fit": "scroll_to_bottom", + "click .size": "select_size", + "click .color": "select_color", + "click .share": "share", + "click .gallery-left": "gallery_left", + "click .gallery-right": "gallery_right", + }, + + initialize: function(){ + this.gallery = new GalleryView () + this.scroller = new IScroll('#product', app.iscroll_options) + + this.$num = this.$(".num") + this.$title = this.$(".title") + this.$type = this.$(".type") + this.$price = this.$(".price") + this.$size = this.$(".size") + this.$color = this.$(".color") + this.$body = this.$(".body") + this.$fit = this.$(".fit") + this.$sizing = this.$(".sizing") + }, + + show: function(){ + app.footer.show("ADD TO CART", "BUY NOW") + document.body.className = "product" + }, + hide: function(){ + }, + + item: null, + details: null, + size: null, + color: null, + code: null, + is_onesize: false, + + sizes: null, + colors: null, + + cache: {}, + + gallery_prev: function(){ + app.product.gallery.gallery.previous() + }, + gallery_right: function(){ + app.product.gallery.gallery.next() + }, + + find: function(code, cb){ + data = app.collection.items[code] || {} + if (code in this.cache) { + return cb(data, this.cache[code]) + } + sdk.product.item({ + code: code + }).done(function(details){ + this.cache[code] = details + cb(data, details) + }.bind(this)) + }, + + load: function(code, data){ + this.gallery.reset() + this.show() + if (app.view && app.view.hide) { + app.view.hide() + } + app.view = this + app.header.set_back(true) + + if (! app.collection.loaded) { + this.el.className = "loading" + app.collection.afterFetchCallback = this.load.bind(this, code, data) + app.collection.fetch() + return + } + else { + app.collection.afterFetchCallback = null + } + window.location.href = "#/store/" + code + + console.log(data) + if (data) { + app.collection.items[code] = data + } + + this.el.className = "loading" + this.find(code, this.populate.bind(this)) + }, + + populate: function(data, details){ + this.el.className = "" + + console.log(data, details) + + var descriptions = this.get_descriptions(details) + + this.gallery.populate( data['Code8'], details['Item']['ImageTypes'] ) + + var name_partz = data['ModelNames'].split(' ') + var num = name_partz.shift() + var title = name_partz.join(' ') + var type = title_case( data['MicroCategory'] ) + var price = "$" + data['DiscountedPrice'] + ".00" + var body = descriptions['EditorialDescription'].replace(/<br>/g, "<br><br>") + + var default_color_id = this.populate_selectors(data, details) + + var color = this.colors[default_color_id] + var color_label = color.label + var sizes = this.find_sizes_for_color(default_color_id) + var size = sizes[0] + var size_label = this.sizes[size].label + + this.is_onesize = !! this.sizes[1] + + // console.log(color, color_label, size, size_label) + + this.item = data + this.details = details['Item'] + this.code = data['DefaultCode10'] + + this.color = color + this.size = size + + this.$num.html(num) + this.$title.html(title) + this.$type.html(type) + this.$price.html(price) + this.$body.html(body) + + this.$size.html(size_label) + if (color_label) { + this.$color.show().html(color_label) + } + else { + this.$color.hide() + } + + this.deferScrollToTop() + }, + + get_descriptions: function (details){ + var descriptions = {} + details['Item']['Descriptions'].forEach(function(pair){ + descriptions[pair.Key] = pair.Value + }) + return descriptions + }, + find_sizes_for_color: function(color_id){ + return Object.keys( this.colors[color_id].sizes ).sort(function(a,b){ + var ao = SIZE_ORDER[ a.label ], bo = SIZE_ORDER[ b.label ] + return ao<bo?-1:ao==bo?0:1 + }) + }, + find_colors_for_size: function(size_id){ + return Object.keys( this.sizes[size_id].colors ) + }, + + populate_selectors: function(data, details){ + var sizes = {}, colors = {}, size_lookup = {}, default_color + details['Item']['ModelColors'].forEach(function(color, index){ + if (! default_color || color['Code10'] == data['DefaultCode10']) { + default_color = color['ColorId'] + } + colors[ color['ColorId'] ] = { + id: color['Code10'], + code: color['Code10'], + label: color['ColorDescription'].toUpperCase(), + sizes: {}, + } + }) + + details['Item']['ModelSizes'].forEach(function(size){ + var label = SIZE_LOOKUP[ size['Default']['Text'] ] + if (! label && ! size['Default']['Labeled']) { + label = size['Default']['Text'] + " " + size['Default']['ClassFamily'] + } + size_lookup[ label ] = size['SizeId'] + console.log( label ) + sizes[ size['SizeId'] ] = { + id: label, + label: label.toUpperCase(), + colors: {}, + } + }) + details['Item']['ModelColorSize'].forEach(function(cs){ + colors[ cs['IdColor'] ].sizes[ cs['IdSize'] ] = true + sizes[ cs['IdSize'] ].colors[ cs['IdColor'] ] = true + }) + + this.sizes = sizes + this.colors = colors + return default_color + }, + + select_size: function(){ + if (this.is_onesize) { return this.select_color() } + if (this.item['Sizes'].length == 0) { return } + var sizes = Object.keys(this.sizes).map(function(key){ + return this.sizes[key] + }.bind(this)) + app.selector.select(sizes, function(size){ + this.size = size.value + this.$size.html(size.label) + }.bind(this)) + }, + + select_color: function(){ + if (this.item['Colors'].length == 0) { return } + var colors = Object.keys(this.colors).map(function(key){ + return this.colors[key] + }.bind(this)) + app.selector.select(colors, function(color){ + this.code = color.code + this.$color.html(color.label) + }.bind(this)) + }, + + // ADD TO CART + save: function(){ + this.add_to_cart({ route: false }) + }, + // BUY NOW + cancel: function(){ + this.add_to_cart({ route: true }) + }, + + add_to_cart: function(opt){ + auth.deferred_product = { Size: this.size, Code10: this.code } + if ( ! auth.logged_in() ) { + app.router.go("account/login") + app.last_view = app.cart + } + else if ( ! auth.has_cart() ) { + app.curtain.show("loading") + auth.create_cart(function(){ + auth.add_deferred_product_to_cart(function(){ + app.curtain.hide("loading") + app.router.go("cart") + }) + }) + } + else { + app.curtain.show("loading") + auth.add_deferred_product_to_cart(function(){ + app.curtain.hide("loading") + if (opt.route) { + app.router.go("cart") + } + }) + } + }, + + back: function(){ + app.router.go('store') + }, + + scroll_to_bottom: function(){ + }, + + share: function(){ + window.plugins.socialsharing.share( this.item['ModelNames'], null, null, "http://stoneisland.com/") + }, + +}) + +var SIZE_LOOKUP = { + "XS": "X-SMALL", + "S": "SMALL", + "M": "MEDIUM", + "L": "LARGE", + "XL": "X-LARGE", + "XXL": "XX-LARGE", + "3XL": "3X-LARGE", + "OneSize": "ONESIZE", +} + +var SIZE_ORDER = "XS S M L XL XXL 3XL".split(" ") + +/* +{ + "Code8": "41504876", + "BrandName": "STONE ISLAND", + "DefaultCode10": "41504876MA", + "MicroCategory": "Jacket", + "MacroCategory": "COATS & JACKETS", + "FullPrice": 728, + "DiscountedPrice": 437, + "PriceListId": 155702498, + "ModelNames": "41764 FLOWING CAMO WATRO", + "Sizes": [ + { + "Id": 4, + "Text": "S", + "ClassFamily": "INT", + "Labeled": true + }, + { + "Id": 6, + "Text": "L", + "ClassFamily": "INT", + "Labeled": true + }, + { + "Id": 7, + "Text": "XL", + "ClassFamily": "INT", + "Labeled": true + }, + { + "Id": 8, + "Text": "XXL", + "ClassFamily": "INT", + "Labeled": true + } + ], + "Colors": [ + { + "Id": 3152, + "Code10": { + "Id": 6769575, + "Value": "41504876MA" + }, + "Description": "Green", + "MacroColorId": 3152, + "Rgb": "3C941F" + } + ], + "SizeTypeId": 928, + "HasFlipSide": false, + "SeasonOfSale": "PE15", + "SalesLineId": "126", + "SalesLine": "18_STONE ISLAND", + "MarketId": 19, + "Criteria": { + "Sizes": [ + "3", + "5", + "6", + "7" + ], + "Looks": [], + "Styles": [], + "WashTypes": [], + "WashStories": [], + "WashCodes": [], + "Waists": [], + "Fabrics": [], + "ColorTypes": [], + "ModelNames": [], + "Material": [] + }, + "NoveltyPoints": 0, + "C10Attributes": [ + { + "Key": "MFC", + "Value": "621541764CC-6215-64V0050", + "C10": "41504876MA" + } + ], + "MacroCategoryId": 224, + "MicroCategoryId": 1319 +}, + +DESCRIPTIONS: + +Age: "Adult" +Appliqué: "Logo detail" +ColoreFoto_ID: "3140" +Composition: "100% Cotton" +CustomsInvoiceDescr: "Woven" +Design: "Solid color" +EditorialDescription: "20081 DATA DRIP PIN<br>Short sleeve T-Shirt in cotton jersey. Garment dyed.<br>Stone Island Compass logo print on the front, made up of a series of numbers." +ItemDescription: "Logo detail<br>Jersey<br>Round collar<br>Solid color<br>" +KeywordDescription: "Logo detail Jersey Round collar Solid color Jersey Woven not made of fur " +Kind of fabric: "Woven" +MFC: "631520081CC-6315-81V0060" +MacroCategory: "POLO SHIRTS & T-SHIRTS" +MadeIn: "Made In Turkmenistan" +MadeInIsoCode: "TN" +MainMaterial: "Cotton" +Material Description: "Jersey" +MicroCategory: "Short sleeve t-shirt" +MicroCategoryPlural: "Short sleeve t-shirts" +ModelFabric: "631520081CC-6315-81" +ModelNames: "20081 DATA DRIP PIN" +Neckline: "Claudine or round collar" + +*/
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/products/Selector.js b/StoneIsland/platforms/android/assets/www/js/lib/products/Selector.js new file mode 100755 index 00000000..76c498ec --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/products/Selector.js @@ -0,0 +1,48 @@ +var Selector = View.extend({ + + el: "#selector", + template: $("#selector .template").html(), + + events: { + "click .close": "hide", + "click .options div": "pick", + }, + + initialize: function(){ + this.$options = this.$(".options") + }, + + lookup: null, + callback: null, + select: function(options, callback){ + this.lookup = {} + this.callback = callback || function(item){ console.log(item) } + this.$options.empty() + options.forEach(function(opt){ + this.lookup[String(opt.id)] = opt + var t = this.template.replace(/{{id}}/, opt.id) + .replace(/{{label}}/, opt.label) + this.$options.append(t) + }.bind(this)) + this.$el.show() + app.curtain.show("white") + this.visible = true + }, + + hide: function(){ + this.lookup = this.callback = null + this.$el.hide() + app.curtain.hide() + this.visible = false + }, + + pick: function(e){ + var $option = $(e.currentTarget) + var id = String($option.data("id")) + var selection = this.lookup[id] + + this.callback( selection ) + this.hide() + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/products/filters/CategoryFilter.js b/StoneIsland/platforms/android/assets/www/js/lib/products/filters/CategoryFilter.js new file mode 100755 index 00000000..4e6baf62 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/products/filters/CategoryFilter.js @@ -0,0 +1,40 @@ +var CategoryFilter = View.extend({ + + initialize: function(opt){ + this.parent = opt.parent + }, + + filter: function(){ + var cats = this.parent.data.SearchResponseFull.Refinements.Filters.Categories.map(function(cat){ + return { + id: cat.Id, + label: cat.Value + } + }) + if (this.last_choice) { + cats.push({ + id: "__remove_filter", + label: "REMOVE FILTER", + }) + } + app.selector.select(cats, this.pick.bind(this)) + }, + + last_choice: null, + + pick: function(choice){ + this.parent.$content.empty() + if (choice.id == "__remove_filter") { + this.last_choice = null + this.parent.data.SearchResponseFull.Results.Items.forEach(this.parent.append.bind(this.parent)) + } + else { + this.last_choice = choice + this.parent.data.SearchResponseFull.Results.Items.filter(function(item){ + return item.MacroCategory == choice.label + }).forEach(this.parent.append.bind(this.parent)) + } + this.parent.deferScrollToTop() + }, + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/view/Router.js b/StoneIsland/platforms/android/assets/www/js/lib/view/Router.js new file mode 100755 index 00000000..a8ec331f --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/view/Router.js @@ -0,0 +1,75 @@ +var Router = View.extend({ + + routeByHash: false, + + go: function(url){ + this.parseRoute(url) + }, + + route: function(){ + var path = this.routeByHash ? window.location.hash.substr(0) : window.location.pathname + path = path || "/" + this.originalPath = path + this.parseRoute(path) + }, + + parseRoute: function(pathname){ + + pathname = pathname.replace(/^#/, "") + + if (pathname[0] !== "/") { pathname = "/" + pathname } + + var routes = this.routes, + path = pathname.split("/"); + + for (var i = 0; i < path.length; i++) { + if (! path[i].length) { + path[i] = null + } + } + + if (pathname in routes) { + this[this.routes[pathname]]() + return + } + + if (path[path.length-1] == null) { + path.pop() + } + + for (var route in routes) { + var routePath = route.split("/") + if (routePath[1] == path[1]) { + if (routePath[2] && routePath[2].indexOf(":") !== -1 && path[2] && (path[3] === routePath[3]) ) { + this[this.routes[route]](path[2]) + return + } + else if (routePath[2] == path[2]) { + if (routePath[3] && path[3]) { + if (routePath[3].indexOf(":") !== -1) { + this[this.routes[route]](path[3]) + return + } + else if (routePath[3] == path[3]) { + this[this.routes[route]]() + return + } + } + else if (! routePath[3] && ! path[3]) { + this[this.routes[route]]() + return + } + } + else if (! routePath[2] && (! path[2].length || ! path[2])) { + this[this.routes[route]]() + return + } + } + } + + if (is_mobile) { + window.location.href = "/" + } + } + +}) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/view/Scrollable.js b/StoneIsland/platforms/android/assets/www/js/lib/view/Scrollable.js new file mode 100755 index 00000000..d06ed590 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/view/Scrollable.js @@ -0,0 +1,27 @@ +var ScrollableView = View.extend({ + + events: { + "load img": "deferRefresh", + }, + + deferScrollToTop: function(){ + setTimeout(this.scrollToTop.bind(this), 0) + }, + + refreshScroller: function(){ + this.scroller.refresh() + clearTimeout( this.scrollerRefreshTimeout ) + }, + + scrollerRefreshTimeout: null, + deferRefresh: function(){ + clearTimeout( this.scrollerRefreshTimeout ) + this.scrollerRefreshTimeout = setTimeout(this.refreshScroller.bind(this)) + }, + + scrollToTop: function(){ + this.scroller.refresh() + app.collection.scroller.scrollTo(0, 0) + }, + +})
\ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/js/lib/view/Serializable.js b/StoneIsland/platforms/android/assets/www/js/lib/view/Serializable.js new file mode 100755 index 00000000..98aa8ce3 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/view/Serializable.js @@ -0,0 +1,164 @@ +var SerializableView = View.extend({ + + events: { + "change select": "update_select", + "change [type=date]": "update_date", + "focus input": "focus_input", + "click .date-wrapper": "focus_date", + "submit form": "save", + }, + + preload: function(data){ + if (! data && sdk.env == "production") { return } + data = data || this.test_data + if (! data) { return } + this.load_data(data) + }, + + load_data: function(data){ + Object.keys(data).forEach(function(key){ + var value = data[key] + var $el = this.$("[name=" + key + "]") + + if ($el.attr("type") == "checkbox") { + $el.prop("checked", value) + } + if ($el.attr("type") == "date") { + $el.val( value ) + this.update_date({ currentTarget: $el }) + } + else if ($el.prop("tagName") == "SELECT") { + $el.val( value ) + this.update_select({ currentTarget: $el }) + } + else { + $el.val( value ) + } + }.bind(this)) + }, + + serialize: function(){ + var fields = {} + this.$("input[name], select[name], textarea[name]").each( function(){ + if (this.type == "checkbox") { + if ($(this).prop("checked")) { + fields[this.name] = this.value + } + } + else { + fields[this.name] = this.value + } + }) + return fields + }, + + deserialize: function(data){ + this.$("input[name], textarea[name]").val("") + Object.keys(data).forEach(function(k){ + this.$("[" + k + "]").val(data[k]) + }) + }, + + focus_input: function(e){ + $(e.currentTarget).removeClass("error_hilite") + }, + + focus_date: function(e){ + $(e.currentTarget).find("input").focus() + }, + + update_select: function(e){ + var $target = $(e.currentTarget), value = $target.val() + var label = $target.find("option").filter(function(){ return this.value === value }).html() + $target.parent().addClass("picked") + $target.parent().find("span").html(label) + }, + + update_date: function(e){ + var $target = $(e.currentTarget), value = $target.val() + var label = moment(value).format("MM/DD/YYYY") + $target.parent().addClass("picked") + $target.parent().find("span").html(label) + }, + + validate: function(data, errors){ + var data = data || this.serialize() + var errors = errors || [] + var presence_msgs = this.validate_presence || {} + if (! this.disabled) { + Object.keys(presence_msgs).forEach(function(k){ + if (! data[k]) errors.push( [ k, presence_msgs[k] ] ) + }) + } + this.validate_fields && this.validate_fields(data, errors) + this.cc && this.cc.validate(data, errors) + this.address && this.address.validate(data, errors) + return { errors: errors, data: data } + }, + + show_errors: function(errors){ + console.log(errors) + var msgs = [] + errors.forEach(function(e, i){ + if (i > 0) { return } + this.$("[name=" + e[0] + "]").addClass('error_hilite') + msgs.push(e[1]) + }.bind(this)) + this.$msg.html(msgs.join("<br>")) + this.$msg.addClass('alert-notice') + }, + + hide_errors: function(){ + this.$msg.removeClass('alert-notice') + this.$msg.html("") + }, + + finalize: function(data){ + return data + }, + + save: function(e){ + e && e.preventDefault() + + var valid = this.validate() + if (valid.errors.length) { + this.show_errors(valid.errors) + return + } + else { + this.hide_errors() + } + + var finalized_data = this.finalize(valid.data) + this.submit( finalized_data ) + }, + + submit: function(data){ + if (! data) { + return + } + app.curtain.show("loading") + this.action({ + data: data, + success: function(data){ + app.curtain.hide("loading") + this.success(data) + }.bind(this), + error: function(data){ + app.curtain.hide("loading") + this.error(data) + }.bind(this), + }) + }, + + success: function(data){ + console.log("SUCCESS", data) + }, + + error: function(data){ + console.log("FAIL", data) + }, + +}) + +var FormView = View.extend(SerializableView.prototype).extend(ScrollableView.prototype) diff --git a/StoneIsland/platforms/android/assets/www/js/lib/view/View.js b/StoneIsland/platforms/android/assets/www/js/lib/view/View.js new file mode 100755 index 00000000..41638ab7 --- /dev/null +++ b/StoneIsland/platforms/android/assets/www/js/lib/view/View.js @@ -0,0 +1,147 @@ +var View = (function($, _){ + + var View = function(options) { + this._id = _.uniqueId('view') + this.type = "view" + options || (options = {}); + _.extend(this, _.pick(options, viewOptions)) + this._ensureElement() + this.initialize.apply(this, arguments) + this.delegateEvents() + } + + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + _.extend(View.prototype, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + $: function(selector) { + return this.$el.find(selector); + }, + + initialize: function(){}, + + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof $ ? element : $(element); + this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save', + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. + delegateEvents: function(events) { + if (!(events || (events = _.result(this, 'events')))) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[events[key]]; + if (!method) continue; + + var match = key.match(delegateEventSplitter); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this._id; + if (is_mobile) { + if (eventName === 'mouseenter' || eventName === 'mouseleave') { + continue + } +// if (eventName === 'click') { +// eventName = 'tap' +// } + } + if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } + } + return this; + }, + + // Clears all callbacks previously bound to the view with `delegateEvents`. + undelegateEvents: function() { + this.$el.off('.delegateEvents' + this._id); + return this; + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + this.setElement(_.result(this, 'el'), false); + }, + + preventDefault: function(e){ + e && e.preventDefault() + }, + + stopPropagation: function(e){ + e && e.stopPropagation() + }, + + }); + + + var extend = function(protoProps, staticProps) { + var staticProps = staticProps || {} + var parent = this; + var child; + var childEvents = {}; + + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent's constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } + + // Extend events so we can subclass views + _.extend(childEvents, parent.prototype.events, protoProps.events) + + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); + + // Set the prototype chain to inherit from `parent`, without calling + // `parent`'s constructor function. + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; + + // Add prototype properties (instance properties) to the subclass, + // if supplied. + if (protoProps) _.extend(child.prototype, protoProps); + + // Set a convenience property in case the parent's prototype is needed + // later. + child.prototype.__super__ = parent.prototype; + child.prototype.events = childEvents + + return child; + }; + + View.extend = extend; + + return View; +})(jQuery, _) |
