Help
RSS
API
Feed
Maltego
Contact
Domain > www.nitrousexpress.com
×
Welcome!
Right click nodes and scroll the mouse to navigate the graph.
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2019-12-03
67.23.168.210
(
ClassC
)
2024-11-19
216.59.42.221
(
ClassC
)
Port 443
HTTP/1.1 200 OKcache-control: no-storecontent-type: text/htmlexpires: Mon, 18 Nov 2024 04:27:10 GMTserver: Microsoft-IIS/10.0x-ua-compatible: IEedgeset-cookie: cookie%5Fsessionsuper%5Fuser%5Fs%5Fid&c%5Ftype&gr%5Fid&a%5Fname&c%5FLastname&c%5FfirstName&l%5Fid&created1&country%5Fid&SessionPriceGroupM&sc%5FidD983C86B75D748E2A2716AE365C35DB7&l%5Fws%5Fid22D996B7582A446C8C943DA1EB90A11D&a%5Fnum&c%5Fid&s%5Fkey1854EFB707B644128F950038F36315EE&CurrencySymbol1033&a%5Fid&sitefrontTrue&url%5Fid&managerfrontFalse; path/set-cookie: customer%5FlogonsitefrontTrue&managerfrontFalse&username&custid&c%5Fid&parent%5Fc%5Fid; path/set-cookie: ASPSESSIONIDQCBAACBBNOIIFLNBMLEEDGHMGKMMAFHG; path/access-control-allow-credentials: trueaccess-control-allow-origin: http://www.nitrousexpress.comdate: Tue, 19 Nov 2024 04:27:11 GMTcontent-length: 633752 !DOCTYPE html>!--if IE>!endif-->!--if IE 9> html classno-js ie9 lt-ie10> !endif-->!--if gt IE 9>!--> html langen classno-js> !--!endif-->head> meta http-equivContent-Type contenttext/html; charsetutf-8 /> meta nameviewport contentwidthdevice-width, initial-scale1, minimum-scale1, maximum-scale1> title>Nitrous Express and Snow Performance/title> meta namedescription content> meta namekeywords content> script> var _rollbarConfig { accessToken: d8019ee7b5984e75ad81a52104fe9b72, captureUncaught: true, captureUnhandledRejections: true, payload: { environment: production, c_key: , s_key: 1854EFB707B644128F950038F36315EE, page_name: } }; // Rollbar Snippet !function(r){var e{};function o(n){if(en)return en.exports;var ten{i:n,l:!1,exports:{}};return rn.call(t.exports,t,t.exports,o),t.l!0,t.exports}o.mr,o.ce,o.dfunction(r,e,n){o.o(r,e)||Object.defineProperty(r,e,{enumerable:!0,get:n})},o.rfunction(r){undefined!typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:Module}),Object.defineProperty(r,__esModule,{value:!0})},o.tfunction(r,e){if(1&e&&(ro(r)),8&e)return r;if(4&e&&objecttypeof r&&r&&r.__esModule)return r;var nObject.create(null);if(o.r(n),Object.defineProperty(n,default,{enumerable:!0,value:r}),2&e&&string!typeof r)for(var t in r)o.d(n,t,function(e){return re}.bind(null,t));return n},o.nfunction(r){var er&&r.__esModule?function(){return r.default}:function(){return r};return o.d(e,a,e),e},o.ofunction(r,e){return Object.prototype.hasOwnProperty.call(r,e)},o.p,o(o.s0)}(function(r,e,o){use strict;var no(1),to(4);_rollbarConfig_rollbarConfig||{},_rollbarConfig.rollbarJsUrl_rollbarConfig.rollbarJsUrl||https://cdn.rollbar.com/rollbarjs/refs/tags/v2.17.0/rollbar.min.js,_rollbarConfig.asyncvoid 0_rollbarConfig.async||_rollbarConfig.async;var an.setupShim(window,_rollbarConfig),lt(_rollbarConfig);window.rollbarn.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,e,o){use strict;var no(2);function t(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error(Rollbar: Internal error,r)}catch(r){}}}}var a0;function l(r,e){this.optionsr,this._rollbarOldOnErrornull;var oa++;this.shimIdfunction(){return o},undefined!typeof window&&window._rollbarShims&&(window._rollbarShimso{handler:e,messages:})}var io(3),sfunction(r,e){return new l(r,e)},dfunction(r){return new i(s,r)};function c(r){return t((function(){var ethis,oArray.prototype.slice.call(arguments,0),n{shim:e,method:r,args:o,ts:new Date};window._rollbarShimsthis.shimId().messages.push(n)}))}l.prototype.loadFullfunction(r,e,o,n,a){var l!1,ie.createElement(script),se.getElementsByTagName(script)0,ds.parentNode;i.crossOrigin,i.srcn.rollbarJsUrl,o||(i.async!0),i.onloadi.onreadystatechanget((function(){if(!(l||this.readyState&&loaded!this.readyState&&complete!this.readyState)){i.onloadi.onreadystatechangenull;try{d.removeChild(i)}catch(r){}l!0,function(){var e;if(void 0r._rollbarDidLoad){enew Error(rollbar.js did not load);for(var o,n,t,l,i0;or._rollbarShimsi++;)for(oo.messages||;no.shift();)for(tn.args||,i0;it.length;++i)if(functiontypeof(lti)){l(e);break}}functiontypeof a&&a(e)}()}})),d.insertBefore(i,s)},l.prototype.wrapfunction(r,e,o){try{var n;if(nfunctiontypeof e?e:function(){return e||{}},function!typeof r)return r;if(r._isWrap)return r;if(!r._rollbar_wrapped&&(r._rollbar_wrappedfunction(){o&&functiontypeof o&&o.apply(this,arguments);try{return r.apply(this,arguments)}catch(o){var eo;throw e&&(stringtypeof e&&(enew String(e)),e._rollbarContextn()||{},e._rollbarContext._wrappedSourcer.toString(),window._rollbarWrappedErrore),e}},r._rollbar_wrapped._isWrap!0,r.hasOwnProperty))for(var t in r)r.hasOwnProperty(t)&&(r._rollbar_wrappedtrt);return r._rollbar_wrapped}catch(e){return r}};for(var ulog,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,captureEvent,captureDomContentLoaded,captureLoad.split(,),p0;pu.length;++p)l.prototypeupc(up);r.exports{setupShim:function(r,e){if(r){var oe.globalAlias||Rollbar;if(objecttypeof ro)return ro;r._rollbarShims{},r._rollbarWrappedErrornull;var anew d(e);return t((function(){e.captureUncaught&&(a._rollbarOldOnErrorr.onerror,n.captureUncaughtExceptions(r,a,!0),e.wrapGlobalEventHandlers&&n.wrapGlobals(r,a,!0)),e.captureUnhandledRejections&&n.captureUnhandledRejections(r,a,!0);var te.autoInstrument;return!1!e.enabled&&(void 0t||!0t||objecttypeof t&&t.network)&&r.addEventListener&&(r.addEventListener(load,a.captureLoad.bind(a)),r.addEventListener(DOMContentLoaded,a.captureDomContentLoaded.bind(a))),roa,a}))()}},Rollbar:d}},function(r,e,o){use strict;function n(r,e,o,n){r._rollbarWrappedError&&(n4||(n4r._rollbarWrappedError),n5||(n5r._rollbarWrappedError._rollbarContext),r._rollbarWrappedErrornull);var te.handleUncaughtException.apply(e,n);o&&o.apply(r,n),anonymoust&&(e.anonymousErrorsPending+1)}function t(r,e,o){if(e.hasOwnProperty&&e.hasOwnProperty(addEventListener)){for(var ne.addEventListener;n._rollbarOldAdd&&n.belongsToShim;)nn._rollbarOldAdd;var tfunction(e,o,t){n.call(this,e,r.wrap(o),t)};t._rollbarOldAddn,t.belongsToShimo,e.addEventListenert;for(var ae.removeEventListener;a._rollbarOldRemove&&a.belongsToShim;)aa._rollbarOldRemove;var lfunction(r,e,o){a.call(this,r,e&&e._rollbar_wrapped||e,o)};l._rollbarOldRemovea,l.belongsToShimo,e.removeEventListenerl}}r.exports{captureUncaughtExceptions:function(r,e,o){if(r){var t;if(functiontypeof e._rollbarOldOnError)te._rollbarOldOnError;else if(r.onerror){for(tr.onerror;t._rollbarOldOnError;)tt._rollbarOldOnError;e._rollbarOldOnErrort}e.handleAnonymousErrors();var afunction(){var oArray.prototype.slice.call(arguments,0);n(r,e,t,o)};o&&(a._rollbarOldOnErrort),r.onerrora}},captureUnhandledRejections:function(r,e,o){if(r){functiontypeof r._rollbarURH&&r._rollbarURH.belongsToShim&&r.removeEventListener(unhandledrejection,r._rollbarURH);var nfunction(r){var o,n,t;try{or.reason}catch(r){ovoid 0}try{nr.promise}catch(r){nunhandledrejection error getting `promise` from event}try{tr.detail,!o&&t&&(ot.reason,nt.promise)}catch(r){}o||(ounhandledrejection error getting `reason` from event),e&&e.handleUnhandledRejection&&e.handleUnhandledRejection(o,n)};n.belongsToShimo,r._rollbarURHn,r.addEventListener(unhandledrejection,n)}},wrapGlobals:function(r,e,o){if(r){var n,a,lEventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload.split(,);for(n0;nl.length;++n)raln&&ra.prototype&&t(e,ra.prototype,o)}}}},function(r,e,o){use strict;function n(r,e){this.implr(e,this),this.optionse,function(r){for(var efunction(r){return function(){var eArray.prototype.slice.call(arguments,0);if(this.implr)return this.implr.apply(this.impl,e)}},olog,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureEvent,captureDomContentLoaded,captureLoad.split(,),n0;no.length;n++)rone(on)}(n.prototype)}n.prototype._swapAndProcessMessagesfunction(r,e){var o,n,t;for(this.implr(this.options);oe.shift();)no.method,to.args,thisn&&functiontypeof thisn&&(captureDomContentLoadedn||captureLoadn?thisn.apply(this,t0,o.ts):thisn.apply(this,t));return this},r.exportsn},function(r,e,o){use strict;r.exportsfunction(r){return function(e){if(!e&&!window._rollbarInitialized){for(var o,n,t(rr||{}).globalAlias||Rollbar,awindow.rollbar,lfunction(r){return new a(r)},i0;owindow._rollbarShimsi++;)n||(no.handler),o.handler._swapAndProcessMessages(l,o.messages);windowtn,window._rollbarInitialized!0}}}}); // End Rollbar Snippet /script> script srchttps://www.paypal.com/sdk/js?client-idATYrh41vWhySuJT4eQPZbKWnGVG5abzAlMLD_6najQ0mjhbBVtjsA-CISaLLuvTiyD-O2yfHU6FeOvxE&componentsmessages,buttons data-namespacePayPalSDK>/script> script typetext/javascript srchttps://snapui.searchspring.io/k5zzdj/bundle.js idsearchspring-context>/script> link relcanonical hrefhttps://www.nitrousexpress.com/ /> !-- Retail/Anonymous Fonts --> link hrefhttps://fonts.googleapis.com/css?familyRaleway:400,700,900 relstylesheet> link relstylesheet hreftemplates/fa/css/font-awesome.min.css> !-- Favicon --> link relshortcut icon hrefhttps://www.nitrousexpress.com/favicon.ico> link relapple-touch-icon-precomposed sizes57x57 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-57x57.png /> link relapple-touch-icon-precomposed sizes114x114 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-114x114.png /> link relapple-touch-icon-precomposed sizes72x72 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-72x72.png /> link relapple-touch-icon-precomposed sizes144x144 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-144x144.png /> link relapple-touch-icon-precomposed sizes60x60 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-60x60.png /> link relapple-touch-icon-precomposed sizes120x120 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-120x120.png /> link relapple-touch-icon-precomposed sizes76x76 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-76x76.png /> link relapple-touch-icon-precomposed sizes152x152 hrefhttps://www.nitrousexpress.com/images/apple-touch-icon-152x152.png /> link relicon typeimage/png hrefhttps://www.nitrousexpress.com/images/favicon-196x196.png sizes196x196 /> link relicon typeimage/png hrefhttps://www.nitrousexpress.com/images/favicon-96x96.png sizes96x96 /> link relicon typeimage/png hrefhttps://www.nitrousexpress.com/images/favicon-32x32.png sizes32x32 /> link relicon typeimage/png hrefhttps://www.nitrousexpress.com/images/favicon-16x16.png sizes16x16 /> link relicon typeimage/png hrefhttps://www.nitrousexpress.com/images/favicon-128.png sizes128x128 /> meta nameapplication-name contentNitrous Express /> meta namemsapplication-TileColor content#FFFFFF /> meta namemsapplication-TileImage contenthttps://www.nitrousexpress.com/images/mstile-144x144.png /> meta namemsapplication-square70x70logo contenthttps://www.nitrousexpress.com/images/mstile-70x70.png /> meta namemsapplication-square150x150logo contenthttps://www.nitrousexpress.com/images/mstile-150x150.png /> meta namemsapplication-wide310x150logo contenthttps://www.nitrousexpress.com/images/mstile-310x150.png /> meta namemsapplication-square310x310logo contenthttps://www.nitrousexpress.com/images/mstile-310x310.png /> link relstylesheet href../css/bootstrap-retail.css?047c7ad> link relstylesheet href../css/retail.css?047c7ad> script> window.dataLayer window.dataLayer || ; /script> !-- Google Tag Manager --> script>(function(w,d,s,l,i){wlwl||;wl.push({gtm.start: new Date().getTime(),event:gtm.js});var fd.getElementsByTagName(s)0, jd.createElement(s),dll!dataLayer?&l+l:;j.asynctrue;j.src https://www.googletagmanager.com/gtm.js?id+i+dl;f.parentNode.insertBefore(j,f); })(window,document,script,dataLayer,GTM-54H34Q9);/script> !-- End Google Tag Manager -->script srccode/js_hooks.asp?047c7ad>/script>script>// This function is needed for JS hooks.function getOriginalPageName() { return default.asp;}/script>script>var pendoData { visitor: { id: -nitrous, key: , package: 4, template: , firstName: , lastName: , email: , companyName: , companyNum: , role: standard }, account: { id: nitrous, key: 22D996B7582A446C8C943DA1EB90A11D, package: 4 }, session: { loggedIn: False, superUser: False, viewingChild: False, } };(function(apiKey){ (function(p,e,n,d,o){var v,w,x,y,z;opdpd||{};o._q; vinitialize,identify,updateOptions,pageLoad;for(w0,xv.length;wx;++w)(function(m){ omom||function(){o._qmv0?unshift:push(m.concat(.slice.call(arguments,0)));};})(vw); ye.createElement(n);y.async!0;y.srchttps://cdn.pendo.io/agent/static/+apiKey+/pendo.js; ze.getElementsByTagName(n)0;z.parentNode.insertBefore(y,z);})(window,document,script,pendo); pendo.initialize(pendoData);})(53aab975-b5c0-47bb-4f37-d7849209d68c);/script>script src/js/bundles/coreTop.js?047c7ad95827131b7e80a38145dd45a0c601738b >/script>!-- Facebook Pixel Code -->script> !function(f,b,e,v,n,t,s) {if(f.fbq)return;nf.fbqfunction(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbqn;n.pushn;n.loaded!0;n.version2.0; n.queue;tb.createElement(e);t.async!0; t.srcv;sb.getElementsByTagName(e)0; s.parentNode.insertBefore(t,s)}(window, document,script, https://connect.facebook.net/en_US/fbevents.js); fbq(init, 851427951622649); fbq(track, PageView);/script>noscript>img height1 width1 styledisplay:none srchttps://www.facebook.com/tr?id851427951622649&evPageView&noscript1/>/noscript>!-- End Facebook Pixel Code -->!-- Start GA4 -->script async srchttps://www.googletagmanager.com/gtag/js?idG-M86L8C554G>/script>script> window.dataLayer window.dataLayer || ; function gtag(){dataLayer.push(arguments);} gtag(js, new Date()); gtag(config, G-M86L8C554G, { debug_mode:true });/script>!-- End GA4 -->!-- include file../global/global_google_head_script_custom.asp-->meta namegoogle-site-verification contentTF8pspRwbBpfkzzT7Gtz2M_oe3OdOoo3ccF21BH8WVs />/head>body classhome retail t-ui-phase-4 site-type-4 loggedout t-ui-phase-4 home loggedout site-type-4> noscript classnoscript-padding>/noscript> !-- Google Tag Manager (noscript) -->noscript>iframe srchttps://www.googletagmanager.com/ns.html?idGTM-54H34Q9height0 width0 styledisplay:none;visibility:hidden>/iframe>/noscript>!-- End Google Tag Manager (noscript) -->header idretail-header classretail-header> div classnavigation> div classcontainer-fluid> nav classmain-navigation> ul classmain-navigation__wrap linkset click-persist> li classlink-parent wrap__link-parent> a classwrap__toggle href#0>i classicon-reorder>/i> Menu/a> ul> li classlink-parent> ul idmain-navigation__prodcat classmain-navigation__prodcat linkset> li classmobile-home> a hrefhttps://www.nitrousexpress.com>Home/a>/li> li classlink-parent prodcat__link-parent> a classprodcat__toggle href#0>Products/a> ul classprodcat prodcat__ul-1>li classprodcat__li-1 >a href/new-products.asp classprodcat__a-1 data-parent-href/new-products.asp data-parent-nameAll New Products data-key22873F9321B94E5E93512943D44297DC>span classcat-nm>All New Products/span>/a>ul classprodcat__ul-2>li classprodcat__li-2>a href/New-Nitrous-Express-Products.asp classprodcat__a-2 data-parent-href/new-products.asp|/New-Nitrous-Express-Products.asp data-parent-nameAll New Products|New Nitrous Express Products data-keyEFB026FBCE9C4E25A8D88B1A09F8749D>span classcat-nm>New Nitrous Express Products/span>/a>/li>li classprodcat__li-2>a href/New-Snow-Fuel-Systems-Products.asp classprodcat__a-2 data-parent-href/new-products.asp|/New-Snow-Fuel-Systems-Products.asp data-parent-nameAll New Products|New Snow Fuel Systems Products data-keyF9AA360B1E974F648A070C3232C6A40C>span classcat-nm>New Snow Fuel Systems Products/span>/a>/li>li classprodcat__li-2>a href/New-Snow-Performance-W-M-Products.asp classprodcat__a-2 data-parent-href/new-products.asp|/New-Snow-Performance-W-M-Products.asp data-parent-nameAll New Products|New Snow Performance W/M Products data-key0C229E60831944FB9A30508FC322C0FA>span classcat-nm>New Snow Performance W/M Products/span>/a>/li>/ul>/li>li classprodcat__li-1 >a href/nitrous/ classprodcat__a-1 data-parent-href/nitrous/ data-parent-nameNitrous Express data-keyD021797BEDB5433C87B88F48C0A15BE9>span classcat-nm>Nitrous Express/span>/a>ul classprodcat__ul-2>li classprodcat__li-2 >a href/efi-nitrous-systems.asp classprodcat__a-2 data-parent-href/nitrous/|/efi-nitrous-systems.asp data-parent-nameNitrous Express|EFI Nitrous systems data-keyF8C7CE46472841788D44BBC130DED8D1>span classcat-nm>EFI Nitrous systems/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/direct-port/10-cylinder-efi-direct-port.asp classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/direct-port/10-cylinder-efi-direct-port.asp data-parent-nameNitrous Express|EFI Nitrous systems|10 Cylinder Direct Port Systems data-keyB3CE624735FF48D6ABEA3B105D6509C3>span classcat-nm>10 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a href/4-cylinder-efi-direct-port-systems/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/4-cylinder-efi-direct-port-systems/ data-parent-nameNitrous Express|EFI Nitrous systems|4 Cylinder Direct Port Systems data-key3DDDAB7C118347CFBA1A58782A70A3DE>span classcat-nm>4 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a hrefpc_combined_results.asp?pc_idDA00CED25A834938910E31E4A6C351E1 classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|pc_combined_results.asp?pc_idDA00CED25A834938910E31E4A6C351E1 data-parent-nameNitrous Express|EFI Nitrous systems|6 Cylinder Direct Port Systems data-keyDA00CED25A834938910E31E4A6C351E1>span classcat-nm>6 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a href/direct-port/8-cylinder-efi-direct-port.asp classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/direct-port/8-cylinder-efi-direct-port.asp data-parent-nameNitrous Express|EFI Nitrous systems|8 Cylinder Direct Port Systems data-key96BE87E403254022B220BBC7E7894D2F>span classcat-nm>8 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a href/dry-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/dry-nitrous-systems/ data-parent-nameNitrous Express|EFI Nitrous systems|Dry Nitrous Systems data-key681FEACA00BF4794A277962F3D145E32>span classcat-nm>Dry Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/n-tercooler/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/n-tercooler/ data-parent-nameNitrous Express|EFI Nitrous systems|N-Tercooler Systems data-key4765FC8A3F1A47188F8B67E042844EFD>span classcat-nm>N-Tercooler Systems/span>/a>/li>li classprodcat__li-3>a href/nitrous-systems-for-bmw/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/nitrous-systems-for-bmw/ data-parent-nameNitrous Express|EFI Nitrous systems|Nitrous Systems For BMW Vehicles data-key38F5AB085F3B4D5F803B4600A3986A7A>span classcat-nm>Nitrous Systems For BMW Vehicles/span>/a>/li>li classprodcat__li-3>a href/nitrous-systems-for-dodge-vehicles/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/nitrous-systems-for-dodge-vehicles/ data-parent-nameNitrous Express|EFI Nitrous systems|Nitrous Systems For Dodge Vehicles data-keyB3C79FDD0B33490E8FC301EEE854E2AE>span classcat-nm>Nitrous Systems For Dodge Vehicles/span>/a>/li>li classprodcat__li-3>a href/nitrous-systems-for-ford/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/nitrous-systems-for-ford/ data-parent-nameNitrous Express|EFI Nitrous systems|Nitrous Systems For Ford Vehicles data-key168F89691CD5452AB5A964A0231ADB87>span classcat-nm>Nitrous Systems For Ford Vehicles/span>/a>/li>li classprodcat__li-3>a href/nitrous-systems-for-gm-vehicles/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/nitrous-systems-for-gm-vehicles/ data-parent-nameNitrous Express|EFI Nitrous systems|Nitrous Systems For GM Vehicles data-key78E3573855344A37B5E0BF1C13B071CB>span classcat-nm>Nitrous Systems For GM Vehicles/span>/a>/li>li classprodcat__li-3>a href/nitrous-systems-for-nissan-and-infiniti/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/nitrous-systems-for-nissan-and-infiniti/ data-parent-nameNitrous Express|EFI Nitrous systems|Nitrous Systems For Nissan/Infiniti Vehicles data-keyC175537026C043A4A62FA1052C6544F4>span classcat-nm>Nitrous Systems For Nissan/Infiniti Vehicles/span>/a>/li>li classprodcat__li-3>a href/nitrous-systems-for-sport-compacts/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/nitrous-systems-for-sport-compacts/ data-parent-nameNitrous Express|EFI Nitrous systems|Nitrous Systems For Sport Compacts data-keyACA01D0036C246B2922B029B1616CA14>span classcat-nm>Nitrous Systems For Sport Compacts/span>/a>/li>li classprodcat__li-3>a href/forced-induction-nitrous-solutions/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/forced-induction-nitrous-solutions/ data-parent-nameNitrous Express|EFI Nitrous systems|Turbo/Supercharged Nitrous Systems data-key3AC9AD5FBCEF4E42850D30CFBCD71B6E>span classcat-nm>Turbo/Supercharged Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/universal-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/efi-nitrous-systems.asp|/universal-nitrous-systems/ data-parent-nameNitrous Express|EFI Nitrous systems|Universal Nitrous Systems data-key6DAE6173E9DC4BB8A22023650B7C1C23>span classcat-nm>Universal Nitrous Systems/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/carbureted-nitrous-systems.asp classprodcat__a-2 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp data-parent-nameNitrous Express|Carbureted Nitrous Systems data-key58BB59823BB2400FBB28BC8DDAC110EA>span classcat-nm>Carbureted Nitrous Systems/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/4-cylinder-carb-direct-port-systems/ classprodcat__a-3 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp|/4-cylinder-carb-direct-port-systems/ data-parent-nameNitrous Express|Carbureted Nitrous Systems|4 Cylinder Direct Port Systems data-key4597E3C4417C4289B8EEB81D57EC9CBE>span classcat-nm>4 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a href/6-cylinder-efi-direct-port-systems/ classprodcat__a-3 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp|/6-cylinder-efi-direct-port-systems/ data-parent-nameNitrous Express|Carbureted Nitrous Systems|6 Cylinder Direct Port Systems data-key9FE197570A7346FAAA046EE59E6A6349>span classcat-nm>6 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a href/8-cylinder-efi-direct-port-systems/ classprodcat__a-3 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp|/8-cylinder-efi-direct-port-systems/ data-parent-nameNitrous Express|Carbureted Nitrous Systems|8 Cylinder Direct Port Systems data-key48373246167542CD8FBE1A954C2D25B1>span classcat-nm>8 Cylinder Direct Port Systems/span>/a>/li>li classprodcat__li-3>a href/Carbureted-Nitrous-Plates.asp classprodcat__a-3 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp|/Carbureted-Nitrous-Plates.asp data-parent-nameNitrous Express|Carbureted Nitrous Systems|Carbureted Plate Systems data-keyAD53CAB360E74BB7A5663164A69F2B10>span classcat-nm>Carbureted Plate Systems/span>/a>/li>li classprodcat__li-3>a href/holley-2-barrel-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp|/holley-2-barrel-nitrous-systems/ data-parent-nameNitrous Express|Carbureted Nitrous Systems|Holley 2 Barrel Nitrous Systems data-key96A27A0D12FE40708BFFB1646B77E80F>span classcat-nm>Holley 2 Barrel Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/quadrajet-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/carbureted-nitrous-systems.asp|/quadrajet-nitrous-systems/ data-parent-nameNitrous Express|Carbureted Nitrous Systems|Quadrajet (Spreadbore Flange) Nitrous System data-key07D64466E6A24C99BF731C7AA600582C>span classcat-nm>Quadrajet (Spreadbore Flange) Nitrous System/span>/a>/li>/ul>/li>li classprodcat__li-2>a href/diesel-nitrous-systems/ classprodcat__a-2 data-parent-href/nitrous/|/diesel-nitrous-systems/ data-parent-nameNitrous Express|Diesel Nitrous System data-key57EA221FA5244689B032E5A4821F9D1D>span classcat-nm>Diesel Nitrous System/span>/a>/li>li classprodcat__li-2 >a href/intake-manifolds/ classprodcat__a-2 data-parent-href/nitrous/|/intake-manifolds/ data-parent-nameNitrous Express|Intake Manifolds data-keyAE443C97DC494700AA4A4F3999EE4F8E>span classcat-nm>Intake Manifolds/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/cathedral-port-manifolds/ classprodcat__a-3 data-parent-href/nitrous/|/intake-manifolds/|/cathedral-port-manifolds/ data-parent-nameNitrous Express|Intake Manifolds|Cathedral Port LS1 Style Manifolds data-key3BF966BAA6A64532A2B387517AF6F498>span classcat-nm>Cathedral Port LS1 Style Manifolds/span>/a>/li>li classprodcat__li-3>a href/square-port-ls-manifolds/ classprodcat__a-3 data-parent-href/nitrous/|/intake-manifolds/|/square-port-ls-manifolds/ data-parent-nameNitrous Express|Intake Manifolds|LS3/L92 (Square Port) LS Manifold data-keyAE31B1AC48B943498BD091D1B12B055F>span classcat-nm>LS3/L92 (Square Port) LS Manifold/span>/a>/li>li classprodcat__li-3>a href/ls7-intake-manifolds/ classprodcat__a-3 data-parent-href/nitrous/|/intake-manifolds/|/ls7-intake-manifolds/ data-parent-nameNitrous Express|Intake Manifolds|LS7 Intake Manifolds data-key008EC289B0024AEE84A0A130A53F5F70>span classcat-nm>LS7 Intake Manifolds/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/motorcycle-nitrous-systems/ classprodcat__a-2 data-parent-href/nitrous/|/motorcycle-nitrous-systems/ data-parent-nameNitrous Express|Motorcycle Nitrous Systems data-key3D9AC1BA87F1469A822D5AA4FE6F2E1A>span classcat-nm>Motorcycle Nitrous Systems/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/4-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/motorcycle-nitrous-systems/|/4-cylinder-nitrous-systems/ data-parent-nameNitrous Express|Motorcycle Nitrous Systems|Four Cylinder Nitrous Systems data-keyB6FAC758712F48D386A0E439EB3900AA>span classcat-nm>Four Cylinder Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/single-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/motorcycle-nitrous-systems/|/single-cylinder-nitrous-systems/ data-parent-nameNitrous Express|Motorcycle Nitrous Systems|Single Cylinder Nitrous Systems data-key89D46EA909B74DEBA525504A238191EC>span classcat-nm>Single Cylinder Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/three-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/motorcycle-nitrous-systems/|/three-cylinder-nitrous-systems/ data-parent-nameNitrous Express|Motorcycle Nitrous Systems|Three Cylinder Nitrous Systems data-key345983F0237B43928AD5BA80F3EDDBCD>span classcat-nm>Three Cylinder Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/two-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/motorcycle-nitrous-systems/|/two-cylinder-nitrous-systems/ data-parent-nameNitrous Express|Motorcycle Nitrous Systems|Two Cylinder Nitrous Systems data-keyAB66E10D63134F6CAB182D1C7153D88C>span classcat-nm>Two Cylinder Nitrous Systems/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/atv-snowmobile-pwc/ classprodcat__a-2 data-parent-href/nitrous/|/atv-snowmobile-pwc/ data-parent-nameNitrous Express|ATV/Snowmobile/PWC data-keyAA3BFB2062E743629ED8583D7E44BB8F>span classcat-nm>ATV/Snowmobile/PWC/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/4-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/atv-snowmobile-pwc/|/4-cylinder-nitrous-systems/ data-parent-nameNitrous Express|ATV/Snowmobile/PWC|Four Cylinder Nitrous Systems data-keyB6FAC758712F48D386A0E439EB3900AA>span classcat-nm>Four Cylinder Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/single-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/atv-snowmobile-pwc/|/single-cylinder-nitrous-systems/ data-parent-nameNitrous Express|ATV/Snowmobile/PWC|Single Cylinder Nitrous Systems data-key89D46EA909B74DEBA525504A238191EC>span classcat-nm>Single Cylinder Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/three-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/atv-snowmobile-pwc/|/three-cylinder-nitrous-systems/ data-parent-nameNitrous Express|ATV/Snowmobile/PWC|Three Cylinder Nitrous Systems data-key345983F0237B43928AD5BA80F3EDDBCD>span classcat-nm>Three Cylinder Nitrous Systems/span>/a>/li>li classprodcat__li-3>a href/two-cylinder-nitrous-systems/ classprodcat__a-3 data-parent-href/nitrous/|/atv-snowmobile-pwc/|/two-cylinder-nitrous-systems/ data-parent-nameNitrous Express|ATV/Snowmobile/PWC|Two Cylinder Nitrous Systems data-keyAB66E10D63134F6CAB182D1C7153D88C>span classcat-nm>Two Cylinder Nitrous Systems/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/utv-nitrous-systems/ classprodcat__a-2 data-parent-href/nitrous/|/utv-nitrous-systems/ data-parent-nameNitrous Express|UTV Nitrous Systems data-key030017484223496A83EB41E689DC8E17>span classcat-nm>UTV Nitrous Systems/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/single-cylinder-side-by-side-systems/ classprodcat__a-3 data-parent-href/nitrous/|/utv-nitrous-systems/|/single-cylinder-side-by-side-systems/ data-parent-nameNitrous Express|UTV Nitrous Systems|1 Cylinder Side By Side Systems data-key8380F69BE0D24FD2A00614D987C95203>span classcat-nm>1 Cylinder Side By Side Systems/span>/a>/li>li classprodcat__li-3>a href/2-cylinder-side-by-side-systems/ classprodcat__a-3 data-parent-href/nitrous/|/utv-nitrous-systems/|/2-cylinder-side-by-side-systems/ data-parent-nameNitrous Express|UTV Nitrous Systems|2 Cylinder Side By Side Systems data-key15B69D37302147AA99E972074F874D4E>span classcat-nm>2 Cylinder Side By Side Systems/span>/a>/li>li classprodcat__li-3>a href/3-cylinder-side-by-side-systems/ classprodcat__a-3 data-parent-href/nitrous/|/utv-nitrous-systems/|/3-cylinder-side-by-side-systems/ data-parent-nameNitrous Express|UTV Nitrous Systems|3 Cylinder Side By Side Systems data-keyFF38201FBD58408E9B94CDD90418103C>span classcat-nm>3 Cylinder Side By Side Systems/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/nitrous-accessories/ classprodcat__a-2 data-parent-href/nitrous/|/nitrous-accessories/ data-parent-nameNitrous Express|Nitrous Accessories data-key3B2DC114DD32405CA112F88427B6381A>span classcat-nm>Nitrous Accessories/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/bottle-brackets/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/bottle-brackets/ data-parent-nameNitrous Express|Nitrous Accessories|Bottle Brackets data-key852BD616D383471694B72DACEA2A518D>span classcat-nm>Bottle Brackets/span>/a>/li>li classprodcat__li-3>a href/bottle-heaters/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/bottle-heaters/ data-parent-nameNitrous Express|Nitrous Accessories|Bottle Heaters data-keyA02DB0804A9749888639DA51AEA0FC8F>span classcat-nm>Bottle Heaters/span>/a>/li>li classprodcat__li-3>a href/bottle-jackets/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/bottle-jackets/ data-parent-nameNitrous Express|Nitrous Accessories|Bottle Jackets data-keyA72E06F4085A4AD2AE2D4B244F079E22>span classcat-nm>Bottle Jackets/span>/a>/li>li classprodcat__li-3>a href/remote-bottle-openers/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/remote-bottle-openers/ data-parent-nameNitrous Express|Nitrous Accessories|Bottle Openers (Remote) data-key4E52F8A92C3E449FACCF84BC7D48784C>span classcat-nm>Bottle Openers (Remote)/span>/a>/li>li classprodcat__li-3>a href/bottle-valves/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/bottle-valves/ data-parent-nameNitrous Express|Nitrous Accessories|Bottle Valves data-key87259CBBDD494581992E352563CCA5BE>span classcat-nm>Bottle Valves/span>/a>/li>li classprodcat__li-3>a href/bottles/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/bottles/ data-parent-nameNitrous Express|Nitrous Accessories|Bottles data-keyDF5CC992397649C68C3FF4E581092361>span classcat-nm>Bottles/span>/a>/li>li classprodcat__li-3>a hrefpc_combined_results.asp?pc_id77149E9391B54CD9898E00B2B263CEF9 classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|pc_combined_results.asp?pc_id77149E9391B54CD9898E00B2B263CEF9 data-parent-nameNitrous Express|Nitrous Accessories|Burst plates data-key77149E9391B54CD9898E00B2B263CEF9>span classcat-nm>Burst plates/span>/a>/li>li classprodcat__li-3>a href/fuel-pressure-safety-switch/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/fuel-pressure-safety-switch/ data-parent-nameNitrous Express|Nitrous Accessories|Fuel Pressure Safety Switch data-keyE407403AB62B4FC79FCA2F435919512D>span classcat-nm>Fuel Pressure Safety Switch/span>/a>/li>li classprodcat__li-3>a href/gauges/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/gauges/ data-parent-nameNitrous Express|Nitrous Accessories|Gauges data-key5448944CE6EB45FF93387EF95F43489D>span classcat-nm>Gauges/span>/a>/li>li classprodcat__li-3>a href/gen-x-accessory-packages/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/gen-x-accessory-packages/ data-parent-nameNitrous Express|Nitrous Accessories|Gen-X Accessory Packages data-keyCFC8709D8CD64B55A24FC398E0DADFED>span classcat-nm>Gen-X Accessory Packages/span>/a>/li>li classprodcat__li-3>a href/Ball_Valves.asp classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/Ball_Valves.asp data-parent-nameNitrous Express|Nitrous Accessories|In-Line Ball Valves data-keyB51B15C0020A48E1AA4737142ADFDB82>span classcat-nm>In-Line Ball Valves/span>/a>/li>li classprodcat__li-3>a href/jets/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/jets/ data-parent-nameNitrous Express|Nitrous Accessories|Jets data-key232B4524A2EF4628B6A07F1D025FBD1B>span classcat-nm>Jets/span>/a>/li>li classprodcat__li-3>a href/line-kits/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/line-kits/ data-parent-nameNitrous Express|Nitrous Accessories|Line Kits data-key6EB897F68B904A7BA56D123286547936>span classcat-nm>Line Kits/span>/a>/li>li classprodcat__li-3>a href/misc-accessories/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/misc-accessories/ data-parent-nameNitrous Express|Nitrous Accessories|Misc Accessories data-key4E5326492E7349A586B47DECA42255A7>span classcat-nm>Misc Accessories/span>/a>/li>li classprodcat__li-3>a href/nitrous-plates/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/nitrous-plates/ data-parent-nameNitrous Express|Nitrous Accessories|Nitrous Plates data-keyFB04B5EC463747759D7E17402FE12A42>span classcat-nm>Nitrous Plates/span>/a>/li>li classprodcat__li-3>a href/nozzles-and-nozzle-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/nozzles-and-nozzle-fittings/ data-parent-nameNitrous Express|Nitrous Accessories|Nozzles and Nozzle Fittings data-key4201FBC73D6C434095996C313491C168>span classcat-nm>Nozzles and Nozzle Fittings/span>/a>/li>li classprodcat__li-3>a href/plumbing-accessories/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/plumbing-accessories/ data-parent-nameNitrous Express|Nitrous Accessories|Plumbing Accessories data-key45E5AC4F1FFC4E368D5BF818B7FF4408>span classcat-nm>Plumbing Accessories/span>/a>/li>li classprodcat__li-3>a href/plumbing-kits/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/plumbing-kits/ data-parent-nameNitrous Express|Nitrous Accessories|Plumbing Kits data-keyB52749C8CF6648ED9F87E90425F551EF>span classcat-nm>Plumbing Kits/span>/a>/li>li classprodcat__li-3>a href/progressive-nitrous-controllers/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/progressive-nitrous-controllers/ data-parent-nameNitrous Express|Nitrous Accessories|Progressive Nitrous Controllers data-key42A99390D20242298910358F4A461574>span classcat-nm>Progressive Nitrous Controllers/span>/a>/li>li classprodcat__li-3>a href/purge-systems/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/purge-systems/ data-parent-nameNitrous Express|Nitrous Accessories|Purge Systems data-key3ECBEEE7B354419B9A3052613BCA0FBE>span classcat-nm>Purge Systems/span>/a>/li>li classprodcat__li-3>a href/Rollbar-Mounts.asp classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/Rollbar-Mounts.asp data-parent-nameNitrous Express|Nitrous Accessories|Roll Bar Mounting Clamps data-key42AD2A475E9E46C3AAEAF9E30F4C26CA>span classcat-nm>Roll Bar Mounting Clamps/span>/a>/li>li classprodcat__li-3>a href/solenoid-brackets/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/solenoid-brackets/ data-parent-nameNitrous Express|Nitrous Accessories|Solenoid Brackets data-keyA18D1FF383BF478DB75819B1F8EED606>span classcat-nm>Solenoid Brackets/span>/a>/li>li classprodcat__li-3>a href/solenoid-rebuild-parts-and-accessories/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/solenoid-rebuild-parts-and-accessories/ data-parent-nameNitrous Express|Nitrous Accessories|Solenoid Rebuild Parts and Accessories data-key4A2B24596BD94344818215DA9C393FA5>span classcat-nm>Solenoid Rebuild Parts and Accessories/span>/a>/li>li classprodcat__li-3>a href/nitrous-and-fuel-solenoids/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/nitrous-and-fuel-solenoids/ data-parent-nameNitrous Express|Nitrous Accessories|Solenoids data-key0F8807C403914A0B8F4CE1D2DDC828BB>span classcat-nm>Solenoids/span>/a>/li>li classprodcat__li-3>a href/switch-panels/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/switch-panels/ data-parent-nameNitrous Express|Nitrous Accessories|Switch Panels data-keyC66F90FEBF7446DD9EBD9DC6628A9AE3>span classcat-nm>Switch Panels/span>/a>/li>li classprodcat__li-3>a href/tools/ classprodcat__a-3 data-parent-href/nitrous/|/nitrous-accessories/|/tools/ data-parent-nameNitrous Express|Nitrous Accessories|Tools data-key30270C1DC70342AE953427F4CABB09D7>span classcat-nm>Tools/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/electronics/ classprodcat__a-2 data-parent-href/nitrous/|/electronics/ data-parent-nameNitrous Express|Electronics data-key6FA39D9DD30A46E89B7F0818685B021C>span classcat-nm>Electronics/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/activation-switches/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/activation-switches/ data-parent-nameNitrous Express|Electronics|Activation Switches data-key445654DC50704FD199AF44DEE8A806D6>span classcat-nm>Activation Switches/span>/a>/li>li classprodcat__li-3>a href/arming-switches/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/arming-switches/ data-parent-nameNitrous Express|Electronics|Arming Switches data-keyB3971DF4689F41B3868C6ADC6EA2F1B3>span classcat-nm>Arming Switches/span>/a>/li>li classprodcat__li-3>a href/delay-timers/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/delay-timers/ data-parent-nameNitrous Express|Electronics|Delay Timers data-key15483155814149C19CAE8914EAE39BB9>span classcat-nm>Delay Timers/span>/a>/li>li classprodcat__li-3>a href/fuel-pressure-safety-switch/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/fuel-pressure-safety-switch/ data-parent-nameNitrous Express|Electronics|Fuel Pressure Safety Switch data-keyE407403AB62B4FC79FCA2F435919512D>span classcat-nm>Fuel Pressure Safety Switch/span>/a>/li>li classprodcat__li-3>a href/progressive-nitrous-controllers/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/progressive-nitrous-controllers/ data-parent-nameNitrous Express|Electronics|Progressive Nitrous Controllers data-key42A99390D20242298910358F4A461574>span classcat-nm>Progressive Nitrous Controllers/span>/a>/li>li classprodcat__li-3>a href/rpm-window-switches/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/rpm-window-switches/ data-parent-nameNitrous Express|Electronics|RPM Window Switches data-key1EB8938AB69E47C7AD24521DB3DA3273>span classcat-nm>RPM Window Switches/span>/a>/li>li classprodcat__li-3>a href/sensors/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/sensors/ data-parent-nameNitrous Express|Electronics|Sensors data-keyE5148162820041108CEA4DFE7F9908A5>span classcat-nm>Sensors/span>/a>/li>li classprodcat__li-3>a href/tps-wot-switches/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/tps-wot-switches/ data-parent-nameNitrous Express|Electronics|TPS WOT Switches data-key73BE46A4BC724CB08FA62D525B82DAF1>span classcat-nm>TPS WOT Switches/span>/a>/li>li classprodcat__li-3>a href/wiring-accessories/ classprodcat__a-3 data-parent-href/nitrous/|/electronics/|/wiring-accessories/ data-parent-nameNitrous Express|Electronics|Wiring Accessories data-key383217CB01B2446398EB08427219BBEF>span classcat-nm>Wiring Accessories/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/fuel-products/ classprodcat__a-2 data-parent-href/nitrous/|/fuel-products/ data-parent-nameNitrous Express|Fuel Products data-key8BFFD0DA0D96413A8E80DFA5CA46BD74>span classcat-nm>Fuel Products/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/SnowFuel/Filters-and-brackets.asp classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/SnowFuel/Filters-and-brackets.asp data-parent-nameNitrous Express|Fuel Products|Fuel Filters and Brackets data-keyE7999A6697774912AC5B65A852B93D43>span classcat-nm>Fuel Filters and Brackets/span>/a>/li>li classprodcat__li-3>a href/fuel-logs-and-mounting-brackets/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/fuel-logs-and-mounting-brackets/ data-parent-nameNitrous Express|Fuel Products|Fuel Logs and Mounting Brackets data-key5FF99473CBAC414C94E7498BA16BEE80>span classcat-nm>Fuel Logs and Mounting Brackets/span>/a>/li>li classprodcat__li-3>a href/fuel-pressure-gauges/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/fuel-pressure-gauges/ data-parent-nameNitrous Express|Fuel Products|Fuel Pressure Gauges data-keyCE6151942C034D62B20A89FF6935243B>span classcat-nm>Fuel Pressure Gauges/span>/a>/li>li classprodcat__li-3>a href/fuel-pressure-regulators/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/fuel-pressure-regulators/ data-parent-nameNitrous Express|Fuel Products|Fuel Pressure Regulators data-keyED67CD428666465BA57365F679386E02>span classcat-nm>Fuel Pressure Regulators/span>/a>/li>li classprodcat__li-3>a href/fuel-pumps/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/fuel-pumps/ data-parent-nameNitrous Express|Fuel Products|Fuel Pumps data-key97A075898D124C2392DD2B983C150978>span classcat-nm>Fuel Pumps/span>/a>/li>li classprodcat__li-3>a href/fuel-rail-adapters/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/fuel-rail-adapters/ data-parent-nameNitrous Express|Fuel Products|Fuel Rail Adapters data-key6ECA8EDCAAB4415D9091A3495E28F7AD>span classcat-nm>Fuel Rail Adapters/span>/a>/li>li classprodcat__li-3>a href/fuel-tank-adapters/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/fuel-tank-adapters/ data-parent-nameNitrous Express|Fuel Products|Fuel Tank Adapters data-key9015E1FE6DCE416DAAB61B47BC4F8AAA>span classcat-nm>Fuel Tank Adapters/span>/a>/li>li classprodcat__li-3>a href/safe-systems/ classprodcat__a-3 data-parent-href/nitrous/|/fuel-products/|/safe-systems/ data-parent-nameNitrous Express|Fuel Products|SAFE Systems data-keyD8B21739AF3B4F8FB6172374550AF4D3>span classcat-nm>SAFE Systems/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/fittings/ classprodcat__a-2 data-parent-href/nitrous/|/fittings/ data-parent-nameNitrous Express|Fittings data-keyEC183FA6C6174D1F86ACE538441D3DE0>span classcat-nm>Fittings/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/an-adapter-manifolds/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/an-adapter-manifolds/ data-parent-nameNitrous Express|Fittings|AN Adapter Manifolds data-key540E6196585D4A3B90918F780A1F450F>span classcat-nm>AN Adapter Manifolds/span>/a>/li>li classprodcat__li-3>a href/an-npt-adapters/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/an-npt-adapters/ data-parent-nameNitrous Express|Fittings|AN To NPT Adapters data-keyA1941427F65747ADA2FD28B58A1BC510>span classcat-nm>AN To NPT Adapters/span>/a>/li>li classprodcat__li-3>a href/b-nuts-and-sleeves/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/b-nuts-and-sleeves/ data-parent-nameNitrous Express|Fittings|B-Nuts and Sleeves data-key2F5FDAA4E27543C3A3F5A2BF9647288B>span classcat-nm>B-Nuts and Sleeves/span>/a>/li>li classprodcat__li-3>a href/bottle-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/bottle-fittings/ data-parent-nameNitrous Express|Fittings|Bottle Fittings data-key9F577FC34A7541DEBC688164CA6993F0>span classcat-nm>Bottle Fittings/span>/a>/li>li classprodcat__li-3>a href/caps-and-plugs/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/caps-and-plugs/ data-parent-nameNitrous Express|Fittings|Caps and Plugs data-key982566BDF1954930BD7AEE8B3055490F>span classcat-nm>Caps and Plugs/span>/a>/li>li classprodcat__li-3>a href/compression-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/compression-fittings/ data-parent-nameNitrous Express|Fittings|Compression Fittings data-key96A676CA6C2C4E1FB958665B1B7A3F35>span classcat-nm>Compression Fittings/span>/a>/li>li classprodcat__li-3>a href/distribution-blocks-and-tubing-kits/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/distribution-blocks-and-tubing-kits/ data-parent-nameNitrous Express|Fittings|Distribution Blocks and Tubing Kits data-keyE865B15BD7FA4012ACF0D98BCE8157CE>span classcat-nm>Distribution Blocks and Tubing Kits/span>/a>/li>li classprodcat__li-3>a hrefpc_combined_results.asp?pc_id7AE99688B57342E6B51949391270E726 classprodcat__a-3 data-parent-href/nitrous/|/fittings/|pc_combined_results.asp?pc_id7AE99688B57342E6B51949391270E726 data-parent-nameNitrous Express|Fittings|Filter Fittings data-key7AE99688B57342E6B51949391270E726>span classcat-nm>Filter Fittings /span>/a>/li>li classprodcat__li-3>a href/fuel-rail-adapters/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/fuel-rail-adapters/ data-parent-nameNitrous Express|Fittings|Fuel Rail Adapters data-key6ECA8EDCAAB4415D9091A3495E28F7AD>span classcat-nm>Fuel Rail Adapters/span>/a>/li>li classprodcat__li-3>a href/hose-barb-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/hose-barb-fittings/ data-parent-nameNitrous Express|Fittings|Hose Barb Fittings data-key8E92555E7BE340E7BA56F3BDC8E5E186>span classcat-nm>Hose Barb Fittings/span>/a>/li>li classprodcat__li-3>a href/jet-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/jet-fittings/ data-parent-nameNitrous Express|Fittings|Jet Fittings data-key36AD796B719F4D17ACDF269B07596B46>span classcat-nm>Jet Fittings/span>/a>/li>li classprodcat__li-3>a href/miscellaneous-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/miscellaneous-fittings/ data-parent-nameNitrous Express|Fittings|Misc Fittings data-key0C1DC7017BF64F92BE480650F23E7572>span classcat-nm>Misc Fittings/span>/a>/li>li classprodcat__li-3>a href/nitrous-filters/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/nitrous-filters/ data-parent-nameNitrous Express|Fittings|Nitrous Filters data-keyA3E7FB983C6F4E66A94DB3C10D5D1FEA>span classcat-nm>Nitrous Filters/span>/a>/li>li classprodcat__li-3>a href/pure-flow-y-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/pure-flow-y-fittings/ data-parent-nameNitrous Express|Fittings|Pure Flow Ys data-key4E58D3F11E2A4FABBDD2FB48FF79A8DA>span classcat-nm>Pure Flow Ys/span>/a>/li>li classprodcat__li-3>a href/reducers/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/reducers/ data-parent-nameNitrous Express|Fittings|Reducers data-key61AD432B9BE84541890E836427B2199F>span classcat-nm>Reducers/span>/a>/li>li classprodcat__li-3>a href/safety-blow-off-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/safety-blow-off-fittings/ data-parent-nameNitrous Express|Fittings|Safety Blow Off Fittings data-key6D08D9772F874229845138F9F196410B>span classcat-nm>Safety Blow Off Fittings/span>/a>/li>li classprodcat__li-3>a href/solenoid-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/solenoid-fittings/ data-parent-nameNitrous Express|Fittings|Solenoid Fittings data-key64C5B67A24DA4D838C67AF7EFBF0E2D4>span classcat-nm>Solenoid Fittings/span>/a>/li>li classprodcat__li-3>a href/t-fittings/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/t-fittings/ data-parent-nameNitrous Express|Fittings|T-Fittings data-key7191F8F7B92A44ECABC9F12D207FE55A>span classcat-nm>T-Fittings/span>/a>/li>li classprodcat__li-3>a href/Throttle-Body-Plate-Bolts.asp classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/Throttle-Body-Plate-Bolts.asp data-parent-nameNitrous Express|Fittings|Throttle Body Plate Bolts data-key178B0AB59D57401FA075F70D4066CCF0>span classcat-nm>Throttle Body Plate Bolts /span>/a>/li>li classprodcat__li-3>a href/unions/ classprodcat__a-3 data-parent-href/nitrous/|/fittings/|/unions/ data-parent-nameNitrous Express|Fittings|Unions data-keyA64F45C71A8C4E5CBD88463977476E01>span classcat-nm>Unions/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/steel-braided-lines/ classprodcat__a-2 data-parent-href/nitrous/|/steel-braided-lines/ data-parent-nameNitrous Express|AN Lines data-keyEDDB328AB66D43AF8EB916D28BC7C2CA>span classcat-nm>AN Lines/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/3an-lines/ classprodcat__a-3 data-parent-href/nitrous/|/steel-braided-lines/|/3an-lines/ data-parent-nameNitrous Express|AN Lines|3AN Lines data-key0ECE0E377CE347448560C81AEE69436A>span classcat-nm>3AN Lines/span>/a>/li>li classprodcat__li-3>a href/4an-lines/ classprodcat__a-3 data-parent-href/nitrous/|/steel-braided-lines/|/4an-lines/ data-parent-nameNitrous Express|AN Lines|4AN Lines data-keyA57B439B2D8241038078BFEBDA1D6B34>span classcat-nm>4AN Lines/span>/a>/li>li classprodcat__li-3>a href/4an-3an-sho/ classprodcat__a-3 data-parent-href/nitrous/|/steel-braided-lines/|/4an-3an-sho/ data-parent-nameNitrous Express|AN Lines|4AN-3AN (S.H.O.) data-keyA8777785B73E4FEDB4249A84A7634E35>span classcat-nm>4AN-3AN (S.H.O.)/span>/a>/li>li classprodcat__li-3>a href/6an-lines/ classprodcat__a-3 data-parent-href/nitrous/|/steel-braided-lines/|/6an-lines/ data-parent-nameNitrous Express|AN Lines|6AN Lines data-key652DADE512A64E4EB5B7E19AAAFE3501>span classcat-nm>6AN Lines/span>/a>/li>li classprodcat__li-3>a href/8an-lines/ classprodcat__a-3 data-parent-href/nitrous/|/steel-braided-lines/|/8an-lines/ data-parent-nameNitrous Express|AN Lines|8AN Lines data-keyAFE3D1C001884BABB9D75D753D6EAA45>span classcat-nm>8AN Lines/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/refill-stations/ classprodcat__a-2 data-parent-href/nitrous/|/refill-stations/ data-parent-nameNitrous Express|Refill Stations data-keyAAA49BE4BFDF4ECA91ED04B52C1BF2E6>span classcat-nm>Refill Stations/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/pump-and-transfer-station/ classprodcat__a-3 data-parent-href/nitrous/|/refill-stations/|/pump-and-transfer-station/ data-parent-nameNitrous Express|Refill Stations|Pump and Transfer Station data-key8266537D3D204F51893059A54263B372>span classcat-nm>Pump and Transfer Station/span>/a>/li>li classprodcat__li-3>a href/refill-fittings-and-accessories/ classprodcat__a-3 data-parent-href/nitrous/|/refill-stations/|/refill-fittings-and-accessories/ data-parent-nameNitrous Express|Refill Stations|Refill Fittings and Accessories data-key29A0C689E9E243508ACE214647F8E8C4>span classcat-nm>Refill Fittings and Accessories/span>/a>/li>/ul>/li>/ul>/li>li classprodcat__li-1 >a href/Snow-Performance-water-methanol/ classprodcat__a-1 data-parent-href/Snow-Performance-water-methanol/ data-parent-nameSnow Water Methanol data-key47ACCD5A99AF4CB9958ECFFE5CE16149>span classcat-nm>Snow Water Methanol/span>/a>ul classprodcat__ul-2>li classprodcat__li-2>a href/turbo-fabrication/ classprodcat__a-2 data-parent-href/Snow-Performance-water-methanol/|/turbo-fabrication/ data-parent-nameSnow Water Methanol|Turbo Fabrication data-keyA00C8B86A56A46A6BD8EE35BDEB90682>span classcat-nm>Turbo Fabrication/span>/a>/li>li classprodcat__li-2 >a href/water-methanol-accessories/ classprodcat__a-2 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/ data-parent-nameSnow Water Methanol|Water Methanol Accessories data-key1AE900E2D84540BB8C471B81863F0C14>span classcat-nm>Water Methanol Accessories/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a hrefpc_combined_results.asp?pc_idB09D62B486C74A44B96BD808D5DDEA17 classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|pc_combined_results.asp?pc_idB09D62B486C74A44B96BD808D5DDEA17 data-parent-nameSnow Water Methanol|Water Methanol Accessories|Boost Taps data-keyB09D62B486C74A44B96BD808D5DDEA17>span classcat-nm>Boost Taps /span>/a>/li>li classprodcat__li-3>a href/water-meth-rings.asp classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-meth-rings.asp data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Meth Rings data-keyDD91DA4B114B4D19B14AFE2A2E70FF04>span classcat-nm>Water Meth Rings/span>/a>/li>li classprodcat__li-3>a href/water-methanol-controllers/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-controllers/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Controllers/Electrical data-key4CC3163E8B6C4573BA87240C88ACAB28>span classcat-nm>Water Methanol Controllers/Electrical/span>/a>/li>li classprodcat__li-3>a href/water-methanol-direct-port-manifolds/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-direct-port-manifolds/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Direct Ports/Manifolds data-keyF04F516933FA46C1901A88002D6F1474>span classcat-nm>Water Methanol Direct Ports/Manifolds/span>/a>/li>li classprodcat__li-3>a hrefpc_combined_results.asp?pc_idCB4AFEF00125459ABB5AFE1310F18083 classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|pc_combined_results.asp?pc_idCB4AFEF00125459ABB5AFE1310F18083 data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Filters data-keyCB4AFEF00125459ABB5AFE1310F18083>span classcat-nm>Water Methanol Filters /span>/a>/li>li classprodcat__li-3>a href/water-methanol-fittings/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-fittings/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Fittings/Plumbing data-keyE0F99221ADFF46569B15D63A1190294A>span classcat-nm>Water Methanol Fittings/Plumbing/span>/a>/li>li classprodcat__li-3>a href/water-methanol-fluid/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-fluid/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Fluid data-key9DF63112DAC14CC4BA566A08F306CF2F>span classcat-nm>Water Methanol Fluid/span>/a>/li>li classprodcat__li-3>a href/water-methanol-nozzles/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-nozzles/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Nozzles data-key6D9C365178A345A58BE0AEB248410703>span classcat-nm>Water Methanol Nozzles/span>/a>/li>li classprodcat__li-3>a href/water-methanol-plates/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-plates/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Plates data-key95935B73F3DF447B9B7E6752AD4F0994>span classcat-nm>Water Methanol Plates/span>/a>/li>li classprodcat__li-3>a href/water-methanol-pumps/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-pumps/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Pumps and Brackets data-key7D0880391C074CB4BA4EA8E98677E134>span classcat-nm>Water Methanol Pumps and Brackets/span>/a>/li>li classprodcat__li-3>a href/water-methanol-solenoids/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-solenoids/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Solenoids data-keyD24087A2FA8141F4B2E04905F2CC4030>span classcat-nm>Water Methanol Solenoids/span>/a>/li>li classprodcat__li-3>a href/water-methanol-tanks/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-accessories/|/water-methanol-tanks/ data-parent-nameSnow Water Methanol|Water Methanol Accessories|Water Methanol Tanks data-key0D503E55A21B4DC7BF7E81C036EFD6E6>span classcat-nm>Water Methanol Tanks/span>/a>/li>/ul>/li>li classprodcat__li-2 >a href/water-methanol-systems/ classprodcat__a-2 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/ data-parent-nameSnow Water Methanol|Water Methanol Systems data-keyF5DE5FA1B7224647917EB87AD36F5534>span classcat-nm>Water Methanol Systems/span>/a>ul classprodcat__ul-3>li classprodcat__li-3 >a href/diesel/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/diesel/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Diesel data-key0134F606F4764F1B91C83D5F1E54AAF2>span classcat-nm>Diesel/span>/a>ul classprodcat__ul-4>li classprodcat__li-4>a href/diesel-stage-1-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/diesel/|/diesel-stage-1-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Diesel|Diesel Stage 1 Boost Cooler data-key14909016DB33448EB00A04700D701A75>span classcat-nm>Diesel Stage 1 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/stage-2-diesel.asp classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/diesel/|/stage-2-diesel.asp data-parent-nameSnow Water Methanol|Water Methanol Systems|Diesel|Diesel Stage 2 Boost Cooler data-keyB4D4D67864B7481A9557736506F668B0>span classcat-nm>Diesel Stage 2 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/diesel-stage-2-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/diesel/|/diesel-stage-2-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Diesel|Diesel Stage 2.5 Boost Cooler data-keyCB0C5C024E64427C838DE62C690E50FA>span classcat-nm>Diesel Stage 2.5 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/diesel-stage-3-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/diesel/|/diesel-stage-3-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Diesel|Diesel Stage 3 Boost Cooler data-key2EEB7BC4B5CE4ED0BE18536DA2A58A57>span classcat-nm>Diesel Stage 3 Boost Cooler/span>/a>/li>/ul>/li>li classprodcat__li-3 >a href/gasoline-e85/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline data-key1FD213254D3E4FA6AA56DE552EC14213>span classcat-nm>Gasoline/span>/a>ul classprodcat__ul-4>li classprodcat__li-4>a href/Side-by-Side-Systems.asp classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/Side-by-Side-Systems.asp data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Side by Side Systems data-key70E0E6043EB54AD8ADAD245FB01283F1>span classcat-nm>Side by Side Systems/span>/a>/li>li classprodcat__li-4>a href/stage-1-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/stage-1-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Stage 1 Boost Cooler data-keyE674F04095F44AC1B648DB5A536DF174>span classcat-nm>Stage 1 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/stage-2-gasoline.asp classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/stage-2-gasoline.asp data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Stage 2 Boost Cooler data-key303B7755557A4F0B847FB54884D3F868>span classcat-nm>Stage 2 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/stage-2-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/stage-2-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Stage 2.5 Boost Cooler data-key9B89051D9B334BADBC1FABD91E5DCE7F>span classcat-nm>Stage 2.5 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/stage-3-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/stage-3-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Stage 3 Boost Cooler data-keyA54A5898A7914D9E8055A62308C39E66>span classcat-nm>Stage 3 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/Stage-3-5-Boost-Cooler.asp classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/Stage-3-5-Boost-Cooler.asp data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Stage 3.5 Boost Cooler data-key37B71D71E8BA483ABBF4124D96D33990>span classcat-nm>Stage 3.5 Boost Cooler/span>/a>/li>li classprodcat__li-4>a href/stage-4-boost-cooler/ classprodcat__a-4 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/gasoline-e85/|/stage-4-boost-cooler/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Gasoline|Stage 4 Boost Cooler data-key710AC12F914B43649C6A9C187787D67D>span classcat-nm>Stage 4 Boost Cooler/span>/a>/li>/ul>/li>li classprodcat__li-3>a href/Naturally-Aspirated/ classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/Naturally-Aspirated/ data-parent-nameSnow Water Methanol|Water Methanol Systems|Naturally Aspirated data-key0A013F476F1C4531920CDB26C7262130>span classcat-nm>Naturally Aspirated /span>/a>/li>li classprodcat__li-3>a href/High-Pressure-Systems.asp classprodcat__a-3 data-parent-href/Snow-Performance-water-methanol/|/water-methanol-systems/|/High-Pressure-Systems.asp data-parent-nameSnow Water Methanol|Water Methanol Systems|High Pressure Systems data-keyF5B506C6B98A4FA3B67A57CC34DDED97>span classcat-nm>High Pressure Systems/span>/a>/li>/ul>/li>/ul>/li>li classprodcat__li-1 >a href/Snow-Performance-Fuel.asp classprodcat__a-1 data-parent-href/Snow-Performance-Fuel.asp data-parent-nameSnow Fuel Products data-keyF289808DB43D481B8A9D3CE7FCCC895D>span classcat-nm>Snow Fuel Products/span>/a>ul classprodcat__ul-2>li classprodcat__li-2>a href/Flex-Fuel.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Flex-Fuel.asp data-parent-nameSnow Fuel Products|Flex Fuel data-keyA3F0C00C77F9431DA273789D43E10EAE>span classcat-nm>Flex Fuel/span>/a>/li>li classprodcat__li-2>a href/SnowFuel/Filters-and-brackets.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/SnowFuel/Filters-and-brackets.asp data-parent-nameSnow Fuel Products|Fuel Filters and Brackets data-keyE7999A6697774912AC5B65A852B93D43>span classcat-nm>Fuel Filters and Brackets/span>/a>/li>li classprodcat__li-2>a href/Snowfuel/gauges.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Snowfuel/gauges.asp data-parent-nameSnow Fuel Products|Fuel Gauges data-key6802F1A0DDE64F15BD3364AF422ADE77>span classcat-nm>Fuel Gauges/span>/a>/li>li classprodcat__li-2>a href/Fuel-Hats.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Hats.asp data-parent-nameSnow Fuel Products|Fuel Hats data-keyA41299BDDA1E45BC94001F8BB0C127C8>span classcat-nm>Fuel Hats/span>/a>/li>li classprodcat__li-2 >a href/Fuel-Hoses/ classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Hoses/ data-parent-nameSnow Fuel Products|Fuel Hose / Line Kits data-key8393E207D4204E18B31A6557FD99750C>span classcat-nm>Fuel Hose / Line Kits/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/10AN-Fuel-Hose/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Hoses/|/10AN-Fuel-Hose/ data-parent-nameSnow Fuel Products|Fuel Hose / Line Kits|10AN Fuel Hose data-key8A9733CB92C34FDE9920FB8C68A77703>span classcat-nm>10AN Fuel Hose/span>/a>/li>li classprodcat__li-3>a href/12AN-Fuel-Hose/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Hoses/|/12AN-Fuel-Hose/ data-parent-nameSnow Fuel Products|Fuel Hose / Line Kits|12AN Fuel Hose data-key8FA8424A420B457D96520448B1033E98>span classcat-nm>12AN Fuel Hose/span>/a>/li>li classprodcat__li-3>a href/6AN-Fuel-Hose/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Hoses/|/6AN-Fuel-Hose/ data-parent-nameSnow Fuel Products|Fuel Hose / Line Kits|6AN Fuel Hose data-key5218A5FF3022434590FC67529E91AF1A>span classcat-nm>6AN Fuel Hose/span>/a>/li>li classprodcat__li-3>a href/8AN-Fuel-Hose/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Hoses/|/8AN-Fuel-Hose/ data-parent-nameSnow Fuel Products|Fuel Hose / Line Kits|8AN Fuel Hose data-keyA6EE66238745495BAAF446EB2012ED31>span classcat-nm>8AN Fuel Hose/span>/a>/li>/ul>/li>li classprodcat__li-2>a href/SnowFuel/Snow-Fuel-Tools.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/SnowFuel/Snow-Fuel-Tools.asp data-parent-nameSnow Fuel Products|Snow Fuel Tools data-key64E50BABDEC0484A98FC5675C0FD18FF>span classcat-nm>Snow Fuel Tools/span>/a>/li>li classprodcat__li-2>a href/Snow-Fuel-Systems.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Fuel-Systems.asp data-parent-nameSnow Fuel Products|Supplemental fuel systems data-key9F80E8E92F924689854B095332AA5264>span classcat-nm>Supplemental fuel systems/span>/a>/li>li classprodcat__li-2 >a href/Fuel-Rails/ classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Rails/ data-parent-nameSnow Fuel Products|Fuel Rails data-key9DF7CF00135F461FBEF8FDF2BA895E04>span classcat-nm>Fuel Rails/span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/Fuel-Rails/Coyote-Fuel-Rails.asp classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Rails/|/Fuel-Rails/Coyote-Fuel-Rails.asp data-parent-nameSnow Fuel Products|Fuel Rails|Coyote Fuel Rails data-keyD3E771015C3C4E72A084411D8CE0B7F8>span classcat-nm>Coyote Fuel Rails/span>/a>/li>li classprodcat__li-3>a href/Fuel-Rails/Hemi-Fuel-Rails.asp classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Rails/|/Fuel-Rails/Hemi-Fuel-Rails.asp data-parent-nameSnow Fuel Products|Fuel Rails|Hemi Fuel Rails data-key7443903D34D34C0C84FA0288637CC0FF>span classcat-nm>Hemi Fuel Rails/span>/a>/li>li classprodcat__li-3>a href/Injector-Spacers-and-O-rings/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Rails/|/Injector-Spacers-and-O-rings/ data-parent-nameSnow Fuel Products|Fuel Rails|Injector Spacers, O-rings, and brackets data-keyFEDCC6B19A494B4ABA6B9A0125CED62C>span classcat-nm>Injector Spacers, O-rings, and brackets/span>/a>/li>li classprodcat__li-3>a href/Fuel-Rails/LS-Engine-Fuel-Rails.asp classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Rails/|/Fuel-Rails/LS-Engine-Fuel-Rails.asp data-parent-nameSnow Fuel Products|Fuel Rails|LS Engine Fuel Rails data-key7C0D2FEB838E4E73A2C595AFFDD09967>span classcat-nm>LS Engine Fuel Rails/span>/a>/li>/ul>/li>li classprodcat__li-2>a href/Fuel-Regulators/ classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Fuel-Regulators/ data-parent-nameSnow Fuel Products|Regulators data-keyC43665D4B9874A96AD4D45CF9519BE36>span classcat-nm>Regulators /span>/a>/li>li classprodcat__li-2 >a href/Snow-Performance-Fuel-Fittings/ classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/ data-parent-nameSnow Fuel Products|Fuel Fittings data-key06A3F3E6EC3D4800A6FB0458C27C1850>span classcat-nm>Fuel Fittings /span>/a>ul classprodcat__ul-3>li classprodcat__li-3>a href/SnowFuel/Bulkheads.asp classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/SnowFuel/Bulkheads.asp data-parent-nameSnow Fuel Products|Fuel Fittings |Bulkheads data-key003BBE32072243F8BEF42D515509DE1D>span classcat-nm>Bulkheads/span>/a>/li>li classprodcat__li-3>a href/caps-and-plugs/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/caps-and-plugs/ data-parent-nameSnow Fuel Products|Fuel Fittings |Caps and Plugs data-key982566BDF1954930BD7AEE8B3055490F>span classcat-nm>Caps and Plugs/span>/a>/li>li classprodcat__li-3>a href/SnowFuel/Check-Valves.asp classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/SnowFuel/Check-Valves.asp data-parent-nameSnow Fuel Products|Fuel Fittings |Check Valves data-keyA0D809F516B74AC8808CD51CC147E52B>span classcat-nm>Check Valves /span>/a>/li>li classprodcat__li-3>a href/Snow-Fuel-Hose-Ends/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/Snow-Fuel-Hose-Ends/ data-parent-nameSnow Fuel Products|Fuel Fittings |Hose Ends data-keyA21FB700A7154F51A6B366BB170BADBF>span classcat-nm>Hose Ends/span>/a>/li>li classprodcat__li-3>a href/pure-flow-y-fittings/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/pure-flow-y-fittings/ data-parent-nameSnow Fuel Products|Fuel Fittings |Pure Flow Ys data-key4E58D3F11E2A4FABBDD2FB48FF79A8DA>span classcat-nm>Pure Flow Ys/span>/a>/li>li classprodcat__li-3>a href/t-fittings/ classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/t-fittings/ data-parent-nameSnow Fuel Products|Fuel Fittings |T-Fittings data-key7191F8F7B92A44ECABC9F12D207FE55A>span classcat-nm>T-Fittings/span>/a>/li>li classprodcat__li-3>a href/SnowFuel/Unions-and-Reducers.asp classprodcat__a-3 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Fuel-Fittings/|/SnowFuel/Unions-and-Reducers.asp data-parent-nameSnow Fuel Products|Fuel Fittings |Unions and Reducers data-keyB04DEBAA18B145FCA25F2FFBDA09AF51>span classcat-nm>Unions and Reducers /span>/a>/li>/ul>/li>li classprodcat__li-2>a href/Pumps/ classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Pumps/ data-parent-nameSnow Fuel Products|Fuel Pumps data-keyA5058AE45F28403FBADB19429DD92CD0>span classcat-nm>Fuel Pumps /span>/a>/li>li classprodcat__li-2>a href/Snow-Performance-Electrical.asp classprodcat__a-2 data-parent-href/Snow-Performance-Fuel.asp|/Snow-Performance-Electrical.asp data-parent-nameSnow Fuel Products|Electrical data-key5A97FCE566D04C239499C332F1120C92>span classcat-nm>Electrical /span>/a>/li>/ul>/li>li classprodcat__li-1 >a href/apparel-and-decals/ classprodcat__a-1 data-parent-href/apparel-and-decals/ data-parent-nameApparel and Merch data-key4028C589F7444B98B15C81DFDB386F49>span classcat-nm>Apparel and Merch/span>/a>ul classprodcat__ul-2>li classprodcat__li-2>a href/hats/ classprodcat__a-2 data-parent-href/apparel-and-decals/|/hats/ data-parent-nameApparel and Merch|Hats data-key700C56AD40E64E9F96461F20EEDFA890>span classcat-nm>Hats/span>/a>/li>li classprodcat__li-2>a href/hoodies/ classprodcat__a-2 data-parent-href/apparel-and-decals/|/hoodies/ data-parent-nameApparel and Merch|Hoodies data-key2BC558C502B447ABA17AA51F4535721A>span classcat-nm>Hoodies/span>/a>/li>li classprodcat__li-2>a href/Leggings classprodcat__a-2 data-parent-href/apparel-and-decals/|/Leggings data-parent-nameApparel and Merch|Leggings/Shorts data-key4DA85646017A45B2BA9965E91A99F8F5>span classcat-nm>Leggings/Shorts/span>/a>/li>li classprodcat__li-2>a href/merchandise/ classprodcat__a-2 data-parent-href/apparel-and-decals/|/merchandise/ data-parent-nameApparel and Merch|Merchandise data-keyDD1BB024077045F0AA081814BAD2B1E0>span classcat-nm>Merchandise/span>/a>/li>li classprodcat__li-2>a href/t-shirts/ classprodcat__a-2 data-parent-href/apparel-and-decals/|/t-shirts/ data-parent-nameApparel and Merch|T-Shirts data-keyF7CB0105DFCD4FF79124A83883293117>span classcat-nm>T-Shirts/span>/a>/li>/ul>/li>li classprodcat__li-1>a href/openbox.asp classprodcat__a-1 data-parent-href/openbox.asp data-parent-nameOpen Box Deals data-key92176BF4F5CD40379E78564C77F4C2BA>span classcat-nm>Open Box Deals/span>/a>/li>/ul> /li> /ul> /li> li classlink-parent> ul idmain-navigation__menu classlinkset main-navigation__menu main-navigation__menu__ul-1> li classmain-navigation__menu__li-1 data-key48CEB3EC804B43EC80680C8651583CC0>a hreflocations.asp classmain-navigation__menu__a-1>Dealers/a>/li> li classmain-navigation__menu__li-1 data-keyEE85F99BC6E2420381BFDB76E6A4EA3F>a hrefcontact_us.asp classmain-navigation__menu__a-1>Contact Us/a>/li> li classmain-navigation__menu__li-1 data-keyD3B5BCFF71A6428999F7F8E5A860F752>a hrefinstructions.asp classmain-navigation__menu__a-1>Instructions/a>/li> li classmain-navigation__menu__li-1 data-key09F1E130F855406CB8CCDFC659F97C61>a hrefjetting.asp classmain-navigation__menu__a-1>Jetting/a>/li>/ul> /li> /ul> /li>/ul> ul idheader__signin classheader__signin linkset click-persist> li class> a idheader__signin-open classheader__signin-open global-modal data-sizesmall data-backdropstatic titleSign in to Your Account hrefsecurity_logon.asp?autopage%2FDefault%2Easp%3F&modal1> i classicon-signin>/i> Sign In /a> /li> /ul>ul idheader__cart-preview classheader__cart-preview linkset click-persist> li classlink-parent> a classheader__cart-preview__toggle href#0> i classicon-shopping-cart>/i> Cart span idcart_window_qty classcart_window_qty badge>0/span> /a> ul> li idcart_window_incl> div idcart_window classcart-preview cart_window> script> var cartQtyTarg #cart_window_qty, cartQtyTotal 0, cartWinTarg #cart_window_incl; /script> div classwell muted>Your shopping cart is empty./div> div classcontrols> a hrefhttps://www.nitrousexpress.com/showcart.asp classbtn btn-block btn-primary view-cart-button> i classicon-shopping-cart>/i> View & Edit Cart /a> /div> script typetext/javascript> jQuery(function(){ // Set the template cart qty on initial load fncUpdateTemplateQty(cartQtyTarg, cartQtyTotal); }); // Function to update the template qty value function fncUpdateTemplateQty(targ, total) { jQuery(targ).text(total); } // Function to remove an item from the cart window function fncCartWinRemove(sUnqID, sConfirmText) { var bUseRemoveMsg true; if(bUseRemoveMsg){ var okay confirm(sConfirmText); } else{ okay true; } if (okay) { jQuery(#li_+sUnqID).remove(); try { jQuery.ajax({ url: i_i_add_to_cart.asp, data: typev200remove&ajaxreturnJSON&rkey+sUnqID, type: GET, dataType: json, success: function(jsonOrder) { fncCartRefresh(jsonOrder1.item_count, jsonOrder1.o_total); } }); } catch (err) { //alert(err.message); location.reload(); } } } //-function fncCartWinRemove(sUnqID) // Refreshes the (#) for the cart items count function fncCartRefresh(item_count, o_total) { if (typeof item_count undefined) { try { jQuery.ajax({ url: shopping_cart_window.asp, data: cartwindowajaxgetcart, type: GET, dataType: json, error: function (jqXHR, textStatus, errorThrown) { alert(Error! + errorThrown + + textStatus); }, success: function (oData) { var cart oData || {}; if (typeof cart ! undefined) { //console.log(cart); jQuery(cartQtyTarg).html(cart.items); jQuery(#cart_window_subtotal).html(cart.total); //return true; } fncReloadCartWindow(); } }); } catch(err) { alert(err.message); } } else { if (jQuery(cartQtyTarg).length1) { //console.log(cart); jQuery(cartQtyTarg).html(item_count); jQuery(#cart_window_subtotal).html(o_total); //return true; } fncReloadCartWindow(); } } //- function fncCartRefresh() // Reload the contents of the cart window function fncReloadCartWindow() { try { jQuery.ajax({ url: shopping_cart_window.asp, data: cartwindowajaxajaxcall, type: get, success: function (oData) { jQuery(cartWinTarg).html(oData); //fncUpdateTemplateQty(cartQtyTarg, cartQtyTotal); $(window).trigger(cartWindowUpdated); return true; } }); } catch(err) { alert(err.message); } } //-function fncReloadCartWindow() function fncConfirmEmptyCart() { if(confirm(Are you sure you want to empty your cart?)) { fncEmptyCart(); } } function fncEmptyCart() { jQuery.ajax({ url: shopping_cart_window.asp, data: pageactionempty_cart, type: get, success: fncReloadCartWindow }); } /script> /div> !-- /#cart_window --> /li> /ul> /li>/ul> /nav> div classlogo-bar> !-- Call getTemplateLogo() --> a classlogo__wrap hrefhttps://www.nitrousexpress.com> img srcimages/nx_logo.png classlogo altNitrous Express> span>and/span> img srcimages/snow_logo.png classlogo altSnow Performance> /a> ul idretail-header__search classretail-header__search linkset click-persist> li classlink-parent> a classsearch__toggle href#0>i classicon-search>/i> Search/a> div classsearch__flyout> form idfrmUnivSearch classu-search-form methodget actionsearch.asp> input typetext namesearch_prod idsearch_prod classsearchspring-ac input-search placeholderSearch... value autocompleteoff autocorrectoff autocapitalizeoff spellcheckfalse aria-labelSearch Text /> /form> /div> /li> /ul> /div> /div> /div> div classheader__hero> div classheader__hero__wrap> div classheader__hero__container> h1>Shop by Vehicle/h1> div idmake_model_container> div idmake_model_select> select idmodel_year onchangeselectionFactory(this) disabled> option value>Year/option> /select> select idselect_make onchangeselectionFactory(this) disabled> option value>Make/option> /select> select idselect_model onchangeselectionFactory(this) disabled> option value>Model/option> /select> select idselect_trim onchangeselectionFactory(this) disabled> option value>Trim/option> /select> select idselect_engine onchangeselectionFactory(this) disabled> option value>Engine/option> /select> p stylecolor: #fff; margin-top: 10px;>We make products for any vehicle on the road. If your vehicle is not listed, please click the product menu above to view our universal options./p> button idmakeModelSubmit typebutton classbtn multi-select-submit disabled onclicksubmitResults()>Submit/button> input typehidden namevm_keys idvm_keys value> div idloadingajax classmake-model-loading hide> div classspinner> img srctemplates/gfx/ajax-loader.gif alt> /div> /div> /div> /div> div idappLoadingWidget classapp-loading hide> svg idappLoadingSpinner classapp-loading-spinner version1.1 xmlnshttp://www.w3.org/2000/svg xmlns:xlinkhttp://www.w3.org/1999/xlink x0px y0px width170px height170px viewBox-220 312 170 170 enable-backgroundnew -220 312 170 170 xml:spacepreserve> g classapp-loading-spinner-svg> path fill#AAAAAA dM-67.6,398.2l13.5-4c-0.3-5.9-1.1-11.6-2.4-17l-14-0.3c-0.5-1.6-1.1-3-1.6-4.6l10.8-8.9 c-2.4-5.1-5.4-10.2-8.6-14.8l-13.2,5.1c-1.1-1.3-2.2-2.4-3.2-3.5l6.5-12.4c-4.3-3.8-8.9-7.3-13.8-10.2l-10,9.7 c-1.3-0.8-3-1.3-4.3-2.2l1.3-14c-5.4-1.9-10.8-3.5-16.7-4.3l-5.7,12.9c-1.6-0.3-3.2-0.3-4.9-0.3l-4-13.5c-5.9,0.3-11.6,1.1-17,2.4 l-0.3,14c-1.6,0.5-3,1.1-4.6,1.6l-8.9-10.8c-5.1,2.4-10.2,5.4-14.8,8.6l5.1,13.2c-1.3,1.1-2.4,2.2-3.5,3.2l-12.4-6.5 c-3.8,4.3-7.3,8.9-10.2,13.8l9.7,10c-0.8,1.3-1.3,3-2.2,4.3l-14-1.3c-1.9,5.4-3.5,10.8-4.3,16.7l12.9,5.7c-0.3,1.6-0.3,3.2-0.3,4.9 l-13.5,4c0.3,5.9,1.1,11.6,2.4,17l14,0.3c0.5,1.6,1.1,3,1.6,4.6l-10.8,8.9c2.4,5.1,5.4,10.2,8.6,14.8l13.2-5.1 c1.1,1.3,2.2,2.4,3.2,3.5l-6.5,12.4c4.3,3.8,8.9,7.3,13.8,10.2l10-9.7c1.3,0.8,3,1.3,4.3,2.2l-1.3,14c5.4,1.9,10.8,3.5,16.7,4.3 l5.7-12.9c1.6,0.3,3.2,0.3,4.9,0.3l4,13.5c5.9-0.3,11.6-1.1,17-2.4l0.3-14c1.6-0.5,3-1.1,4.6-1.6l8.9,10.8 c5.1-2.4,10.2-5.4,14.8-8.6l-5.1-13.5c1.3-1.1,2.4-2.2,3.5-3.2l12.4,6.5c3.8-4.3,7.3-8.9,10.2-13.8l-9.7-10c0.8-1.3,1.3-3,2.2-4.3 l14,1.3c1.9-5.4,3.5-10.8,4.3-16.7l-12.9-5.7C-67.9,401.4-67.6,399.8-67.6,398.2z M-135,437.3c-22.4,0-40.4-18.1-40.4-40.4 c0-22.4,18.1-40.4,40.4-40.4s40.4,18.1,40.4,40.4C-94.6,419.2-112.7,437.3-135,437.3z>/path> /g> image classapp-loading-spinner-img srctemplates/gfx/loading/loading.gif altLoading...>/image> /svg> /div> script> //Global Vars var currentStep 0; var bIsManagerfront false; var sPageName Default.asp; //Initial load. Populate the Year dropdown. window.onload function() { //populate the year dropdown. clearAllSelects(true); showLoading(true); if(bIsManagerfront) { var currDate new Date; var min 1900, max currDate.getFullYear() + 1, //Generate the Max Year. Models are usually one year ahead of the current year. select document.getElementById(model_year); for (var i max; i>min; i--){ var opt document.createElement(option); opt.value i; opt.innerHTML i; select.appendChild(opt); } $(#model_year).removeAttr(disabled); showLoading(false); } else { proceessAjax(load_years); } } function selectionFactory(element) { var selectedYear processYears($(#model_year).val()); var selectedMake $(#select_make).val(); var selectedModel $(#select_model).val(); var selectedTrim $(#select_trim).val(); var selectedEngine $(#select_engine).val(); $(#makeModelSubmit).prop(disabled, true); //disable the submit if(typeof selectedEngine ! undefined || selectedEngine ! ){ selectedEngine selectedEngine.replace(cc, ); } if(bIsManagerfront) { if((element.id model_year && !bIsManagerfront) || selectedYear ! && selectedMake && selectedModel && selectedTrim && selectedEngine ) { selectYear($(#model_year)); } else if(selectedYear ! && selectedMake ! && selectedModel && selectedTrim && selectedEngine ) { selectMake($(#select_make)); } else if(selectedYear ! && selectedMake ! && selectedModel ! && selectedTrim && selectedEngine ) { selectModel($(#select_model)); } else if(selectedYear ! && selectedMake ! && selectedModel ! && selectedTrim ! && selectedEngine ) { selectTrim($(#select_trim)); } else if(selectedYear ! && selectedMake ! && selectedModel ! && selectedTrim ! && selectedEngine ! ) { selectEngine($(#select_engine)); } } else { if(element.id model_year) { selectYear($(#model_year)); } else if(element.id select_make) { selectMake($(#select_make)); } else if(element.id select_model) { selectModel($(#select_model)); } else if(element.id select_trim) { selectTrim($(#select_trim)); } else if(element.id select_engine) { selectEngine($(#select_engine)); } } } //These functions handle the change events. function selectYear(element) { showLoading(true); var selectedYear processYears(element.val()); if(selectedYear ! ) { if(checkSelectSteps(1)) { currentStep 1; } proceessAjax(model_year, selectedYear); } } function selectMake(element) { showLoading(true); var selectedYear processYears($(#model_year).val()); var selectedMake element.val(); if(selectedMake ! ) { if(checkSelectSteps(2)) { currentStep 2; } proceessAjax(select_make, selectedYear, selectedMake); } } function selectModel(element) { showLoading(true); var selectedYear processYears($(#model_year).val()); var selectedMake $(#select_make).val(); var selectedModel element.val(); if(checkSelectSteps(3)) { currentStep 3; } if(selectedYear ! && selectedModel ! && selectedMake ! ){ proceessAjax(select_model, selectedYear, selectedMake, selectedModel); } else { alert(There is something wrong with your search. Try again.); } } function selectTrim(element) { showLoading(true); var selectedYear processYears($(#model_year).val()); var selectedMake $(#select_make).val(); var selectedModel $(#select_model).val(); var selectedTrim element.val(); if(checkSelectSteps(4)) { currentStep 4; } if(selectedYear ! && selectedModel ! && selectedMake ! && selectedTrim ! ){ proceessAjax(select_trim, selectedYear, selectedMake, selectedModel, selectedTrim); } } function selectEngine(element) { showLoading(true); var selectedYear processYears($(#model_year).val()); var selectedMake $(#select_make).val(); var selectedModel $(#select_model).val(); var selectedTrim $(#select_trim).val(); var selectedEngine element.val().replace(cc, ); if(checkSelectSteps(5)) { currentStep 5; } if(selectedYear ! && selectedModel ! && selectedMake ! && selectedTrim ! && selectedEngine ! ){ proceessAjax(select_engine, selectedYear, selectedMake, selectedModel, selectedTrim, selectedEngine); } else { alert(There is something wrong with your search. Try again.); } } //The following functions take the JSON returned from our AJAX, cleans the data if needed, and populates the selects. function processMappedYears(results) { var uniqueYears uniqVals(results).sort(sortAlphaNum); select document.getElementById(model_year); uniqueYears.forEach(function(year){ var opt document.createElement(option); opt.value year; opt.innerHTML year; select.appendChild(opt); }); $(#model_year).removeAttr(disabled); showLoading(false); } function processYearResults(results) { var uniqueMakes uniqVals(results).sort(sortAlphaNum); var select document.getElementById(select_make); var options uniqueMakes; for (var i 0; i options.length; i++){ var opt capitalizeFirstLetter(optionsi); if(opt ! ) { //Some values are blank. Dont want those in the droplist var el document.createElement(option); el.textContent opt; el.value opt; select.appendChild(el); } else{ continue; } } $(#select_make).removeAttr(disabled); showLoading(false); } function processMakeResults(results) { var uniqueModels uniqVals(results).sort(sortAlphaNum); var select document.getElementById(select_model); var options uniqueModels; for (var i 0; i options.length; i++){ var opt capitalizeFirstLetter(optionsi); if(opt ! ) { //Some values are blank. Dont want those in the droplist var el document.createElement(option); el.textContent opt; el.value opt; select.appendChild(el); } else{ continue; } } $(#select_model).removeAttr(disabled); showLoading(false); } function processModelResults(results) { var uniqueTrims uniqVals(results).sort(sortAlphaNum); var select document.getElementById(select_trim); var options uniqueTrims; for (var i 0; i options.length; i++){ var opt optionsi; if(opt ! ) { //Some values are blank. Dont want those in the droplist var el document.createElement(option); el.textContent opt; el.value opt; select.appendChild(el); } else{ continue; } } $(#select_trim).removeAttr(disabled); showLoading(false); } function processTrimResults(results) { var uniqueEngines uniqVals(results).sort(sortAlphaNum); var select document.getElementById(select_engine); var options uniqueEngines; for (var i 0; i options.length; i++){ var opt optionsi; if(opt ! ) { //Some values are blank. Dont want those in the droplist var el document.createElement(option); el.textContent (opt * 1/1000).toFixed(1) + L; //convert the dropdown display to Liters. el.value opt; select.appendChild(el); } else{ continue; } } $(#select_engine).removeAttr(disabled); showLoading(false); } function processEngineResults(results) { var sVmKey results0; if(bIsManagerfront){ updateManagerfrontDOM(sVmKey); } else { proceessAjax(sitefrontresults, sVmKey); } showLoading(false); } function processSitefrontResults(results) { var uniqueProds uniqVals(results); var sKeys ; for (var i 0; i uniqueProds.length; i++){ sKeys + uniqueProdsi + ; } $(#vm_keys).val(sKeys); $(#makeModelSubmit).removeAttr(disabled); showLoading(false); } function processSingleResult(results) { var makeSelect document.getElementById(select_make); var modelSelect document.getElementById(select_model); var trimSelect document.getElementById(select_trim); var engineSelect document.getElementById(select_engine); var sVmKey results.vm_key; var lastSelect results.lastTypeSelected; if(!selectValExists(select_make, capitalizeFirstLetter(results.vehicle_make))) { populateSelect(makeSelect, capitalizeFirstLetter(results.vehicle_make)); } if(!selectValExists(select_model, results.model_name)) { populateSelect(modelSelect, results.model_name); } if(!selectValExists(select_trim, results.model_trim)) { populateSelect(trimSelect, results.model_trim); } if(!selectValExists(select_engine, (parseInt(results.engine_cc) * 1/1000).toFixed(1) + L)) { populateSelect(engineSelect, (parseInt(results.engine_cc) * 1/1000).toFixed(1) + L); } makeSelect.disabled false; modelSelect.disabled false; trimSelect.disabled false; engineSelect.disabled false; if(bIsManagerfront){ updateManagerfrontDOM(sVmKey); } else { proceessAjax(sitefrontresults, sVmKey); } } //Supporting Functions. //This function checks the passed in Step against the global step that we are keeping track of function checkSelectSteps(selectedStep) { if(selectedStep currentStep + 1) { return true; } else { switch (selectedStep) { case 1: clearDroplists(select_make); clearDroplists(select_model); clearDroplists(select_trim); clearDroplists(select_engine); currentStep 1; return false; case 2: clearDroplists(select_model); clearDroplists(select_trim); clearDroplists(select_engine); currentStep 2; return false; case 3: clearDroplists(select_trim); clearDroplists(select_engine); currentStep 3; return false; case 4: clearDroplists(select_engine); currentStep 4; return false; } } } function selectValExists(element, val) { var IsExists false; var ddloption document.getElementById(element).options; for(var i 0; i ddloption.length; i++) { if( ddloptioni.value val ) { IsExists true; break; } } return IsExists; } function populateSelect(element, value) { var opt document.createElement(option); opt.value value; opt.innerHTML value; element.appendChild(opt); element.value value; } function clearAllSelects(bResetYear) { if(bResetYear) { $(#model_year).val(0); } clearDroplists(select_make); clearDroplists(select_model); clearDroplists(select_trim); clearDroplists(select_engine); } //Clears the Droplists. Disables them and the Submit button. function clearDroplists(id) { $(# + id).find(option).not(:first).remove(); //Remove everything but the placeholder. $(# + id).val(); $(# + id).prop(disabled, true); //disable the droplist if(bIsManagerfront){ if($(#vm_id).val() ){ $(#form_builder_submit).addClass(disabled); } } } //helper function to update the DOM once we have our final results. function updateManagerfrontDOM(sVmKey) { $(#makeModelSubmit).removeAttr(disabled) $(#form_builder_submit).removeClass(disabled); $(#vm_id_vehicle_model_id).val(sVmKey); $(#vm_id_VehicleYear).val($(#model_year).val()); $(#vm_id_VehicleName).val($(#select_model).val()); $(#vm_id_VehicleTrim).val($(#select_trim).val()); showLoading(false); } //this function catches the onclick event for the submit button. function submitResults() { if(bIsManagerfront) { $(#vm_id_add_link).click(); checkSelectSteps(1); currentStep 1; $(#model_year).val(0); //reset the year dropdown $(#makeModelSubmit).prop(disabled, true); //disable the droplist } else{ $(#appLoadingWidget).show(); var sSearchstring ; sSearchString buildCatalogSearchString(); if(sSearchString.length > 0){ window.location.href pc_combined_results.asp? + sSearchString; } } } //This is where we build out the Searchstring for the Catalog. function buildCatalogSearchString() { var aKeys $(#vm_keys).val().split(;); var sReturn search_prod(; if(aKeys.length > 0) { for (var i 0; i aKeys.length; i++){ if(aKeysi.trim() ! ){ sReturn + searchexact~p_key~ + aKeysi + |OR|; } else{ continue; } } } else{ alert(There was a problem with your Year selection, please try again.) } return sReturn + )&makemodelsearch1; } function showLoading(bShow) { if(bShow) { $(#loadingajax).css(display, inline-block); } else { $(#loadingajax).css(display, none); } } //Helper function to process dates correctly. function processYears(value) { if(value ! ) { var selectedDate new Date(value); var selectedYear selectedDate.getFullYear() + 1; //Not sure why, but the date conversion subtracts a year. return selectedYear; } else{ alert(There was a problem with your Year selection, please try again.) } } //Self explanitory, capitalize the first letter. function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } //This parses the JSON arrays and returns an array of unique values. function uniqVals(a) { var seen {}; return a.filter(function(item) { return seen.hasOwnProperty(item) ? false : (seenitem true); }); } //Sort values AlphaNumerically function sortAlphaNum(a, b) { var reA /^a-zA-Z/g; var reN /^0-9/g; var aA a.replace(reA, ); var bA b.replace(reA, ); if (aA bA) { var aN parseInt(a.replace(reN, ), 10); var bN parseInt(b.replace(reN, ), 10); return aN bN ? 0 : aN > bN ? 1 : -1; } else { return aA > bA ? 1 : -1; } } //Our AJAX function. function proceessAjax(type, year, make, model, trim, engine) { if(typeof(year) undefined) { year ; } if(typeof(make) undefined) { make ; } if(typeof(model) undefined) { model ; } if(typeof(trim) undefined) { trim ; } if(typeof(engine) undefined) { engine ; } jQuery.ajax({ url: i_i_ + sPageName + ?pageactionmakemodelaction, data: { type: type, year: year, make: make, model: model, trim: trim, engine: engine }, success : function(oData){ var resultJSON JSON.parse(oData); if(typeof resultJSON.error undefined){ switch (resultJSON.resultType) { case load_years: processMappedYears(resultJSON.results); break; case model_year: processYearResults(resultJSON.results); break; case select_make: processMakeResults(resultJSON.results); break; case select_model: processModelResults(resultJSON.results); break; case select_trim: processTrimResults(resultJSON.results); break; case select_engine: processEngineResults(resultJSON.results); break; case sitefrontresults: processSitefrontResults(resultJSON.results); break; case single_result: processSingleResult(resultJSON); break; } } else{ $(#model_year).val(0); //reset the year dropdown showLoading(false); alert(resultJSON.error); clearDroplists(select_make); clearDroplists(select_model); clearDroplists(select_trim); clearDroplists(select_engine); } }, error: function(xhr, status, error) { $(#model_year).val(0); //reset the year dropdown showLoading(false); var err eval(( + xhr.responseText + )); alert(err.Message); clearDroplists(select_make); clearDroplists(select_model); clearDroplists(select_trim); clearDroplists(select_engine); } }); } /script> /div> /div> /div> /header> !-- Retail Bot WPC Home - Middle Marketing Well - EABDB47BF00946F5B4E8FBF4FB34BDCA --> div classhome__marketing-well> div classmarketing-well__col marketing-well__col-1> div classmarketing-well__wrap> div idslide_show_114B0379B0414100957400C1288072FE classcarousel slide> div idcarousel_slide classcarousel-inner> div classitem active > a hrefhttps://www.nitrousexpress.com/contact_us.asp target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/bottlepromo3.png alt class>/a> /div> div classitem > a hrefhttps://www.nitrousexpress.com/Fuel-Hats.asp target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/fuelhat1.png alt class>/a> /div> div classitem > a hrefhttps://www.nitrousexpress.com/Maximizer-6-Progressive-Nitrous-Controller.asp target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/max61.png alt class>/a> /div> div classitem > a hrefhttps://www.nitrousexpress.com/t-shirts/ target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/tshirt1.png alt class>/a> /div> div classitem > img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/free_ship2021.png alt class> /div> div classitem > a hrefhttps://www.nitrousexpress.com/Fuel-Regulators/ target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/regulator1.png alt class>/a> /div> div classitem > a hrefhttps://www.nitrousexpress.com/Snow-Performance-water-methanol/ target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/snowslide.png alt class>/a> /div> div classitem > a hrefhttps://www.nitrousexpress.com/nitrous/ target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/nxslide.png alt class>/a> /div> div classitem > a hrefhttps://www.nitrousexpress.com/search.asp?search_prodquick+disconnect target_blank>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/qdcclamp1.png alt class>/a> /div> /div> a href#slide_show_114B0379B0414100957400C1288072FE classcarousel-control left data-slideprev>‹/a> a href#slide_show_114B0379B0414100957400C1288072FE classcarousel-control right data-slidenext>›/a> ol classcarousel-indicators> li classactive data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to0> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to1> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to2> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to3> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to4> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to5> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to6> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to7> /li> li class data-target#slide_show_114B0379B0414100957400C1288072FE data-slide-to8> /li> /ol> /div> script> $(function(){ $(#slide_show_114B0379B0414100957400C1288072FE).carousel({interval:6000}); }); /script> /div> /div> /div> div idhome__featured-categories classhome__featured-categories> div classcontainer-fluid> !-- Retail Top WPC Home - Featured Categories:003ABC17D3D84AD4BA62DA481AF851B7 --> h2>Featured Categories/h2>div classowl-carousel owl-theme>div classfeatured-categories__wrapper>img srcimages/sno-60003_l.jpg alt />div classfeatured-categories__text>h4>Water/Methanol Electronics/h4>p>Check out the latest Electronics for your Snow water methanol system!/p>a classfeatured-categories__btn href../pc_combined_results.asp?pc_id1AE900E2D84540BB8C471B81863F0C14>View More i classicon-angle-right>/i>/a>/div>/div>div>div classfeatured-categories__wrapper>img srcimages/home-electronics.jpg alt />div classfeatured-categories__text>h4>Nitrous Electronics/h4>p>Check out the latest Electronics for your nitrous system!/p>a classfeatured-categories__btn href../pc_combined_results.asp?pc_id42A99390D20242298910358F4A461574>View More i classicon-angle-right>/i>/a>/div>/div>/div>div>div classfeatured-categories__wrapper>img srcimages/genx-2_n.jpg alt />div classfeatured-categories__text>h4>Accessory Packages/h4>p>Every nitrous system loves accessorizing! upgrade your System to include a purge, heater, gauge or nitrous controller!/p>a classfeatured-categories__btn href../pc_combined_results.asp?pc_idCFC8709D8CD64B55A24FC398E0DADFED>View More i classicon-angle-right>/i>/a>/div>/div>/div>/div> /div> /div> h2 classfeatured-products__title>Featured Products/h2> div idwpc_featured_products> div classowl-carousel owl-theme thumbnails> div classspecials_item > div classspecials_item_inner > !-- Product Picture --> div classspecials_img> a href/automatic-remote-bottle-opener-11107.asp>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/11107_t.jpg titleAutomatic Remote Bottle Opener alt class onerrorutils.handleImageError(this)>/a> /div> div classspecials_info caption> !-- Product Name --> div classspecials_nm>a href/automatic-remote-bottle-opener-11107.asp class>Automatic Remote Bottle Opener/a>/div> !-- Product SKU --> !-- Product Rating --> !-- Product Description --> !-- Product Price --> div classspecials_price text-small> div classretail> Price: $381.62 /div> /div> div classspecials_inv_msg>span classidp-instock>In Stock/span>/div> !-- Search Fields --> /div> /div> /div> div classspecials_item > div classspecials_item_inner > !-- Product Picture --> div classspecials_img> a href/mainline-carb-system-with-10lb-bottle-ml1000.asp>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/ml1000_t.jpg titleMainline Carb. System With 10Lb Bottle alt class onerrorutils.handleImageError(this)>/a> /div> div classspecials_info caption> !-- Product Name --> div classspecials_nm>a href/mainline-carb-system-with-10lb-bottle-ml1000.asp class>Mainline Carb. System With 10Lb Bottle/a>/div> !-- Product SKU --> !-- Product Rating --> !-- Product Description --> !-- Product Price --> div classspecials_price text-small> div classretail> Price: $524.31 /div> /div> div classspecials_inv_msg>span classidp-instock>In Stock/span>/div> !-- Search Fields --> /div> /div> /div> div classspecials_item > div classspecials_item_inner > !-- Product Picture --> div classspecials_img> a href/maximizer-ez-progressive-nitrous-controller-16006.asp>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/16006_t.jpg titleMaximizer EZ Progressive Nitrous Controller alt class onerrorutils.handleImageError(this)>/a> /div> div classspecials_info caption> !-- Product Name --> div classspecials_nm>a href/maximizer-ez-progressive-nitrous-controller-16006.asp class>Maximizer EZ Progressive Nitrous Controller/a>/div> !-- Product SKU --> !-- Product Rating --> !-- Product Description --> !-- Product Price --> div classspecials_price text-small> div classretail> Price: $159.57 /div> div classsretail muted> List Price: del>$159.57/del> /div> /div> div classspecials_inv_msg>span classidp-instock>In Stock/span>/div> !-- Search Fields --> /div> /div> /div> div classspecials_item > div classspecials_item_inner > !-- Product Picture --> div classspecials_img> a href/pc_product_detail.asp?keyE78038294B3E4E938DADE6F559320857>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/sno-210-b_t.jpg titleStage 2.5 Boost Cooler Forced Induction Progressive Water-Methanol Injection Kit (Red High Temp Nylon Tubing, Quick-Connect Fittings) alt class onerrorutils.handleImageError(this)>/a> /div> div classspecials_info caption> !-- Product Name --> div classspecials_nm>a href/pc_product_detail.asp?keyE78038294B3E4E938DADE6F559320857 class>Stage 2.5 Boost Cooler Forced Induction Progressive Water-Methanol Injection Kit (Red High Temp Nylon Tubing, Quick-Connect Fittings)/a>/div> !-- Product SKU --> !-- Product Rating --> !-- Product Description --> !-- Product Price --> div classspecials_price text-small> div classretail> Price: $583.33 /div> div classsretail muted> List Price: del>$583.33/del> /div> /div> div classspecials_inv_msg>span classidp-instock>In Stock/span>/div> !-- Search Fields --> /div> /div> /div> div classspecials_item > div classspecials_item_inner > !-- Product Picture --> div classspecials_img> a href/Stand-up-Billet-Bottle-Bracket-for-10lb-Bottle-Roll-Bar-Mount.asp>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/temprollbarfix_t.jpg titleStand up Billet Bottle Bracket for 10lb Bottle (Roll Bar Mount) alt class onerrorutils.handleImageError(this)>/a> /div> div classspecials_info caption> !-- Product Name --> div classspecials_nm>a href/Stand-up-Billet-Bottle-Bracket-for-10lb-Bottle-Roll-Bar-Mount.asp class>Stand up Billet Bottle Bracket for 10lb Bottle (Roll Bar Mount)/a>/div> !-- Product SKU --> !-- Product Rating --> !-- Product Description --> !-- Product Price --> div classspecials_price text-small> div classretail> Price: $373.45 /div> div classsretail muted> List Price: del>$373.45/del> /div> /div> div classspecials_inv_msg>span classidp-instock>In Stock/span>/div> !-- Search Fields --> /div> /div> /div> div classspecials_item > div classspecials_item_inner > !-- Product Picture --> div classspecials_img> a href/Universal-90-Solenoid-Bracket.asp>img srchttps://d1vlavvlsa6jkm.cloudfront.net/images/15700-t.jpg titleUniversal 90° Solenoid Bracket alt class onerrorutils.handleImageError(this)>/a> /div> div classspecials_info caption> !-- Product Name --> div classspecials_nm>a href/Universal-90-Solenoid-Bracket.asp class>Universal 90° Solenoid Bracket/a>/div> !-- Product SKU --> !-- Product Rating --> !-- Product Description --> !-- Product Price --> div classspecials_price text-small> div classretail> Price: $49.99 /div> /div> div classspecials_inv_msg>/div> !-- Search Fields --> /div> /div> /div> /div> /div> div idhome__bottom-marketing-well classhome__bottom-marketing-well> div classbottom-marketing-well__wrap> !-- Retail Top WPC Home - Featured Categories:322D5F316DE6418090B160678A51729D --> div classbottom-marketing-well__tile tile-1>div classtile-background> /div>a hrefhttps://www.facebook.com/media/set/?seta.142314869112419&type3>h3>Custom Intake Plumbing Gallery/h3>/a>/div>div classbottom-marketing-well__tile tile-2>div classtile-background> /div>a href../Apparel-and-Decals/>h3>Apparel and Merch/h3>/a>/div>div classbottom-marketing-well__tile tile-3>div classtile-background> /div>a classvenobox vbox-item video__link hrefhttps://www.youtube.com/watch?vifiqOOm8TXA&t3s data-vbtypeyoutube> span classvideo__pic>span classicon-play> /span>/span>/a>/div> /div> /div> div idhome__bottom-videos classhome__bottom-videos> div classcontainer-fluid> !-- Retail Top WPC Home - Bottom Videos:B2E838F7205D4689B7CBE3C7D891DA56 --> h2>NX & Snow Performance Links/h2>div classbottom-videos__tile tile-1>div classvideo__item play>a classvenobox vbox-item video__link hrefhttps://www.youtube.com/watch?vF0pk0h-umfY data-vbtypeyoutube> span classvideo__pic> img srcimages/towingvid.jpg alt /> /span> /a>/div>/div>div classbottom-videos__tile tile-2>a href../downloads> span classvideo__pic> img srcimages/downloads.jpg alt /> /span> /a>/div>div classbottom-videos__tile tile-3>div classvideo__item play>a classvenobox vbox-item video__link hrefhttps://www.youtube.com/watch?v4Mdi3fBFJLg data-vbtypeyoutube> span classvideo__pic> img srcimages/ezvid.jpg alt /> /span> /a>/div>/div>p>a classbottom-videos__btn hrefhttps://www.youtube.com/user/NitrousExpressVids>View All Videos i classicon-angle-right>/i>/a>/p> /div> /div> div idhome__bottom-description classhome__bottom-description> div classcontainer-fluid> !-- Retail Top WPC Home - Bottom Description:3067416F2DA04B5B9C651A03F8259B45 --> p>strong>Nitrous Express , the leading manufacturer of high performance nitrous oxide systems, now owns Snow Performance, the water methanol experts./strong>/p>p>At NX and Snow Performance, we live and dream Nitrous Oxide and Water Methanol. Customer service is taken very seriously and we work constantly to develop and improve our product lines. Our company is comprised of experienced and passionate people who use our products every day. If you ever need advice or technical help, just call us. A real, live human will answer the phone and provide you with accurate information based on years of experience. It is our commitment and our mission to provide the best service, performance, quality and value./p>p>We promise our customers complete satisfaction. If our products dont live up to your expectations, we want to hear from you. Our Nitrous and Water Methanol products are guaranteed to be of the highest quality and free of manufacturing defects./p> /div> /div>footer idretail-footer-1 classretail-footer-1 print-hide> div classfooter-cc-icons> !-- Footer - Payment Icons --> p>img srcimages/cc-logo-visa.png altVisa Card Logo /> img srcimages/cc-logo-mastercard-2.png altMasterCard Logo /> img srcimages/cc-logo-american-express.png altAmerican Express Card Logo /> img srcimages/cc-logo-discover.png altDiscover Card Logo /> img srcimages/cc-logo-paypal.png altPayPal Logo />/p> /div> div classcontainer-fluid retail-footer__area> div classretail-footer__col retail-footer__col-1> a classretail-footer__logo-wrap hrefdefault.asp> img srcimages/logo.gif classretail-footer__logo altNitrous Express> /a> /div> div classretail-footer__col retail-footer__col-2> div classnav-header> span class>Corporate/span> /div> ul classlinkset click> li classlink-parent drop> a href classnav-header show-mobile>Corporate i classicon-plus>/i> /a> address> Nitrous Express br> 5411 Seymour HwyBR>Wichita Falls, TX 76310 br> a hrefmailto:info@nitrousexpress.com?subjectWebsite Customer Service Request>i classicon-envelope icon-fixed-width>/i> Customer Service/a> /address> /li> /ul> /div> div classretail-footer__col retail-footer__col-3> ul classlinkset click> li classlink-parent drop> a href classnav-header show-mobile>Social i classicon-plus>/i> /a> ul idretail-footer-nav__social classlinkset retail-footer-nav__social retail-footer-nav__social__ul-1> li classretail-footer-nav__social__li-1 data-key44FD07733333450CBCFADB166F029A0B>div classnav-header>span class>Social/span>/div>/li> li classretail-footer-nav__social__li-1 data-key45A44DEB98374A92BE93E2A2A9B26DAD>a hrefhttps://www.facebook.com/nitrousexpress/ classretail-footer-nav__social__a-1 target_blank>i classicon-facebook icon-fixed-width>/i> Facebook/a>/li> li classretail-footer-nav__social__li-1 data-key7A5E15CB34B24E1096AC5E298BA1A373>a hrefhttps://twitter.com/nitrousexpress1 classretail-footer-nav__social__a-1 target_blank>i classicon-twitter icon-fixed-width>/i> Twitter/a>/li> li classretail-footer-nav__social__li-1 data-keyE0211240D0D34EAAB365C7EC949DD221>a hrefhttps://www.instagram.com/nitrousexpress classretail-footer-nav__social__a-1 target_blank>i classicon-instagram icon-fixed-width>/i> Instagram/a>/li> li classretail-footer-nav__social__li-1 data-key682797C3A35C407CA6EE542830365905>a hrefhttps://www.youtube.com/user/NitrousExpressVids classretail-footer-nav__social__a-1 target_blank>i classicon-youtube icon-fixed-width>/i> YouTube/a>/li>/ul> /li> /ul> /div> div classretail-footer__col retail-footer__col-4> ul classlinkset click> li classlink-parent drop> a href classnav-header show-mobile>Navigation i classicon-plus>/i> /a> ul idretail-footer-nav__menu classlinkset retail-footer-nav__menu retail-footer-nav__menu__ul-1> li classretail-footer-nav__menu__li-1 data-key6274472664B74036B01C84C9410B292C>div classnav-header>span class>Navigation/span>/div>/li> li classretail-footer-nav__menu__li-1 data-keyA4270171CCD040278C810AF3B1BCC994>a hrefpc_combined_results.asp classretail-footer-nav__menu__a-1>All Products/a>/li> li classretail-footer-nav__menu__li-1 data-keyF9638A64A5094D60A776EB9C4A75B68F>a hreflocations.asp classretail-footer-nav__menu__a-1>Dealers/a>/li> li classretail-footer-nav__menu__li-1 data-keyA2DE1369FD0743EC918CA3AD78E7A030>a href/instructions.asp classretail-footer-nav__menu__a-1>Instructions/a>/li> li classretail-footer-nav__menu__li-1 data-keyF6DB6D6E97874886A74CE49DC225BC7B>a href/Jetting.asp classretail-footer-nav__menu__a-1>Jetting/a>/li> li classretail-footer-nav__menu__li-1 data-key54E73909B7A94504A4457726E697E9CE>a href/downloads classretail-footer-nav__menu__a-1>Downloads/a>/li>/ul> /li> /ul> /div> div classretail-footer__col retail-footer__col-5> ul classlinkset click> li classlink-parent drop> a href classnav-header show-mobile>Resources i classicon-plus>/i> /a> ul idretail-footer-nav__resources classlinkset retail-footer-nav__resources retail-footer-nav__resources__ul-1> li classretail-footer-nav__resources__li-1 data-key0E75664DA61A49FDBA4048A205134339>div classnav-header>span class>Resources/span>/div>/li> li classretail-footer-nav__resources__li-1 data-keyD2C70CB6A4134ED295A9B16EF6E963E6>a href/about.asp classretail-footer-nav__resources__a-1>About Us/a>/li> li classretail-footer-nav__resources__li-1 data-key9242BC9B3A124610B3893CF9DD2FD800>a hrefcustomer-service-faqs classretail-footer-nav__resources__a-1>FAQ/a>/li> li classretail-footer-nav__resources__li-1 data-key52ABA00C95B84111B0F65AF506FA4B60>a hrefcontact_us.asp classretail-footer-nav__resources__a-1>Contact Us/a>/li> li classretail-footer-nav__resources__li-1 data-key33DDCFBFF0854F7086F749842F5079E7>a hrefreturns classretail-footer-nav__resources__a-1>Warranty/Return Info/a>/li>/ul> /li> /ul> /div> div classretail-footer__col retail-footer__col-6> div classnav-header> span class>Secure Shopping/span> /div> a classretail-footer__sema hrefhttp://www.sema.org/ relnofollow>img altSEMA Member border0 height120 srcimages/sema-member.jpg stylemargin-left: 10px; width75> /a> div classretail-footer__warning> a hrefhttps://www.p65warnings.ca.gov/ target_blank>img alt classwarning__image srcimages/warning-sign-50.png style> /a> div classwarning__message> p>strong>Warning:/strong> Some products may cause cancer or reproductive harm./p> a hrefhttps://www.p65warnings.ca.gov/ target_blank>www.p65warnings.ca.gov/a> /div> /div> /div> /div> div idbottom-bar classbottom-bar> div classcontainer-fluid> div classbottom-bar__copyright> p> ©2024. Nitrous Express. All rights reserved./p> /div> div classbottom-bar__colophon> p>a hrefhttps://www.cimcloud.com relnofollow target_blank>Ecommerce & ERP Integration by CIMCloud/a>/p> /div> /div> /div> /footer>div classglobal-body-append> svg xmlnshttp://www.w3.org/2000/svg xmlns:xlinkhttp://www.w3.org/1999/xlink classhide> symbol idicon-user-circle-o viewBox0 0 28 28> path dM14 0c7.734 0 14 6.266 14 14 0 7.688-6.234 14-14 14-7.75 0-14-6.297-14-14 0-7.734 6.266-14 14-14zM23.672 21.109c1.453-2 2.328-4.453 2.328-7.109 0-6.609-5.391-12-12-12s-12 5.391-12 12c0 2.656 0.875 5.109 2.328 7.109 0.562-2.797 1.922-5.109 4.781-5.109 1.266 1.234 2.984 2 4.891 2s3.625-0.766 4.891-2c2.859 0 4.219 2.312 4.781 5.109zM20 11c0-3.313-2.688-6-6-6s-6 2.688-6 6 2.688 6 6 6 6-2.688 6-6z>/path> /symbol> symbol idicon-address-card viewBox0 0 32 28> path dM16 17.672c0-2.422-0.594-5.109-3.063-5.109-0.766 0.438-1.797 1.188-2.938 1.188s-2.172-0.75-2.938-1.188c-2.469 0-3.063 2.688-3.063 5.109 0 1.359 0.891 2.328 2 2.328h8c1.109 0 2-0.969 2-2.328zM13.547 9.547c0-1.953-1.594-3.547-3.547-3.547s-3.547 1.594-3.547 3.547c0 1.969 1.594 3.547 3.547 3.547s3.547-1.578 3.547-3.547zM28 17.5v-1c0-0.281-0.219-0.5-0.5-0.5h-9c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h9c0.281 0 0.5-0.219 0.5-0.5zM28 13.438v-0.875c0-0.313-0.25-0.562-0.562-0.562h-8.875c-0.313 0-0.562 0.25-0.562 0.562v0.875c0 0.313 0.25 0.562 0.562 0.562h8.875c0.313 0 0.562-0.25 0.562-0.562zM28 9.5v-1c0-0.281-0.219-0.5-0.5-0.5h-9c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h9c0.281 0 0.5-0.219 0.5-0.5zM32 4.5v19c0 1.375-1.125 2.5-2.5 2.5h-5.5v-1.5c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1.5h-12v-1.5c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1.5h-5.5c-1.375 0-2.5-1.125-2.5-2.5v-19c0-1.375 1.125-2.5 2.5-2.5h27c1.375 0 2.5 1.125 2.5 2.5z>/path> /symbol> symbol idicon-building viewBox0 0 22 28> path dM21 0c0.547 0 1 0.453 1 1v26c0 0.547-0.453 1-1 1h-20c-0.547 0-1-0.453-1-1v-26c0-0.547 0.453-1 1-1h20zM8 4.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5zM8 8.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5zM8 12.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5zM8 16.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5zM6 21.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM6 17.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM6 13.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM6 9.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM6 5.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM14 25.5v-3c0-0.281-0.219-0.5-0.5-0.5h-5c-0.281 0-0.5 0.219-0.5 0.5v3c0 0.281 0.219 0.5 0.5 0.5h5c0.281 0 0.5-0.219 0.5-0.5zM14 17.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM14 13.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM14 9.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM14 5.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM18 21.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM18 17.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM18 13.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM18 9.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5zM18 5.5v-1c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5v1c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5z>/path> /symbol> symbol idicon-currency-dollar viewBox0 0 20 20> path dM10 20c-5.523 0-10-4.477-10-10s4.477-10 10-10v0c5.523 0 10 4.477 10 10s-4.477 10-10 10v0zM11 15h1c1.657 0 3-1.343 3-3s-1.343-3-3-3v0h-4.010c-0.552 0-1-0.448-1-1s0.448-1 1-1v0h6.010v-2h-3v-2h-2v2h-1c-1.657 0-3 1.343-3 3s1.343 3 3 3v0h4c0.552 0 1 0.448 1 1s-0.448 1-1 1v0h-6v2h3v2h2v-2z>/path> /symbol> symbol idicon-check-square viewBox0 0 24 28> path dM10.703 20.297l9.594-9.594c0.391-0.391 0.391-1.016 0-1.406l-1.594-1.594c-0.391-0.391-1.016-0.391-1.406 0l-7.297 7.297-3.297-3.297c-0.391-0.391-1.016-0.391-1.406 0l-1.594 1.594c-0.391 0.391-0.391 1.016 0 1.406l5.594 5.594c0.391 0.391 1.016 0.391 1.406 0zM24 6.5v15c0 2.484-2.016 4.5-4.5 4.5h-15c-2.484 0-4.5-2.016-4.5-4.5v-15c0-2.484 2.016-4.5 4.5-4.5h15c2.484 0 4.5 2.016 4.5 4.5z>/path> /symbol> symbol idicon-life-bouy viewBox0 0 28 28> path dM14 0c7.734 0 14 6.266 14 14s-6.266 14-14 14-14-6.266-14-14 6.266-14 14-14zM14 2c-2.031 0-3.953 0.516-5.641 1.406l3.031 3.031c0.828-0.281 1.703-0.438 2.609-0.438 0.922 0 1.781 0.156 2.609 0.438l3.031-3.031c-1.687-0.891-3.609-1.406-5.641-1.406zM3.406 19.641l3.031-3.031c-0.281-0.828-0.438-1.703-0.438-2.609 0-0.922 0.156-1.781 0.438-2.609l-3.031-3.031c-0.891 1.687-1.406 3.609-1.406 5.641s0.516 3.953 1.406 5.641zM14 26c2.031 0 3.953-0.516 5.641-1.406l-3.031-3.031c-0.828 0.281-1.687 0.438-2.609 0.438-0.906 0-1.781-0.156-2.609-0.438l-3.031 3.031c1.687 0.891 3.609 1.406 5.641 1.406zM14 20c3.313 0 6-2.688 6-6s-2.688-6-6-6-6 2.688-6 6 2.688 6 6 6zM21.562 16.609l3.031 3.031c0.891-1.687 1.406-3.609 1.406-5.641s-0.516-3.953-1.406-5.641l-3.031 3.031c0.281 0.828 0.438 1.703 0.438 2.609s-0.156 1.781-0.438 2.609z>/path> /symbol> symbol idicon-calendar-plus-o viewBox0 0 26 28> path dM24 4c1.094 0 2 0.906 2 2v20c0 1.094-0.906 2-2 2h-22c-1.094 0-2-0.906-2-2v-20c0-1.094 0.906-2 2-2h2v-1.5c0-1.375 1.125-2.5 2.5-2.5h1c1.375 0 2.5 1.125 2.5 2.5v1.5h6v-1.5c0-1.375 1.125-2.5 2.5-2.5h1c1.375 0 2.5 1.125 2.5 2.5v1.5h2zM18 2.5v4.5c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5v-4.5c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5zM6 2.5v4.5c0 0.281 0.219 0.5 0.5 0.5h1c0.281 0 0.5-0.219 0.5-0.5v-4.5c0-0.281-0.219-0.5-0.5-0.5h-1c-0.281 0-0.5 0.219-0.5 0.5zM24 26v-16h-22v16h22zM14 17h3.5c0.281 0 0.5 0.219 0.5 0.5v1c0 0.281-0.219 0.5-0.5 0.5h-3.5v3.5c0 0.281-0.219 0.5-0.5 0.5h-1c-0.281 0-0.5-0.219-0.5-0.5v-3.5h-3.5c-0.281 0-0.5-0.219-0.5-0.5v-1c0-0.281 0.219-0.5 0.5-0.5h3.5v-3.5c0-0.281 0.219-0.5 0.5-0.5h1c0.281 0 0.5 0.219 0.5 0.5v3.5z>/path> /symbol> symbol idicon-sticky-note viewBox0 0 24 28> path dM16 19.5v6.5h-14.5c-0.828 0-1.5-0.672-1.5-1.5v-21c0-0.828 0.672-1.5 1.5-1.5h21c0.828 0 1.5 0.672 1.5 1.5v14.5h-6.5c-0.828 0-1.5 0.672-1.5 1.5zM18 20h5.953c-0.141 0.75-0.547 1.594-1.016 2.063l-2.875 2.875c-0.469 0.469-1.313 0.875-2.063 1.016v-5.953z>/path> /symbol> symbol idicon-document-add viewBox0 0 32 32> path dM21 25v-3h1v3h3v1h-3v3h-1v-3h-3v-1h3zM17.257 29v0 0c1.009 1.221 2.535 2 4.243 2 3.038 0 5.5-2.462 5.5-5.5 0-2.137-1.219-3.99-3-4.9v-11.6l-6-7h-10.997c-1.106 0-2.003 0.898-2.003 2.007v22.985c0 1.109 0.891 2.007 1.997 2.007h10.26zM16.6 28h-9.6c-0.545 0-1-0.446-1-0.995v-23.009c0-0.54 0.446-0.995 0.996-0.995h10.004v4.994c0 1.119 0.895 2.006 1.998 2.006h4.002v10.207c-0.477-0.135-0.98-0.207-1.5-0.207-3.038 0-5.5 2.462-5.5 5.5 0 0.9 0.216 1.75 0.6 2.5v0 0zM18 3.5l4.7 5.5h-3.703c-0.546 0-0.997-0.452-0.997-1.009v-4.491zM21.5 30v0c-2.485 0-4.5-2.015-4.5-4.5s2.015-4.5 4.5-4.5c2.485 0 4.5 2.015 4.5 4.5s-2.015 4.5-4.5 4.5z>/path> /symbol> symbol idicon-document-add1 viewBox0 0 32 32> path dM21 25v-3h1v3h3v1h-3v3h-1v-3h-3v-1h3zM16.022 29h-9.024c-1.107 0-1.997-0.899-1.997-2.007v-22.985c0-1.109 0.899-2.007 2.009-2.007h9.991v6.002c0 1.111 0.898 1.998 2.006 1.998h4.994v9.498c-0.77-0.321-1.614-0.498-2.5-0.498-3.59 0-6.5 2.91-6.5 6.5 0 1.289 0.375 2.49 1.022 3.5v0 0zM18 2v5.997c0 0.554 0.451 1.003 0.991 1.003h5.009l-6-7zM21.5 31c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5c-3.038 0-5.5 2.462-5.5 5.5s2.462 5.5 5.5 5.5v0z>/path> /symbol>/svg> /div>div classretail-scripts-bot> div classglobal-scripts> script> var bValidIp false; var sOfUrl https://www.nitrousexpress.com; var jsConfig { static_pages: { content_key: , content_type: } } /script> script srccode/global_modal_js.asp?047c7ad>/script> script src../hooks/js_custom_functions.asp?047c7ad>/script> script srcjs/vendor/stretchy.min.js?047c7ad data-filter.stretchy, .stretchy *>/script> noscript classnoscript> WARNING: You will not be able to place an order or use most features of this site with JavaScript disabled /noscript>/div>script src/js/bundles/coreBot.js?047c7ad95827131b7e80a38145dd45a0c601738b >/script> script src../js/retail.js?047c7ad>/script> /div>div idappLoadingWidget classapp-loading hide> svg idappLoadingSpinner classapp-loading-spinner version1.1 xmlnshttp://www.w3.org/2000/svg xmlns:xlinkhttp://www.w3.org/1999/xlink x0px y0px width170px height170px viewBox-220 312 170 170 enable-backgroundnew -220 312 170 170 xml:spacepreserve> g classapp-loading-spinner-svg> path fill#AAAAAA dM-67.6,398.2l13.5-4c-0.3-5.9-1.1-11.6-2.4-17l-14-0.3c-0.5-1.6-1.1-3-1.6-4.6l10.8-8.9 c-2.4-5.1-5.4-10.2-8.6-14.8l-13.2,5.1c-1.1-1.3-2.2-2.4-3.2-3.5l6.5-12.4c-4.3-3.8-8.9-7.3-13.8-10.2l-10,9.7 c-1.3-0.8-3-1.3-4.3-2.2l1.3-14c-5.4-1.9-10.8-3.5-16.7-4.3l-5.7,12.9c-1.6-0.3-3.2-0.3-4.9-0.3l-4-13.5c-5.9,0.3-11.6,1.1-17,2.4 l-0.3,14c-1.6,0.5-3,1.1-4.6,1.6l-8.9-10.8c-5.1,2.4-10.2,5.4-14.8,8.6l5.1,13.2c-1.3,1.1-2.4,2.2-3.5,3.2l-12.4-6.5 c-3.8,4.3-7.3,8.9-10.2,13.8l9.7,10c-0.8,1.3-1.3,3-2.2,4.3l-14-1.3c-1.9,5.4-3.5,10.8-4.3,16.7l12.9,5.7c-0.3,1.6-0.3,3.2-0.3,4.9 l-13.5,4c0.3,5.9,1.1,11.6,2.4,17l14,0.3c0.5,1.6,1.1,3,1.6,4.6l-10.8,8.9c2.4,5.1,5.4,10.2,8.6,14.8l13.2-5.1 c1.1,1.3,2.2,2.4,3.2,3.5l-6.5,12.4c4.3,3.8,8.9,7.3,13.8,10.2l10-9.7c1.3,0.8,3,1.3,4.3,2.2l-1.3,14c5.4,1.9,10.8,3.5,16.7,4.3 l5.7-12.9c1.6,0.3,3.2,0.3,4.9,0.3l4,13.5c5.9-0.3,11.6-1.1,17-2.4l0.3-14c1.6-0.5,3-1.1,4.6-1.6l8.9,10.8 c5.1-2.4,10.2-5.4,14.8-8.6l-5.1-13.5c1.3-1.1,2.4-2.2,3.5-3.2l12.4,6.5c3.8-4.3,7.3-8.9,10.2-13.8l-9.7-10c0.8-1.3,1.3-3,2.2-4.3 l14,1.3c1.9-5.4,3.5-10.8,4.3-16.7l-12.9-5.7C-67.9,401.4-67.6,399.8-67.6,398.2z M-135,437.3c-22.4,0-40.4-18.1-40.4-40.4 c0-22.4,18.1-40.4,40.4-40.4s40.4,18.1,40.4,40.4C-94.6,419.2-112.7,437.3-135,437.3z>/path> /g> image classapp-loading-spinner-img srctemplates/gfx/loading/loading.gif altLoading...>/image>/svg>/div> !-- KO Templates --> div classcatalog-templates-scripts> script> var utils {}; utils.isMainProduct function (product) { return product && ko.unwrap(viewModel.mainProduct) product; }; utils.formatProductLink function(data){ console.log(data); }; utils.setCookie function (name, value) { //need to also set expiry date? document.cookie name + + value + ;path/;; }; // www.the-art-of-web.com/javascript/getcookie/ utils.getCookie function (name) { var re new RegExp(\\b + name + (^;+)); var value re.exec(document.cookie); return value ? unescape(value1) : undefined; }; utils.isActiveQuote (utils.getCookie(activequote) && utils.getCookie(activequote).length 32); //http://stackoverflow.com/questions/5999118/add-or-update-query-string-parameter utils.setParameter function (key, value, uriArg) { var uri uriArg || window.location.toString(); var re new RegExp((?&) + key + .*?(&|$), i); var separator; if (uri.indexOf(?) -1) { separator ?; } else { if (uriuri.length - 1 ?) { separator ; } else { separator &; } } if (uri.match(re)) { return uri.replace(re, $1 + key + + value + $2); } else { return uri + separator + key + + value; } }; utils.getParameter function (param) { var value; var parameters window.location.search.replace(?, ); if (parameters) { var pattern new RegExp(\\b + param + (^;&+), gi); value parameters.split(pattern)1; } return value || ; }; utils.handleImageError function (img) { if ($(img).attr(src) ! oConfig.noImagePath) { $(img).attr(src, oConfig.noImagePath); } }; utils.buildImagePath function(image){ image image.replace(oConfig.storefrontUrl, oConfig.sessionData.cdnUrl).toLowerCase(); image image.replace(images/images/, images/); if(!image){ return oConfig.noImagePath || oConfig.sessionData.cdnUrl.replace(/\/+$/, ) + /images/ + oConfig.defaultImage.replace(/^\/+/, ); } else if(image.indexOf(http) > -1){ return image.replace(/http:/i, https:); } else if(image.indexOf(/) > -1){ return oConfig.sessionData.cdnUrl.replace(/\/+$/, ) + / + image.replace(/^\/+/, ); } else{ return oConfig.sessionData.cdnUrl.replace(/\/+$/, ) + /images/ + image.replace(/^\/+/, ); } } utils.drawHidePriceMessage function(){ return ; } utils.removeHTML function(text){ return $(text).text(); } utils.decodeHTML function(text) { return $(textarea>).html(text).text() }; utils.getStoredBreadcrumbs function() { try { return JSON.parse(localStorage.getItem(breadcrumbs)); } catch(e) { return null; } }; utils.setStoredBreadcrumbs function(obj) { try { var config { allow: true, breadcrumb: obj }; runHook(setStoredBreadcrumbs, config); if(config.allow) { localStorage.setItem(breadcrumbs, JSON.stringify(config.breadcrumb)); } } catch(e) { // nothing to do if it didnt work console.error(failed to save breadcrumbs); } }; utils.breadCrumbProperty function(link) { if(link || link null ){ return ; }else{ return itemListElement; } }; utils.breadCrumbItemType function(link) { if(link || link null ){ return ; }else{ return ListItem; } }; utils.pageUrl location.pathname + location.search; if(utils.pageUrl.charAt(0) /) { utils.pageUrl utils.pageUrl.substring(1); } utils.loginUrl security_logon.asp?autopage + encodeURIComponent(utils.pageUrl); utils.formatMoney (function (positiveExample, negativeExample) { /* This takes an example of a formatted currency and returns a function to format numbers in that same format. The first argument is the number 1111.2222 formatted with the desired default number of decimals. The second argument is the additive inverse of the first. For example: $1,111.22 ¥ 1,111.22 €1.111,22 1 111,22F */ use strict; function buildFormatter(example) { var thousandsSeperator getGroup(/1(^1?)1/); var decimalSymbol getGroup(/1(^12?)2/); var decimalPlaces (example.match(/2/g) || ).length; var thousandsRegex /(\d)(?(?:\d{3})+$)/g; var escapedDecimalSymbol _.escapeRegExp(decimalSymbol); var symbolRegex new RegExp(^(^1 + escapedDecimalSymbol + *).+?(^12 + escapedDecimalSymbol + *)$); var symbolMatch symbolRegex.exec(example); var prefix symbolMatch ? symbolMatch1 || : ; var suffix symbolMatch ? symbolMatch2 || : ; var infoLost 0; function getGroup(pattern) { var match pattern.exec(example) return match ? match1 : ; } function decimalToString(decimal, places) { if (!places) { return ; } else { var result getZeroString(places); if (decimal) { // Converting to an integer and rounding helps with // floating point errors. var int Math.round(decimal * Math.pow(10, places)); // Because leading zeroes will be dropped after // converting to integer, the string needs to be // padded with zeroes after being converted to a // string. result (result + int.toString()).slice(-places); } if(intMath.pow(10,places)) { // in this case, we have to track a +1 to add to the result because 100 sliced down to 2 places loses info /* * 2020-07-22 - EJ - More info: This is due to things like utils.formatPrice(1.995, 2) returning 1.00 instead * of 2.00 or utils.formatPrice(1.9995, 3) returning 1.000 instead of 2.000 * This is because the whole number is truncated, then the decimal is rounded and only the decimal portion * is added back to the whole number portion. * This means the rounded decimal portion is always 1 or less. If its less than 1 (ex .89) this works. * However, if its 1.000, it would lose 1 since only the decimal portion is added back. * PS - Dont ask me about the original design, I didnt design it that way. I only corrected the if * statement above where it was hard-coded to 100 to be Math.pow(10,places) so it would work when * rounded to something other than 2 decimal places. */ infoLost 1; } else { infoLost 0; } return decimalSymbol + result; } } function getZeroString(length) { var pow Math.pow(10, length); return pow.toString().slice(1); } function addThousandsSeperator(integer) { return (integer + infoLost).toString().replace(thousandsRegex, $1 + thousandsSeperator); } return function (value, places) { places typeof places undefined ? decimalPlaces : parseInt(places); // Truncate the value to get the integer portion. var integer value | 0; var decimal decimalToString(value % 1, places); //do first because we need to know if info was lost. var number addThousandsSeperator(integer) + decimal; return prefix + number + suffix; } } var formatPositive buildFormatter(positiveExample); var formatNegative buildFormatter(negativeExample); return function (value, places) { value parseFloat(ko.unwrap(value)); if (isNaN(value)) return value.toString(); return (value 0 ? formatNegative : formatPositive)(Math.abs(value), places); } }($1,111.22, ($1,111.22))); utils.formatPrice _.partialRight(utils.formatMoney, parseInt(2)); utils.scrollTo function (elementArg) { var element $(elementArg).first(); if (!element.length) return; // If the element is in an inactive tab, make the tab active. utils.activateTab(element); $(html, body).animate({ scrollTop: $(element0).offset().top - 120 //offset to account for header bar }, 500); }; utils.activateTab function (element) { var tab element.hasClass(.tab-pane) ? element : element.closest(.tab-pane); if (!tab.length || tab.hasClass(active)) return; var id tab.attr(id); tab .closest(.tabbable) .find(.nav-tabs > li > a) .filter(href# + id + , data-target# + id + ) .tab(show); } utils.plural function (singularForm, quantifier, includeQuantity) { var quantifierValue ko.unwrap(quantifier); var quantity _.isArray(quantifierValue) ? quantifierValue.length : quantifier; return (includeQuantity ? quantity + : ) + attache.plural(singularForm, quantity); }; utils.atcListButtonText function() { if(utils.isActiveQuote) { return Add to Active + oConfig.labels.savedCarts; } else { return oConfig.labels.addToCartList || Add to Cart; } }; utils.resetATCForm function() { if(!runHook(catalogTemplatesOverrideResetATCForm, { utils: this })) { document.getElementById(atc_form).reset(); _.forEach(viewModel.results(), function(result) { if (setSelectedQty()) { result.selectedQty(result.minQty() || 1); }else{ result.selectedQty(undefined); } result.selectedQty.notifySubscribers(); }); } } utils.addToCart function (details, cart, parentKey, useInstances) { function getQueryStringParameters() { var params { type : v200add, sc_id : oConfig.overrideCartKey || oConfig.sessionData.sc_id, s_key : oConfig.sessionData.sessionKey, s_url : oConfig.sessionData.storefrontUrl, o_url : oConfig.sessionData.orderfrontUrl, createsessioncookie : 1, noredirect : 1, l_ws_key : , mobile : no, action : postlogic }; // Only one order detail can be edited at a time, so if there // are more than one, choose an arbitrary one to edit. var editedOrderDetail _.find(details, configuratorEditData); if (editedOrderDetail) params.odeditkey editedOrderDetail.configuratorEditData.od_id; if (cart) { _.assign(params, { type: add-to-saved-cart, o_id: cart.key, nickname: cart.nickname }); } return params; } function getPostData() { var data {}; var productKeys ; var instanceKeys ; var instancesWithKeys {}; // Force use instances on if its off / undefined and we detect duplicate p_keys if(!useInstances && details.length) { var distinctProductKeys details.reduce(function(distinctValues, detail, index) { if(distinctValues && distinctValues.indexOf(detail.key()) 0) { distinctValues.push(detail.key()); } }, ); if(distinctProductKeys && distinctProductKeys.length ! details.length) { // Always use instances if were adding the same product key to cart in one post useInstances true; } } buildConfiguratorData function(product) { /* config_json field example: { question:F4E82B1A5F5A4A3F915B6618A766754F, questionText:STRIKE (required), name:6800_000_10, answer:790BA1B41D6E48ECB2A825CB02EDAB93, answerText:A - 4-7/8 ASA Strike, question_erp_code:10_001, answer_erp_code:01, question_status:True } Full config_json structure: { choices: { field1 }, { field2 } , configType: cartoptions // or configurator } */ /* Were setting configType based on the customForm value, but we should never hit this code if its true until we put configurator in KO. This is here just in case or for future use. customForm not be ndefined if not on the product detail page. */ if(typeof customForm ! undefined && !!customForm) { configType configurator; } else { configType cartoptions; } var configJson { choices: , configType: configType }; var cartOptions ; if(product.questions && product.questions().length > 0) { product.questions().forEach(function(question) { configJsonQuestion { question: question.q_key(), name: question.questionText(), questionText: question.questionText(), answerText: question.selectedAnswer(), question_status: true }; if(question.erpCode()) { configJsonQuestionquestion_erp_code question.erpCode(); } configJson.choices.push(configJsonQuestion); cartOptions + question.questionText() + ~ + question.selectedAnswer() + | }); } return { configJson: configJson, cartOptions: cartOptions.slice(0, -1) // trim trailing pipe }; } _.forEach(details, function (item) { var product item.selectedProduct(); var productKey product.key(); var minQty product.minQty() || 1; var uom ko.toJS(product.selectedUom()); var lineKey productKey; if(useInstances) { lineKey utils.createGuid(); var tempInstanceKey item.instance || utils.createGuid(); product.instanceKey tempInstanceKey; product.lineKey lineKey; instanceKeys.push(tempInstanceKey); if(!instancesWithKeystempInstanceKey) { instancesWithKeystempInstanceKey ; } instancesWithKeystempInstanceKey.push(lineKey); datainstance_ + lineKey tempInstanceKey; datap_id_ + lineKey productKey; dataremove_type_ + lineKey instance; datainstance_key_set 1; } dataqty_ + lineKey product.selectedQty() || minQty; if(oConfig.useUom){ datauom_ + lineKey uom.description; if(uom.hasOwnProperty(UomId)) datauom_id_ + lineKey uom.UomId; datauom_conversion_ + lineKey uom.uom_conversion; } datapw_id_ + lineKey ko.unwrap(product.selectedWarehouse().key) || oConfig.defaultWarehouse; if(item.type child && parentKey) { dataparent_p_id_ + lineKey parentKey; } dataurl_ + lineKey item.link(); dataminqty_ + lineKey product.selectedUom().minQty(); datamaxqty_ + lineKey product.selectedUom().maxQty(); dataqty_increment_ + lineKey product.selectedUom().step(); _.assign(data, buildConfiguratorPostData(productKey)); if (minQty ! 1) datamin_order_qty_ + lineKey minQty; if(product.configuratorEditData && product.configuratorEditData.lineNumber) { dataline_number_ + lineKey product.configuratorEditData.lineNumber; } if(product.configuratorEditData && product.configuratorEditData.minQty) { dataminqty_ + lineKey product.configuratorEditData.minQty; } if(product.configuratorEditData && product.configuratorEditData.maxQty) { datamaxqty_ + lineKey product.configuratorEditData.maxQty; } if(product.configuratorEditData && product.configuratorEditData.qtyIncrement) { dataqty_increment_ + lineKey product.configuratorEditData.qtyIncrement; } if(product.configuratorEditData && product.configuratorEditData.removeType) { dataremove_type_ + lineKey product.configuratorEditData.removeType; } if(product.configuratorEditData && product.configuratorEditData.priceCalcType) { dataprice_calc_type_ + lineKey product.configuratorEditData.priceCalcType; if(product.configuratorEditData.priceCalcType fixed) { dataprice_ + lineKey product.configuratorEditData.price; } } if(product.questions && product.questions().length > 0 && product.hasCartOptions()) { var configData buildConfiguratorData(product); dataconfig_json_ + lineKey JSON.stringify(configData.configJson); datacart_option_ + lineKey configData.cartOptions; } productKeys.push(lineKey); //This needs to be above the hook so that the order in which the items are added to cart will persist. - cainb 2019-01-23 12:35:49 runHook(getPostDataBeforeReturn, { self: self, data: data, product: product, productKeys: productKeys }); }); data.keys _.uniq(productKeys).join(,); if(instanceKeys.length) { data.instances _.uniq(instanceKeys).join(,); for(key in instancesWithKeys) { datakey + _keys instancesWithKeyskey.join(,); } } return data; } function getAjaxConfig() { return { url: i_i_add_to_cart.asp? + $.param(getQueryStringParameters()), type: POST, data: $.param(getPostData(), true), // true forces jquery to not add brackets to array keys headers: { X-Requested-With: XMLHttpRequest, Accept: application/json, text/plain, * / *, Content-Type: application/x-www-form-urlencoded } }; } function logSummary() { var cartName cart ? + cart.nickname + : ; console.log(Items added to cart + cartName + :\n + _.map(details, function (product) { return \tQty: + product.selectedQty() + - + product.name(); }).join(\n)); } function successHandler(responseData, status, request) { if(oConfig.isModal) { parent.modal.done(); return; } if(viewModel.mainProduct && viewModel.mainProduct.configuratorEditData) { window.location showcart.asp; return; } if(!cart) { try{ fncReloadCartWindow(); }catch(err){ } if(typeof ofConfig undefined || !ofConfig.stopToastrATC) { utils.toastrATC(details, cart); } } else { utils.modalATC(cart, data, details); } if(oConfig.pageName pc_combined_results.asp && isActiveLayout(list)) { utils.resetATCForm(); } logSummary(); toggleLoadingWidget(false); //render promo messaging template and display if applicable. element utils.renderTemplateToContainer(catalog.promo_bar, data); if(viewModel.atcComplete) { viewModel.atcComplete(); } postGoogleAnalytics(details); runHook(addToCartSuccessHandler, { self: self, responseData: responseData, details: details }); } function errorHandler(responseData, status, request) { logSummary(); var errorToastrConfig { closeButton: true, newestOnTop: true, positionClass: toast-top-right, preventDuplicates: false, showDuration: 200, hideDuration: 1000, tapToDismiss: true, timeOut: 3000, extendedTimeOut: 1000 } toggleLoadingWidget(false); console.log(responseData); toastr.error( Unable to add item to cart, There was an error, errorToastrConfig ); } function postGoogleAnalytics(details){ if(oConfig.t_analytics uae){ var gtmProducts ; _.forEach(details, function(item){ var gtmProduct { name: item.name(), id: item.sku(), price: item.unitPrice(), quantity: Number(item.selectedQty()) } gtmProducts.push(gtmProduct); }); ga(ec:addProduct, gtmProducts); ga(ec:setAction, add); ga(send, event, UX, click, add to cart); } /* If using GTM pass add to cart event on sucess */ if(oConfig.t_gtm) { var gtmProducts ; _.forEach(details, function (item) { var gtmProduct { name: item.name(), id: item.sku(), price: item.unitPrice(), quantity: Number(item.selectedQty()) } gtmProducts.push(gtmProduct); }); if (gtmProducts.length > 1) { dataLayer.push({ event: oConfig.t_gtm_add_to_cart_event_name, ecommerce: { currencyCode: USD, add: { products: gtmProducts } } }); } } } var bPass true; // TODO: add UoM support (qty_display, etc). Fields arent available on the UoM Price objects yet. if (!_.isArray(details)) { details details ; } var data { details: details, cart: cart }; var questionsValid true; details.some(function(detail) { if(detail.hasOwnProperty(questionsHaveValidAnswers)) { questionsValid detail.questionsHaveValidAnswers(); if(!questionsValid) { detail.atcErrorText(Required option fields missing.); } else { detail.atcErrorText(); } if(!questionsValid && detail.hasOwnProperty(currentParent)) { detail.currentParent().rowsAtcAttempted(true); } } return !questionsValid; }); if(!questionsValid) { return false; } if(details.length > 0 && details0.useConfigurator()){ /* doing an eval on an undefined throws an error. so, we have to try-catch. The template may be overriden to allow a product (with configurator) to be added to cart w/o any config options selected. */ try { if(!eval(formValidation + oConfig.formValidationKey).check()){ bPass false; } } catch(e) { //not using FormBuilder } }else if(details.length 0) { bPass false; } if(bPass){ toggleLoadingWidget(true); cart ko.toJS(cart); var promise $.ajax(getAjaxConfig()) .error(errorHandler) .done(successHandler); return promise; }else{ return false; } }; utils.popToastr function(title, subtext, config) { var confirmToastrConfig config ? config : { closeButton: true, newestOnTop: true, positionClass: toast-top-right, preventDuplicates: false, showDuration: 200, hideDuration: 1000, tapToDismiss: false, timeOut: 3000, extendedTimeOut: 1000 }; toastr.success( subtext, title, confirmToastrConfig ); }; utils.popToastrError function(title, subtext, config) { var errorToastrConfig { closeButton: true, newestOnTop: true, positionClass: toast-top-right, preventDuplicates: false, showDuration: 200, hideDuration: 1000, tapToDismiss: true, timeOut: 3000, extendedTimeOut: 1000 } $.extend(errorToastrConfig, config); toggleLoadingWidget(false); toastr.error( subtext, title, errorToastrConfig ); } utils.toastrATC function(details, cart) { var sPage showcart.asp; if(utils.isActiveQuote){ sPage payment.asp } var confirmToastrConfig { closeButton: true, newestOnTop: true, onclick: function() { window.location oConfig.sessionData.orderfrontUrl + / + sPage; }, positionClass: toast-top-right, preventDuplicates: false, showDuration: 200, hideDuration: 1000, tapToDismiss: false, timeOut: 3000, extendedTimeOut: 1000 } if(cart) { var confirmTextConfig {title: utils.plural(oConfig.labels.savedCartsLabels.itemText, details, true) + + oConfig.labels.savedCartsLabels.modalConfirmationHeader } }else{ if(utils.isActiveQuote){ var confirmTextConfig { title: utils.plural( item, details, true) + added to + oConfig.labels.savedCarts } }else{ var confirmTextConfig { title: utils.plural( item, details, true) + added to Cart} } }; utils.popToastr( confirmTextConfig.title, Click or tap to view, confirmToastrConfig ); } utils.modalATC function(cart, data, details) { var modalConfig cart ? { body: catalog.saved_cart_confirmation_body, size: , title: utils.plural(oConfig.labels.savedCartsLabels.itemText, details, true) + + oConfig.labels.savedCartsLabels.modalConfirmationHeader } : { body: catalog.atc_body, footer: catalog.atc_popup_buttons, size: getATCModalSize(), title: utils.plural( Item, details, true) + Added to Cart }; runHook(modalATCAfterConfiguration, { self: self, cart: cart, modalConfig: modalConfig, details: details }); utils.openModal(modalConfig, data); } utils.renderTemplateToContainer function (template, data) { var surrogate document.createElement(div); var $container $(div>).append(surrogate); ko.renderTemplate( template, data, null, surrogate, replaceNode ); return $container; }; utils.getSavedCart function (carts, callback) { var selectedCart ko.observable(); selectedCart.subscribe(callback); var data { savedCarts: carts, selectedCart: selectedCart }; utils.openModal({ body: oConfig.savedCartPopupTemplate, size: small, title: oConfig.labels.savedCartsLabels.modalHeader, backdrop: static }, data); }; utils.createGuid function () { // https://stackoverflow.com/a/8809472 var d new Date().getTime(); if(window.performance && typeof window.performance.now function){ d + performance.now(); //use high-precision timer if available } var guid xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx.replace(/xy/g, function(c) { var r (d + Math.random()*16)%16 | 0; d Math.floor(d/16); return (cx ? r : (r&0x3|0x8)).toString(16); }); return guid.toUpperCase(); }; // Generates a unique ID and returns it twice in a row. Intended for use with the `for` // attribute on `label` elements. (function () { var previousId; utils.labelId function () { var id previousId || utils.createGuid(); previousId previousId ? null : id; return id; }; }()); utils.openModal function (options, data) { _.forEach(header, body, footer, function (prop) { if (optionsprop) { optionsprop utils.renderTemplateToContainer(optionsprop, data); } }); modal.open(options); }; var productModel function (product) { var self this; var productCollectionMapping { create: function (options) { return new productModel(options.data); } } ko.mapping.fromJS(product, { copy: tab2_html, opt1, opt2, opt3, opt4, opt5, opt6, opt7, opt8, opt9, accountHistory, reviews, tabs, type, promoDescriptions, configuratorEditData, calc_inv_message, use_cart_options , related: productCollectionMapping, secondRelated: productCollectionMapping, children: productCollectionMapping, alsoBought: productCollectionMapping }, self); self.children.extend({ deferred: true }); self.atcButtonText ko.observable(); self.atcErrorText ko.observable(); self.updateAtcButtonText function() { if(self.configuratorEditData && self.configuratorEditData.od_id) { self.atcButtonText(oConfig.labels.updateCartItem || Update); } else if (utils.isActiveQuote) { self.atcButtonText(Add Active + oConfig.labels.savedCarts); } else { self.atcButtonText(oConfig.labels.addToCart || Add); } }; self.updateAtcButtonText(); self.hasCartOptions ko.computed(function() { if(self.questions && self.questions() && self.questions().length && (self.type parent || self.useCartOptions())) { return true; } else { if(self.children && self.children().length) { return self.children().reduce(function(hasQuestions, child) { return hasQuestions || (!!child.questions && !!child.questions() && !!child.questions().length && child.useCartOptions()); }, false); } else { return false; } } }); self.isParent function() { if (self.type.toLowerCase() parent){ return true; }else{ return false; } } self.requireInfoForAtc ko.computed(function () { return !!(self.isParent() || self.useConfigurator() || self.hasCartOptions()); }); self.priceDisplay ko.observable(function () { var template catalog.details_link; if (self.useConfigurator()){ template catalog.configurator_price_display; }else if (self.requireInfoForAtc() && self.childStartingPrice()) { template catalog.price_start_at } else if (!self.requireInfoForAtc()) { template catalog.selected_product_price_display; } //Manually check for template overrides since this is dynamically returned. //Need to convert this to a function and use any time template names are returned. if(document.getElementById(template + _custom)){ return template + _custom; }else{ return template; } return template; }()); self.selectedQty ko.observable(function() { if(self.configuratorEditData) { return self.configuratorEditData.qty; } else { return undefined; } }()); //self.selectedQty ko.observable(); self.isQtyValid ko.observable(true); self.selectedWarehouse ko.observable(_.find(self.inventory.warehouses(), function(wh){ return wh.isDefault() } ) || ); if(self.configuratorEditData && self.configuratorEditData.pw_id) { self.selectedWarehouse(_.find(self.inventory.warehouses(), function(wh){ return wh.key() self.configuratorEditData.pw_id } ) || ); } self.selectedUom ko.observable( (function () { var uom undefined; // Its possible that this is a parent product and the configurator // edit data will not match a uom on the parent, however the selectedProduct // has not been set at this point, so we cant just use selectedProduct // With the previous version of this code, this would make the selectedUom // undefined and break other parts of the code because it skipped all other // checks if configuratorEditData had a uom value. Now it will check the // other conditions if the configuratorEditData doesnt match an available uom. // Theres certainaly a better way to handle this, but this will do for now. if(self.configuratorEditData && self.configuratorEditData.uom) { uom _.find(self.uomPrice(), function (price) { return price.description() self.configuratorEditData.uom; }); } if(!uom) { uom _.find(self.uomPrice(), function (price) { if (price.hasOwnProperty(isDefault)){ return price.isDefault(); //set from SSJS } else if(typeof price.IsDefault() undefined){ return price.ConversionRate() 1; //fallback } else{ return price.IsDefault() || price.ConversionRate() 1 || price.ConversionRate() 12; //returned from COM } }); } return uom; })()); _.each(self.uomPrice(),function(uom){ var bHasBreaks false; bHasBreaks uom.breaks().length > 0; uom.hasBreaks(bHasBreaks); }); self.processedBreaks ko.computed(function() { if (!( self.selectedUom() && self.selectedUom().hasBreaks() )) { return ; } var processed ; var data self.selectedUom().breaks(); //converted from price break popup window to properly display single breaks that actually have multiple break records if(datadata.length -1.qty() 1000000 || datadata.length -1.qty() 100000000){ data.pop(); } //If theres only one break we will skip showing the price break information if(data.length 1) { return ; } processed data.map(function(lineBreak) { var price, startQ, endQ, range; price lineBreak.price(); startQ lineBreak.qty(); endQ lineBreak.qtyEnd(); if (endQ ! 0) { range startQ + - + endQ; } else { range startQ + +; } return { price: price, range: range }; }); return processed; }); self.configPrice buildConfiguratorPriceObservable(self.key()); self.unitPrice ko.computed(function () { if(self.configuratorEditData && self.configuratorEditData.priceCalcType fixed) { return self.configuratorEditData.price; } return self.selectedUom().price() + self.configPrice(); }); self.priceTrace ko.computed(function() { var bPriceErrorMessage ; if(utils.getParameter(action) showpricetrace) { bPriceErrorMessage Price trace is not available when using WSP Search Service; } return self.selectedUom().priceTrace ? self.selectedUom().priceTrace() : bPriceErrorMessage; }); self.youSavePercent ko.computed(function () { return (((self.selectedUom().suggestedPrice() - self.selectedUom().price()) / self.selectedUom().suggestedPrice()) * 100).toFixed(2) + %; }); self.suggestedPrice ko.computed(function () { return self.selectedUom().suggestedPrice(); }); self.showYouSave ko.computed(function () { return parseFloat((self.selectedUom().suggestedPrice() || 0).toFixed(oConfig.detailConfig.globalUnitPriceDecimalPlaces)) > parseFloat((self.selectedUom().price() || 0).toFixed(oConfig.detailConfig.globalUnitPriceDecimalPlaces)) && self.selectedUom().suggestedPrice() > 0 && oConfig.showProdYouSave 1; }); self.childView function () { // return (self.childDisplayType() || stand-alone) + -layout; return stand-alone-layout; }(); self.showAtc function () { var primary1 self.inventory.showAtc() && oConfig.searchConfig.showAtc && self.mapPriceType() ! show_message; var secondary1 oConfig.isLoggedIn || self.mapPriceType() ! require_login_for_atc; var secondary2 oConfig.isLoggedIn || self.mapPriceType() ! require_login_for_price_and_atc; var tertiary1 self.mapPriceType() require_atc || (self.mapPriceType() require_login_or_atc && !oConfig.isLoggedIn); var tertiary2 self.mapPriceType() ! hide && (self.showProdAtc() ! 0); var quaternary1 !(self.type parent && self.childDisplayType() droplist && oConfig.pageName ! pc_combined_results.asp) return primary1 && (secondary1) && (secondary2) && ( (tertiary1) || (tertiary2) ) && quaternary1; }(); self.showQuickAtc ko.computed(function () { var showQuickAtc self.showAtc && !self.requireInfoForAtc() && self.type ! parent; //initial setting if(oConfig.showChildrenSelection && self.type child ){ if(self.unitPrice() > 0 && self.showAtc){ showQuickAtc true; } else{ showQuickAtc false; } } return showQuickAtc; //(self.showAtc && !self.requireInfoForAtc()) }); self.showPrice function () { return self.type ! parent && ( (self.mapPriceType() ! show_message) && !((self.mapPriceType() require_login_for_price_and_atc) && !oConfig.isLoggedIn) && !(self.mapPriceType() require_atc || (self.mapPriceType() require_login_or_atc && !oConfig.isLoggedIn)) ) && (self.mapPriceType() ! hide) && (self.showProdPrice() ! 0) && oConfig.showPricingOrderEntry; }(); self.mapPriceMessage function () { if (self.mapPriceType() show_message) { return oConfig.mapBehaviorMessages.showMessage; } else if (self.mapPriceType() require_login_for_price_and_atc && !oConfig.isLoggedIn) { return oConfig.mapBehaviorMessages.requireLoginMessage; } else if (self.mapPriceType() require_login_for_atc && !oConfig.isLoggedIn) { return oConfig.mapBehaviorMessages.requireLoginAtcMessage; } else if (self.mapPriceType() require_atc) { return oConfig.mapBehaviorMessages.requireAtcMessage; } else if (self.mapPriceType() require_login_or_atc && !oConfig.isLoggedIn) { return oConfig.mapBehaviorMessages.requireLoginOrAtcMessage; } else if (self.mapPriceType() ! hide) { return ; } }(); self.warehouseTemplate function () { if (oConfig.showWarehouses && self.inventory.warehouses().length > 0 && self.inventory.inventoryStatus() in) { if ((oConfig.allowWarehouseSelection && oConfig.searchConfig.hideAtcShowInv) || (oConfig.allowWarehouseSelection && self.showQuickAtc())) { return warehouse_droplist; } else if (oConfig.useWarehousesTable) { return warehouse_table; } else { return warehouse_info; } } else { return warehouse_off; } }(); self.priceBreaksTemplate function(){ if(oConfig.useBreaks && self.selectedUom().hasBreaks){ if(oConfig.useBreaksTable && !oConfig.useUom && oConfig.pageName pc_product_detail.asp){ return catalog.qty_breaks_table; }else{ return catalog.qty_breaks; } }else{ return catalog.breaks_off; } }(); self.uomTemplate ko.computed(function() { if (self.selectedProduct().uomPrice().length > 1) { return catalog.uom_select; } else { return catalog.uom_input; } }); self.documentsTemplate function () { return catalog.documents; }(); self.qtyInputClick function (key) { jQuery(#qty_+key).focus(); jQuery(#qty_+key).select(); }; self.validateQtyInput function (data) { if (utils.getCookie(productLayout) list) { return ; } else { return 1; } }; self.hideOnListView function () { if ((isActiveLayout(list) && !oConfig.detailConfig.productKey ) || (self.type child && oConfig.detailConfig.productKey)) { return hide; } }; self.isChild function () { if (self.type.toLowerCase() child){ return true; }else{ return false; } } self.minQty ko.computed(function () { if (self.configuratorEditData && self.configuratorEditData.minQty) { self.selectedProduct().selectedUom().minQty(self.configuratorEditData.minQty); } if (oConfig.useQtyRestrictions) { return self.selectedProduct().selectedUom().minQty(); } else { return 0; } }); self.stepQty ko.computed(function () { if (self.configuratorEditData && self.configuratorEditData.qtyIncrement) { self.selectedProduct().selectedUom().step(self.configuratorEditData.qtyIncrement); } if (oConfig.useQtyRestrictions) { return self.selectedProduct().selectedUom().step(); } else { return 1; } }); self.maxQty ko.computed(function () { if (self.configuratorEditData && self.configuratorEditData.maxQty) { self.selectedProduct().selectedUom().maxQty(self.configuratorEditData.maxQty); } if (oConfig.useQtyRestrictions && self.selectedProduct().selectedUom().maxQty() > 0) { return self.selectedProduct().selectedUom().maxQty(); } else { return ; } }); self.hasQuantityRestrictions ko.computed(function () { return !!(self.minQty() || self.stepQty() ! 1 || self.maxQty()); }); self.quantityRestrictionsHtml ko.computed(function () { var lines ; if (self.minQty()) lines.push(oConfig.labels.minQtyPopover.replace(/min_qty>/,self.minQty())); if (self.stepQty() ! 1) lines.push(Qty Increment: + self.stepQty()); if (self.maxQty()) lines.push(Maximum Qty: + self.maxQty()); return lines.join(br>); }); self.addToSavedCart function () { utils.getSavedCart(viewModel.savedCarts(), function (cart) { if (cart) { if (!_.includes(viewModel.savedCarts(), cart)) { // Insert the new cart in sorted order, notifying exactly once. var index _.sortedIndex(viewModel.savedCarts(), cart, nickname); viewModel.savedCarts.splice(index, 0, cart); } var parentKey; if(self.type child && viewModel.mainProduct) { parentKey ko.unwrap(viewModel.mainProduct).key(); } utils.addToCart(self, cart, parentKey); } }); }; self.addToCart function () { var parentKey; if(self.type child && viewModel.mainProduct) { parentKey ko.unwrap(viewModel.mainProduct).key(); } return utils.addToCart(self, undefined, parentKey); }; self.atcPopupSuccess function () { }; self.atcPopupFail function () { }; self.selectFirstTab function () { $(#tab1 > a).click(); }; self.getWebPage function (webPageId) { return page.asp?p_key + webPageId + .wpc_page_content; }; self.useTabs function () { return oConfig.detailConfig.useAdvancedTabs && self.tabs && self.tabs.length && self.showTabs(); } self.usingDownloadsTab function() { var index _.findIndex(self.tabs, function(t) { return t.dynamicSource downloads }); return self.useTabs() && index > -1; } self.getSmartListLinkOrderStats function(parent){ if(!parent){ return product_history_detail.asp } if(!oConfig.detailConfig.useAliases){ return product_history_detail.asp?search2searchexact~p.sku~ + parent.sku() + &s + parent.sku() }else{ return product_history_detail.asp?search2searchexact~pa.sku_alias~ + parent.sku() + &s + parent.sku() } }; self.getSmartListLinkInvoiceStats function(parent){ if(!parent){ return products_invoiced_detail.asp } if(!oConfig.detailConfig.useAliases){ return products_invoiced_detail.asp?search2searchexact~p.sku~ + parent.sku() + &s + parent.sku() }else{ return products_invoiced_detail.asp?search2searchexact~pa.sku_alias~ + parent.sku() + &s + parent.sku() } }; self.tableColumns ko.computed( function () { var columns Array.prototype.concat( { if: oConfig.showImgCol, label: oConfig.labels.imgCol, field: thumb, template: catalog.input_qty_thumb_display, cellClass: qty-input-table-thumb }, { if: oConfig.showNameCol && self.childDisplayType() ! add-row, label: oConfig.labels.nameCol, field: nm, template: catalog.input_qty_nm_display }, { label: SKU, field: sku, template: catalog.input_qty_sku_display }, { if: self.hasCartOptions(), label: Options, field: questions, template: catalog.cart_options } , self.childDisplayType() ! add-row ? self.childSelectors() || : , { if: oConfig.usePromos, label: Promo, template: catalog.input_qty_promo_display }, { if: oConfig.useIdp, label: Status, template: _.property(warehouseTemplate) }, { label: Price, headerClass: cell-right, cellClass: cell-right, field: unitPrice, format: utils.formatPrice, template: catalog.selected_product_price_display }, { label: Actions, headerClass: cell-right, cellClass: cell-right, template: catalog.atc_qty_input, width: 1% } ); // diagram_number needs to be added to the child products using the pos field on the mapping table if (self.childDisplayType() exploded-view) { columns.unshift({ label: ID, field: diagramNumber }); } return _.filter(columns, function (column) { return !(if in column) || ko.unwrap(column.if); }); }); self.reviews new PagedArray(self.reviews, 3); self.setupQuestions function() { self.questions().forEach(function(question) { question.answers ko.observableArray(); if(question.type() select) { if(question.useSelectOne) { question.answers.push({ label: question.selectOneText(), value: }); } if(question.answerList().length > 0) { var answersSplit question.answerList().split(|); answersSplit.forEach(function(answer) { var answerSet answer.split(~); question.answers.push( { label: answerSet0, value: answerSet0 }); }); } } }); } self.rowCollection ko.observableArray(); self.addRows function(numberOfRows) { numberOfRows numberOfRows || 1; for(i0;inumberOfRows;i++) { var row { selectedChild: ko.observable(undefined) } // Clone the children for the selector so that the child // references across rows are not the same. row.children self.children ? self.children().map( function(item) { var jsChild ko.mapping.toJS(item); var koChild ko.mapping.fromJS(jsChild, productMapping); // Add the currentParent back as the re-mapping rests it koChild.currentParent ko.observable(self); // Add a new property for the current row index // to make it easier to remove the items // We use a guid to ensure its always consistent. koChild.rowKey utils.createGuid(); return koChild; }) : ; self.rowCollection.push(row); } } self.setupAddRowView function() { if(self.childDisplayType() add-row) { self.addRows(); if(!!oConfig.childSkuMatch) { var matchedChild self.rowCollection()0.children.filter(function(child) { return oConfig.childSkuMatch child.sku(); }); if(matchedChild && matchedChild.length > 0){ self.rowCollection()0.selectedChild( matchedChild0 ); } } } } self.childSelectors ko.observableArray(); self.processChildren function() { _.each(self.children(), function(child){ child.promoDescriptions ; _.each(self.promoDescriptions, function(promo){ if(promo.targetKeys.indexOf(child.key()) > -1){ child.promoDescriptions.push(promo); } }); child.configuratorEditData self.configuratorEditData; child.currentParent(self); child.updateAtcButtonText(); child.setupQuestions(); }); _.forEach(self, function (value, key) { var keyString String(key); var matched keyString.match(/^opt(\d)$/); if (matched && value) { var selector {}; selector.field matched0; selector.label value; // _.sortByAll has been absorbed into _.sortBy in lodash 4.0.0+ var lodashSortBy typeof(_.sortByAll) function ? _.sortByAll : _.sortBy; selector.options lodashSortBy( _.uniq( _.map(self.children(), function (child) { var optXsort (typeof(childmatched0 + _sort) function ? childmatched0 + _sort() : childmatched0 + _sort) || 0; var optSort (typeof(childmatched0) function ? childmatched0() : childmatched0) || 0; var thisOpt { option: childmatched0, sort: optXsort || optSort }; runHook(selectorOptionsItemOverride, { key: key, option: thisOpt, product: child }); return thisOpt; }), option ), sort, option ); selector.selectedOption ko.observable(); if (oConfig.detailConfig.selectChildProductOnLoad) { selector.selectedOption(selector.options0); } var childSku oConfig.childSkuMatch || (!!self.configuratorEditData ? self.configuratorEditData.sku : ) || ; if (childSku){ var oChild {}; _.each(self.children(),function(child){ if(childSku child.sku()) { oChild child; return false; } }); _.each(selector.options,function(option){ if(option.option oChildselector.field){ selector.selectedOption(option); } }) } selector.showSelector ko.observable(true); self.childSelectors.push(selector); } }); self.selectedOptions ko.computed(function () { return _.map(ko.unwrap(self.childSelectors), function (item) { var selection { option: , sort: }; if (item.selectedOption()) { selection item.selectedOption().option; } return { field: item.field, option: selection }; }); }); self.selectedProduct ko.computed(function () { var filter {}; _.forEach(self.selectedOptions(), function (option) { filteroption.field option.option; }); var filteredChildren _.filter(self.children(), filter); if (filteredChildren && filteredChildren.length 1 && self.childDisplayType() ! input-qty && self.childDisplayType() ! exploded-view && self.childDisplayType() ! matrix-all && self.childDisplayType() ! add-row ) { return filteredChildren0; } else { return self; } }); self.setupQuestions(); self.setupAddRowView(); } if (self.children && self.children().length) { self.processChildren(); } else { self.selectedProduct ko.observable(self); } self.loadNextSelector function(optNumber, callback, asyncLoadOptions) { var selectedOpts _.map(self.childSelectors().filter(function(selector) {return !!selector.selectedOption && !!selector.selectedOption();}), function(s) { return s.selectedOption().option; }).join(~); $.ajax({ url: oConfig.pageName, //current page. data: { ajax: get-product-opts, key: self.key(), optFields: selectedOpts }, dataType: json, success: function(data) { var selector self.childSelectors().find(function(selector) { return selector.field opt + optNumber; }); if(!selector) { selector { field: opt + optNumber, label: selfopt + optNumber, showSelector: ko.observable(oConfig.displayDroplistPlaceholdersForLazyLoad) } self.childSelectors.push(selector); } selector.index optNumber; selector.options data.map(function(o) { return { option: o.opt, sort: 0, count: o.count, pKey: o.p_key } }); selector.loading ko.observable(false); selector.selectedOption ko.observable(); selector.showSelector(oConfig.displayDroplistPlaceholdersForLazyLoad || !!selector.options.length); selector.selectedOption.subscribe(function(newValue) { //clear any selectors after this one self.childSelectors().forEach(function(s) { if(s.index > selector.index) { s.selectedOption(undefined); s.options.splice(0, s.options.length); s.selectedOption.notifySubscribers(); s.showSelector(oConfig.displayDroplistPlaceholdersForLazyLoad); } }); self.childSelectors.notifySubscribers(); self.selectedProduct(self); if(self.children) self.children.removeAll(); // did we actually select something if (newValue) { selector.loading(true); var callback function() { selector.loading(false); } if (selector.index self.childSelectors().length) { self.loadNextSelector(selector.index + 1, callback, asyncLoadOptions); } else { //load the child if (asyncLoadOptions) asyncLoadOptions.done true; self.loadChildProduct(newValue.pKey, callback); } } }); self.childSelectors.notifySubscribers(); }, error: function() { utils.popToastrError(Error Loading List, There was an error loading the product drop list); }, complete: function() { if (callback) callback(); if (asyncLoadOptions) { var asyncLoadOptionsArray asyncLoadOptions.getArray(); var index optNumber - 1; var option self.childSelectors()index; var availableOptions option.options; var selectedOption null; if (index asyncLoadOptionsArray.length) { _.forEach(availableOptions, function (value, key) { if (value.option asyncLoadOptionsArrayindex) selectedOption value; }); } else if (oConfig.detailConfig.selectChildProductOnLoad) { selectedOption availableOptions0; } option.selectedOption(selectedOption); } } }) } self.loadChildProduct function(pKey, callback) { $.ajax({ url: oConfig.pageName, //current page. data: { ajax: get-child-product, key: pKey, parentKey: oConfig.mainProductKey }, dataType: json, success: function(data) { var product ko.mapping.fromJS(data.products0, productMapping); product.type child; // self.children.push(product); if(self.questions && self.questions().length && product.useCartOptions() && !product.f_id()) { if(product.questions) { product.questions(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); } else { product.questions ko.observableArray(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); } } product.setupQuestions(); product.configuratorEditData self.configuratorEditData; product.updateAtcButtonText(); self.selectedProduct(product); }, error: function() { utils.popToastrError(Error Loading Product, There was an error loading the product); }, complete: callback }); } self.lazyLoadingInProgress ko.observable(false); if (self.key() oConfig.mainProductKey && self.type parent && self.children().length 0 && getOriginalPageName() pc_product_detail.asp && self.childDisplayType() ! droplist) { if (!runHook(productDetailGetChildProductsByParentKey, { self: self }, {}, this)) { self.lazyLoadingInProgress(true); $.ajax({ url: oConfig.pageName, //current page. data: { ajax: get-child-products-by-parent-key, key: oConfig.mainProductKey }, dataType: json, success: function(data) { data.forEach(function(childProduct) { var product ko.mapping.fromJS(childProduct, productMapping); product.type child; if(self.questions && self.questions().length && product.useCartOptions() && !product.f_id()) { if(product.questions) { product.questions(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); } else { product.questions ko.observableArray(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); } //product.hasCartOptions(true); } product.configuratorEditData self.configuratorEditData; product.updateAtcButtonText(); //self.selectedProduct(product); self.children.push(product); }); self.processChildren(); /* if(self.childDisplayType() matrix-all) { self.matrix(ko.unwrap(ko.mapping.fromJS(generateMatrixData(ko.mapping.toJS(self))))); } */ self.lazyLoadingInProgress(false); }, error: function() { utils.popToastrError(Error Loading Product, There was an error loading the product); }, complete: function() { self.lazyLoadingInProgress(false); } }); } } /* This function generates the display data for parent products whose childDisplayType is matrix-all. It returns a data structure that looks like this: { label: Label of row>>, swatch: Either an HTML color without the # or blank. E.g. 00ff44>>, thumb: A thumbnail image link to display if the swatch is blank>>, cols: { label: Label of column>>, product: This links to the product.childrenx data. When KO maps this, it will be its own self-contained ProductModel.>> }, { ... more columns } }, { ... more rows } */ self.matrix ko.computed(function () { if(self.childDisplayType() matrix-all) { // Functionality changed between 3.10 and 4.10, new name to not break other things _.uniqBySpecial _.uniqBy || _.uniq; var rowOpt ; var colOpt ; var swatchOpt color_code; // Get sorted, unique row and column values, so that we can form the matrix var prodRows _.map(_.sortBy(_.uniqBySpecial(self.children(), rowOpt), rowOpt + _sort), rowOpt); var prodCols _.map(_.sortBy(_.uniqBySpecial(self.children(), colOpt), colOpt + _sort), colOpt); // Make this easily accessible by hooks var hookInfo { rowOpt: rowOpt, colOpt: colOpt, swatchOpt: swatchOpt, prodRows: prodRows, prodCols: prodCols } // Construct the matrix, one row at a time var matrix _.map(prodRows, function(rowLabel) { // Set defaults var swatch ; var thumb images/no-image.png; // Set the swatch var swatchProd _.find(self.children(), function(child) { return (childrowOpt rowLabel) && childswatchOpt; }); if (swatchProd) { swatch swatchProdswatchOpt; } // Set the thumbnail image var thumbProd _.find(self.children(), function(child) { return (childrowOpt rowLabel) && child.thumb && child.thumb() && child.thumb() ! images/no-image.png; }); if (thumbProd) { thumb thumbProd.thumb(); } // Generate the columns var cols _.map(prodCols, function(colLabel) { // Find the product that sits at the intersection of row and col var currentProduct _.find(self.children(), function(child) { return (childrowOpt rowLabel && childcolOpt colLabel); }); var col { label: colLabel, product: currentProduct }; runHook(productDetailMatrixCol, { parent: self, info: hookInfo, col: col }); return col; }); // Return the results var row { label: rowLabel, swatch: swatch, thumb: ko.observable(thumb), cols: cols }; runHook(productDetailMatrixRow, { parent: self, info: hookInfo, row: row }); return row; }); runHook(productDetailMatrixData, { parent: self, info: hookInfo, matrix: matrix }); return matrix; } else { return ; } }).extend({ deferred: true });; if ((self.key() oConfig.mainProductKey || oConfig.mainProductKey ) && self.type ! parent) { self.setupQuestions(); } // 2019-07-05 EJ - This only needs to run on the mainProduct on // the product detail page so I added a mainProductKey // var and check it against the current products key if (self.key() oConfig.mainProductKey && self.type parent && self.childSelectors().length 0 && getOriginalPageName() pc_product_detail.asp && self.childDisplayType() droplist) { var selectorCount 0; _.forEach(self, function (value, key) { var keyString String(key); var matched keyString.match(/^opt(\d)$/); if (matched && value) { selectorCount++; var selector {}; selector.field matched0; selector.label value; selector.options ; selector.selectedOption ko.observable(); selector.loading ko.observable(matched0 opt1); selector.index selectorCount; selector.showSelector ko.observable(oConfig.displayDroplistPlaceholdersForLazyLoad); self.childSelectors.push(selector); } }); // as third option: // pass an array of options to do loading // pass a shorter array to load up to that point then load first option from then on // pass null/false to not do loading self.loadNextSelector(1, null, new (function() { // this is an inplace constructor this.array oConfig.childOptionList, this.done false; this.getArray function() { if (this.done) return ; else return this.array; } })()); } self.matrixColors ko.observable(product.matrixColors); self.removeRow function(rowKey) { var index _.findIndex(self.rowCollection(), function(row) { return row.selectedChild().rowKey rowKey; }); self.rowCollection.splice(index, 1); } self.currentParent ko.observable(function() { if(self.type ! child) { return self; } if (self.currentparent && self.currentParent()) { return self.currentParent } if (self.type child && viewModel && ko.unwrap(viewModel.mainProduct)) { var matchingParent self.parents().find( function(parent) { return parent.key() ko.unwrap(viewModel.mainProduct).key(); } ) return matchingParent ? ko.unwrap(viewModel.mainProduct) : self; } return self; }()); self.addRowsToCart function() { var items self.rowCollection().map( function(item) { return item.selectedChild(); }) .filter( function(item) { return item ! undefined }); utils.addToCart(items, undefined, self.key(), true); } self.rowsAtcAttempted ko.observable(false); self.questionsHaveValidAnswers ko.computed(function() { var validOptions true; if(self.useCartOptions()) { self.questions().some(function(question) { var answer question.selectedAnswer(); var answerPopulated (answer ! && answer ! undefined); if(question.required() && !answerPopulated) { validOptions false; } return !validOptions; }); } return validOptions; }); self.allRowsValid ko.computed(function() { var rowsValid true; self.rowCollection().some(function(row) { rowsValid row.selectedChild() undefined || row.selectedChild().questionsHaveValidAnswers(); return !rowsValid; }); return rowsValid; }); // List of fields that will have legitimate HTML in them. Note - we // are intentionally not putting these in a site option in order to // force any changes to go through source control. var fieldsToDecode inventory.stockMessage, description, name, tabs>staticContent ; runHook(fieldsToDecodeFilter, { self: self, product: product, fieldsToDecode: fieldsToDecode }); // Set each field in the above list to the decoded version of itself fieldsToDecode.forEach(function(propName) { //using a > to denote a property on an array. if(propName.indexOf(>) > -1){ //get the array and the property on that array to be decoded var collection selfpropName.split(>)0; var propName propName.split(>)1; //now check to see if the array is observable before looping if(typeof collection function){ _.each(collection(), function(obj){ if (typeof obj()propName function) { // If it is an observable obj()propName(utils.decodeHTML(obj()propName()) ); } else if (typeof obj()propName string) { // If it is a string obj()propName utils.decodeHTML(obj()propName); } else { // Do nothing } }) }else{ _.each(collection, function(obj){ if (typeof objpropName function) { // If it is an observable objpropName(utils.decodeHTML(objpropName()) ); } else if (typeof objpropName string) { // If it is a string objpropName utils.decodeHTML(objpropName); } else { // Do nothing } }) } }else{ var field _.get(self, propName); if (typeof field function) { // If it is an observable field( utils.decodeHTML(field()) ); } else if (typeof field string) { // If it is a string _.set(self, propName, utils.decodeHTML(field)); } else { // Do nothing } } }); if(self.currentParent()) { if(self.documents().length 0 && self.currentParent().documents().length > 0 ){ self.documents(self.currentParent().documents()); } if(!self.description() && self.currentParent().description()) { self.description(self.currentParent().description()) } if(!self.tabs || !self.tabs.length) { self.tabs self.currentParent().tabs; } } runHook(productModelBottom, { self: self, product: product }); }; var productMapping { create: function (options) { return new productModel(options.data); } }; var searchResultsPropertiesModel function (properties) { var self this; self.selectedSort ko.observable(utils.getParameter(sortby) || oConfig.searchConfig.defaultSort); self.selectedRpp ko.observable(utils.getParameter(rpp) || oConfig.searchConfig.rpp); self.startCount ko.observable((oConfig.searchConfig.page - 1) * oConfig.searchConfig.rpp + 1); self.endCount ko.observable(function () { var rpp (oConfig.searchConfig.rpp 0) ? oConfig.searchConfig.total : oConfig.searchConfig.rpp; return Math.min(((oConfig.searchConfig.page - 1) * rpp) + rpp, oConfig.searchConfig.total); }()); self.maxPage ko.observable( Math.ceil(oConfig.searchConfig.total / oConfig.searchConfig.rpp) ); self.selectedLayout ko.observable( utils.getCookie(productLayout) ); self.changeSort function (value) { window.location utils.setParameter(sortby, value ); }; self.changeRpp function (value) { var sUrl utils.setParameter(rpp, value); sUrl sUrl + &page1; window.location sUrl; }; self.layoutTemplate ko.computed(function () { utils.setCookie(productLayout, self.selectedLayout()); window.location.reload(); return catalog. + self.selectedLayout() + _view }); runHook(searchResultsPropertiesModelBottom, { self: self, properties: properties }); }; function PagedArray(array, pageSize) { // if array has already been processed, just return it if(array && array.all) { return array; } var self this; self.all ko.observableArray(array || ); self.pageSize ko.observable(pageSize || 10); self.page ko.observable(1).extend({ counter: 1 }); self.numPages ko.computed(function () { return Math.ceil(self.size() / self.pageSize()); }); self.size ko.computed(function () { return self.all().length; }); self.items ko.computed(function () { var pageSize self.pageSize(); var start (self.page() - 1) * pageSize; return self.all.slice(start, start + pageSize); }); } /script> script typetext/html idcatalog.breadcrumbs> ul iddetail_breadcrumbs classbreadcrumb itempropbreadcrumb vocabhttp://schema.org/ typeofBreadcrumbList> !-- ko if: oConfig.activeBreadcrumb && oConfig.activeBreadcrumb.length > 0 --> !-- ko foreach: oConfig.activeBreadcrumb --> li data-bindcss: { active: !link }, attr: {property: utils.breadCrumbProperty(link), typeof: utils.breadCrumbItemType(link)} > !-- ko if: link --> a propertyitem typeofWebPage data-bindattr: { href: link }>span data-bindhtml: name propertyname>/span>/a> span classdivider>/span> !-- /ko --> span data-bindhtml: link ? : utils.decodeHTML(name) >/span> meta propertyposition data-bindattr: { content : $index() + 1 }> /li> !-- /ko --> !-- /ko --> !-- ko ifnot: oConfig.activeBreadcrumb && oConfig.activeBreadcrumb.length > 0 --> !-- ko foreach: $data --> li data-bindcss: { active: !link }, attr: {property: utils.breadCrumbProperty(link), typeof: utils.breadCrumbItemType(link)} > !-- ko if: link --> a propertyitem typeofWebPage data-bindattr: { href: link }>span data-bindhtml: name propertyname>/span>/a> span classdivider>/span> !-- /ko --> span data-bindhtml: link ? : utils.decodeHTML(name) >/span> meta propertyposition data-bindattr: { content : $index() + 1 }> /li> !-- /ko --> !-- /ko --> /ul> /script> script typetext/html idcatalog.detail> !-- ko if: mainProduct.selectedProduct --> div iddetail_page_product> span data-bindtemplate: { name: catalog.breadcrumbs, data: breadcrumbs }>/span> span data-bindtemplate: { name: mainProduct.childDisplayType() input-qty || mainProduct.childDisplayType() exploded-view || mainProduct.childDisplayType() matrix-all || mainProduct.childDisplayType() add-row ? catalog.advanced_parent_layout : catalog.product_view, data: mainProduct }>/span> !-- ko if: !oConfig.fastTrack --> span data-bindtemplate: { name: catalog.additional_sections, data: mainProduct }>/span> !-- /ko --> /div> !-- /ko --> !-- ko ifnot: viewModel.mainProduct.selectedProduct --> div iddetail_page_product> div classalert alert-warning data-bindhtml: oConfig.labels.productNotFound>/div> /div> !-- /ko --> /script> script typetext/html idcatalog.results> !-- ko ifnot: oConfig.searchConfig.pageType category && !$data.category --> div idlist_wrap> div idlist_wrap_pad> div idlist_head data-bind template: $data.category ? { name: catalog.category_header, data: category } : catalog.page_title >/div> div idproducts_header classlist-toolbar well well-small products_header data-bindtemplate: catalog.header>/div> div idproducts_view data-bindattr : { data-layout : getActiveLayout() }, template: getLayoutTemplate($data)>/div> div idproducts_footer classlist-toolbar products_footer data-bindtemplate: { name : catalog.footer } >/div> /div> /div> !-- /ko --> !-- ko if: oConfig.searchConfig.pageType category && !$data.category --> div idlist_wrap> div idlist_wrap_pad> div classalert alert-warning data-bindhtml: oConfig.labels.categoryNotFound>/div> /div> /div> !-- /ko --> /script> script typetext/html idcatalog.category_header> !-- template: { name: catalog.breadcrumbs, data: breadcrumbs } --> !-- ko if: pic --> div classhead_thumb> img data-bindattr: { src: utils.buildImagePath(pic) }/> /div> !-- /ko --> h1 classhead_title data-bindhtml: name>/h1> !-- ko if: !oConfig.fastTrack && description --> div classhead_desc data-bindhtml: description>/div> !-- /ko --> !-- template: { name: catalog.category_list, data: children, if: children.length > 0 } --> /script> script typetext/html idcatalog.category_list> div classcategory-listings data-layoutgallery data-bindforeach: $data> div classprod-card> div classprod-thumb data-bindvisible: !oConfig.fastTrack && pic2> a data-bindattr: { href: link, title: utils.decodeHTML(name), data-key: key }> img data-bindattr: { src: utils.buildImagePath(pic2), alt: utils.decodeHTML(name) }/> /a> /div> div classprod-info> div classprod-desc> div classprod-nm> a data-bindattr: { href: link, title: utils.decodeHTML(name), data-key: key }, html: name>/a> /div> /div> /div> /div> /div> /script> script typetext/html idcatalog.page_title> !-- ko if: oConfig.searchConfig.pageType ! category && oConfig.searchConfig.pageType ! favlist --> h1 data-bind text: oConfig.searchConfig.labels.searchResultsHeader .replace(count>, oConfig.searchConfig.total) .replace(keyword>, ‘ + decodeURIComponent(utils.getParameter(search_keyword)) + ’), visible: utils.getParameter(search_keyword).length > 0 > /h1> h1 data-bind text: oConfig.searchConfig.total + results, visible: utils.getParameter(search_keyword).length 0 > /h1> !-- /ko --> !-- ko if: oConfig.searchConfig.pageType favlist --> h1 data-bindtext: decodeURIComponent(utils.getParameter(nm))>/h1> !-- /ko --> /script> script typetext/html idcatalog.header> div idsort_control classlist-toolbar-control sort-control data-bindtemplate: catalog.order_by>/div> div idrpp_control classlist-toolbar-control rpp-control data-bindtemplate: catalog.rpp>/div> div idlayout_control classlist-toolbar-control layout-control data-bindtemplate: catalog.layout>/div> /script> script typetext/html idcatalog.order_by> label classinput-prepend data-bindif: oConfig.searchConfig.showSort> span classadd-on toolbar__sort-by__text data-bindhtml: oConfig.searchConfig.labels.sort>/span> select idpage_sort classtoolbar__sort-by__drop data-bind foreach: oConfig.searchConfig.productSortOptions, value: getSelectedSort(), event: { change: changeSort } > option data-bindtext: display, attr: { value: field ? field + ~ + direction : }>/option> /select> /label> /script> script typetext/html idcatalog.rpp> label classinput-append data-bindif: oConfig.searchConfig.showRpp, visible: !utils.getParameter(favorites) > select idrpp classtoolbar__per-page__drop data-bind options: oConfig.searchConfig.rppOptions, value: getSelectedRpp(), event: { change: changeRpp } > /select> span classadd-on toolbar__per-page__text data-bindhtml: oConfig.searchConfig.labels.rpp >/span> /label> /script> script typetext/html idcatalog.page_count> div data-bindtext: Showing + getStartCount() + - + getEndCount() + of + oConfig.searchConfig.total + results>/div> /script> script typetext/html idcatalog.layout> div data-bindif: oConfig.searchConfig.showLayout> span data-bindhtml: oConfig.searchConfig.labels.layout>/span> div classbtn-group btn-group-small layout-control__wrap> button typebutton idgallery_layout_toggle data-bind click: function () { setLayout(gallery) }, css: { active: isActiveLayout(gallery) }, html: oConfig.searchConfig.labels.galleryView classbtn >/button> button typebutton idlist_layout_toggle data-bind click: function () { setLayout(list) }, css: { active: isActiveLayout(list) }, html: oConfig.searchConfig.labels.listView classbtn >/button> /div> div classresults-download data-bindtemplate: { if: oConfig.searchConfig.showDownload && oConfig.isLoggedIn}> a hrefjavascript: window.location utils.pageUrl + (utils.pageUrl.indexOf(?)>0?&:?) + downloadasfile1; classcust_download titleDownload> img data-bindattr: { src: utils.buildImagePath(common_images/ddt_download.png) } border0 alignabsmiddle> Download /a> /div> /div> /script> script typetext/html idcatalog.no_product_found> div classalert alert-warning>Product Not Found./div> /script> script typetext/html idcatalog.no_results> !-- ko if: oConfig.searchConfig.pageType favlist --> p>There are no products in this favorites list./p> !-- /ko --> !-- ko if: oConfig.searchConfig.pageType ! category && oConfig.searchConfig.pageType ! favlist --> !-- ko if : oConfig.labels.noResults --> span data-bind html : oConfig.labels.noResults >/span> !-- /ko --> !-- ko ifnot : oConfig.labels.noResults --> p classalert alert-info>There are no products that match your search./p> h5>Search Tips:/h5> ul> li>You may want to broaden your search. This can be accomplished by shortening or generalizing the words you are using in your search./li> li>If you are entering a part number, do not include any hyphens or other punctuation marks. You may even try using a portion of the number if it is a long one./li> li>Spelling does makes a difference. Be sure to check for spelling errors as this will affect your results./li> li>Mutations of a word also make a difference. For example, the word accessory will return different results than accessories./li> li>Plural makes a difference too. Adding an s may impact results. Often it is better to search for the singular./li> li>The search is not case sensitive, so you can type in all lower case, all caps, or any mixture./li> li>Contact customer service for assistance if you still cannot find what you are looking for./li> /ul> !-- /ko --> !-- /ko --> /script> script typetext/html idcatalog.paging> div classpagination data-bindif: oConfig.searchConfig.rpp > 0 && oConfig.searchConfig.total > oConfig.searchConfig.rpp > ul data-bindforeach: pagingNodes()> li data-bindcss: { active: page oConfig.searchConfig.page, disabled: !page }> !-- ko if: page && page ! oConfig.searchConfig.page --> a data-bindattr: { href: utils.setParameter(page, page) }> span data-bindhtml: text>/span> /a> !-- /ko --> !-- ko ifnot: page && page ! oConfig.searchConfig.page --> span data-bindhtml: text>/span> !-- /ko --> /li> /ul> /div> /script> script typetext/html idcatalog.footer> div idresults_paging classlist-toolbar-control data-bindtemplate: catalog.paging>/div> div idresults_text classlist-toolbar-control data-bindtemplate: catalog.page_count>/div> /script> script typetext/html idcatalog.gallery_view> div idprod_listings classprod-listings data-bindfastForEach: results > !-- ko template: catalog.product_card --> !-- /ko --> /div> /script> script typetext/html idcatalog.gallery_actions> span data-bindtemplate: catalog.atc_full>/span> /script> script typetext/html idcatalog.list_view> form nameatc_form idatc_form classfrmAddToCart methodPOST data-bindattr: { action: oConfig.formAction, submit: submitForm($data) } > div idprod_listings classprod-listings data-bindfastForEach: results > !-- ko template: { name: catalog.product_card } --> !-- /ko --> /div> div data-bindtemplate: catalog.list_view_atc>/div> /form> /script> script typetext/html idcatalog.list_view_atc> div data-bindif: oConfig.searchConfig.showAtc && showAddAllToCart() && !oConfig.showListViewATC> span idbtn_multi_add_to_cart_anchor>/span> div idbtn_multi_add_to_cart classcontainer-fluid data-bindsticky: btn_multi_add_to_cart_anchor> div data-bindattr: { class: oConfig.searchConfig.gridListViewRowClass }> div data-bindattr: { class: oConfig.searchConfig.gridListViewATCColumnClass }> div classform-actions> button typebutton classbtn btn-block btn-primary btn-large data-bind html: utils.atcListButtonText(), click: function(data,event) {addToCartWithValidation(results(), event);}> /button> /div> /div> /div> /div> /div> /script>script typetext/html idcatalog.product_card_with_children> !-- template: catalog.product_card -->/script>script typetext/html idcatalog.product_card_no_children> !-- template: catalog.product_card -->/script>script typetext/html idcatalog.product_card> div classprod-card> !-- ko if: isActiveLayout(gallery) || oConfig.pageName pc_product_detail.asp --> div classprod-thumb data-bindvisible: !oConfig.fastTrack, css: { -using-flags: oConfig.usingFlags } > span classprod-thumb-img data-bindtemplate: catalog.image_link>/span> span classprod-thumb-flags data-bindtemplate: catalog.flags_thumb>/span> /div> div classprod-info> div classprod-desc> div classprod-nm> !-- template: catalog.name_link --> /div> !-- template: catalog.rating_score --> /div> div classprod-idp data-bindtemplate: catalog.inventory>/div> div classprod-pricing data-bindtemplate: { name: priceDisplay, data: selectedProduct } >/div> !-- ko if: oConfig.showChildrenSelection && $data.children --> div classprod-children data-bind template:{ name: catalog.children_selection, if: oConfig.showChildrenSelection && $data.children && children().length }>/div> !-- /ko --> div classprod-actions data-bindtemplate: catalog.product_actions>/div> div classprod-details> !-- template: { name: catalog.detail_info } --> /div> !-- ko if: utils.getParameter(favorites) && oConfig.pageName pc_combined_results.asp --> !-- template: catalog.remove_fav_button --> !-- /ko --> /div> !-- /ko --> !-- ko if: isActiveLayout(list) --> div classprod-thumb data-bindvisible: !oConfig.fastTrack, css: { -using-flags: oConfig.usingFlags } > span classprod-thumb-img data-bindtemplate: catalog.image_link>/span> span classprod-thumb-flags data-bindtemplate: catalog.flags_thumb>/span> /div> div classprod-info> div classprod-desc> div classprod-nm> !-- template: catalog.name_link --> /div> div classprod-ds data-bind html: selectedProduct().description, visible: !oConfig.fastTrack && oConfig.searchConfig.showDescription && selectedProduct().description()> /div> !-- template: catalog.rating_score --> div classprod-details> !-- ko template: { name: catalog.detail_info } -->!-- /ko --> /div> /div> /div> !-- ko template: { name: catalog.product_account_history_short,data: accountHistory, if: accountHistory }-->!-- /ko --> div classprod-atc> div classprod-idp data-bindtemplate: catalog.inventory>/div> div classprod-pricing data-bindtemplate: { name: priceDisplay, data: selectedProduct } >/div> !-- ko if: oConfig.showChildrenSelection && $data.children --> div classprod-children data-bind template:{ name: catalog.children_selection, if: oConfig.showChildrenSelection && $data.children && children().length }>/div> !-- /ko --> div classprod-actions data-bindtemplate: catalog.product_actions>/div> /div> !-- ko if: utils.getParameter(favorites) && oConfig.pageName pc_combined_results.asp --> !-- template: catalog.remove_fav_button --> !-- /ko --> !-- /ko --> /div>/script>script typetext/html idcatalog.advanced_parent_layout> !-- template: { name: catalog.product_title, data: selectedProduct } --> div idproduct_view classproduct_view data-bindattr: { class: oConfig.detailConfig.gridRowClass }> div data-bindattr: { class: oConfig.detailConfig.gridLeftColumnClass + product-detail__left }> div idproduct_images data-bindtemplate: { name: catalog.image_gallery, data: selectedProduct }>/div> /div> div data-bindattr: { class: oConfig.detailConfig.gridRightColumnClass + product-detail__right }> div classproduct_view__share-code data-bindtemplate: catalog.share_code>/div> span classproduct_view__detail-info data-bindtemplate: catalog.detail_info >/span> span classproduct_view__rating-detail data-bindtemplate: catalog.rating_detail>/span> div data-bind template: { name: promotions.descriptions, if: promoDescriptions.length, data: { title: Item on Promotion, descriptions: promoDescriptions, selectedProduct: selectedProduct } } > /div> div classdetail-docs data-bindtemplate: { if: oConfig.detailConfig.showDocuments && !selectedProduct().usingDownloadsTab(), name: catalog.documents, data: documents() }>/div> !-- ko if: oConfig.detailConfig.showProductDescriptionTop --> span data-bindtemplate: { name: catalog.product_description, data: selectedProduct }>/span> !-- /ko --> a classbtn btn-large btn-primary scroll-to data-bind attr: { href: #input-qty }, html : oConfig.detailConfig.labels.inputQtyATCLabel, click: function() { scrollToTarget($element); return false; } > /a> /div> /div> !-- template: catalog.additional_info --> h2 idinput-qty data-bindhtml : oConfig.detailConfig.labels.inputQty>/h2> div idatcform data-bindvisible: !lazyLoadingInProgress(), template: childDisplayType() matrix-all ? catalog.matrix_form : childDisplayType() add-row ? catalog.add_row_form : catalog.input_qty_form>/div> div data-bindif: lazyLoadingInProgress> div classsk-three-bounce stylemargin: 0 auto;> div classsk-child sk-bounce1>/div> div classsk-child sk-bounce2>/div> div classsk-child sk-bounce3>/div> /div> div classtext-center> small>em>Loading options.../em>/small> /div> /div>/script>script typetext/html idcatalog.matrix_form> form idatc_form> !-- template: catalog.matrix_table --> div classform-actions> button namebtnAddToCart typesubmit classbtn btn-large btn-block btn-primary data-bind click: function (data, event) { var isSelected _.flow(_.property(selectedQty), ko.unwrap); var products _.filter(children(), isSelected); addToCartWithValidation(products, event); }, html : utils.atcListButtonText() >/button> /div> /form>/script>script typetext/html idcatalog.matrix_table> div classcim-matrix data-bindfastForEach: matrix> div data-bindtemplate: catalog.matrix_row, css: cim-matrix__option cim-matrix__option- + $index()>/div> /div>!-- .cim-matrix -->/script>script typetext/html idcatalog.matrix_row> div classcim-matrix__child__preview> div classcim-matrix__child__preview__wrap> !-- ko if: swatch --> div classcim-matrix__child__preview__thumb data-bindstyle: { background-color: # + swatch() }>/div> !-- /ko --> !-- ko ifnot: swatch --> div classcim-matrix__child__preview__thumb> img data-bindattr: { src: utils.buildImagePath(thumb()) } onerrorutils.handleImageError(this)> /div> !-- /ko --> h3 classcim-matrix__child__preview__name data-bindtext: label>/h3> /div> /div>!-- cim-matrix__child__preview --> div classcim-matrix__children> div classcim-matrix__children__wrap data-bindfastForEach: cols> div classcim-matrix__child data-bindtemplate: catalog.matrix_row_column>/div> /div> /div>!-- .cim-matrix__children -->/script>script typetext/html idcatalog.matrix_row_column> div classcim-matrix__child__outer-wrap> div classcim-matrix__child__inner-wrap> !-- ko if: product --> p classcim-matrix__child__size data-bindtext: label>/p> !-- template: { name: catalog.matrix_prod, data: product} --> !-- /ko --> !-- ko ifnot: product --> !-- template: catalog.matrix_prod_not_found --> !-- /ko --> /div> /div>!-- /.cim-matrix__child -->/script>script typetext/html idcatalog.matrix_prod> div classcim-matrix__child__found> div classcim-matrix__child__pricing data-bindtemplate: catalog.selected_product_price_display>/div> div classcim-matrix__child__qty-input> span data-bindtemplate: {name: catalog.atc_qty_input } >/span> /div> div classcim-matrix__child__idp> p classcim-matrix__child__idp-stock data-bindtext: inventory.stock>/p> p classcim-matrix__child__idp-stock-msg data-bindhtml: inventory.stockMessage>/p> /div> p classcim-matrix__child__qty-price data-bindtemplate: {name: priceBreaksTemplate } >/p> /div>/script>script typetext/html idcatalog.matrix_prod_not_found> div classcim-matrix__child__not-found>p> - /p>/div>/script>script typetext/html idcatalog.input_qty_form> form idatc_form> !-- template: catalog.input_qty_table --> !-- ko if: !oConfig.showListViewATC --> div classform-actions> button namebtnAddToCart typesubmit classbtn btn-large btn-block btn-primary data-bind click: function (data, event) { var isSelected _.flow(_.property(selectedQty), ko.unwrap); var products _.filter(children(), isSelected); addToCartWithValidation(products, event, key()); }, html : utils.atcListButtonText() >/button> /div> !-- /ko --> /form>/script>script typetext/html idcatalog.cart_options> !-- ko if: hasCartOptions() && !oConfig.fastTrack --> ul classunstyled data-bindforeach: questions> li classform-inline data-bindtemplate: { name: catalog.cart_option_ + type() }>/li> /ul> !-- /ko --> !-- ko if: !hasCartOptions() && !oConfig.fastTrack --> span classmute>No options available/span> !-- /ko -->/script>script typetext/html idcatalog.cart_option_textbox> div classcontrol-group> label classcontrol-label data-bindtext: questionText>/label> div classcontrols> input stylemin-width: 180px !important /* temp fix for stretchy */;max-width: 80%; data-bindvalue: selectedAnswer, attr: {required: required, maxlength: maxLength() 0 ? : maxLength() }, init: function() { setSelectedCartOptionAnswer($data); } typetext /> span classtext-error data-bindtext:requiredText, visible: required>/span> /div> /div>/script>script typetext/html idcatalog.cart_option_textarea> div classcontrol-group> label classcontrol-label data-bindtext: questionText>/label> div classcontrols> textarea stylemin-width: 180px !important /* temp fix for stretchy */;max-width: 80%; data-bindvalue: selectedAnswer, attr: {required: required, maxlength: maxLength() 0 ? : maxLength() }, init: function() { setSelectedCartOptionAnswer($data); }>/textarea> span classtext-error data-bindtext:requiredText, visible: required>/span> /div> /div>/script>script typetext/html idcatalog.cart_option_select> div classcontrol-group> label classcontrol-label data-bindtext: questionText>/label> div classcontrols> select stylemin-width: 162px !important /* temp fix for stretchy */;max-width: 80%; data-bindvalue: selectedAnswer, attr: {required: required, maxlength: maxLength() 0 ? : maxLength() }, options: answers, optionsText: label, optionsValue: value, init: function() { setSelectedCartOptionAnswer($data); }> option>-- Select One --/option> /select> span classtext-error data-bindtext:requiredText, visible: required>/span> /div> /div>/script>script typetext/html idcatalog.add_row_form> form idatc_form > !-- template: catalog.add_row_table --> div classtext-error pull-right data-bindvisible: !allRowsValid() && rowsAtcAttempted()>Please ensure all required fields are populated./div> div classform-actions data-bindvisible: !oConfig.childSkuMatch> button classbtn btn-medium btn-success data-bindclick: function () { addRows(1) }>i classicon-add>/i> Add Row/button> button classbtn btn-medium btn-success data-bindclick: function () { addRows(5) }>i classicon-add>/i> Add 5 Rows/button> button classbtn btn-medium btn-default pull-right data-bindclick: addRowsToCart>i classicon-add>/i> Add To Cart/button> /div> /form> !-- ko ifnot: showAtc --> div data-bindhtml: mapPriceMessage>/div> !-- /ko -->/script>script typetext/html idcatalog.add_row_table> div classtablesaw-overflow qty-input-table> table classtablesaw tablesaw-stack data-tablesaw-modestack> thead> tr> th>Option/th> !-- ko fastForEach: tableColumns --> th data-bind text: ko.unwrap($data).label, css: ko.unwrap($data).headerClass, attr: { width: ko.unwrap($data).width } > /th> !-- /ko --> /tr> /thead> !-- ko template: { afterRender: function() { $(document).trigger(enhance.tablesaw); } } --> tbody data-bindfastForEach: rowCollection> tr> td> select stylewidth: auto; data-bindoptions: children, optionsText: name, optionsCaption: -- Select Option --, value: selectedChild> !-- option data-bindtext: name, value: $data>/option --> option data-bindvalue: undefined>-- Select One--/option> /select> /td> !-- ko fastForEach: $parent.tableColumns --> !-- ko if: $parent.selectedChild() && $data.template --> td data-bind template: {name: template, data: $parent.selectedChild(), if: $parent.selectedChild }, css: ko.unwrap($data).cellClass > /td> !-- /ko --> !-- ko if: $parent.selectedChild() && !$data.template --> td data-bind text: ($data.format || _.identity)($parent.selectedChild()field), css: ko.unwrap($data).cellClass > /td> !-- /ko --> !-- ko if: !$parent.selectedChild() --> td>span data-bindtext: $data.placeholder ? $data.placeholder || - : ->/span>/td> !-- /ko --> !-- /ko --> /tr> /tbody> !-- /ko --> /table> /div>/script>script typetext/html idcatalog.input_qty_table> div classtablesaw-overflow qty-input-table> table classtablesaw tablesaw-stack data-tablesaw-modestack> thead> tr data-bindfastForEach: tableColumns> th data-bind text: ko.unwrap($data).label, css: ko.unwrap($data).headerClass, attr: { width: ko.unwrap($data).width } > /th> /tr> /thead> !-- ko template: { afterRender: function() { $(document).trigger(enhance.tablesaw); } } --> tbody data-bindfastForEach: children> tr data-bindfastForEach: $parent.tableColumns> !-- ko if: $data.template --> td data-bind template: {name: template, data: ko.unwrap($parent) }, css: ko.unwrap($data).cellClass > /td> !-- /ko --> !-- ko if: !$data.template --> td data-bind text: ($data.format || _.identity)(ko.unwrap($parent)field), css: ko.unwrap($data).cellClass > /td> !-- /ko --> /tr> /tbody> !-- /ko --> /table> /div>/script>script typetext/html idcatalog.product_title> div classpage-header detail-title> h1 data-bindhtml: selectedProduct().name() || name()>/h1> !-- template: catalog.product_links --> /div>/script>script typetext/html idcatalog.product_view> !-- template: { name: catalog.product_title, data: selectedProduct } --> div idproduct_view classrow-fluid product_view> div data-bindattr: { class: oConfig.detailConfig.gridLeftColumnClass + product-detail__left }> !-- ko if: oConfig.fastTrack --> !-- ko template: catalog.detail_info_container -->!-- /ko --> !-- /ko --> !-- ko if: !oConfig.fastTrack --> div idproduct_images data-bindtemplate: { name: catalog.image_gallery, data: selectedProduct }>/div> !-- /ko --> /div> div data-bindattr: { class: oConfig.detailConfig.gridRightColumnClass + product-detail__right}> !-- ko if: oConfig.fastTrack --> span data-bindtemplate: { name: catalog.smart_lists, data: selectedProduct() }>/span> !-- /ko --> !-- ko if: !oConfig.fastTrack --> !-- ko template: catalog.detail_info_container -->!-- /ko --> !-- /ko --> /div> /div> !-- template: catalog.additional_info -->/script>script typetext/html idcatalog.detail_info_container> div classdetail-product-info> div data-bindtemplate: catalog.share_code>/div> span classproduct_view__detail-info data-bindtemplate: catalog.detail_info>/span> div classdetail-docs data-bindtemplate: { if: oConfig.detailConfig.showDocuments && !selectedProduct().usingDownloadsTab(), name: catalog.documents, data: selectedProduct().documents() }>/div> div data-bind template: { name: promotions.descriptions, if: promoDescriptions && promoDescriptions.length, data: { title: Item on Promotion, descriptions: promoDescriptions, selectedProduct: selectedProduct } } > /div> !-- ko if: oConfig.detailConfig.showProductDescriptionTop && !oConfig.fastTrack --> span data-bindtemplate: { name: catalog.product_description, data: selectedProduct }>/span> !-- /ko --> div classdetail-child-selector> span data-bindtemplate: { name: catalog.child_selectors, if: $data.childSelectors, data: $data.childSelectors }>/span> /div> span data-bindtemplate: catalog.rating_detail>/span> div idatcform> div data-bindtemplate: { name: catalog.atc_full, data: selectedProduct }>/div> /div> /div>/script>script typetext/html idcatalog.child_selectors> !-- ko foreach: $data --> span data-bindtemplate: catalog.child_droplist_select>/span> !-- /ko -->/script>script typetext/html idcatalog.child_droplist_select> div classchild-droplist-selector styleclear: left; data-bindvisible: showSelector> label data-bindtext: label, attr: { for: field }> /label> select data-bind attr: { id: field, name: field }, options: options, optionsText: option, value: selectedOption, optionsCaption: -- Select One --, optionsAfterRender: function (option, item) { setChildOptionDisable(field, option, item) }, enable: !!options.length > /select> /div> div data-bindif: $data.loading> div classsk-three-bounce stylefloat: left;> div classsk-child sk-bounce1>/div> div classsk-child sk-bounce2>/div> div classsk-child sk-bounce3>/div> /div> /div>/script>script typetext/html idcatalog.product_description> div classproduct-detail__description-wrap data-bindif: description() || $parent.description()> h2 classproduct-detail__description-title data-bindhtml : oConfig.labels.description>/h2> span classproduct-detail__description-text data-bindhtml: description() || $parent.description()>/span> /div>/script>script typetext/html idcatalog.additional_info> span data-bindif: selectedProduct().useTabs(), attr: { data-layout : oConfig.detailConfig.tabLayoutMode } > !-- template: catalog.advanced_tabs --> /span>/script>script typetext/html idcatalog.additional_sections> span data-bindifnot: selectedProduct().useTabs(), attr: { data-layout : oConfig.detailConfig.pageLayoutMode } > !-- ko if: !oConfig.detailConfig.showProductDescriptionTop && !oConfig.fastTrack --> span data-bindtemplate: { name: catalog.product_description, data: selectedProduct }>/span> !-- /ko --> span data-bindtemplate: { name: catalog.related_products, data: related().filter(function(item) { return !item.relatedGroup() }) }>/span> span data-bindtemplate: { name: catalog.second_related_products, data: secondRelated }>/span> span data-bindtemplate: catalog.reviews>/span> span data-bindtemplate: { name: catalog.smart_lists, data: selectedProduct() }>/span> /span> span data-bindtemplate: { name: catalog.also_bought, data: alsoBought }>/span> span data-bindtemplate: { name: catalog.recently_viewed, data: $parent.recentlyViewed }>/span>/script>script typetext/html idcatalog.advanced_tabs> div idtabs classdetail_desc> div classtabbable tabbable-detail > span data-bindtemplate: catalog.tab_header>/span> span data-bindtemplate: catalog.tab_content>/span> /div> /div>/script>script typetext/html idcatalog.tab_header> ul idnav-tabs classnav nav-tabs data-bindforeach: selectedProduct().tabs> li data-bindattr: { data-tabtype: dynamicSource, id: tab + ($index()+1) }> a data-toggletab data-bindattr: { href: #tab_section_ + ($index() + 1) }> span data-bindhtml: label || _.startCase(dynamicSource)>/span> /a> /li> /ul>/script>script typetext/html idcatalog.tab_content> div classtab-content data-bindforeach: { data: selectedProduct().tabs, afterUpdate: selectFirstTab }> div classtab-pane data-bindattr: { id: tab_section_ + ($index() + 1) }> p data-bindhtml: staticPos above ? staticContent : >/p> span data-bind template: { name: catalog.tab_ + dynamicSource, data: { tab: $data, mainProduct: $parent } }> /span> p data-bindhtml: staticPos below ? staticContent : >/p> /div> /div>/script>script typetext/html idcatalog.tab_description> span data-bindhtml: mainProduct.selectedProduct().description>/span>/script>script typetext/html idcatalog.tab_downloads> ul classdoc_downloads data-bindwith: mainProduct.selectedProduct().documents> !-- ko foreach: $data --> li> a data-bindattr: { href: utils.buildImagePath(link()) }, text: name target_blank >/a> /li> !-- /ko --> /ul>/script>script typetext/html idcatalog.tab_web_page> span data-bindtemplate: catalog.web_page_get>/span>/script>script typetext/html idcatalog.web_page_get> span data-bind load: { url: mainProduct.selectedProduct().getWebPage(tab.webPageId), cache: true } > /span>/script>script typetext/html idcatalog.tab_related_products> span data-bindtemplate: { name: catalog.related_products, data: mainProduct.related().filter(function(item) { return item.relatedGroup() tab.relatedProductsGroup }) }>/span>/script>script typetext/html idcatalog.tab_second_related_products> span data-bindtemplate: { name: catalog.second_related_products, data: mainProduct.secondRelated }>/span>/script>script typetext/html idcatalog.tab_reviews> !-- template: { name: catalog.reviews, data: mainProduct } -->/script>script typetext/html idcatalog.tab_smart_list> span data-bindtemplate: { name: catalog.smart_lists, data: mainProduct.selectedProduct() }>/span>/script>script typetext/html idcatalog.tab_rys> !-- template: { name: catalog.product_facets_table, data: mainProduct.selectedProduct() } -->/script>script typetext/html idcatalog.product_facets_table> !-- ko if: facets --> table classtable table-striped> tbody> tr data-bindforeach: facets> th data-bindtext: search_group>/th> td data-bindtext: search_term>/td> /tr> /tbody> /table> !-- /ko -->/script>script typetext/html idcatalog.tab_hook> span data-bindtemplate: { name: tab_hook_ + tab.hook, data: viewModel }>/span>/script>script typetext/html idcatalog.tab_none>/script> script typetext/html idcatalog.reviews> !-- ko if: oConfig.useReviews --> h2 data-bindhtml : oConfig.labels.reviews>/h2> div idreviews itempropaggregateRating itemscope itemtypehttp://schema.org/AggregateRating > !-- ko if: reviews.size() --> div classwell reviews-header> h4 data-bind html : oConfig.labels.averageRating>/h4> p> div classraty data-bindraty: averageRating>/div> small classmuted> span itempropratingValue data-bindtext: averageRating().toFixed(1)>/span> out of span itempropbestRating>5.0/span> stars /small> /p> div classbtn-group> !-- ko if: !oConfig.allowAddReviews --> a classbtn btn-small data-bindattr: { href: utils.loginUrl }, html: oConfig.labels.reviewSignInText>/a> !-- /ko --> !-- ko if: oConfig.allowAddReviews --> a classglobal-modal btn btn-primary data-sizelarge data-backdropstatic data-bind attr: { href: ae_sf_review_comment.asp?contentkey + key() }, html: oConfig.labels.reviewsAddText >/a> !-- /ko --> /div> /div> !-- /ko --> !-- template: { name: catalog.reviews_list, data: reviews } --> /div> !-- /ko --> /script> script typetext/html idcatalog.reviews_list> div classmedia-list reviews-list> !-- template: { name: catalog.review, if: size, foreach: items } --> /div> !-- ko ifnot: size --> p classalert alert-info>This product has not been reviewed./p> !-- ko ifnot: oConfig.allowAddReviews --> a classbtn data-bindattr: { href: utils.loginUrl }, html: oConfig.labels.reviewSignInText>/a> !-- /ko --> !-- ko if: oConfig.allowAddReviews --> a classglobal-modal btn btn-primary data-bind attr: { href: ae_sf_review_comment.asp?contentkey + $parent.key() }, html: oConfig.labels.reviewsAddText data-sizelarge >/a> !-- /ko --> !-- /ko --> div classbtn-group reviews-paging data-bindif: numPages() > 1> button classbtn data-bindclick: page.decrement, enable: page() > 1> Prev /button> button classbtn data-bindclick: page.increment, enable: page() numPages()> Next /button> /div> /script> script typetext/html idcatalog.review> div classmedia> div classmedia-body> div classmedia-heading> div data-bindraty: rating>/div> small classmuted>By span data-bindtext: name || Anonymous User>/span> on span data-bindtext: new Date(create_date).toDateString()>/span>/small> /div> div classtext-small data-bindtext: comments>/div> /div> !-- template: { name: catalog.review, if: children, foreach: children } --> /div> /script> script typetext/html idcatalog.rating_detail> div data-bindif: oConfig.useReviews classaverage-rating-header> div classdetail_rating detail_info> !-- template: catalog.rating_score --> span data-bindtemplate: { name: catalog.read_reviews, if: ratingsCount }>/span> /div> /div> /script> script typetext/html idcatalog.rating_score> !-- ko if: oConfig.useReviews --> div classraty data-bindraty: averageRating>/div> span classmuted text-xsmall data-bindtext: ratingsCount() ? ( + ratingsCount() + + utils.plural(review, ratingsCount()) + ) : >/span> !-- /ko --> /script> script typetext/html idcatalog.read_reviews> a href# classbtn btn-small btn-link data-bind text: oConfig.detailConfig.labels.readReviews, click: _.partial(utils.scrollTo, #reviews) >/a> /script> script typetext/html idcatalog.product_actions> !-- ko if: selectedProduct().showQuickAtc --> div classinput-prepend input-append> !-- ko if: hasQuantityRestrictions --> a href#0 classadd-on data-bindpopover, attr: { data-content: quantityRestrictionsHtml, data-key : key } data-triggerhover data-htmltrue data-placementtop > i classicon-question-sign>/i> /a> !-- /ko --> input data-bind value: selectedProduct().selectedQty, init: function () { if (setSelectedQty()) selectedQty(minQty() || 1); }, attr: { min : minQty() || 1, step: stepQty() || 1, max : maxQty() }, visible: !isChild() || oConfig.allowChildATC, validateQty typenumber pattern\d* classqty-input placeholderQty aria-labelQty > !-- template: {name: catalog.product_actions_add, if: selectedProduct().childDisplayType() ! matrix-all} --> /div> div classtext-error data-bindvisible: !questionsHaveValidAnswers() && currentParent().rowsAtcAttempted()>Please ensure all required fields are populated./div> !-- /ko --> !-- ko ifnot: selectedProduct().showQuickAtc --> a classbtn btn-view-details data-bind attr: { href: link }, visible: (isParent()) || ((!isChild() || oConfig.allowChildATC) && (showAtc) && !(oConfig.showChildrenSelection && selectedProduct().isChild())), html: oConfig.labels.selectOptionsLabel >/a> !-- /ko --> /script> script typetext/html idcatalog.product_actions_add> div classbtn-group> button typebutton classprod-card__atc btn btn-cart-add data-bind html: atcButtonText(), click: addToCart, visible: function(){ if(currentParent().childDisplayType() input-qty && !oConfig.showListViewATC){ return false; }else{ return (!isChild() || oConfig.allowChildATC) && (getActiveLayout() ! list || oConfig.showListViewATC) && (!(currentParent().childDisplayType() add-row) || !!oConfig.childSkuMatch) } }() , enable: isQtyValid() > /button> !-- ko if: oConfig.showFavLink && oConfig.useSavedCarts --> button classbtn dropdown-toggle data-toggledropdown> i classicon-angle-down>/i> /button> ul classdropdown-menu pull-right prod-card__atwrap> !-- ko if: oConfig.showFavLink && oConfig.searchConfig.pageType ! favlist && currentParent().childDisplayType() ! add-row --> li classprod-card__atf data-bindtemplate: catalog.fav_link>/li> !-- /ko --> !-- ko if: oConfig.useSavedCarts --> li classprod-card__ats> a href#0 data-bindclick: addToSavedCart> span data-bindhtml: oConfig.labels.savedCartsLabels.addToSavedCart>/span> /a> /li> !-- /ko --> /ul> !-- /ko --> !-- ko if: (oConfig.showFavLink && !oConfig.useSavedCarts) && oConfig.searchConfig.pageType ! favlist && currentParent().childDisplayType() ! add-row --> a classbtn global-modal data-bindattr: { title: utils.decodeHTML(oConfig.labels.favLink), data-title: utils.decodeHTML(oConfig.labels.favLink), href: add_product_to_favorites.asp?p_id + key(), aria-label: utils.decodeHTML(oConfig.labels.favLink) }, tooltip data-iconheart data-sizesmall> i classicon-heart>/i> /a> !-- /ko --> !-- ko if: !oConfig.showFavLink && oConfig.useSavedCarts --> button typebutton classbtn data-bindattr: { title: utils.decodeHTML(oConfig.labels.savedCartsLabels.addToSavedCart) }, click: addToSavedCart, tooltip> i data-bindattr: { class: oConfig.labels.savedCarts.toLowerCase() quote ? icon-comments : icon-save }>/i> /button> !-- /ko --> !-- ko if: (currentParent().childDisplayType() add-row) --> button typebutton classbtn data-bindattr: { title: utils.decodeHTML(oConfig.labels.addRowRemoveRowLink) || Remove, data-title: oConfig.labels.addRowRemoveRowLink || Remove }, click: function() { currentParent().removeRow($data.rowKey) }> i classicon-trash>/i>/button> !-- /ko --> /div> /script> script typetext/html idcatalog.atc_full> !-- ko ifnot: $data.type parent --> !-- ko if: oConfig.useIdp --> !-- template: catalog.inventory --> !-- /ko --> fieldset idcart_options data-bindvisible: selectedProduct().hasCartOptions() && !oConfig.fastTrack> legend>Additional Options/legend> !-- ko template: { name: catalog.cart_options, data: selectedProduct, if: selectedProduct().questions().length > 0 } -->!-- /ko --> /fieldset> !-- template: catalog.configurator --> !-- ko if: oConfig.UseTaxExempt --> !-- template: catalog.tax_exempt --> !-- /ko --> !-- /ko --> !-- ko if: $data.isDangerous --> !-- template: catalog.hazmat --> !-- /ko --> !-- ko if: oConfig.detailConfig.showSoftGoodAuthorizations --> !-- template: catalog.softgoods --> !-- /ko --> div classprod-pricing data-bindtemplate: { name: priceDisplay, data: selectedProduct } >/div> !-- ko if: utils.isMainProduct($data) ? showAtc : selectedProduct().showAtc --> !-- template: { name: catalog.atc_form_submit, data: selectedProduct } --> !-- /ko --> /script> script typetext/html idcatalog.product_quantity> div> div classinput-prepend product-detail__qty-wrap> label classadd-on product-detail__qty-label data-bindfor: next>QTY:/label> input data-bind value: selectedQty, init: function () { if (setSelectedQty()) selectedQty(minQty() || 1); }, attr: { min: minQty() || stepQty() || 1, step: stepQty() || 1, max : maxQty() || }, validateQty onclickthis.focus();this.select(); typenumber pattern\d* classqty-input product-detail__qty-input > /div> div data-bindtemplate: { name: catalog.qty_restrictions, if: oConfig.useQtyRestrictions }>/div> /div> /script> script typetext/html idcatalog.atc_form_submit> div classmedia atc-large> !-- ko if: atcErrorText() ! --> div classalert alert-error data-bindhtml:atcErrorText>/div> !-- /ko --> div classpull-left data-bindtemplate: catalog.product_quantity>/div> div classmedia-body> div classbtn-group> button typebutton classbtn btn-primary btn-large button product-detail-atc__button data-bind click: addToCart, html: atcButtonText() >/button> /div> div data-bindtemplate: { name: catalog.saved_cart_form_submit, if: oConfig.useSavedCarts }>/div> /div> /div> /script> script typetext/html idcatalog.atc_qty_input> div classprod-actions data-bindtemplate: catalog.product_actions>/div> /script> script typetext/html idcatalog.atc_popup> div idatc_msg_product> div stylemargin: 5px auto;text-align: center;> span data-bindtext: details.length>/span> span data-bindplural: details>item/span> added to cart. span data-bindif: details.length 1> h3 data-bindtext: details0.name>/h3> img data-bind if: details0.pic(), attr: { src: utils.buildImagePath(details0.pic() || oConfig.defaultImage), alt: utils.decodeHTML(details0.thumbAltText() || details0.name()) } onerrorutils.handleImageError(this) /> /span> /div> /div> /script> script typetext/html idcatalog.atc_popup_buttons> div stylemargin: 5px auto;text-align: center;> a idatc_msg_btn_close classbtn btn-default href# data-dismissmodal data-bindtext: oConfig.labels.continueShoppingLink>/a> a idatc_msg_btn_cart classbtn btn-primary hrefshowcart.asp data-bindtext: oConfig.labels.showCartLink>/a> /div> /script> script typetext/html idcatalog.atc_splash> div classsk-wave> div classsk-rect sk-rect1>/div> div classsk-rect sk-rect2>/div> div classsk-rect sk-rect3>/div> div classsk-rect sk-rect4>/div> div classsk-rect sk-rect5>/div> /div> /script> script typetext/html idcatalog.atc_body> !-- template: catalog.atc_popup --> !-- ko ifnot: cart --> !-- promoMessages: details --> !-- /ko --> /script> script typetext/html idcatalog.promo_bar> div data-bindpromoMessages: details>/div> /script> script typetext/html idcatalog.atc_invalid_qty> div classinvalid-qty data-bindtext: oConfig.labels.invalidQtyText>/div> /script> script typetext/html idcatalog.saved_cart_select_popup> !-- ko if: oConfig.isLoggedIn --> h5>span data-bindtext: oConfig.labels.savedCartsLabels.modalCreateNew>/span>/h5> div classinput-append> input typetext idnickname data-bindattr: { placeholder: oConfig.labels.savedCartsLabels.modalCreateNewInputPlaceholder }> button idsaved_cart_add classbtn btn-primary input-append data-bind init: function () { $data.errorMessage ko.observable(); }, click: function () { var input $(#nickname); var nickname input.val().trim(); if (!nickname) { input.val(); errorMessage(Please enter a nickname); } else if (_.includes(_.pluck(ko.toJS(savedCarts), nickname), nickname)) { errorMessage(That nickname is already in use); } else { selectedCart({ key: utils.createGuid(), nickname: nickname }); } }, text: oConfig.labels.savedCartsLabels.modalCreateNewSaveButton > i classicon-save>/i> /button> /div> !-- ko if: errorMessage --> div classalert alert-error data-bindtext: errorMessage>/div> !-- /ko --> h5 data-bindhtml: oConfig.labels.savedCartsLabels.modalExisting>/h5> !-- template: catalog.saved_carts_table--> !-- /ko --> !-- ko ifnot: oConfig.isLoggedIn --> div classtext-center> p classalert alert-info without-close>You must be signed in to take this action./p> a data-bindattr: { href: utils.loginUrl } classbtn btn-primary btn-block>Sign In Now/a> button typebutton classbtn btn-block data-dismissmodal>Cancel/button> /div> !-- /ko --> /script> script typetext/html idcatalog.saved_carts_table> !-- ko if: savedCarts.length --> table classtable data-bindif: savedCarts.length > 0> tbody data-bindforeach: { data: savedCarts, as: cart }> tr>td> a classbtn btn-block btn-link text-left href# data-bind click: function () { $parent.selectedCart(cart); }, spacedtext: cart.nickname || cart.refId >/a> /td>/tr> /tbody> /table> !-- /ko --> !-- ko ifnot: savedCarts.length --> div> h6>None Found/h6> /div> !-- /ko --> /script> script typetext/html idcatalog.saved_cart_form_submit> span data-bindif: showQuickAtc> button classbtn btn-small btn-secondary data-bindclick: addToSavedCart, html: oConfig.labels.savedCartsLabels.addToSavedCart>/button> /span> /script> script typetext/html idcatalog.saved_cart_confirmation_body> div classtext-center styledisplay: block;> h4 classtext-success> span data-bindplural: details, text: oConfig.labels.savedCartsLabels.itemText>/span> span data-bindtext: oConfig.labels.savedCartsLabels.modalConfirmationSubHeader>/span> /h4> div classcart-sc-nm data-bindtext: cart.nickname>/div> div classwell well-small> a classbtn btn-block data-bindattr: { href : oConfig.sessionData.orderfrontUrl + /payment.asp?o_key + cart.key } > span data-bindtext: oConfig.labels.savedCartsLabels.modalConfirmationViewButton>/span> /a> a hrefmy_saved_carts.asp classbtn btn-block>span data-bindtext: oConfig.labels.savedCartsLabels.modalConfirmationManageButton>/span>/a> a href# classbtn btn-block data-dismissmodal>span data-bindtext: oConfig.labels.savedCartsLabels.modalConfirmationCloseButton>/span>/a> /div> /div> /script> script typetext/html idcatalog.qty_restrictions> div classtext-small muted data-bindattr: { data-key : key() } > div idqty_controls_msg > span data-bindif: selectedUom().minQty() > 0> span data-bindtext: oConfig.labels.minQty>/span>: span data-bindtext: selectedUom().minQty()>/span>br> input typehidden data-bindattr: { name: minQty_+ key() }, value: selectedUom().minQty() /> /span> span data-bindif: selectedUom().maxQty() > 0> span data-bindtext: oConfig.labels.maxQty>/span>: span data-bindtext: selectedUom().maxQty()>/span>br> input typehidden data-bindattr: { name: maxQty_+ key() }, value: selectedUom().maxQty() /> /span> span data-bindif: selectedUom().step() && selectedUom().step() ! 1> span data-bindtext: oConfig.labels.step>/span>: span data-bindtext: selectedUom().step()>/span>br> input typehidden data-bindattr: { name: qty_increment_+ key() }, value: selectedUom().step() /> /span> /div> /div> /script> script typetext/html idcatalog.inventory> span data-bindif: inventory.isInventoryItem && oConfig.useIdp> span data-bindtemplate: warehouseTemplate>/span> /span> /script> script typetext/html idcatalog.selected_product_price_display> span data-bindif: unitPrice() 0 && oConfig.showZeroPriceMessage && showPrice> ul classunstyled prod-pricing__wrap> li classretail> span data-bindtext: oConfig.zeroPriceMessage>/span> /li> li classtext-small data-bindtemplate: { name: priceBreaksTemplate, if: oConfig.useBreaks }>/li> /ul> /span> span data-bindif: !(unitPrice() 0 && oConfig.showZeroPriceMessage) && showPrice && uomPrice()> ul classprice-display__wrap unstyled> !-- ko if: priceTrace --> li classtext-small> div classalert alert-info data-bindhtml: priceTrace().replace(/\n/gi,br>) >/div> /li> !-- /ko --> li classretail> b data-bindhtml: utils.formatPrice(unitPrice())>/b> span classprod-uom data-bindtemplate: catalog.uom>/span> /li> !-- ko if: showYouSave --> li classsretail> del data-bindhtml: utils.formatPrice(suggestedPrice())>/del> span classyousave data-bindspacedtext: oConfig.labels.youSaveLabel + + youSavePercent()>/span> /li> !-- /ko --> li classtext-small data-bindtemplate: { name: priceBreaksTemplate, if: oConfig.useBreaks }>/li> /ul> /span> !-- ko if: (!showPrice || !showAtc) && oConfig.showPricingOrderEntry --> div classretail data-bindhtml: $data.mapPriceMessage>/div> !-- /ko --> !-- ko if: !oConfig.showPricingOrderEntry --> div classhidden-price data-bindhtml: utils.drawHidePriceMessage()>/div> !-- /ko --> /script> script typetext/html idcatalog.configurator_price_display> div classretail> b data-bindhtml: utils.formatPrice(unitPrice())>/b> span classprod-uom data-bindtemplate: catalog.uom>/span> /div> /script> script typetext/html idcatalog.input_qty_sku_display> !-- ko if : oConfig.detailConfig.inputQtyLinkToChild --> a data-bindhtml: sku, attr: { href : link}>/a> !-- /ko --> !-- ko if : !oConfig.detailConfig.inputQtyLinkToChild --> span data-bindhtml: sku>/span> !-- /ko --> /script> script typetext/html idcatalog.input_qty_nm_display> !-- ko if : oConfig.detailConfig.inputQtyLinkToChild --> a data-bindhtml: name, attr: { href : link}>/a> !-- /ko --> !-- ko if : !oConfig.detailConfig.inputQtyLinkToChild --> span data-bindhtml: name>/span> !-- /ko --> /script> script typetext/html idcatalog.input_qty_thumb_display> !-- ko if : oConfig.detailConfig.inputQtyLinkToChild --> a data-bindattr: { href : link}> img data-bind attr: { src: utils.buildImagePath(thumb()), alt: name } onerrorutils.handleImageError(this)> /a> !-- /ko --> !-- ko if : !oConfig.detailConfig.inputQtyLinkToChild --> img data-bind attr: { src: utils.buildImagePath(thumb()), alt: name } onerrorutils.handleImageError(this)> !-- /ko --> /script> script typetext/html idcatalog.input_qty_promo_display> !-- ko if : promoDescriptions.length --> div classpromo-icon data-bindattr: { title: utils.decodeHTML(setPromoDescriptionTitleText(promoDescriptions)) }>P/div> !-- /ko --> /script> script typetext/html idcatalog.price_start_at> !-- ko if: !oConfig.showPricingOrderEntry --> div classhidden-price data-bindhtml: utils.drawHidePriceMessage()>/div> !-- /ko --> !-- ko if: oConfig.showPricingOrderEntry && childStartingPrice --> span classstarting-price data-bindhtml: oConfig.searchConfig.labels.pricesStartingAt + utils.formatPrice(childStartingPrice())>/span> !-- /ko --> /script> script typetext/html idcatalog.qty_breaks> span data-bindif: showPrice && selectedUom().hasBreaks()> a data-bindattr: { href: pricebreakpopup.asp?p_key + key() }, text: oConfig.labels.breaks classglobal-modal data-sizesmall>/a>br> /span> !-- ko if: !oConfig.showPricingOrderEntry --> div classhidden-price data-bindutils.drawHidePriceMessage()>/div> !-- /ko --> /script> script typetext/html idcatalog.qty_breaks_table> span data-bindif: showPrice && processedBreaks().length> table idbreaks_table classtable table-bordered border0 cellpadding0 cellspacing0> caption data-bindhtml: oConfig.priceBreaksTableHeader>/caption> tr> td>Quantity Range/td> td>Price Each/td> /tr> tbody data-bindfastForEach: processedBreaks> tr> td data-bindtext: range>/td> td data-bindtext: utils.formatPrice(price)>/td> /tr> /tbody> /table> /span> !-- ko if: !oConfig.showPricingOrderEntry --> div classhidden-price data-bindhtml: utils.drawHidePriceMessage()>/div> !-- /ko --> /script> script typetext/html idcatalog.breaks_off> /script> script typetext/html idcatalog.related_products> div idrelated_products classclearfix detail_related data-bindif: oConfig.detailConfig.useRelatedProducts> span data-bindif: $data.length > 0> h2 data-bindhtml: oConfig.detailConfig.labels.relatedProducts>/h2> span data-bindtemplate: catalog.simple_product_gallery>/span> /span> /div> /script> script typetext/html idcatalog.second_related_products> div idsecond_related_products classclearfix detail_related data-bindif: oConfig.detailConfig.useSecondRelatedProducts> span data-bindif: $data.length > 0> h2 data-bindhtml: oConfig.detailConfig.labels.secondRelatedProducts>/h2> span data-bindtemplate: catalog.simple_product_gallery>/span> /span> /div> /script> script typetext/html idcatalog.also_bought> div idalso_bought classclearfix detail_related data-bindif: oConfig.detailConfig.useAlsoBoughtProducts> span data-bindif: $data.length > 0> h2 data-bindhtml: oConfig.detailConfig.labels.alsoBoughtProducts>/h2> span data-bindtemplate: catalog.simple_product_gallery>/span> /span> /div> /script> script typetext/html idcatalog.recently_viewed> div idrecently_viewed_products classclearfix detail_related recently-viewed data-bindif: oConfig.detailConfig.useRecentlyViewedProducts && $data && $data.length > 0 && oConfig.searchConfig.pageType ! favlist> span data-bindif: oConfig.centerRecentlyViewed> h2 classrecently-viewed__title -centered data-bindhtml: oConfig.detailConfig.labels.recentlyViewedProducts>/h2> span classrecently-viewed__gallery -centered data-bindtemplate: catalog.simple_product_gallery>/span> /span> span data-bindif: !oConfig.centerRecentlyViewed> h2 classrecently-viewed__title data-bindhtml: oConfig.detailConfig.labels.recentlyViewedProducts>/h2> span classrecently-viewed__gallery data-bindtemplate: catalog.simple_product_gallery>/span> /span> /div> /script> script typetext/html idcatalog.simple_product_gallery> div classprod-listings data-bind fastForEach: { data: $data } data-layoutgallery> !-- template: catalog.product_card --> /div> /script> script typetext/html idcatalog.flags> !-- ko foreach: flags --> div data-bindif: $data, attr: { id: flag + ($index() + 1) } classproduct_flags> !-- ko if: oConfig.flags$index().link && oConfig.flags$index().link ! \\--> a data-bind attr: { href: oConfig.flags$index().link, title: utils.decodeHTML(oConfig.flags$index().title) } classglobal-modal > img data-bindattr: { src: utils.buildImagePath(oConfig.flags$index().pic) } /> /a> !-- /ko --> !-- ko ifnot: oConfig.flags$index().link && oConfig.flags$index().link ! \\--> img data-bindattr: { src: utils.buildImagePath(oConfig.flags$index().pic) } /> !-- /ko --> /div> !-- /ko --> /script> script typetext/html idcatalog.flags_thumb> !-- ko foreach: flags --> div data-bindif: $data, attr: { id: flag + ($index() + 1) } classproduct_flags> !-- ko if: oConfig.flags$index().link && oConfig.flags$index().link ! \\--> a data-bind attr: { href: oConfig.flags$index().link, title: utils.decodeHTML(oConfig.flags$index().title) } classglobal-modal > img data-bindattr: { src: utils.buildImagePath(oConfig.flags$index().thumb) } /> /a> !-- /ko --> !-- ko ifnot: oConfig.flags$index().link && oConfig.flags$index().link ! \\--> img data-bindattr: { src: utils.buildImagePath(oConfig.flags$index().thumb) } /> !-- /ko --> /div> !-- /ko --> /script> script typetext/html idcatalog.uom> !-- ko if: selectedProduct().showQuickAtc --> span data-bindtemplate: selectedProduct().uomTemplate>/span> !-- /ko --> /script> script typetext/html idcatalog.uom_select> !-- ko if: oConfig.useUom --> / select data-bind options: selectedProduct().uomPrice, optionsText: description, value: selectedProduct().selectedUom > /select> !-- /ko --> /script> script typetext/html idcatalog.uom_input> !-- ko if: oConfig.useUom && oConfig.useMultiUomMultiCurrency && uomPrice().length > 0 && uomPrice()0.UomId --> input typehidden data-bindattr: { name: uom_id_+ key() }, value: uomPrice()0.UomId()> small>/ span data-bindhtml: uomPrice()0.UomName()>/span>/small> !-- /ko --> !-- ko if: oConfig.useUom && !oConfig.useMultiUomMultiCurrency && uomPrice().length > 0 --> input typehidden data-bindattr: { name: uom_+ key() }, value: uomPrice()0.description> small>/ span data-bindhtml: uomPrice()0.description()>/span>/small> !-- /ko --> /script> script typetext/html idwarehouse_off> !-- ko if: inventory.showQty() || !$.isNumeric(inventory.stock()) --> div classidp-instock__qty data-bindhtml: inventory.stock>/div> !-- /ko --> !-- ko if: inventory.showMessage --> div classidp-stock__message data-bindhtml: inventory.stockMessage>/div> !-- /ko --> !-- ko if: (inventory.inventoryStatus() out || inventory.inventoryStatus() onorder) && oConfig.showInventoryWatch && show_inv_watch--> span classprod-inv-watch> a data-bind html: oConfig.searchConfig.labels.inventoryWatchLinkText, attr: { href: prod_inv_watch_add.asp?p_id + key() + &p_nm + name() + &p_sku + sku(), title: utils.decodeHTML(oConfig.labels.inventoryWatch), data-title: oConfig.labels.inventoryWatch }, tooltip: { placement: top, container: body } classprod-inv-watch__btn global-modal btn btn-secondary data-sizesmall >/a> /span> !-- /ko --> /script> script typetext/html idwarehouse_droplist> label data-bind attr : { for : pw_id_ + key() }, html: oConfig.labels.warehouses >/label> select classwh-droplist data-bind options: inventory.warehouses, optionsText: function(item){ var quantity item.qty_available(); var message ; if($data.inventory.inventoryStatus() in){ if(quantity > 0 || !$.isNumeric(quantity)){ message quantity + ; }else{ message 0 ; } } if($data.inventory.showMessage){ message message + utils.removeHTML($data.inventory.stockMessage()); } if(message ! ){ message ( + message + ); } return item.name() + + message; }, optionsValue: $data, value: selectedWarehouse, attr: { id: pw_id_ + key(), name: pw_id_ + key() } > /select> /script> script typetext/html idwarehouse_table> table classtable table-bordered> tr>th data-bind html : oConfig.labels.warehouses>/th> th data-bind html : oConfig.labels.inventoryStatus>/th>/tr> tbody data-bind foreach: inventory.warehouses> tr data-bind css : { default_warehouse : isDefault }> td data-bind html: name>/td> td data-bind html: qty_available()>/td> /tr> /tbody> /table> input typehidden data-bind attr : { id : selectedWarehouse().key, name : selectedWarehouse().key, value : selectedWarehouse().key } > /script> script typetext/html idwarehouse_info> div classidp-warehouse clearfix data-bindif: selectedWarehouse().key> div classwh-selected> div classwh-selected-nm data-bind attr : { id : selected_warehouse_ + selectedWarehouse.key }, html : selectedWarehouse().name() >/div> span data-bind attr : { id : stock_message_ + key() }, html : selectedWarehouse().qty_available() >/span> /div> input typehidden data-bind attr : { id : selectedWarehouse().key, name : selectedWarehouse().key, value : selectedWarehouse().key } > /div> /script> script typetext/html idcatalog.image_gallery> div classdetail-img-gallery> div classdetail-img> div classdetail-img-container> div data-bindtemplate: catalog.flags>/div> !-- ko if: largePic() || $parent.largePic() --> a iddetail_large data-bind attr: { href: utils.buildImagePath(largePic() || $parent.largePic()), title: utils.decodeHTML((picAltText() || $parent.picAltText() || name() || $parent.name())) }, venobox data-galldetailmultipic classdetail-img-main > !-- template: catalog.thumbnail_image --> /a> !-- /ko --> !-- ko ifnot: largePic() || $parent.largePic() --> !-- template: catalog.thumbnail_image --> !-- /ko --> /div> div classdetail-img-enlarge data-bindif: largePic() || $parent.largePic() > a href# classbtn btn-small btn-link onclick$(#detail_large).click(); return false;> i classicon-zoom-in icon-fixed-width>/i>View Larger /a> /div> /div> !-- ko if: multiPic().length > 0 || $parent.multiPic().length > 0 --> div classdetail-img-multi data-bindforeach: { data: multiPic().length ? multiPic(): $parent.multiPic() }> a classdetail-img-multi-item venobox vbox-item data-bindattr: { href: utils.buildImagePath(link() || image()), title: utils.decodeHTML(name) }, venobox data-galldetailmultipic> img data-bindattr: { src: utils.buildImagePath(image()) }> /a> /div> !-- /ko --> /div> /script> script typetext/html idcatalog.thumbnail_image> img data-bind attr: { src: utils.buildImagePath(pic() || $parent.pic()), alt: utils.decodeHTML(thumbAltText() || $parent.thumbAltText() || name() || $parent.name()), title: utils.decodeHTML(thumbAltText() || $parent.thumbAltText() || name() || $parent.name()) } idprodpicthumb nameprodpic itempropimage onerrorutils.handleImageError(this) > /script> script typetext/html idcatalog.name_link> a classdetail_link data-bindattr: { href: link, title: utils.decodeHTML(name()), data-key: key }, html: name>/a> /script> script typetext/html idcatalog.image_link> a classdetail_link data-bindattr: { href: link, title: utils.decodeHTML(thumbAltText() || name()), data-key: key }> img data-bind attr: { src: utils.buildImagePath(thumb()), alt: utils.decodeHTML(thumbAltText() || name()) } onerrorutils.handleImageError(this)> /a> /script> script typetext/html idcatalog.details_link> /script> script typetext/html idcatalog.product_links> div classdetail-links button-group> !-- ko if: oConfig.showEmailFriend --> !-- template: catalog.email_friend --> !-- /ko --> !-- ko if: oConfig.showFavLink --> !-- template: catalog.fav_button --> !-- /ko --> !-- ko if: oConfig.showRFQLink --> !-- template: catalog.rfq_button --> !-- /ko --> /div> /script> script typetext/html idcatalog.children_selection> !-- ko foreach: $data.childSelectors --> label data-bindtext: label, attr: { for: field }> /label> select data-bind attr: { id: field, name: field }, options: options, optionsText: option, value: selectedOption, optionsCaption: -- Select One -- >/select> !-- /ko --> /script> script typetext/html idcatalog.email_friend> a classbtn btn-link global-modal data-bindattr: { href: email_friend_request.asp?p_id + key() + &typeproduct } data-iconenvelope data-sizesmall > i classicon-envelope>/i> span data-bindhtml: oConfig.labels.emailFriend>/span> /a> /script> script typetext/html idcatalog.fav_link> a classglobal-modal data-bindattr: { href: add_product_to_favorites.asp?p_id + key() } data-iconheart data-sizesmall > span data-bindhtml: oConfig.labels.favLink>/span> /a> /script> script typetext/html idcatalog.fav_button> a classbtn btn-link global-modal data-bindattr: { href: add_product_to_favorites.asp?p_id + key() } data-iconheart data-sizesmall > i classicon-heart>/i> span data-bindhtml: oConfig.labels.favLink>/span> /a> /script> script typetext/html idcatalog.remove_fav_button> div classremove-from-faves prod-fav-remove> a data-bind click: function() { fncRemoveItem(key(), selectedProduct()); }, attr: { title: utils.decodeHTML(oConfig.labels.removeFavLink), href: javascript:void(0); }> i classicon-remove>/i> span data-bindhtml: oConfig.labels.removeFavLink>/span> /a> /div> /script> script typetext/html idcatalog.rfq_button> a classbtn btn-link global-modal data-bindattr: { href: rfq_ae.asp?lightbox1&p_id + key() } data-iconusd > i classicon-usd>/i> span data-bindhtml: oConfig.labels.rfqLinkLabel>/span> /a> /script> script typetext/html idcatalog.share_code> /script> script typetext/html idcatalog.hazmat> span data-bindtext: oConfig.labels.hazmat>/span>br> !-- ko if: dangerousRatio() ! 1 --> span data-bindhtml: oConfig.labels.hazmatBoxRatio + dangerousRatio()>/span>br> !-- /ko --> !-- ko if: oConfig.hazmatLink--> a classglobal-modal data-bindtext: oConfig.labels.hazmatHelpText, attr: { href: oConfig.hazmatLink }>/a> br> !-- /ko --> /script> script typetext/html idcatalog.softgoods> !-- ko if: createSoftGoodsAuth --> span data-bindtext: oConfig.labels.softgoods>/span> !-- /ko --> /script> script typetext/html idcatalog.documents> ul classdoc_downloads unstyled> !-- ko if: $data.length > 0 --> li data-bindhtml: oConfig.labels.downloads>/li> !-- ko foreach: $data --> li> a data-bindattr: { href: utils.buildImagePath(link()) }, text: name target_blank >/a> /li> !-- /ko --> !-- /ko --> /ul> /script> script typetext/html idcatalog.product_account_history_short> !-- if: oConfig.fastTrack && oConfig.showProductHistory && oConfig.isLoggedIn--> div classsmart-lists-container > div classsmart-list> !-- ko if: isOrdered--> div classlist-group-item total-qty-ordered> Total Qty Ordered span classpull-right data-bindtext: sumQty>/span> /div> div classlist-group-item total-times-ordered> Total Times Ordered span classpull-right data-bindtext: orderCount>/span> /div> div classlist-group-item most-recent-order-date> Most Recent Order span classpull-right data-bindtext: mostRecentOrderDate>/span> /div> !-- /ko --> /div> !-- /ko --> /script> script typetext/html idcatalog.smart_lists> !-- ko if: oConfig.showProductHistory && oConfig.isLoggedIn--> h2 data-bindhtml: oConfig.labels.productHistory>/h2> div classsmart-lists-container> div classsmart-list> !-- ko ifnot: accountHistory --> p classalert alert-warning>No additional information available./p> !-- /ko --> !-- ko if: accountHistory --> div classwell well-small clearfix smart-list-meta> div classpull-left data-bindif: accountHistory.accountName> strong>Account:/strong> !-- text: accountHistory.accountName --> /div> div classpull-right data-bindif: accountHistory.lastUpdate> strong>Last Updated:/strong> !-- text: accountHistory.lastUpdate --> /div> /div> !-- template: { name: catalog.smart_lists_panels, data: accountHistory, if: accountHistory } --> !-- /ko --> /div> /div> !-- /ko --> /script> script typetext/html idcatalog.smart_lists_panels> div classrow-fluid> div classspan4> div classpanel panel-default order-stats> div classpanel-heading> div classpanel-title>Order Stats/div> /div> div classlist-group> !-- ko if: isOrdered --> div classlist-group-item total-qty-ordered> Total Qty Ordered span classpull-right data-bindtext: sumQty>/span> /div> div classlist-group-item total-times-ordered> Total Times Ordered span classpull-right data-bindtext: orderCount>/span> /div> div classlist-group-item most-recent-order-date> Most Recent Order span classpull-right data-bindtext: mostRecentOrderDate>/span> /div> div classlist-group-item oldest-order-date> Oldest Order span classpull-right data-bindtext: oldestOrderDate>/span> /div> a classlist-group-item text-center data-bindattr: { href: $parent.getSmartListLinkOrderStats($parent) }> View Details i classicon-angle-right>/i> /a> !-- /ko --> !-- ko ifnot: isOrdered --> div classlist-group-item previously-ordered> Previously Ordered span classpull-right>No/span> /div> !-- /ko --> /div> /div> /div> div classspan4> div classpanel panel-default invoice-stats> div classpanel-heading> div classpanel-title>Invoice Stats/div> /div> div classlist-group> !-- ko if: isInvoiced --> div classlist-group-item total-qty-invoiced> Total Qty Invoiced span classpull-right data-bindtext: sumInvoiceQty>/span> /div> div classlist-group-item total-times-invoiced> Total Times Invoiced span classpull-right data-bindtext: invoiceCount>/span> /div> div classlist-group-item most-recent-invoice-date> Most Recent Invoice span classpull-right data-bindtext: mostRecentInvoiceDate>/span> /div> div classlist-group-item oldest-invoice-date> Oldest Invoice span classpull-right data-bindtext: oldestInvoiceDate>/span> /div> div classlist-group-item amount-invoiced-mtd> Invoiced MTD span classpull-right data-bindhtml: utils.formatMoney(sumInvoicedMtd)>/span> /div> div classlist-group-item amount-invoiced-last-month> Invoiced Last Month span classpull-right data-bindhtml: utils.formatMoney(sumInvoicedLastMonth)>/span> /div> div classlist-group-item amount-invoiced-ytd> Invoiced YTD span classpull-right data-bindhtml: utils.formatMoney(sumInvoicedYtd)>/span> /div> div classlist-group-item amount-invoiced-last-year> Invoiced Last Year span classpull-right data-bindhtml: utils.formatMoney(sumInvoicedLastYear)>/span> /div> div classlist-group-item total-amount-invoiced> Total Invoiced span classpull-right data-bindhtml: utils.formatMoney(sumInvoiced)>/span> /div> a classlist-group-item text-center data-bindattr: { href: $parent.getSmartListLinkInvoiceStats($parent) }> View Details i classicon-angle-right>/i> /a> !-- /ko --> !-- ko ifnot: isInvoiced --> div classlist-group-item previously-invoiced> Previously Invoiced span classpull-right>No/span> /div> !-- /ko --> /div> /div> /div> div classspan4> div classpanel panel-default other-stats> div classpanel-heading> div classpanel-title>Other Stats/div> /div> div classlist-group> !-- ko if: viewedCount --> div classlist-group-item times-viewed> Times Viewed span classpull-right data-bindtext: viewedCount>/span> /div> div classlist-group-item most-recent-view-date> Most Recent View span classpull-right data-bindtext: mostRecentViewDate>/span> /div> !-- /ko --> div data-bindvisible: oConfig.smartListShowFavorites classlist-group-item on-favorites-list> span data-bindhtml: oConfig.smartListFavoritesText>/span> span classpull-right data-bindtext: isOnFavList ? Yes : No>/span> /div> div data-bindvisible: oConfig.smartListShowInventoryWatch classlist-group-item on-inventory-watch> span data-bindhtml: oConfig.smartListInventoryWatchText>/span> span classpull-right data-bindtext: isOnInventoryWatch ? Yes : No>/span> /div> div data-bindvisible: oConfig.smartListShowAbandonedCart classlist-group-item in-abandoned-cart> span data-bindhtml: oConfig.smartListAbandonedCartText>/span> span classpull-right data-bindtext: isInAbandondedCart ? Yes : No>/span> /div> /div> /div> /div> /div> /script> script typetext/html idcatalog.smart_lists_table> table classtable table-bordered> tr classheader-row order-stats> th colspan2> Order Stats !-- ko if: isOrdered --> - a data-bind attr: { href: $parent.getSmartListLinkOrderStats($parent) } > View Details /a> !-- /ko --> /th> /tr> !-- ko if: isOrdered --> tr classtotal-qty-ordered> td>Total Qty Ordered/td> td data-bindtext: sumQty>/td> /tr> tr classtotal-times-ordered> td>Total Times Ordered/td> td data-bindtext: orderCount>/td> /tr> tr classmost-recent-order-date> td>Most Recent Order Date/td> td data-bindtext: mostRecentOrderDate>/td> /tr> tr classoldest-order-date> td>Oldest Order Date/td> td data-bindtext: oldestOrderDate>/td> /tr> !-- /ko --> !-- ko ifnot: isOrdered --> tr classpreviously-ordered> td>Previously Ordered/td> td>No/td> /tr> !-- /ko --> tr classheader-row invoice-stats> th colspan2> Invoice Stats !-- ko if: isInvoiced --> - a data-bind attr: { href: $parent.getSmartListLinkInvoiceStats($parent) } > View Details /a> !-- /ko --> /th> /tr> !-- ko if: isInvoiced --> tr classtotal qty invoiced> td>Total Qty Invoiced/td> td data-bindtext: sumInvoiceQty>/td> /tr> tr classtotal-times-invoiced> td>Total Times Invoiced/td> td data-bindtext: invoiceCount>/td> /tr> tr classmost-recent-invoice-date> td>Most Recent Invoice Date/td> td data-bindtext: mostRecentInvoiceDate>/td> /tr> tr classoldest-invoice-date> td>Oldest Invoice Date/td> td data-bindtext: oldestInvoiceDate>/td> /tr> tr classamount-invoiced-mtd> td>Amount Invoiced MTD/td> td data-bindhtml: utils.formatMoney(sumInvoicedMtd)>/td> /tr> tr classamount-invoiced-last-month> td>Amount Invoiced Last Month/td> td data-bindhtml: utils.formatMoney(sumInvoicedLastMonth)>/td> /tr> tr classamount-invoiced-ytd> td>Amount Invoiced YTD/td> td data-bindhtml: utils.formatMoney(sumInvoicedYtd)>/td> /tr> tr classamount-invoiced-last-year> td>Amount Invoiced Last Year/td> td data-bindhtml: utils.formatMoney(sumInvoicedLastYear)>/td> /tr> tr classtotal-amount-invoiced> td>Total Amount Invoiced/td> td data-bindhtml: utils.formatMoney(sumInvoiced)>/td> /tr> !-- /ko --> !-- ko ifnot: isInvoiced --> tr classpreviously-invoiced> td>Previously Invoiced/td> td>No/td> /tr> !-- /ko --> tr classheader-row other-stats> th colspan2>Other Stats/th> /tr> !-- ko if: isOnFavList --> tr classon-favorites-list> td>On Favorites List/td> td>Yes/td> /tr> !-- /ko --> !-- ko if: viewedCount --> tr classtimes-viewed> td>Times Viewed/td> td data-bindtext: viewedCount>/td> /tr> tr classmost-recent-view-date> td>Most Recent View Date/td> td data-bindtext: mostRecentViewDate>/td> /tr> !-- /ko --> !-- ko if: isOnInventoryWatch --> tr classon-inventory-watch> td>On Inventory Watch/td> td>Yes/td> /tr> !-- /ko --> tr classin-abandoned-cart> td>In Abandoned Cart/td> td data-bindtext: isInAbandondedCart ? Yes : No>/td> /tr> /table> /script> script typetext/html idcatalog.detail_info> dl classprod-searchfields> !-- template: catalog.sku_label --> !-- template: { name: catalog.searchfields, foreach: _.values(selectedProduct().searchfields) } --> /dl> /script> script typetext/html idcatalog.sku_label> dt data-bindhtml: oConfig.labels.sku>/dt> dd itempropsku data-bindhtml: selectedProduct().sku>/dd> /script> script typetext/html idcatalog.searchfields> !-- ko if: !oConfig.fastTrack && show() --> dt classprod-searchfields__label data-bindhtml: label>/dt> dd classprod-searchfields__value data-bindhtml: value>/dd> !-- /ko --> /script> script typetext/html idpromotions.descriptions> div classpromo-panel-container> h4 classpromo-panel-heading data-bindtext: title>/h4> ul classpromo-panel-content data-bindforeach: descriptions> li classpromo-panel data-bind text: description, css: { faded: $parent.selectedProduct().type ! parent && !_.contains(targetKeys, $parent.selectedProduct().key()) } > /li> /ul> /div> /script> script typetext/html idcatalog.configurator> form idfrmAddToCart> div idconfigurator data-bindconfigurator: $data>/div> /form> /script> script typetext/javascript> // The configurator markup cannot be placed directly in a template // because it can contain scripts and scripts cannot be nested. Instead, // a surrogate is used to allow the scripts to run and then its contents // are moved when the template is called. This means that each surrogate // can only be used once, and thus, only one product per page can // display a configurator form. However, this isnt a new limitation to // configurator since configurator uses generic IDs for all the elements // it creates. ko.bindingHandlers.configurator { init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { var product ko.unwrap(valueAccessor()); var data product.configuratorEditData var $surrogate $(#configurator_surrogate).detach(); var $element $(element); // Remove the scripts to prevent jQuery from running them again upon insertion. // Form builder does not allow disabling the use of form actions. $surrogate.find(script, .form-actions).remove(); // In order to preserve bindings and jQuery data, the elements // are moved from the surrogate rather than copied. This wont // cause a reflow because the surrogate has `display: none`. $element.html($surrogate); $surrogate.children(:first-child).unwrap(); //Stretchy.js is adding a style tag with height and width to text inputs and textareas. //This will remove those hardcoded heigths/widths but leave any StyleOverride props in place. _.each($element.find(textarea, inputtypetext), function(child){ $(child).css(height,); $(child).css(width,); }); if (data) { _.each(data.choices, function (choice) { var $inputs $element.find(name + choice.name + ); var answerVal; if (oConfig.configuratorUseAnswerIdNotName) { answerVal choice.answer; } else { answerVal choice.answerText; } if ($inputs.is(:checkbox, :radio)) { $inputs.filter(value + answerVal + ).prop(checked, true); } else { $inputs.val(answerVal); } // Update display activators. $inputs.change(); }) product.selectedQty(data.qty); } runHook(afterBindingHandlersConfigInit, {product: product}); } }; ko.bindingHandlers.validateQty { init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { $(element).on(click blur, function (event) { var min parseFloat($(element).attr(min)); var max parseFloat($(element).attr(max)) || 0; var step parseFloat($(element).attr(step)); var currentQty parseFloat($(element).val()); var newQty currentQty; var lowerBound; var minFound false; var maxFound false; var accessor valueAccessor() || ; viewModel.updateQty function(args){ if(viewModel.orderDetailKey){ viewModel.qty(args); }else{ viewModel.selectedQty(args); } }; if($(element).val() ){ if((isActiveLayout(gallery) && event.type blur) || event.type click ) { viewModel.updateQty(min); $(element).select(); return; } } if(currentQty min){ newQty min; viewModel.updateQty(newQty); invalidQtyNotification(bindingContext.$data) return; } if(currentQty > max && max > 0){ newQty max; viewModel.updateQty(newQty); invalidQtyNotification(bindingContext.$data) return; } var stepMod parseFloat((currentQty - min) % step); if(stepMod ! 0 && (!maxFound && !minFound)){ newQty Math.ceil((currentQty - min) / step) * step + min; viewModel.updateQty(newQty); invalidQtyNotification(bindingContext.$data) return; } }); } }; ko.bindingHandlers.validateQtyControlInput { init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { $(element).on(click blur, function (event) { var min parseFloat($(element).attr(min)); var max parseFloat($(element).attr(max)) || 0; var step parseFloat($(element).attr(step)); var currentQty parseFloat($(element).val()); var newQty currentQty; var lowerBound; var minFound false; var maxFound false; var accessor valueAccessor() || allBindings().value; if(currentQty ! 0 && currentQty min){ newQty min; accessor(newQty); return; } if(currentQty > max && max > 0){ newQty max; accessor(newQty); return; } var stepMod parseFloat((currentQty - min) % step); if(stepMod ! 0 && (!maxFound && !minFound)){ if(ko.unwrap(valueAccessor())) { newQty Math.ceil((currentQty - min) / step) * step + min; } else { newQty Math.floor((currentQty - min) / step) * step + min; } accessor(newQty); return; } }); } }; (function () { function getInputs(productKey) { var keyAttribute data-configurator-product-key; // The container will vary based on whether this function is called // before or after the `catalog.configurator` template is used. var $container $(#configurator_surrogate); if (!$container.length) $container $(#configurator); var $dataElement $container.find( + keyAttribute + ); return $dataElement.attr(keyAttribute) productKey ? $container.find(:input) : null; } function getPrice($inputs) { var price 0; $inputs .filter(:visible:not(:disabled)) .find(:selected) .add($inputs.filter(:checked)) .each(function () { console.log($(this)); price + $(this).data(price) || 0; }); return price; } window.buildConfiguratorPriceObservable function (productKey) { var priceObservable ko.observable(0); var $inputs getInputs(productKey); if ($inputs) { priceObservable(getPrice($inputs)); $inputs.change(function () { var newPrice getPrice($inputs); if (priceObservable() ! newPrice) priceObservable(newPrice); }); } return priceObservable; }; window.buildConfiguratorPostData function (productKey) { var $inputs getInputs(productKey); var postData {}; if ($inputs) { var ary $inputs.filter(:not(:disabled)).serializeArray(); // cant exclude non-visible items; configurator uses them a lot! _.each(ary, function (datum) { if (datum.value) { if (postData.hasOwnProperty(datum.name)) { if(!Array.isArray(postDatadatum.name)) { postDatadatum.name postDatadatum.name ; } postDatadatum.name.push(datum.value); } else { postDatadatum.name datum.value; } } }); postDatause_config_questions_ + productKey true; } return postData; }; }()); /script> div idconfigurator_surrogate styledisplay: none> div classconfigurator> /div> /div> script> function invalidQtyNotification(data) { // change where key is derived from (different on payment page than catalog) var elementSelector data.key ? *data-key+ data.key() + : *data-key+ data.orderDetailKey() + ; element $(elementSelector); if ($(element).length){ if(oConfig.preventATCInvalidQty) data.isQtyValid(false); $(element).popover(show).addClass(text-error) ; setTimeout(function () { $(element).popover(toggle).removeClass(text-error); // check to see if prop exists (doesnt on payment page) if(data.isQtyValid) { data.isQtyValid(true); } }, 3000 ); } } function changeSort(data, event) { window.location utils.setParameter(sortby, event.target.value ); } function getSelectedSort() { return decodeURI(utils.getParameter(sortby)) || oConfig.searchConfig.defaultSort; } function changeRpp(data, event) { var sUrl utils.setParameter(rpp, event.target.value); sUrl utils.setParameter(page, 1, sUrl); window.location sUrl; } function getSelectedRpp() { if(utils.getParameter(favorites)){ //force a single page for favorites lists. oConfig.searchConfig.rpp 9999; }else{ return utils.getParameter(rpp) || oConfig.searchConfig.rpp; } } function isActiveLayout(layout) { return getActiveLayout() layout; } function getActiveLayout() { return oConfig.pageName pc_combined_results.asp ? oConfig.searchConfig.showLayout ? utils.getCookie(productLayout) || oConfig.searchConfig.layout : oConfig.searchConfig.layout : null; } function getStartCount() { var startCount (oConfig.searchConfig.page - 1) * oConfig.searchConfig.rpp + 1; return startCount; } function getEndCount() { var rpp oConfig.searchConfig.rpp || oConfig.searchConfig.total; var endCount Math.min(((oConfig.searchConfig.page - 1) * rpp) + rpp, oConfig.searchConfig.total); return endCount; } function maxPage() { return Math.ceil(oConfig.searchConfig.total / oConfig.searchConfig.rpp); } function setLayout(layout) { utils.setCookie(productLayout, layout); window.location.reload(); } function getLayoutTemplate(data) { if(data.results().length 0 && !data.category && oConfig.isUsingFacetedSearch){ hideSidebar(); } if(data.results().length 0){ hideSearchTools(); return catalog.no_results } else { return catalog. + (utils.getCookie(productLayout) || oConfig.searchConfig.layout) + _view; } } function hideSidebar(){ $(#catalog-sidebar).hide(); $(.main-content).removeClass(span9); } function hideSearchTools(){ $(#products_header, #products_footer, .hidesearchtools).hide() } function pagingNodes() { var page oConfig.searchConfig.page; var labels oConfig.searchConfig.labels; var maxPage window.maxPage(); nodes { if: page > 1 && labels.prevPage, page: page - 1, text: labels.prevPage }, { if: page > 2, page: 1, text: labels.firstPage || 1 }, { if: page > 3, text: … }, { if: page > 1, page: page - 1 }, { if: true, text: page, page: page }, { if: page maxPage, page: page + 1 }, { if: page maxPage - 2, text: … }, { if: page maxPage - 1, page: maxPage, text: labels.maxPage || maxPage }, { if: page maxPage && labels.nextPage, page: page + 1, text: labels.nextPage }, ; return _.compact(_.map(nodes, function (node) { return node.if ? { page: node.page, text: node.text || node.page } : null; })); } function getATCModalSize(){ if(oConfig.usePromos){ return ; }else{ return small; } } function isTextSelected(input) { if (typeof input.selectionStart number) { return input.selectionStart 0 && input.selectionEnd input.value.length; } else if (typeof document.selection ! undefined) { input.focus(); return document.selection.createRange().text input.value; } } function setChildOptionDisable(field, optionElement, item) { function isInvalidChildOption(children, options, field, item) { return ko.computed(function () { var match {}; _.forEach(options, function (option) { // Dont unwrap unnecessary observables. if (option.field field) return; var selected option.selectedOption(); if (selected) matchoption.field selected.option; }); matchfield item.option; return !_.find(children, match); }); } if (item && ko.unwrap(viewModel.mainProduct).children() && ko.unwrap(viewModel.mainProduct).children().length) { var obs isInvalidChildOption( ko.unwrap(viewModel.mainProduct).children(), ko.unwrap(viewModel.mainProduct).childSelectors(), field, item ); ko.applyBindingsToNode(optionElement, {disable: obs}, item); } } function addToCartWithValidation(products, event, parentKey) { var invalidQtyIndex _.findIndex(products, function(product) {return !product.isQtyValid()}); //If the total quantity selected on the page is 0 then display an error message var iTotalQtyToAtc _.filter(products,function(product) {return product.selectedProduct().selectedQty() > 0; }).length; if (iTotalQtyToAtc 0) { var data { products: products, event: event }; utils.openModal({ body : oConfig.atcInvalidQtyTemplate, size : getATCModalSize(), title : oConfig.labels.invalidQtyTitle }, data); return; } if(oConfig.preventATCInvalidQty && invalidQtyIndex ! -1) { utils.scrollTo(data-key + productsinvalidQtyIndex.key() + ); } else { utils.addToCart( _.filter(products, function (product) { return product.selectedProduct().selectedQty() > 0; }), undefined, parentKey); } } function replaceSavedCartKeywordWithGlobal(sLabel) { return sLabel.replace(cart>, Quote); } $(function () { ko.bindingHandlers.raty { init: function () { return { controlsDescendantBindings: true }; }, update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { var value ko.unwrap(valueAccessor()); var isRated value ! null; var $element $(element); // This is no longer necessary since we are displaying ratings all the time, // plus it was setting inline style of block when element needed inline-block - jonr 2016-10-25 // $element.toggle(isRated); if (isRated) { var options typeof value object ? value : { score: value }; _.defaults(options, { path: templates/gfx/, space: false, readOnly: true, width: 90, hints: oConfig.ratingNames }); $(element).html($(div>).raty(options)); } } }; ko.applyBindings(); runHook(afterApplyBindings, { }); }); function setPromoDescriptionTitleText(promoDescription) { var productPromotions ; _.forEach(promoDescription, function (descriptions) { productPromotions + descriptions.description + \n; }); return productPromotions; } function setSelectedQty() { if(!!viewModel.mainProduct && !!ko.unwrap(viewModel.mainProduct).configuratorEditData && !!ko.unwrap(viewModel.mainProduct).configuratorEditData.qty) { ko.unwrap(viewModel.mainProduct).selectedProduct().selectedQty(ko.unwrap(viewModel.mainProduct).configuratorEditData.qty); return false; } if (oConfig.pageName pc_combined_results.asp) { return getActiveLayout() ! list || oConfig.showListViewATC; } else if(oConfig.pageName pc_product_detail.asp) { return viewModel.mainProduct.childDisplayType() ! input-qty && viewModel.mainProduct.childDisplayType() ! exploded-view && viewModel.mainProduct.childDisplayType() ! matrix-all && !viewModel.mainProduct.configuratorEditData; } else { return true; } } function setSelectedCartOptionAnswer(question) { if(ko.unwrap(viewModel.mainProduct).configuratorEditData) { var editAnswer ko.unwrap(viewModel.mainProduct).configuratorEditData.choices.filter(function(item) { return item.question question.q_key(); }); if(editAnswer && editAnswer.length) { var editAnswerText editAnswer0.answerText; if(question.type() select) { questionAnswer question.answers().filter(function(answer) { return ko.unwrap(answer.value) editAnswerText; }); if(!!questionAnswer.length) { question.selectedAnswer(ko.unwrap(questionAnswer0.value)); } } else { question.selectedAnswer(editAnswerText); } } } } //AJAX Call to remove item from favorites list. function fncRemoveItem (sProdKey , product) { jQuery.ajax({ url: pc_combined_results.asp, data: ajaxremovefavitems&p_key + sProdKey + &fl_key + utils.getParameter(fl_key), type: GET, dataType: text, success: function () { //remove from viewmodel viewModel.results.remove(product); } }); } //If no products can be added to cart in list view then do not display the ATC button at the bottom of the page. function showAddAllToCart() { var productsShowingAtc _.filter(viewModel.results(), function(result) { return result.showQuickAtc(); }).length; return productsShowingAtc > 0; } var pageType ; var defaultHomeLink pc_combined_results.asp; var breadcrumbKey ; var breadcrumbObj utils.getStoredBreadcrumbs() || {breadcrumbs:{}}; var activeBreadcrumb breadcrumbObj.breadcrumbsbreadcrumbKey; $(function() { if(pageType category && !activeBreadcrumb){ //no breadcrumb, add one var categoryName $(#category-window li.active a).first().text(); var categoryLink $(#category-window li.active a).first().attr(href); categoryBreadcrumb ; $(#detail_breadcrumbs li).each(function(){ if(categoryName ! $($(this).children()).text()) { categoryLink $($(this).children()).attr(href) || categoryLink } categoryBreadcrumb.push({ name: $($(this).children()).text(), link: categoryLink } ); }); breadcrumbObj.breadcrumbsbreadcrumbKey categoryBreadcrumb; utils.setStoredBreadcrumbs(breadcrumbObj); activeBreadcrumb breadcrumbObj.breadcrumbsbreadcrumbKey; } }); $(document).on(click, #prod_listings .detail_link, function(){ var productKey $(this).data(key); var productName $(this).attr(title); var defaultBreadcrumb { name: Home, link: window.location.pathname + window.location.search }; if(window.location.search ! && window.location.pathname /pc_combined_results.asp){ defaultBreadcrumb { name: Search Results, link: window.location.pathname + window.location.search }; } var productBreadcrumb activeBreadcrumb || defaultBreadcrumb; productBreadcrumb.push({ name: productName, link: }); var breadcrumbObj utils.getStoredBreadcrumbs() || {breadcrumbs: {}}; breadcrumbObj.breadcrumbsproductKey productBreadcrumb; utils.setStoredBreadcrumbs(breadcrumbObj); }); $(document).on(click, .category-listings a, function(){ var categoryKey $(this).data(key); var categoryName $(this).attr(title); var categoryLink $(this).attr(href); var categoryBreadcrumb activeBreadcrumb; categoryBreadcrumb.push({ name: categoryName, link: categoryLink }); var breadcrumbObj utils.getStoredBreadcrumbs() || {breadcrumbs: {}}; breadcrumbObj.breadcrumbscategoryKey categoryBreadcrumb; utils.setStoredBreadcrumbs(breadcrumbObj); }); $(document).on(click, #category-window a, #header__prodcat a, .linkset .prodcat a, function(){ if($(this).data(key)){ var parentName ; var parentHref ; if($(this).data(parent-name) ){ parentName $(this).data(parent-name).split(|); parentHref $(this).data(parent-href).split(|); } var contentKey $(this).data(key); var categoryName $(this).text(); var categoryUrl $(this).attr(href); var parents ; for( i 0; i parentName.length ; i++ ){ parents.push({ name: parentNamei, link: parentHrefi }); } var home ; home.push( { name: Home, link: defaultHomeLink } ); var breadcrumb home.concat(parents); var breadcrumbObj utils.getStoredBreadcrumbs() || {breadcrumbs: {}}; breadcrumbObj.breadcrumbscontentKey breadcrumb; utils.setStoredBreadcrumbs(breadcrumbObj); } }); var oConfig { pageName: default.asp, mainProductKey: , isModal: false, atcSplashTemplate: catalog.atc_splash, atcInvalidQtyTemplate : catalog.atc_invalid_qty, savedCartPopupTemplate: catalog.saved_cart_select_popup, ratingNames: Bad, Poor, Good, Very Good, Excellent, formValidationKey: , isUsingFacetedSearch: false, overrideCartKey: || || || , activeBreadcrumb: activeBreadcrumb, t_analytics : none, t_tracking_company : , t_tracking_id : , t_gtm : true, t_gtm_id : GTM-54H34Q9, sessionData : { sc_id : 0184CDF83ABA456188F53CAFE0D8ACC8, sessionKey : 1854EFB707B644128F950038F36315EE, storefrontUrl : https://www.nitrousexpress.com, orderfrontUrl : https://www.nitrousexpress.com, cdnUrl: https://d1vlavvlsa6jkm.cloudfront.net, isSuperUserSession : false }, detailConfig : { productKey : , useAdvancedTabs : true, useRelatedProducts : true, useSecondRelatedProducts : true, useAlsoBoughtProducts : false, useRecentlyViewedProducts : true, useAliases : false, selectChildProductOnLoad : true, tabLayoutMode : list, pageLayoutMode : gallery, showDocuments : true, inputQtyLinkToChild : false, globalUnitPriceDecimalPlaces : 2, gridRowClass : , gridLeftColumnClass : , gridRightColumnClass : , showProductDescriptionTop : false, showSoftGoodAuthorizations : false, labels : { relatedProducts : Related Products, secondRelatedProducts : Additional Products, alsoBoughtProducts : Customers Who Bought This Also Bought..., readReviews : Read Reviews, inputQty : Options, inputQtyATCLabel : Add to Cart Below i class\icon-chevron-down\>/i>, recentlyViewedProducts : Recently Viewed, pricesStartingAt : Starting at } }, searchConfig : { pageType : , page : 0, total : 0, showAtc : true, hideAtcShowInv : false, showLayout : true, layout : gallery || gallery, showRpp : true, rppOptions : 24,48,96, showSort : true, productSort : { field : p.sku, direction : asc, display : SKU (a-z) }, productSortOptions : { field : p.sku, direction : asc, display : SKU (a-z) },{ field : p.sku, direction : desc, display : SKU (z-a) },{ field : p.nm, direction : asc, display : Name (a-z) },{ field : p.nm, direction : desc, display : Name (z-a) },{ field : ISNULL(pah.sum_order_qty, 0), direction : desc, display : Total Qty Ordered },{ field : pah.ordered, direction : desc, display : Total Times Ordered },{ field : pah.most_recent_date_ordered, direction : desc, display : Most Recent Ordered }, showDownload : false, gridListViewRowClass : , gridListViewATCColumnClass : , showDescription : true, labels : { layout : , sort : Sort by, rpp : per page, firstPage : , maxPage : , prevPage : i class\icon-angle-left\>/i> Prev, nextPage : Next i class\icon-angle-right\>/i>, favListRemoveColumnHeader : , searchResultsHeader : count> results for keyword>, pricesStartingAt : Starting at , galleryView : i class\icon-th\>/i> Gallery, listView : i class\icon-list-ul\>/i> List, inventoryWatchLinkText : i class\icon-eye-open\>/i> Watch } }, formAction : https://www.nitrousexpress.com/i_i_add_to_cart.asp, isLoggedIn : false, showChildrenSelection: false, usePromos : false, useIdp : true, useUom : (false || false), useMultiUomMultiCurrency : false, useQtyRestrictions : true, useReviews : true, allowAddAnonymousReviews : false, get allowAddReviews() { return this.isLoggedIn || this.allowAddAnonymousReviews; }, useBreaks : false, useBreaksTable : false, priceBreaksTableHeader : Quantity Price Breaks, useSavedCarts : false, useTaxExempt : false, showInventoryWatch : false, showEmailFriend : true, showFavLink : true, showRFQLink : false, showProductHistory : true, showProductHistoryResults: true, showWarehouses : false, showProdYouSave : false, allowWarehouseSelection : false, useWarehousesTable : false, defaultWarehouse : 6094BD2BCD6A4921ABD3A58B09477E3A, hazmatLink : , allowChildATC : true, showListViewATC : true, showNameCol : true, showImgCol : true, preventATCInvalidQty : false, showZeroPriceMessage : false, zeroPriceMessage : Pricing is not currently available on this product. If purchased you will be contacted with pricing and updated order totals before processing your order., fastTrack : false, showPricingOrderEntry : true, configuratorUseAnswerIdNotName: false, labels : { pic : Pic, price : Price, sku : SKU, uom : Unit:, description : Description, reviews : Reviews, productHistory : Product History, qty : QTY, breaks : Qty Pricing, inventoryWatch : Add to Watch List, warehouses : Warehouses, inventoryStatus : Status, downloads : Downloads:, suggestedPrice : List Price, nameCol : Name, imgCol : Image, emailFriend : Email a Friend, favLink : Add to Favorites, step : Qty Increment, minQty : Min Qty, minQtyPopover : Minimum Qty: min_qty>, maxQty : Max Qty, showCartLink : Proceed to Cart, continueShoppingLink : Continue Shopping, hazmat : Hazardous Material, hazmatBoxRatio : Box Ratio, hazmatHelpText : Whats This?, softgoods : Purchasing this item provides a digital file that will be delivered upon placing the order., invalidQtyText : Please enter a valid quantity greater than 1, invalidQtyTitle : Invalid Quantity, youSaveLabel : You Save, removeFavLink : Remove From Favorites, rfqLinkLabel : Request a Custom Quote, savedCarts : Quote, savedCartsLabels : { addToSavedCart : replaceSavedCartKeywordWithGlobal(Add to cart>), itemText : replaceSavedCartKeywordWithGlobal(Item), modalHeader : replaceSavedCartKeywordWithGlobal(Add Item to cart>), modalCreateNew : replaceSavedCartKeywordWithGlobal(Create a new cart>), modalCreateNewSaveButton : replaceSavedCartKeywordWithGlobal(Save), modalCreateNewInputPlaceholder : replaceSavedCartKeywordWithGlobal(cart> Name), modalExisting : replaceSavedCartKeywordWithGlobal(Add to Existing cart>), modalConfirmationHeader : replaceSavedCartKeywordWithGlobal(Added to cart>), modalConfirmationSubHeader : replaceSavedCartKeywordWithGlobal(Added to cart>), modalConfirmationViewButton : replaceSavedCartKeywordWithGlobal(View cart>), modalConfirmationManageButton : replaceSavedCartKeywordWithGlobal(Manage cart>s), modalConfirmationCloseButton : replaceSavedCartKeywordWithGlobal(Close) }, addToCart : i class\icon-shopping-cart\>/i> Add, addToCartList : i class\icon-shopping-cart\>/i> Add to Cart, updateCartItem: Update, taxExempt : Tax Exempt?, selectOptionsLabel : Select optionsi class\icon-angle-right icon-fixed-width\>/i>, noResults : , productNotFound : Product Not Found., categoryNotFound : Category Not Found., averageRating : Average Rating, reviewSignInText : Sign in to add a review, reviewsAddText : Add a Review }, mapBehaviorMessages : { showMessage : Call for Price, requireLoginMessage : div class\text-small muted\>a class\global-modal\ data-size\small\ data-backdrop\static\ title\Sign in to Your Account\ href\security_logon.asp?autopage/Default.asp?&target_parent\>Sign in/a> to see price/div>, requireAtcMessage : div class\text-small muted\>View price in cart/div>, requireLoginAtcMessage : div class\text-small muted\>a class\global-modal\ data-size\small\ data-backdrop\static\ title\Sign in to Your Account\ href\security_logon.asp?autopage/Default.asp?&target_parent\>Sign in/a> to add to cart/div>, requireLoginOrAtcMessage: div class\text-small muted\>a class\global-modal\ data-size\small\ data-backdrop\static\ title\Sign in to Your Account\ href\security_logon.asp?autopage/Default.asp?&target_parent\>Sign in/a> or add to cart to see price/div> }, flags : { link : content/page-1.asp, title : Page 1, pic : flag1_n.png, thumb : flag1_t.png }, { link : , title : , pic : flag2_n.png, thumb : flag2_t.png }, { link : , title : , pic : flag3_n.png, thumb : flag3_t.png }, { link : , title : , pic : flag4_n.png, thumb : flag4_t.png } , childOptionList : , childSkuMatch : , defaultImage : no-image.png || no-image.png, noImagePath : images/no-image.png || images/no-image.png, displayDroplistPlaceholdersForLazyLoad : false, centerRecentlyViewed : false, smartListShowFavorites : true, smartListFavoritesText : On Favorites List?, smartListShowInventoryWatch : true, smartListInventoryWatchText : On Inventory Watch?, smartListShowAbandonedCart : true, smartListAbandonedCartText : In Abandoned Cart?, t_analytics : none, t_tracking_company : , t_tracking_id : , t_gtm : true, t_gtm_id : GTM-54H34Q9, t_gtm_add_to_cart_event_name : }; oConfig.usingFlags oConfig.flags.reduce(function(anyFlagSet, flag) { var flagSet flag.pic || flag.thumb return flagSet || anyFlagSet }, false); /script>/div>div classcart-templates-scripts>script typetext/javascript>function scrollToSection(id) { $(html, body).animate({ // subtracting body padding-top accounts for toolbars with absolute // position, such as the SU bar scrollTop: $(id).offset().top - parseInt($(body).css(padding-top)) }, 300, function(){ $(html, body).clearQueue(); }); } function reloadPage() { viewModel.processing(true); location.reload(); } function sendError(message) { if (windowinsightRUM) { insightRUM.rawErrors.push(Error, sPageName, 1, 1, new Error(message.substring(0,149))); } } function isValidRequestedDate(date) { try { isBusinessDay businessDaySettings1.work_days_of_week undefined || businessDaySettings1.work_days_of_week.indexOf(date.getDay()+1) > -1; isHoliday businessDaySettings1.holiday_dates ! undefined && businessDaySettings1.holiday_dates.indexOf(moment(date).format(MM/DD/YYYY)) > -1; if(isBusinessDay && !isHoliday) { return true; } else { return false; } } catch (error) { sendError(isValidRequestedDate: + error.message); return true; } } function calculateAdjustedLeadTimeDays(effectiveOrderDate, leadTimeDays) { /* EJ - 2016-11-10 - adding 1 initially due to JS interpreting the date from the db as UTC date when in fact it is a local date at midnight. This causes the date in JS to be the day before at 7pm (-5) or 8pm (-4) depending on time of year. Since we are only really concerned with the day, we can add one to compensate for this. */ var adjustedLeadTimeDays leadTimeDays; /* EJ - 2016-11-10 - This if block helps mitigate when the cuttoff time has passed, but the effective_order_date on the SelectedShipVia has not be recalced by the ordering object yet. It essentially checks the cutoff if the effective_order_date is today. Otherwise, there is no need to calculate it. */ if(moment(effectiveOrderDate).date() moment().date()) { var currentDateTime new Date(); var currentUTCSeconds currentDateTime.getUTCSeconds() + (60 * currentDateTime.getUTCMinutes()) + (60 * 60 * currentDateTime.getUTCHours()); if(currentUTCSeconds > businessDaySettings1.utc_cutoff_time_seconds) { adjustedLeadTimeDays + 1; } } var startingDate moment(); for(var i 1; i adjustedLeadTimeDays + 1; i++) { if(!isValidRequestedDate(startingDate.add(1, days).toDate())) { adjustedLeadTimeDays + 1; } } return adjustedLeadTimeDays; } function autoAllocateItems() { if(viewModel.shipments().length 1 && viewModel.shipments()0.shipTo().key() ! && viewModel.shipments()0.shipTo().key() ! null) { if(viewModel.shipments()0.details().length 0) { viewModel.moveAllItemsToShipment(viewModel.shipments()0); } } } //This div is contained in the SU dashboard bar. utils.setActiveQuote function (orderKey) { if(orderKey ! ofConfig.SessionOrderKey) { utils.setCookie(activequote, orderKey); } } utils.removeActiveQuote function (bStartNewQuote) { utils.setCookie(activequote, ); if(bStartNewQuote){ window.location payment.asp + (ofConfig.isModal ? ?modal1 : ); }else{ $(.active-quote-message).hide(); } }; var orderInfoPostUrl payment.asp; //https:// + window.location.hostname + window.location.pathname; var countries ; var newCustomer false; var viewModel; var order; function addAddressHandler() { viewModel.allocateShipments(false); apiGetShippingAddresses(); } function apiGetShippingAddresses(editedKey) { $.ajax({ url: orderInfoPostUrl + ?o_key + viewModel.orderKey() + &ajaxtrue&pageactionapiGetShippingAddresses, success: function(data) { // viewModel.shippingAddresses processShippingAddresses(JSON.parse(data))(); // viewModel.shippingAddresses.notifySubscribers(); var newVarForTesting processShippingAddresses(JSON.parse(data))(); var editedShaKey editedKey || ; var bFound; _.each(newVarForTesting, function(newItem){ _.each(viewModel.shippingAddresses(),function(oldItem){ if(editedShaKey ! ){ if(oldItem.key() editedShaKey && newItem.key() editedShaKey){ oldItem.address1(newItem.address1()); oldItem.address2(newItem.address2()); oldItem.address3(newItem.address3()); oldItem.address4(newItem.address4()); oldItem.address5(newItem.address5()); oldItem.city(newItem.city()); oldItem.state(newItem.state()); oldItem.zipCode(newItem.zipCode()); oldItem.country(newItem.zipCode()); return false; } bFound true; }else{ bFound false; if(oldItem.key() newItem.key()){ bFound true; return false; } } }); if(!bFound && editedShaKey ){ viewModel.shippingAddresses.push(ko.mapping.fromJS(newItem, shippingAddressMappingOptions)); return false; } }); viewModel.availableAddresses viewModel.shippingAddresses; }, error: function(){ alert(error getting shipping addresses); } }); } var shippingAddressMappingOptions { create: function(options) { var address new addressInfo(options.data); address.summaryLine ko.computed(function() { var lineText ; function separator(separatorText) { return lineText ? : separatorText; } function addField(field, separatorText) { if(!separatorText) { separatorText , } lineText + field ? separator(separatorText) + field : ; } addField(address.name()); addField(address.company()); addField(address.attention()); addField(address.firstName()); addField(address.lastName(), address.firstName() ? : ); addField(address.address1()); addField(address.address2()); addField(address.address3()); addField(address.address4()); addField(address.address5()); addField(address.global()); addField(address.city()); addField(address.state()); addField(address.zipCode(), ); addField(address.country()); return lineText; }); return address; } } function getNewAddress() { return { name: , firstName: , lastName: , company: , attention: , address1: , address2: , address3: , address4: , address5: , country: USA, city: , state: , county: , zipCode: , phone: , email: , global: 0, key: utils.createGuid() } } function getShippingFromBilling() { var newAddress JSON.parse(ko.toJSON(viewModel.Account)); newAddress.firstName viewModel.Customer().firstName(); newAddress.LastName viewModel.Customer().LastName(); newAddress.Email viewModel.Customer().Email(); newAddress.Phone viewModel.Customer().Phone(); newAddress.Name ; newAddress.Attention viewModel.Customer().firstName() + + viewModel.Customer().LastName(); newAddress.key utils.createGuid(); return newAddress; } function getNewShipment() { return new Shipment({ Key: utils.createGuid(), SelectedShipVia: {}, ShipViaChoices: , Details: , LeadTimeDays: null, ShipTo: getNewAddress(), Comments: , availableAddresses: shippingAddresses }); } function generateRefId(){ var today new Date(); var dd today.getDate(); var mm today.getMonth()+1; //January is 0! var yyyy today.getFullYear(); var rand Math.floor(Math.random() * 1000000) if(dd10) { dd0+dd } if(mm10) { mm0+mm } today yyyy+mm+dd+-+rand; return today; } var StateChoice function(code, name) { var self this; var choice {}; choicecode code; choicename name; ko.mapping.fromJS(choice, {}, self); } var detailLineInstanceSort function (a, b) { var aInstance a.instance(); var bInstance b.instance(); var aParentId a.parentProductID().trim(); var bParentId b.parentProductID().trim(); if(aInstance bInstance) { return (aParentId bParentId) ? -1 : (aParentId > bParentId) ? 1 : 0; } else { return (aInstance bInstance) ? -1 : 1; } } var shipmentDetailsInstanceSort function(a, b) { return detailLineInstanceSort(a.orderDetail, b.orderDetail); } var addressInfo function(addressData, addressType) { var self this; if(!addressData) { addressData getNewAddress(); } if(!addressData.global){ addressData.global 1; } addressData.addressType ko.observable(addressType || shipping); ko.mapping.fromJS(addressData, {}, self); if(!self.state()) { self.state(undefined); } for(var prop in self) { if(self.hasOwnProperty(prop) && typeof selfprop function) { if(selfprop() null || selfprop() null) { selfprop(); } } } self.address1.extend({ required: true }); self.country.extend({ required: true }); self.city.extend({ required: true }); self.state.extend({ required: ofConfig.bRequireStateForShipping }); self.zipCode.extend({ required: ofConfig.bRequireZIPCodeForShipping }); if(!self.country()) { self.country(USA); } self.stateChoices ko.observableArray(); self.editing ko.observable(false); self.loadStates function() { countries.forEach(function(country) { if(country.iso3 self.country()) { self.stateChoices(country.states); } }); if(!self.country()){ self.stateChoices.removeAll(); } } self.country.subscribe(function() { self.loadStates(); }); self.loadStates(); } var detailMap function(detailLine, shipment, order) { var self this; self.detailLine detailLine; self.shipment shipment; self.totalOrderQty ko.computed(function() { return detailLine.qty(); }); self.qtyToShip ko.observable(); self.qtyInShipment ko.observable(function() { self.qtyToShip(self.shipment.details().reduce(function(prev, curr, index, arr) { if(curr.orderDetailId() detailLine.orderDetailKey()) { return prev + Number(curr.qtyToShip()); } else { return prev; } }, 0)); return self.qtyToShip(); }() ); self.qtyInAllShipments ko.computed(function() { var theKey self.shipment.key(); var allShipmentsTotal order.shipments().reduce(function(runningTotal, individualShipment) { var individualShipmentTotal individualShipment.details().reduce(function(runningSubTotal, detail) { if(detail.orderDetailId() detailLine.orderDetailKey()) { return runningSubTotal + Number(detail.qtyToShip() || 0); } else { return runningSubTotal; } }, 0); return runningTotal + individualShipmentTotal; }, 0); var currentShipmentTotal self.shipment.details().reduce(function(runningSubTotal, detail) { if(detail.orderDetailId() detailLine.orderDetailKey()) { return runningSubTotal + Number(detail.qtyToShip() || 0); } else { return runningSubTotal; } }, 0) var otherShipmentsTotal allShipmentsTotal - currentShipmentTotal; return otherShipmentsTotal + Number(self.qtyToShip() || 0); }); self.unallocatedQty ko.computed(function() { return self.detailLine.qty() - self.qtyInAllShipments(); }); self.toggleItemSelect ko.computed({ read: function() { return this.qtyToShip() > 0; }, write: function(isChecked) { if(isChecked){ this.qtyToShip(1); } else { this.qtyToShip(0); } } }, self); runHook(detailLineModelBottom, { self: self, detailLine: self }); }; var Shipment function(shipmentData) { var self this; ko.mapping.fromJS(shipmentData, { shipTo : shippingAddressMappingOptions, shipViaChoices : { create: function(options) { if(options.data null) { return ko.mapping.fromJS(); } else { return ko.mapping.fromJS(options.data); } } }, selectedShipVia : { create: function(options) { if(options.data null) { return ko.mapping.fromJS({requestDate: 0001-01-01T00:00:00}); } else { return ko.mapping.fromJS(options.data); } } }, details: { create: function(options) { options.data.orderDetail.configuratorJson options.data.orderDetail.configuratorJson ? JSON.parse(options.data.orderDetail.configuratorJson) : {}; if(options.data.orderDetail.configuratorJson && options.data.orderDetail.configuratorJson.choices) { options.data.orderDetail.configuratorJson.choices options.data.orderDetail.configuratorJson.choices.sort(function(a, b) { if(a.pos b.pos) { return 0; } return a.pos b.pos ? -1 : 1; }); } if(options.data.orderDetail.configuratorJson) { options.data.orderDetail.configuratorJson.configType options.data.orderDetail.configuratorJson.configType || configurator; } options.data.orderDetail.parentProductID options.data.orderDetail.parentProductID.trim() || ; options.data.orderDetail.editing false; return ko.mapping.fromJS(options.data); } } }, self); self.details().forEach(function(detail) { var detailLine detail.orderDetail; detailLine.instanceChildren self.details().filter(function(item) { return item.orderDetail.instance() detailLine.instance() && item.orderDetail.parentProductID().trim() ! && item.orderDetail ! detailLine; }).map(function(item) { return item.orderDetail; }) || ; var mainProductArray self.details().filter(function(item) { return item.orderDetail.instance() detailLine.instance() && item.orderDetail.removeType() instance; }); var mainProduct mainProductArray.length > 0 ? mainProductArray0.orderDetail : detailLine; var mainProductQty mainProduct.qty(); detailLine.instanceUnitPrice ko.observable(self.details().reduce(function(current, item) { if(item.orderDetail.instance() detailLine.instance()) { if(item.orderDetail.parentProductID().trim() ! && item.orderDetail.removeType() ! instance) { return current + ((item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()) * item.qtyToShip()) / mainProductQty; } else { return current + (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()); } } else { return current; } },0)); detailLine.instanceExtPrice ko.observable(self.details().reduce(function(current, item) { if(item.orderDetail.instance() detailLine.instance()) { return current + (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()) * item.qtyToShip(); // return current + item.orderDetail.extTotal(); } else { return current; } },0)); }); self.availableAddresses shippingAddresses; self.shipTo ko.observable(self.shipTo); self.availableAddresses().forEach(function(address,index){ if(!self.shipTo()){ self.shipTo(address); return false; } if(address.key() self.shipTo().key()){ self.shipTo(address); } }); self.earliestShipDate ko.observable( function() { if(self.selectedShipVia && self.selectedShipVia.effectiveOrderDate) { var adjustedLeadTimeDays calculateAdjustedLeadTimeDays(self.selectedShipVia.effectiveOrderDate(), self.leadTimeDays()); return moment().add(adjustedLeadTimeDays, days).format(MM/DD/YYYY); } else { return moment(new Date(self.ExpectedShipDate)).format(MM/DD/YYYY); } }() ); self.requestedShipDate ko.observable( function() { if(self.selectedShipVia && self.selectedShipVia.requestDate()) { if(self.selectedShipVia.requestDate() > self.earliestShipDate()) { return moment(new Date(self.selectedShipVia.requestDate())).format(MM/DD/YYYY); } else { return self.earliestShipDate(); } } else { if(self.selectedShipVia && self.selectedShipVia.effectiveOrderDate) { var adjustedLeadTimeDays calculateAdjustedLeadTimeDays(self.selectedShipVia.effectiveOrderDate(), self.selectedShipVia.leadTimeDays()); return moment().add(adjustedLeadTimeDays - 1, days).format(MM/DD/YYYY); } else { return moment(new Date(self.ExpectedShipDate)).format(MM/DD/YYYY); } } }() ); if(self.selectedShipVia && self.selectedShipVia.shippingAccountId){ self.selectedShipVia.shippingAccountId ko.validatedObservable(self.selectedShipVia.shippingAccountId() || ).extend({ required: true, message: Please select a shipping account.}); self.selectedShipVia.shippingAccountId.subscribe(function(shippingAccountKey){ var postData {}; var orderShipViaDetails ; orderShipViaDetails { osvd_key : self.selectedShipVia.orderShipViaDetailKey(), sa_id : shippingAccountKey } postData { Tables: { TableName : orders_ship_via_details, TableKeyField : osvd_key, UserKeyField : osvd_key, UserKeyIsPrimaryKey : True, Data : orderShipViaDetails } }; postLogicJsonAjax(postData, true); }); }else{ self.selectedShipVia {}; self.selectedShipVia.shippingAccountId ko.observable(); self.selectedShipVia.collectShippingAccount ko.observable(false); self.selectedShipVia.name ko.observable(); self.selectedShipVia.description ko.observable(); self.selectedShipVia.total ko.observable(0); self.selectedShipVia.shipViaChoiceID ko.observable(); }; if(self.shipViaChoices && self.shipViaChoices().length > 0){ self.selectedShipViaChoice ko.observable(self.shipViaChoices().find(function(choice) { return (choice.shipViaChoiceKey() self.selectedShipVia.shipViaChoiceID() || choice.shipViaRefID() self.selectedShipVia.sv_ref_id()); }) || self.shipViaChoices()0); }else{ self.selectedShipViaChoice ko.observable(); } self.shipToValid ko.computed(function() { return ko.validatedObservable(self.shipTo()).isValid(); }); self.saveShipToAddress function(shipment) { var shipmentArray ; var details shipment.details().map(function(map, index, array) { return { orderDetailId : map.orderDetailId(), qtyToShip: map.qtyToShip() } }); var shipmentInfo { Key: shipment.key(), ShipmentId: shipment.key(), ShipTo: { key : shipment.shipTo().key(), name : shipment.shipTo().name(), company : shipment.shipTo().company(), attention : shipment.shipTo().attention(), address1 : shipment.shipTo().address1(), address2 : shipment.shipTo().address2(), address3 : shipment.shipTo().address3(), address4 : shipment.shipTo().address4(), address5 : shipment.shipTo().address5(), city : shipment.shipTo().city(), state : shipment.shipTo().state(), zipCode : shipment.shipTo().zipCode(), county : shipment.shipTo().county(), country : shipment.shipTo().country(), email : shipment.shipTo().email(), firstName : shipment.shipTo().firstName(), lastName : shipment.shipTo().lastName(), phone : shipment.shipTo().phone(), global : shipment.shipTo().global() }, Details: details }; shipmentArray.push(shipmentInfo); var postOptions { data: shipmentJson + encodeURIComponent(JSON.stringify(shipmentArray)), success: function(data) { autoAllocateItems(); self.showShippingAddressEdit(false); }, error: function() { alert(error saving shipping address); } } postInfo(postOptions, updateShipToAddress, shipment.key()); }; self.setShippingToBilling function(shipment) { var newAddress getShippingFromBilling(); shipment.shipTo(ko.mapping.fromJS(newAddress,shippingAddressMappingOptions)); shipment.saveShipToAddress(shipment); } self.showShippingAddressEdit ko.computed({ read: function() { if(!self.shipToValid()) { self.shipTo().editing(true); } return self.shipTo().editing(); }, write: function(newValue) { if(!newValue && self.shipToValid()) { self.shipTo().editing(false); } else { self.shipTo().editing(true); } } }); // self.EarliestShipDate.extend(); // self.RequestedShipDate.extend({ min: self.EarliestShipDate }); // self.RequestedShipDate.extend({ min: { params: self.EarliestShipDate, message: The earliest ship date available is {0} } }); self.detailsMap ko.observableArray(); self.valid ko.computed(function() { return self.shipToValid() && self.details().length > 0; // && self.RequestedShipDate.isValid(); }); self.itemsSelected ko.computed(function() { return self.details().length > 0; }); self.selectItemsComplete function(shipment) { var shipmentArray ; var lineMappings shipment.detailsMap().map(function(map, index, array) { return { OrderDetailId : map.detailLine.orderDetailKey(), QtyToShip: map.qtyToShip() } }); var shipmentInfo { Key: shipment.key(), ShipmentId: shipment.key(), Details: }; shipmentInfo.Details lineMappings; shipmentArray.push(shipmentInfo); var postOptions { data: shipmentJson + encodeURIComponent(JSON.stringify(shipmentArray)), error: function() { alert(error saving item list on shipment); } } postInfo(postOptions, updateShipToAddress); $(#modal_add_prodstabindex-1:hidden).remove() $(#modal_add_prods).modal(hide); }; self.selectedShipViaChoice.subscribe(function(newShipViaChoiceValue) { var shipViaChoiceKey newShipViaChoiceValue.shipViaChoiceKey(); var shipmentKey self.key(); var postOptions { url: orderInfoPostUrl + ?ajaxtrue&pageactionsetShipmentShipVia&o_key + viewModel.orderKey() + &shipViaChoiceKey + shipViaChoiceKey + &shipmentKey + shipmentKey, error: function() { alert(error setting ship via); } } postInfo(postOptions, setShipmentShipVia); }); self.comments.subscribe(function(newComment) { var shipmentCommentPostData {}; var shipmentInfo { os_key: self.key(), comments: newComment }; shipmentCommentPostData { Tables: { TableName : order_shipments, TableKeyField : os_key, UserKeyField : os_key, UserKeyIsPrimaryKey : True, Data : shipmentInfo } }; postLogicJsonAjax(shipmentCommentPostData); }); self.requestedShipDate.subscribe(function(newRequestedShipDate) { var postOptions { data: shipmentId + encodeURIComponent(self.key()) + &requestedShipDate + encodeURIComponent(moment(newRequestedShipDate).format(MM/DD/YYYY)), error: function() { alert(error setting shipment requested ship date); } } postInfo(postOptions, setRequestedShipDate); }); self.details().forEach(function(thisLine) { thisLine.hasChildProducts ko.observable(function() { return self.details().filter(function(outerLine) { return outerLine.orderDetail.instance() thisLine.orderDetail.instance() && thisLine.orderDetail.removeType() ! instance; // main product has removeType of instance }).length > 1; }()); thisLine.orderDetail.hasParentInCart ko.observable(function() { return self.details().filter(function(outerLine) { return outerLine.orderDetail.orderDetailKey() ! thisLine.orderDetail.orderDetailKey() && outerLine.orderDetail.instance() thisLine.orderDetail.instance() && outerLine.orderDetail.removeType() instance; }).length > 0; }()); }); if(ofConfig.useAccountDefaultShipVia && self.shipViaChoices && self.shipViaChoices().length > 0) { var filteredChoice self.shipViaChoices().find(function(choice) { return choice.shipViaChoiceKey() ofConfig.accountDefaultShipViaKey || choice.shipViaRefID() ofConfig.accountDefaultShipViaCode }); if(filteredChoice) { self.shipViaChoices( filteredChoice ); } } self.shipTo.subscribe(function(shipTo) { if(viewModel && viewModel.setShipTo) { viewModel.setShipTo(self, shipTo); } }) runHook(shipmentModelBottom, { self: self, shipmentData: shipmentData }); } var Customer function(customerData) { var self this; ko.mapping.fromJS(customerData, {}, self); self.firstName.extend({ required: true }); self.lastName.extend({ required: true }); self.email.extend({ email: { message: A valid email address is required., params: true }, required: { message: A valid email address is required., params: true} }); self.phone.extend({ required: true }); } /* var Account function(accountData) { var self this; ko.mapping.fromJS(accountData, { create: function(options) { return new addressInfo(options.data); } }, self); if(!self.Country()) { self.Country(USA); } self.Company.extend({ required: true }); self.Address1.extend({ required: true }); self.Country.extend({ required: true }); self.City.extend({ required: true }); if(!self.State()) { self.State(); } self.State.extend({ required: true }); self.ZipCode.extend({ required: true }); } */ var Order function(orderData) { var self this; self.activeAjaxRequestCount ko.observable(0); ko.mapping.fromJS(orderData, { detailLines : { create: function(options) { options.data.configuratorJson options.data.configuratorJson ? JSON.parse(options.data.configuratorJson) : {}; options.data.parentProductID options.data.parentProductID.trim() || ; options.data.editing false; return ko.mapping.fromJS(options.data); } }, orderActions : { create: function(options) { if(options.data) { if(!options.data.hasOwnProperty(showPaymentMethods)) { options.data.showPaymentMethods true; } } return ko.mapping.fromJS(options.data); } }, shipments : { create: function(options) { return new Shipment(options.data); } }, customer : { create: function(options) { return options.data ? new Customer(options.data) : {}; } }, account : { create: function(options) { return new addressInfo(options.data); } }, paymentMethod : { create: function(options) { if(options.data null || options.data ) { return ko.mapping.fromJS({ paymentMethodKey: , paymentType: , }); } else { options.data.paymentType (options.data.paymentType || ).toLowerCase(); return ko.mapping.fromJS(options.data); } } }, vaultedPayment : { create: function(options) { if(options.data null) { return ko.mapping.fromJS({}); } else { return ko.mapping.fromJS(options.data); } } }, roRunDate : { update: function(options) { //Quick fix to hide invalid expiration. //ToDo: update to check for other invalid dates. date new Date(options.data); var isValid date instanceof Date && !isNaN(date); if(moment(date).format(MM/DD/YYYY) 01/01/0001){ isValid false; } if(!isValid) { return moment().format(MM/DD/YYYY); } else { return moment(date).format(MM/DD/YYYY); } } }, roRecCase : { update: function(options) { if(!options.data) { return month; } else { return options.data; } } }, roRecQty : { update: function(options) { if(!options.data || options.data 0) { return 1; } else { return options.data; } } }, ignore: errorMessages }, self); self.showCredits ko.observable(false); self.allowQtyControls ko.observable(false); self.detailLines().forEach(function(detailLine) { detailLine.instanceChildren self.detailLines().filter(function(item) { return item.instance() detailLine.instance() && item ! detailLine; }) || ; var mainProduct self.detailLines().filter(function(item) { return item.instance() detailLine.instance() && item.removeType() instance; })0 || detailLine; var mainProductQty mainProduct.qty(); detailLine.instanceUnitPrice ko.observable(self.detailLines().reduce(function(current, item) { if(item.instance() detailLine.instance()) { if(item.parentProductID().trim() ! && item.removeType() ! instance) { return current + item.extTotal() / mainProductQty; } else { return current + item.price(); } } else { return current; } },0)); detailLine.instanceExtPrice ko.observable(self.detailLines().reduce(function(current, item) { if(item.instance() detailLine.instance()) { return current + item.extTotal(); } else { return current; } },0)); }); self.needToChoosePromos ko.observable(); self.paymentMethodSelected ko.observable(function() { return typeof self.paymentMethod.paymentType function; }() ); self.termsAgreement ko.observable(function() { return self.legalResponse() agreed; }() ); //self.detailLines.sort(detailLineInstanceSort); self.shipments.sort(function(left, right) { return left.position() right.position() ? 0 : (left.position() right.position() ? -1 : 1); }); self.processing ko.observable(false); self.populatingShippingAddresses ko.observable(false); self.availableShippingAddresses ko.observableArray(); self.newCouponCode ko.observable(); self.newGiftCertificate ko.observable(); if(!self.errorMessages) { self.errorMessages ko.observableArray(); }; // self.orderPlaced ko.observable(false); self.orderPlaced ko.computed(function() { return self.completed() }); self.Customer ko.validatedObservable(self.Customer); self.Account ko.validatedObservable(self.Account); self.shippingAddresses shippingAddresses; self.addressTypes function(){ var addressTypes ; addressTypes.push({ label: ofConfig.addressBookLabel, global: 0 }); if(ofConfig.useLocalPickup){ addressTypes.push({ label: ofConfig.localPickupLabel, global: 1 }) } return addressTypes; }; self.defaultShaKey function() { sShaKey sDefaultShaKey; if (sShaKey ){ sShaKey self.shippingAddresses()0.sha_key; } return sShaKey; } self.billingSectionValid ko.computed(function () { return self.Customer.isValid() && self.Account.isValid(); }); self.toggleShowBillingEdit function() { if(self.showBillingEdit()) { // && newCustomer) { var postData new CreateCustomerPost(self); self.postBillingUpdate(postData); } else { self.showBillingEdit(!self.showBillingEdit()); } }; self.postBillingUpdate function(postData) { var postUrl orderInfoPostUrl + ?o_key + viewModel.orderKey() + &originbill-ship; var dataString; var keyCount 0; $.each(postData, function(key, value) { keyCount + 1; if(keyCount > 1) { dataString + & } dataString + key + + encodeURIComponent(value); }); var postOptions { url: postUrl, type: POST, data: dataString, success: function(data) { self.showBillingEdit(!self.showBillingEdit()); }, error: function() { alert(error posting billing update); } } postInfo(postOptions, , checkout_shipping); } self.editingBilling ko.observable(false); self.showBillingEdit ko.computed({ read: function() { if(!self.billingSectionValid()) { self.editingBilling(true); } return self.editingBilling(); // && !self.billingSectionValid(); }, write: function(newValue) { if(!newValue && self.billingSectionValid()) { self.editingBilling(false); } else { self.editingBilling(true); } } }); self.moveAllItemsToShipment function(shipment) { self.processing(true); var shipmentArray ; var lineMappings self.detailLines().map(function(map, index, array) { return { OrderDetailId : map.orderDetailKey(), QtyToShip: map.qty() } }); var shipmentInfo { Key: shipment.key(), ShipmentId: shipment.key(), Details: }; self.shipments().forEach(function(otherShipment) { if(otherShipment.key() ! shipment.key()) { shipmentArray.push({ key: otherShipment.key(), ShipmentId: otherShipment.key(), Delete: true }); } }); shipmentInfo.Details lineMappings; shipmentArray.push(shipmentInfo); var postOptions { data: shipmentJson + encodeURIComponent(JSON.stringify(shipmentArray)), error: function() { alert(error moving all items to shipment); }, complete: function() { self.processing(false); } } postInfo(postOptions, updateShipToAddress); $(#modal_add_prodstabindex-1:hidden).remove() $(#modal_add_prods).modal(hide); }; self.shippingComplete ko.observable(isShippingComplete()); function isShippingComplete(){ if ( self.completed() || self.lifecycleStage() cancelled) { return true; } // force step 2 if there are no lines on the order. if (self.detailLines().length 0){ return false; } // force step 2 if any shipments are missing an address. _.each(self.shipments(),function(shipment){ if(!shipment.shipTo().key()){ return false; } }); if(utils.getCookie(self.orderKey()+-step) undefined){ if(ofConfig.defaultShippingSectionOpen){ utils.setCookie(self.orderKey() + -step, 2); }else{ utils.setCookie(self.orderKey() + -step, 3); } } if (utils.getCookie(self.orderKey() + -step) 2){ return false; }else{ return true; } }; self.shipmentsComplete ko.observable(false || self.completed()); self.shipmentsSectionsValid ko.computed(function() { var result true; self.shipments().forEach(function(shipment) { if(!shipment.valid() || (shipment.shipTo && shipment.shipTo().editing())) { result false; } }); return result; }); self.toggleShowShippingEdit function() { self.showShippingEdit(!self.showShippingEdit()); if(!self.showShippingEdit()) { scrollToSection(#checkout_summary); } }; self.moveItemToNewShipTo function(item){ self.itemShipToMap().push({ orderDetailKey: item.orderDetailKey, instance: ko.observable(item.instance()), key: ko.observable(item.orderDetailKey), qty: ko.observable(item.qtyIncrement() || 1), qtyControlledFrom: ko.observable(item.qtyControlledFrom()), minQty: ko.observable(item.minQty()), qtyIncrement: ko.observable(item.qtyIncrement()), getPrice: item.getPrice, suPrice: item.suPrice, shaKey: ko.observable(item.shaKey()), shipTo: ko.observable({}), moveItemToNewShipTo: self.moveItemToNewShipTo, removeItemToShipToMap: self.removeItemToShipToMap, availableAddresses: shippingAddresses, parentProductID: item.parentProductID }); item.qty(item.qty() - (item.qtyIncrement() || 1)); self.itemShipToMap.notifySubscribers(); }; self.currentPackage ko.observable(function(){ var item new Object(); item.shippingAddressId ko.observable(sDefaultShaKey); item.shipTo ko.observable() item.details ko.observableArray(); return item; }()); self.toggleItemInCurrentPackage function(item){ if(!_.contains(self.currentPackage().details(),item)){ self.currentPackage().details().push(item) }else{ _.pull(self.currentPackage().details(), item) } self.currentPackage.notifySubscribers(); }; self.isInCurrentPackage function(item){ return _.contains(self.currentPackage().details(),item); }; self.removeItemToShipToMap function(item){ _.pull(self.itemShipToMap(),item); self.itemShipToMap.notifySubscribers(); }; self.getTotalQty function(instance){ var totalQty 0; _.each(self.itemShipToMap(), function(map){ if(map.instance() instance && map.qtyControlledFrom() ! 1){ totalQty + parseFloat(map.qty()); //exit after the first item is found so the carrier product qty will display. //or not - added && map.qtyControlledFrom() ! 1 to account for config products // qtyControlledFrom is 1 when controlled by the parent //return false; } }); return totalQty; }; self.getOrderDetailQty function(instance){ var totalQty 0; self.itemsOnOrder().forEach(function(map){ if(map.instance() instance && map.qtyControlledFrom() ! 1){ totalQty + parseFloat(map.qty()); } }); return totalQty; }; self.setItemShipToMapPrice function(data){ self.itemShipToMap().forEach(function(map){ if(map.instance() data.instance()){ if(self.superUserRestrictMinPrice() & data.superUserMinPrice() ! null && data.price() data.superUserMinPrice()) { data.price(undefined); data.price(data.superUserMinPrice()); } map.suPrice data.price(); } }); }; self.resetSuperUserPriceOverride function(data){ var orderDetail ; orderDetail.push({ orderDetailKey: data.orderDetailKey(), PriceCalculationType: std }); var postOptions { data: orderDetail + encodeURIComponent(JSON.stringify(orderDetail)), success: function(data) { }, error: function() { alert(error saving shipping address); } } postInfo(postOptions, setOrderDetailFields); }; self.resetSuperUserShippingPrice function(data){ var postOptions { url: payment.asp?o_key + viewModel.orderKey() + &svc_key + data.shipViaChoiceKey() + &ajaxtrue&pageactionresetShippingPrice&randomnum + new Date().getTime() , success: function(data) { }, error: function() { alert(error resetting shipping price); } } postInfo(postOptions, resetSuperUserShippingPrice); } self.toggleSuperUserMode function(){ viewModel.superUserOrderFormMode(!viewModel.superUserOrderFormMode()); var postOptions { data: { superUserMode: viewModel.superUserOrderFormMode() }, success: function(data) { // }, error: function() { alert(error reloading shipping accounts); } } postInfo(postOptions, setSuperUserMode); }; self.returnToPendingOrders function() { window.location su_pending_orders_man.asp?revert1; } self.superUserOrderFormMode ko.observable(ofConfig.superUserOrderFormMode && ofConfig.isSuperUserSession); self.superUserSetShipViaPrice function(data, event){ var postOptions { url: payment.asp + ?o_key + viewModel.orderKey() + &svc_key + data.shipViaChoiceKey() + &price + event.target.value + &ajaxtrue&pageactionsetShippingPrice&randomnum + new Date().getTime(), success: function(data) { }, error: function() { alert(error resetting shipping price); } }; postInfo(postOptions, setShippingPrice); }; self.hasMultipleShipToAddresses function() { var shaKeys ; var hasMultipleAddresses false; self.shipments().forEach(function(shipment) { var shaKey shipment.shipTo().key(); if(shaKeys.indexOf(shaKey)) { shaKeys.push(shaKey); } if(shaKeys.length > 1) { hasMultipleAddresses true; return; } }); return hasMultipleAddresses; }; self.useMultiShipEditUI ko.observable(self.hasMultipleShipToAddresses()); self.allocateShipments function(moveToNextStep){ var shipmentArray ; var listOfShaKeys ; var newShipmentKey; var orderDetail ; toggleLoadingWidget(true); if(viewModel.useMultiShipEditUI()){ //Get a unique list of shipping address keys self.itemShipToMap().forEach(function(item){ if ( listOfShaKeys.indexOf( item.shipTo().key() ) -1 ){ listOfShaKeys.push(item.shipTo().key()); } }) //Loop the sha_keys to create shipments for each var items self.itemShipToMap(); var newShipmentCount 0; listOfShaKeys.forEach(function(shaKey){ //reuse existing shipment keys if they exist. if( newShipmentCount+1 self.shipments().length ){ newShipmentKey self.shipments()newShipmentCount.key(); }else{ newShipmentKey utils.createGuid(); } var shipmentInfo { Key: newShipmentKey, ShipmentId: newShipmentKey, ShippingAddressId: shaKey, Details: }; //Loop the product - ship to mapping records to create shipment details var shipments items; shipments.forEach(function(shipment){ if(shipment.shipTo().key() shaKey){ shipmentInfo.Details.push( { OrderDetailId: shipment.orderDetailKey, QtyToShip: shipment.qty() }) } }); newShipmentCount++; shipmentArray.push(shipmentInfo); }); }else{ listOfShaKeys.push(self.shipments()0.shipTo().key()); //Single Shipping - reuse the first shipment key newShipmentKey self.shipments()0.key(); var shipmentInfo { Key: newShipmentKey, ShipmentId: newShipmentKey, ShippingAddressId: self.shipments()0.shipTo().key(), Details: }; //Loop the unique products and sum the quantities before adding them back to the shipment. // EJ - I _think_ this loops and sums by instance so that previously split instances will end up // with the correct qty instead of the last item in that instance. This however breaks // when configurator products are in the cart that contain more than one distinct product // in the instance. _.sortBy(viewModel.itemShipToMap(),instance).forEach(function(map){ shipmentInfo.Details.push( { OrderDetailId: map.orderDetailKey, QtyToShip: viewModel.getOrderDetailQty(map.instance()) }); }); shipmentArray.push(shipmentInfo); } //Remove any orphaned shipments from the original data if the user is created shipments if(listOfShaKeys.length self.shipments().length && oConfig.allowUserCreatedShipments){ var count 0; _.eachRight(self.shipments(), function(oldShipment){ if( count + 1 (self.shipments().length - listOfShaKeys.length ) ){ shipmentArray.push({ Key: oldShipment.key(), Delete: true }); count++; } }); } //Order Detail Field Updates var details self.itemShipToMap() _.each(details, function(item){ var superUserPrice parseFloat(item.suPrice); var getprice parseFloat(item.getPrice()); if( isNaN(superUserPrice)){ superUserPrice getprice; } if(viewModel.superUserOrderFormMode()) { if (getprice ! superUserPrice) { //build OD object if(!_.find(orderDetail, {orderDetailKey: item.orderDetailKey}) ){ var obj { orderDetailKey: item.orderDetailKey, Price: superUserPrice, PriceDisplay: getprice, PriceCalculationType: fixed }; if(ofConfig.useTradeAdjustmentOnSession){ obj.PriceBeforeAdjustment superUserPrice; } orderDetail.push(obj); } } var detail _.find(orderDetail, {orderDetailKey: item.orderDetailKey}); if(!detail) { detail { orderDetailKey: item.orderDetailKey } orderDetail.push(detail); } // var newValues _.find(viewModel.itemsOnOrder(), {orderDetailKey: item.orderDetailKey}); var itemOnOrder viewModel.itemsOnOrder().reduce(function(returnItem, currentItem) { if(currentItem.orderDetailKey() item.orderDetailKey) { returnItem currentItem; } return returnItem; }) detail.MinQty parseFloat(itemOnOrder.minQty ? itemOnOrder.minQty() : 0); detail.MaxQty parseFloat(itemOnOrder.maxQty ? itemOnOrder.maxQty() : 0); detail.QtyIncrement parseFloat(itemOnOrder.qtyIncrement ? itemOnOrder.qtyIncrement() : 1); // TODO: Need to track original removeType value - checking has children for now var defaultRemoveType itemOnOrder.hasChildProducts() ? instance : OD_Key; detail.RemoveType itemOnOrder.removeType ? itemOnOrder.removeType() : defaultRemoveType; runHook(allocateShipmentsOrderDetailUpdate, { itemOnOrder: itemOnOrder, detailLine: detail }); } toggleLoadingWidget(false); }); var postOptions { data: shipmentJson + encodeURIComponent(JSON.stringify(shipmentArray)) + &orderDetail + encodeURIComponent(JSON.stringify(orderDetail)), success: function(){ if(ofConfig.bUsePromotions){ jQuery.ajax({ url: payment.asp + ?o_key + viewModel.orderKey() + &ajaxtrue&pageactioncheckPromos&randomnum + new Date().getTime() , cache: false , type: GET , success: function(data,status,request){ if(JSON.parse(data)){ viewModel.processing(true); //redirect to reward selection page. //This is not opening in a modal for responsive reasons. var nextPage encodeURIComponent(payment.asp?o_key + viewModel.orderKey() + (ofConfig.isModal ? &modal1 : )); document.location promo_reward_selection.asp?next_page + nextPage + &o_key + viewModel.orderKey() + (ofConfig.isModal ? &modal1 : ); } } , error: function(data) { console.log(Error checking Promos); } , complete: function(data) { } }); } }, error: function() { self.addShipment(); autoAllocateItems(); alert(error saving item list on shipment); } } postInfo(postOptions, updateShipToAddress); if(moveToNextStep undefined) { moveToNextSteptrue; } self.shippingComplete(moveToNextStep); self.shippingComplete.notifySubscribers(); if(moveToNextStep) { utils.setCookie(self.orderKey() + -step , 3); } }; self.showShippingEdit ko.observable(!self.completed()); self.currentShipment ko.observable(); self.toggleMultiShip function (data, event) { event.preventDefault(); self.useMultiShipEditUI(!self.useMultiShipEditUI()); self.shippingComplete.notifySubscribers(); }; self.toggleOrderPlaced function (data, event) { event.preventDefault(); var postData {}; if(viewModel.paymentMethod.paymentType() cc) { var defaultCcnChecked $(#ccpm_default_ccn_id_selection).is(:checked); if(defaultCcnChecked) { postData.setDefaultCcn 1 } postData.ccn_key $(#ccpm_ccn_id).val(); postData.address $(#ccpm_address_input).val(); postData.city $(#ccpm_city_input).val(); postData.country $(#ccpm_country_input).val(); postData.state $(#ccpm_state_dropdown).prop(disabled) ? $(#ccpm_state_text).val() : $(#ccpm_state_dropdown).val(); postData.zip $(#ccpm_zip_input).val(); //oSavedPaymentMethodsCreditCard.saveBillingAddress(); } var postOptions { data: postData, success: function(data){ viewModel.updateOrderAccess(); var response JSON.parse(data); if(Object.keys(response0.Errors).length 0) { //document.location payment.asp?o_key + viewModel.orderKey() + #checkout_confirmation; scrollToSection(#checkout_container); }else{ scrollToSection(#checkout_container); } }, error: function(data) { alert(error placing order); } } if ($.active > 0) { viewModel.processing(true); $( document ).one(ajaxStop, function(){ postInfo(postOptions, placeOrder); }); } else { postInfo(postOptions, placeOrder); } }; self.showItemSelector function(shipment) { shipment.detailsMap(); self.detailLines().forEach(function(detailLine, detailIndex, detailArray) { shipment.detailsMap().push(new detailMap(detailLine, shipment, self)); }); self.currentShipment(shipment); $(#modal_add_prods).modal(show); }; self.showAddressBook function(shipment) { self.currentShipment(shipment); getShippingAddresses(); //$(#modal_addressbook)0.remove(); $(#modal_addressbook).modal(show); }; self.addShipment function() { var newShipment getNewShipment(); var successFunction; if(self.shipments().length 0) { /* EJ - 2016-11-15 I feel dirty about this, but its a quick workaround for an odd issue happening on first load of the payment page for a new order, before the first shipment is added. The issue presents as a corrupt countries array (missing states for first country) and validation issues on Account form. The only difference in code on client (verified with Arraxis Merge) is the orderPayload. The first page load doesnt have shipments or paymethods (empty array and null respectively), whereas the second and all subsequent page loads do. The issue goes away once the first shipment is added, so Im forcing a reload the first time a shipment is added, which was already happening already on first page load if there were no shipments on the order. The first shipment being added needs to be moved to the ordering object eventually, which will negate the need for this code anyway, so I didnt spend more hours trying to find the root cause. */ // so spinner stays active until location.reload happens self.activeAjaxRequestCount(self.activeAjaxRequestCount() + 1); successFunction function() { location.reload(); } } else { successFunction autoAllocateItems; } var shipmentArray ; var shipmentInfo { Key: newShipment.key(), ShipmentId: newShipment.key(), Details: }; shipmentArray.push(shipmentInfo); var postOptions { data: shipmentJson + encodeURIComponent(JSON.stringify(shipmentArray)), error: function() { alert(error setting ship via); }, success: successFunction } postInfo(postOptions, updateShipToAddress, newShipment.key(), self); }; self.deleteShipment function(shipmentToDelete, e, index) { var shipmentArray ; var shipmentInfo { Key: shipmentToDelete.key(), Delete: true }; shipmentArray.push(shipmentInfo); var postOptions { data: shipmentJson + encodeURIComponent(JSON.stringify(shipmentArray)), error: function() { alert(error moving all items to shipment); }, success: autoAllocateItems } postInfo(postOptions, updateShipToAddress, checkout_shipping); }; self.setShipTo function(shipment, shipToAddress) { var sha_id shipToAddress.key(); var shipmentId shipment.key(); var postOptions { data: shipmentId + shipmentId + &sha_id + sha_id, success: function(data) { autoAllocateItems(); self.shipmentsSectionsValid.notifySubscribers(); }, error: function() { alert(error saving shipping address); } } postInfo(postOptions, setSha); $(#modal_addressbooktabindex-1:hidden).remove() $(#modal_addressbook).modal(hide); }; self.showNewAddressForm function(shipment) { shipment.shipTo(new addressInfo(getNewAddress())); $(#modal_addressbooktabindex-1:hidden).remove() $(#modal_addressbook).modal(hide); }; self.showAddAddress function(shipment){ $(#modal_add_shipto).modal(show); }; self.shipments().forEach(function(shipment) { self.detailLines().forEach(function(detailLine, detailIndex, detailArray) { shipment.detailsMap().push(new detailMap(detailLine, shipment, self)); }); }); self.updatePoRequired function() { if(self.paymentMethod && self.paymentMethod.paymentMethodKey() ! ){ var isReallyRequired self.paymentMethod.poRequired() && self.paymentMethod.collectPO(); self.paymentMethod.poRequired(isReallyRequired); } } self.updatePoRequired(); self.poNumber.extend({ required: { onlyIf: function() { return viewModel && viewModel.paymentMethod.poRequired() } } }); self.poNumber.subscribe(function(poNumber) { postOrderHeaderField(ponumber, viewModel.poNumber()); }); self.comments.subscribe(function(newComments) { postOrderHeaderField(comment, viewModel.comments()); }); self.nickname.subscribe(function(nickname) { self.buildOrderHeaderFields(Nickname); }); self.isValidDate function(date){ //Quick fix to hide invalid expiration. //ToDo: update to check for other invalid dates. // Parse the date parts to integers var parts date.split(-); var day parseInt(parts2, 10); var month parseInt(parts1, 10); var year parseInt(parts0, 10); // Check the ranges of month and year if(year 1000 || year > 3000 || month 0 || month > 12) return false; var monthLength 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ; // Adjust for leap years if(year % 400 0 || (year % 100 ! 0 && year % 4 0)) monthLength1 29; // Check the range of the day return day > 0 && day monthLengthmonth - 1; }; self.getMinimumRecurringOrderDate function(){ var today moment(); var minimumDate moment(today).add(1, days); return moment(minimumDate).format(MM/DD/YYYY); } self.roRunDate.subscribe(function(roRunDate) { postOrderHeaderField(ro_rundate, viewModel.roRunDate()); }); self.roRecCase.subscribe(function(roRecCase) { postOrderHeaderField(ro_rec_case, viewModel.roRecCase()); }); self.roRecQty.subscribe(function(roRecQty) { postOrderHeaderField(ro_rec_qty, viewModel.roRecQty()); }); self.updateRecurringType function(data, event){ newValue event.target.value; sOrderDetailKey data.orderDetailKey(); switch(newValue){ case fixed: postOrderDetailFields(sOrderDetailKey, ro_recurring_type,ro_skip_next_runs, fixed,0); break; case recurring: postOrderDetailFields(sOrderDetailKey, ro_recurring_type,ro_skip_next_runs, recurring,0); break; case skipnext: postOrderDetailFields(sOrderDetailKey, ro_recurring_type,ro_skip_next_runs, recurring,1); break; case remove: viewModel.removeProduct(data); break; } }; self.getRecurringLabel function(data){ var sMessage ; var sAction data.orderDetail.roRecurringType(); var sSkipRuns data.orderDetail.roSkipNextRuns(); switch(sAction){ case recurring: case : if(sSkipRuns 0){ //recurring sMessage ofConfig.roRecurringItemLabel; }else{ //skip. sMessage ofConfig.roSkippedItemLabel; } break; case fixed: sMessage ofConfig.roOnetimeItemLabel; break; case disabled: sMessage ofConfig.roDisabledItemLabel; break; } return sMessage; }; self.customerComment ko.observable(); self.noteBook ko.observable(); self.populateNoteBook function(){ var noteBook {}; var count 0; noteBook.notes ko.observableArray(); if(noteBookPayload.length > 0 ){ noteBook.nbKey noteBookPayload0.nb_key; noteBook.id noteBookPayload0.id; noteBook.refId noteBookPayload0.ref_id; _.each(noteBookPayload,function(note){ if(note.internal_notes || note.external_notes) { count++; item {}; item.internalNotes note.internal_notes; item.externalNotes note.external_notes; item.postedByName note.c_f_nm + + note.c_l_nm; item.postedByUsername note.username; item.createDate note.create_date; noteBook.notes.push(ko.observable(item)); } }); } self.noteBook(noteBook); }(); self.buildOrderHeaderFields function(aFields) { //Available order header fields that can be POSTed using this function var orderHeaderFields { UseMultipleShipments: viewModel.useMultipleShipments(), Nickname : viewModel.nickname(), QuoteExpirationDate: viewModel.expirationDate() }; var orderHeaderFieldsJson {}; //Add only the field(s) that are passed in aFields. _.forEach(aFields, function(sField) { orderHeaderFieldsJsonsField orderHeaderFieldssField; }); self.setOrderHeaderFields(orderHeaderFieldsJson); }; self.setOrderHeaderFields function(orderHeaderFieldsJson) { var postOptions { data: orderHeaderFields + encodeURIComponent(JSON.stringify(orderHeaderFieldsJson)), error: function(data) { alert(error setting Order Header fields); } }; postInfo(postOptions, setOrderHeaderFields); }; if(self.shipments().length 0) { //self.addShipment(); } self.setPaymentMethod function(paymentMethod) { if(paymentMethod.paymentType() ! viewModel.paymentMethod.paymentType()){ var postOptions { data: pm_id + paymentMethod.paymentMethodKey(), error: function(data) { alert(error setting pm); }, success: function() { $(#ccpm_container).removeClass(hide); viewModel.updatePoRequired(); } } postInfo(postOptions, setPmId); } } self.ccn_id.subscribe(function(newCCN) { if(newCCN ! ) { var payload ccn_id + newCCN; var postOptions { data: payload, error: function(data) { alert(error setting CCN); } } postInfo(postOptions, setCCN); } }); self.SetCouponCode function(couponCode) { var payload couponcode + encodeURIComponent(couponCode); var postOptions { data: payload, error: function(data) { alert(error applying coupon); } } postInfo(postOptions, setCoupon); } self.SetGiftCertificate function(giftCertCode) { var payload giftCertCode + encodeURIComponent(giftCertCode); var postOptions { data: payload, error: function(data) { alert(error applying gift certificate); } } postInfo(postOptions, setGiftCertCode); }; self.allItemsAllocated ko.computed(function() { var totalItemCount self.detailLines().reduce(function(previous, current) { return previous + current.qty(); }, 0); var allocatedItemCount 0; self.shipments().forEach(function(shipment) { allocatedItemCount + shipment.details().reduce(function(previous, current) { return previous + current.qtyToShip(); }, 0); }); return totalItemCount allocatedItemCount; }); self.itemsOnOrder ko.computed(function() { var items ; self.detailLines().forEach(function(detailLine) { detailLine.hasChildProducts ko.observable(function() { return self.detailLines().filter(function(outerLine) { return outerLine.instance() detailLine.instance() && detailLine.removeType() ! instance }).length > 1 }()); detailLine.hasParentInCart ko.observable(function() { return self.detailLines().filter(function(outerLine) { return outerLine.orderDetailKey() ! detailLine.orderDetailKey() && outerLine.instance() detailLine.instance() && detailLine.removeType() instance }).length > 0 }()); detailLine.instanceChildren self.detailLines().filter(function(item) { return item.instance() detailLine.instance() && item.removeType() ! instance && item.parentProductID().trim() ! && item ! detailLine; }) || ; var mainProduct self.detailLines().filter(function(item) { return item.instance() detailLine.instance() && item.removeType() instance; })0 || detailLine; var mainProductQty mainProduct.qty(); detailLine.superUserMinPrice ko.observable(detailLine.commodityofConfig.superUserMinPriceProperty() || 0); detailLine.instanceUnitPrice ko.observable(self.detailLines().reduce(function(current, item) { if(item.instance() detailLine.instance()) { if(item.parentProductID().trim() ! && item.removeType() ! instance) { return current + item.extTotal() / mainProductQty; } else { return current + item.price(); } } else { return current; } },0)); detailLine.instanceExtPrice ko.observable(self.detailLines().reduce(function(current, item) { if(item.instance() detailLine.instance()) { return current + item.extTotal(); } else { return current; } },0)); detailLine.allocatedQty ko.observable(function() { var runningTotal 0; self.shipments().forEach(function(shipment) { shipment.details().forEach(function(shipDetail) { if(shipDetail.orderDetailId() detailLine.orderDetailKey()) { runningTotal + shipDetail.qtyToShip(); } }); }); return runningTotal; }()); detailLine.minGrossMarginPercent ko.computed(function() { if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() ! null) { return ( (detailLine.superUserMinPrice() - detailLine.commodity.cost()) / detailLine.superUserMinPrice() * 100 ).toFixed(); } else { return undefined; } }); detailLine.grossMarginPercent ko.computed({ write: function(newVal) { var minGrossMarginPercent parseInt(detailLine.minGrossMarginPercent() || 0); var val parseInt(newVal); if(val minGrossMarginPercent()) { val minGrossMarginPercent(); } var marginPercent val / 100; var markup marginPercent / (1 - marginPercent); var newPrice (detailLine.commodity.cost() * (1 + markup)).toFixed(2); detailLine.price(undefined); detailLine.price(newPrice); detailLine.priceCalculationType(fixed); }, read: function() { var marginPercent (detailLine.price() - detailLine.commodity.cost()) / detailLine.price(); return (marginPercent * 100).toFixed(0); }, deferEvaluation: true }); detailLine.minMarkupPercent ko.computed(function() { if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() ! null) { return ( detailLine.superUserMinPrice() / detailLine.commodity.cost() - 1 ).toFixed(); } else { return undefined; } }); detailLine.markupPercent ko.computed({ write: function(newVal) { var minMarkupPercent parseInt(detailLine.minMarkupPercent || 0); var val parseInt(newVal); if(val minMarkupPercent) { val minMarkupPercent; } var markup val / 100; var newPrice (detailLine.commodity.cost() * (1 + markup)).toFixed(2); detailLine.price(undefined); detailLine.price(newPrice); detailLine.priceCalculationType(fixed); }, read: function() { var markup (detailLine.price() - detailLine.commodity.cost()) / detailLine.commodity.cost(); return (markup * 100).toFixed(0); }, deferEvaluation: true }); detailLine.maxDiscountPercent ko.computed(function() { if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() ! null) { return (100 * (1 - (detailLine.superUserMinPrice() / detailLine.commodity.retailPrice()))).toFixed(); } else { return undefined; } }); detailLine.discountPercent ko.computed({ write: function(newVal) { var maxDiscountPercent parseInt(detailLine.maxDiscountPercent() || 100); var val parseInt(newVal); if(val > maxDiscountPercent) { val maxDiscountPercent; } var discount val / 100; var newPrice (detailLine.commodity.retailPrice() * (1 - discount)).toFixed(2); detailLine.price(undefined); detailLine.price(newPrice); detailLine.priceCalculationType(fixed); }, read: function() { var discount 1 - detailLine.price() / detailLine.commodity.retailPrice(); return (discount * 100).toFixed(0); }, deferEvaluation: true }); detailLine.minGrossMarginAmount ko.computed(function() { if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() ! null) { return detailLine.superUserMinPrice() - detailLine.commodity.cost(); } else { return undefined; } }); detailLine.grossMarginAmount ko.computed({ write: function(newVal) { var minGrossMarginAmount parseInt(detailLine.minGrossMarginAmount() || 0); var val parseInt(newVal); if(val minGrossMarginAmount()) { val minGrossMarginAmount(); } var grossMargin parseFloat(val); var newPrice (detailLine.commodity.cost() + grossMargin).toFixed(2); detailLine.price(undefined); detailLine.price(newPrice); detailLine.priceCalculationType(fixed); }, read: function() { return (detailLine.price() - detailLine.commodity.cost()).toFixed(2); }, deferEvaluation: true }); detailLine.allowDeletes ko.computed({ write: function(val) { // TODO: need to store previous value for removeType (od_key, hide, instance) - checking child prods for now if(val) { detailLine.hasChildProducts() ? detailLine.removeType(instance) : detailLine.removeType(OD_Key); } else { detailLine.removeType(hide); } }, read: function() { return !(detailLine.removeType() hide) } }); detailLine.suMinQty ko.computed({ write: function(val) { val parseFloat(val); if(isNaN(val)) { val detailLine.minQty(); } if(!detailLine.maxQty() 0 && val > detailLine.maxQty()) { detailLine.minQty(detailLine.maxQty()); } else { detailLine.minQty(val); } detailLine.suMaxQty(detailLine.maxQty()); detailLine.suMinQty.notifySubscribers(); }, read: function() { return detailLine.minQty(); } }); detailLine.suMaxQty ko.computed({ write: function(val) { var originalValue detailLine.maxQty(); var newValue parseFloat(val);; if(isNaN(newValue)) { newValue originalValue; } if(newValue > 0) { if(detailLine.minQty() > 0 && newValue detailLine.minQty()) { newValue detailLine.minQty(); } else { var diff (newValue-detailLine.minQty()) % detailLine.qtyIncrement(); newValue newValue - diff; newValue detailLine.minQty() > 0 && newValue detailLine.minQty() ? detailLine.minQty() : newValue; } } else { newValue 0; } // reset maxQty to workaround KO bug that causes // underlying value to be changed, but the UI to // not update if the end value is the same as the // original value detailLine.maxQty(99); detailLine.maxQty(0); // set valid newValue detailLine.maxQty(newValue); }, read: function() { return detailLine.maxQty(); } }); detailLine.suQtyIncrement ko.computed({ write: function(val) { val parseFloat(val); if(isNaN(val)) { val detailLine.qtyIncrement(); } detailLine.qtyIncrement(val); detailLine.suMaxQty(detailLine.maxQty()); detailLine.suQtyIncrement.notifySubscribers(); }, read: function() { return detailLine.qtyIncrement(); } }); detailLine.selectedRoAction ko.computed(function(){ var sAction detailLine.roRecurringType(); var skipNextRuns detailLine.roSkipNextRuns(); if( sAction || sAction recurring){ if( skipNextRuns 0){ sAction recurring; }else{ sAction skipnext; } } return sAction; }); items.push(detailLine); }); runHook(ItemsOnOrderArrayBeforeReturn, { detailLines: items }); return items; }); self.itemShipToMap ko.computed(function(){ var items ; self.shipments().forEach(function(shipment) { oShipTo shipment.shipTo(); shipment.details().forEach(function(shipDetail) { var item new Object(); item.shaKey ko.observable(oShipTo.key()); item.key ko.observable(shipDetail.orderDetailId()); item.orderDetailKey shipDetail.orderDetailId(); item.instance ko.observable(shipDetail.orderDetail.instance()); item.qty ko.observable(shipDetail.qtyToShip()); item.qtyControlledFrom ko.observable(shipDetail.orderDetail.qtyControlledFrom()); item.qtyIncrement ko.observable(shipDetail.orderDetail.qtyIncrement()); item.getPrice shipDetail.orderDetail.price, item.suPrice shipDetail.orderDetail.price, item.minQty ko.observable(shipDetail.orderDetail.minQty()); item.moveItemToNewShipTo self.moveItemToNewShipTo; item.removeItemToShipToMap self.removeItemToShipToMap; item.availableAddresses shippingAddresses; item.shipTo ko.observable({}); item.parentProductID shipDetail.orderDetail.parentProductID(); item.availableAddresses().forEach(function(address,index){ if( address.key() oShipTo.key()){ item.shipTo(address); } }); if(shipDetail.orderDetail.instanceChildren.length > 0){ item.shipTo.subscribe(function(newValue) { items.forEach(function(map) { if(map.instance() item.instance() && map.shipTo().key() ! item.shipTo().key()) { map.shipTo(item.shipTo()); } }) }); } items.push(item); }) }); return items; }); self.selectedOrderActionRefId ko.observable( function(){ if(self.orderActions().length > 0 ){ return self.orderActions()0.refID(); }else{ return ; } }() ); self.selectedOrderAction ko.computed( function(){ var action _.find(self.orderActions(), function(action){ if( action.refID() self.selectedOrderActionRefId() ){ return action; } }); if(action && action.refID()){ return action; }else if(self.orderActions().length > 0 ){ return self.orderActions()0; }else{ return { showPaymentMethods: ko.observable(true), showRecurringOrderSettings: ko.observable(false) }; } } ); self.selectedLifecycleStage ko.computed(function(){ var stage _.find(self.lifecycleStages(), function(stage){ if( stage.refID() self.lifecycleStage() ){ return stage; } }); if(stage){ return stage; }else{ return { alwaysShowMessage: ko.observable(false), confirmationMessage: ko.observable() }; } }); if(self.lifecycleStage() cancelled){ self.completed(true); } self.showConfirmationMessage ko.observable(function(){ return (self.completed() || self.lifecycleStage() pending || self.lifecycleStage() cancelled || self.selectedLifecycleStage().alwaysShowMessage()); }()) self.allowAccountEdits ko.observable(self.allowAccountEdits() && ofConfig.AllowAccountEdits); self.allowShaEdits ko.observable(self.allowShaEdits() && ofConfig.AllowShippingEdits); self.allowWarehouseSelection ko.observable(ofConfig.allowWarehouseSelection ); self.superUserRestrictMinPrice ko.observable(ofConfig.superUserRestrictMinPrice); self.postOrderToGoogleAnalytics function() { if (self.completed() && self.tracked() ! 1 ) { if(ofConfig.t_gtm) { try { var productsOrdered ; var transactionProducts ; for(var i 0; i self.detailLines().length; i++) { var line self.detailLines()i; productsOrdered.push({ orderNumber: self.orderNumber(), name: self.customer.firstName() + + self.customer.lastName(), sku: line.sku(), category: line.searchfield1(), brand: line.searchfield5(), unitPrice: line.price(), quantityOrdered: line.qty() }); // id is used for Enhanced Ecommerce // sku is used for Google Analytics (non-EE) transactionProducts.push({ id: line.sku(), sku: line.sku(), name: line.name(), category: line.searchfield1(), price: line.price(), quantity: line.qty() }); } dataLayer.push({ pageType : confirmation }); dataLayer.push({ orderNumber : self.orderNumber() }); dataLayer.push({ storeName : ofConfig.t_tracking_company }); dataLayer.push({ productTotal : self.productTotal() }); dataLayer.push({ shippingTotal : self.shippingTotal() }); dataLayer.push({ taxTotal : self.taxTotal() }); dataLayer.push({ orderTotal : self.orderTotal() }); dataLayer.push({ customerName : self.customer.firstName() + + self.customer.lastName() }); dataLayer.push({ customerFirstname : self.customer.firstName() }); dataLayer.push({ customerLastName : self.customer.lastName() }); dataLayer.push({ customerCity : self.account.city() }); dataLayer.push({ customerState : self.account.state() }); dataLayer.push({ customerCountry : self.account.country() }); dataLayer.push({ customerEmail : self.customer.email() }); dataLayer.push({ couponCode : self.couponCode() }); dataLayer.push({ couponAmount : self.couponDiscountTotals.totalDiscount() }); dataLayer.push({ paymentMethod : self.paymentMethod.name() }); dataLayer.push({ sessionIP : ofConfig.SessionIP }); // For Google Analytics (non-EE) dataLayer.push({ transactionId: self.orderNumber(), transactionAffiliation: ofConfig.t_tracking_company, transactionTotal: self.orderTotal(), transactionTax: self.taxTotal(), transactionShipping: self.shippingTotal(), transactionProducts: transactionProducts }); // For Enhanced Ecommerce dataLayer.push({ event: ofConfig.t_gtm_transaction_event_name, ecommerce: { purchase: { actionField: { id: self.orderNumber(), affiliation: ofConfig.t_tracking_company, revenue: self.orderTotal(), tax: self.taxTotal(), shipping: self.shippingTotal(), coupon: self.couponCode() }, products: transactionProducts } } }); dataLayer.push({ productsOrdered : productsOrdered }); } catch(err) {} } switch(ofConfig.t_analytics) { case ga: // do old analytics try { // add transaction details var _gaq _gaq || ; _gaq.push(_addTrans, self.orderNumber(), // Order ID self.customer.firstName() + + self.customer.lastName(), // Customer self.orderTotal(), // Total self.taxTotal(), // Tax self.shippingTotal(), // Shipping self.account.city(), // City self.account.state(), // State self.account.country() // Country ); for(var i 0; i self.detailLines().length; i++) { var line self.detailLines()i; // add order item details _gaq.push(_addItem, self.orderNumber, // Order ID line.sku(), // SKU line.name(), // Product Name line.searchfield1(), // Category line.price(), // Price line.qty() // Quantity ); } _gaq.push(_trackTrans); } catch(err) {} break; case ua: // do new universal analytics try { // add transaction details (Universal) ga(require, ecommerce); // Load the ecommerce plug-in. ga(ecommerce:addTransaction, { id:self.orderNumber(), // Transaction ID. Required affiliation: ofConfig.t_tracking_company, // Affiliation or store name revenue:self.orderTotal(), // Grand Total shipping:self.shippingTotal(), // Shipping tax:self.taxTotal() // Tax }); for(var i 0; i self.detailLines().length; i++) { var line self.detailLines()i; // add order item details (Universal) ga(ecommerce:addItem, { id: self.orderNumber(), // Transaction ID. Required. name: line.name(), // Product name. Required. sku: line.sku(), // SKU/code. category: line.searchfield1(), // Category or variation. price: line.price(), // Unit price. quantity: line.qty() // Quantity. }); } ga(ecommerce:send); } catch(err) {} break; case uae: // do new universal analytics with enhanced ecommerce try { for(var i 0; i self.detailLines().length; i++) { var line self.detailLines()i; ga(ec:addProduct, { // Provide product details in an productFieldObject. id: line.sku(), // Product ID (string). name: line.name(), // Product name (string). category: line.searchfield1(), // Product category (string). brand: line.searchfield5(), // Product brand (string). variant: , // Product variant (string). price: line.price(), // Product price (currency). coupon: self.couponCode(), // Product coupon (string). quantity: line.qty() // Product quantity (number). }); } ga(ec:setAction, purchase, { // Transaction details are provided in an actionFieldObject. id: self.orderNumber(), // (Required) Transaction id (string). affiliation: ofConfig.t_tracking_company, // Affiliation (string). revenue: self.orderTotal(), // Revenue (currency). tax: self.taxTotal(), // Tax (currency). shipping: self.shippingTotal(), // Shipping (currency). coupon: self.couponCode() // Transaction coupon (string). }); ga(send, pageview); } catch(err) {} break; default: break; } } } /* Runs when order is completed but payment page doesnt re-fresh - Example user pays with a credit card or bill me payment option */ self.orderPlaced.subscribe(function() { self.postOrderToGoogleAnalytics(); postOrderHeaderField(tracked, 1); self.tracked(1); }); /* Runs when order is completed and the payment page re-freshes - Happens when user checks out with paypal and is re-directed back to payment page - with a completed order */ if (self.completed() && self.tracked() ! 1 ) { self.postOrderToGoogleAnalytics(); postOrderHeaderField(tracked, 1); self.tracked(1); } self.updateOrderAccess function(){ if( self.completed() || self.lifecycleStage() cancelled){ self.allowAccountEdits( false ); self.allowContactEdits( false ); self.allowShaEdits( false ); self.allowWarehouseSelection( false ); self.allowProductAdds( false ); self.allowShipViaEdits( false ); self.allowPayMethodEdits( false ); self.allowCcnChanges( false ); self.allowPlaceOrder( false ); self.allowQtyControls( false ); }else if(self.superUserOrderFormMode()){ self.allowAccountEdits(self.allowAccountEdits() || ofConfig.superUserAllowAccountEdits); self.allowContactEdits(self.allowContactEdits() || ofConfig.superUserAllowContactEdits); self.allowShaEdits(self.allowShaEdits() || ofConfig.superUserAllowShaEdits); self.allowWarehouseSelection(ofConfig.allowWarehouseSelection || ofConfig.superUserAllowWarehouseSelection ); self.allowProductAdds(ofConfig.bAllowProductAdds || ofConfig.superUserAllowProductAdds); self.allowShipViaEdits(self.allowShipViaEdits() || ofConfig.superUserAllowShipViaEdits); self.allowPayMethodEdits(self.allowPayMethodEdits() || ofConfig.superUserAllowPayMethodEdits); self.allowCcnChanges(self.allowCcnChanges() || ofConfig.superUserAllowCcnChanges); self.allowPlaceOrder(self.allowPlaceOrder() || ofConfig.superUserAllowPlaceOrder); self.allowQtyControls( ofConfig.superUserAllowQtyControls ); }else{ self.allowAccountEdits( self.allowAccountEdits() && ofConfig.AllowAccountEdits ); self.allowContactEdits( self.allowContactEdits() && ofConfig.allowContactEdits ); self.allowShaEdits( self.allowShaEdits() && ofConfig.AllowShippingEdits ); self.allowWarehouseSelection( ofConfig.allowWarehouseSelection ); self.allowProductAdds( self.allowProductAdds() && ofConfig.bAllowProductAdds ); self.allowQtyControls( false ); } }; self.updateOrderAccess(); self.processOrderAction function(data){ var bContinueProcessing true; //TODO: Get this validation working using the validation plugin. //This is a quick fix to prevent the page from processing the order action //when the shipping account is required but not set. _.each(viewModel.shipments(), function(shipment, index){ if(ofConfig.CollectShipAccount && shipment.selectedShipVia.collectShippingAccount() && !shipment.selectedShipVia.shippingAccountId.isValid() ){ //form is not valid scrollToSection(#shipping-account-info + (index+1)); //jQuery(#shipping-account-select + shipmentCount).addClass(control-group error); bContinueProcessing false; return false; } }); if(viewModel.selectedOrderAction ! undefined && viewModel.selectedOrderAction().showPaymentMethods()) { //TODO: Do CC validation in a less janky way //This is a quick fix to prevent the page from processing the order action //when the CC billing address info is invalid //Currently doesnt provide any messaging if(viewModel.paymentMethod.paymentType() cc && data.placeOrderActionType() place) { if( ($(#ccpm_cvv2_code).is(:visible) && !$(#ccpm_cvv2_code).val()) || !$(#ccpm_address_input).val() || !$(#ccpm_city_input).val() || !$(#ccpm_country_input).val() || !($(#ccpm_state_dropdown).prop(disabled) ? $(#ccpm_state_text).val() : $(#ccpm_state_dropdown).val()) || !$(#ccpm_zip_input).val() ) { // CC billing address form is not valid $(#ccpm_card_billing_address_section).addClass(in).css({ height : auto }); $(#ccpm_card_billing_address_section :input:visible:not(button)) .filter(function() { return $(this).val() ; }) .trigger(change); $(#ccpm_cvv2_code).trigger(change); scrollToSection(#payment_methods); bContinueProcessing false; return false; } } //Pretty much just following the same pattern as cc validation. //Need to stop the page from processing if the poNum is required and not entered. if(viewModel.paymentMethod.collectPO() && viewModel.paymentMethod.poRequired() && !$(#ponumber).val()) { jQuery(#controlgroup_invoice_ponumber).addClass(control-group error); scrollToSection(#payment_methods); bContinueProcessing false; return false; } } if(!bContinueProcessing){ }else{ if( data.showComments() && viewModel.customerComment() ! ){ self.saveCustomerComment(); } if(data.showRecurringOrderSettings()){ self.saveRecurringOrderSettings(); } var postData {}; var bPost true; postData.orderActionKey data.orderActionKey(); if(viewModel.paymentMethod.paymentType() cc && (viewModel.selectedOrderAction ! undefined && viewModel.selectedOrderAction().showPaymentMethods())) { var defaultCcnChecked $(#ccpm_default_ccn_id_selection).is(:checked); if(defaultCcnChecked) { postData.setDefaultCcn 1 } postData.ccn_key $(#ccpm_ccn_id).val(); postData.cvv $(#ccpm_cvv2_code).val(); postData.address $(#ccpm_address_input).val(); postData.city $(#ccpm_city_input).val(); postData.country $(#ccpm_country_input).val(); postData.state $(#ccpm_state_dropdown).prop(disabled) ? $(#ccpm_state_text).val() : $(#ccpm_state_dropdown).val(); postData.zip $(#ccpm_zip_input).val(); postData.tsm_id viewModel.paymentMethod.merchantId(); }else if(viewModel.paymentMethod.paymentType() paypal && data.placeOrderActionType() place){ bPost false; postPayPal(data.orderActionKey()); } var postOptions { data: postData, error: function() { alert(Error Processing Order Action); } } var scrollToId checkout_container; runHook(cartTemplateOverridePostOptions, { postOptions: postOptions, data: data, self: self }); if (bPost){ if ($.active > 0) { viewModel.processing(true); $( document ).one(ajaxStop, function(){ postInfo(postOptions, processOrderAction, scrollToId); }); } else { postInfo(postOptions, processOrderAction, scrollToId); } } } }; self.saveRecurringOrderSettings function(){ var postData ; var order ; var orderKey viewModel.orderKey(); var roRunDate viewModel.roRunDate(); var roRecCase viewModel.roRecCase(); var roRecQty viewModel.roRecQty(); //This has to be set before processOrderAction or the OO will unset the values above when the record_type isnt set to recurring. var recordType recurring; order.push({ o_key : orderKey, ro_rundate: roRunDate, ro_rec_case: roRecCase, ro_rec_qty: roRecQty, record_type: recordType }); postData { Tables: { TableName : orders, TableKeyField : o_key, UserKeyField : o_key, UserKeyIsPrimaryKey : True, Data : order } } jQuery.ajax({ url: payment.asp + ?o_key + viewModel.orderKey() + &ajaxtrue&pageactionpostLogicJSON&randomnum + new Date().getTime() , data: postLogicJSON + encodeURIComponent(JSON.stringify(postData)) , cache: false , type: POST , dataType: json , success: function(data,status,request){ viewModel.roRunDate(roRunDate); viewModel.roRecCase(roRecCase); viewModel.roRecQty(roRecQty); } , error: function(data) { alert(Error posting Recurring Order Settings); } , complete: function(data) { } }); }; self.saveCustomerComment function(){ var postData ; var noteBook ; var note ; var order ; var notebookTableName ofConfig.useNewNotebooks ? Notebooks : note_books; var notebookKeyField ofConfig.useNewNotebooks ? Id : nb_key; var notebookRefField ofConfig.useNewNotebooks ? ReferenceId : ref_id; var ref_id self.noteBook().refId || generateRefId(); var n_key utils.createGuid(); if(ofConfig.useNewNotebooks) { var notebookId parseInt(self.noteBook().id || 0) || ref_id; noteBook.push({ Id: notebookId, ReferenceId: notebookId }); order.push({ o_key : self.orderKey(), NotebookId: notebookId }); note.push({ n_key : n_key, ref_id : generateRefId(), NotebookId : notebookId, a_id : ofConfig.superUserAccountKey || ofConfig.AccountKey, c_id : ofConfig.superUserCustomerKey || ofConfig.CustomerKey, create_date : new Date().toDateString(), external_notes : self.customerComment() }); } else { var nb_key self.noteBook().nbKey || utils.createGuid(); order.push({ o_key : self.orderKey(), nb_id : nb_key }); noteBook.push({ nb_key : nb_key, ref_id : ref_id, create_date : new Date().toDateString(), book_type : order, resource_c_id : ofConfig.superUserCustomerKey || ofConfig.CustomerKey }); note.push({ n_key : n_key, ref_id : generateRefId(), nb_id : nb_key, a_id : ofConfig.superUserAccountKey || ofConfig.AccountKey, c_id : ofConfig.superUserCustomerKey || ofConfig.CustomerKey, create_date : new Date().toDateString(), external_notes : self.customerComment() }); } postData { Tables: { TableName : notebookTableName, TableKeyField : notebookKeyField, UserKeyField : notebookRefField, UserKeyIsPrimaryKey : False, Data : noteBook }, { TableName : orders, TableKeyField : o_key, UserKeyField : o_key, UserKeyIsPrimaryKey : True, Data : order }, { TableName : notes, TableKeyField : n_key, UserKeyField : ref_id, UserKeyIsPrimaryKey : False, Data : note } } jQuery.ajax({ url: payment.asp + ?o_key + viewModel.orderKey() + &ajaxtrue&pageactionpostLogicJSON&randomnum + new Date().getTime() , data: postLogicJSON + encodeURIComponent(JSON.stringify(postData)) , cache: false , type: POST , dataType: json , success: function(data,status,request){ viewModel.updateNoteBook(note0); viewModel.customerComment(); return data.PostedKeysnotebookTableName0; } , error: function(data) { alert(Error posting Comment); } , complete: function(data) { } }); }; self.updateNoteBook function(note) { var item {}; item.internalNotes note.internal_notes; item.externalNotes note.external_notes; item.postedByName ofConfig.superUserName || ofConfig.customerName; item.postedByUsername ofConfig.superUserUsername || ofConfig.customerUsername; item.createDate note.create_date; viewModel.noteBook().notes.unshift(item); }; self.genericModalComplete function(data){ var postOptions { success: function(data) { }, error: function() { alert(error reloading shipping accounts); } } postInfo(postOptions, getOrderJSON); }; self.removeProduct function(data){ if(ofConfig.bUseRemoveMsg){ var bRemove confirm(ofConfig.sRemoveProductMessage); } else{ bRemove true; } if (bRemove) { viewModel.processing(true); var itemToDelete data; var removeType itemToDelete.removeType(); var orderDetailKey itemToDelete.orderDetailKey(); var instance itemToDelete.instance(); var sRemoveUrl i_i_add_to_cart.asp?typeremove&unq + orderDetailKey + &o_id + data.orderID(); jQuery.ajax({ url: sRemoveUrl , cache: false , type: GET , success: function(data,status,request){ var newArray _.remove(viewModel.detailLines(), function(line){ return !(line.instance() instance); }); viewModel.detailLines(newArray); viewModel.processing(false); } , error: function(data) { alert(Error removing item.); viewModel.processing(false); } , complete: function(data) { viewModel.processing(false); } }); } }; self.resetProductEdits function(editingDetailLine) { viewModel.detailLines() .forEach(function(detailLine) { detailLine.editing(false); }); viewModel.shipments() .forEach(function(shipment) { shipment.details() .forEach(function(detail) { detail.orderDetail.editing(false); }); }); viewModel.mainProduct(undefined); utils.removeActiveQuote(); if(editingDetailLine) { editingDetailLine.editing(true); } } self.editProduct function(data) { self.resetProductEdits(); var detailLine data; if(data.orderDetail) { detailLine data.orderDetail; } var detailKey detailLine.orderDetailKey(); var productKey detailLine.parentProductID().trim() || detailLine.productID(); var productInfo { productKey: detailLine.productID(), productSku: detailLine.sku(), parentChildType: detailLine.commodity.parentChildType() || , parentProductId: detailLine.parentProductID().trim() } self.loadProductForEdit(productInfo, detailKey, detailLine) } self.cancelEditProduct function(data) { self.resetProductEdits(); } self.loadProductForEdit function(productInfo, detailLineId, detailLine) { viewModel.processing(true); self.resetProductEdits(detailLine); var postOptions { success: function(data) { var response JSON.parse(data); var product response.product; switch(product.childDisplayType) { case input-qty: case exploded-view: case matrix-all: case add-row: product.childDisplayType droplist break; default: }; if(!!response.childSkuMatch) { oConfig.childSkuMatch response.childSkuMatch; } utils.setActiveQuote(viewModel.orderKey()); viewModel.mainProduct(ko.mapping.fromJS(product, productMapping)); viewModel.productFinderSearchTerm(); }, url: orderInfoPostUrl + ?o_key + self.orderKey() + &p_key + (productInfo.parentProductId || productInfo.productKey) + &od_key + detailLineId + &sku + productInfo.productSku + &ajaxtrue&pageactiongetProductData&modal1, type: GET, error: function() { alert(Error loading product data!); } } $.ajax({ url : postOptions.url, success : postOptions.success, type : postOptions.type, error : postOptions.error, complete : function() { viewModel.processing(false); } }); } self.productFinderSearchTerm ko.observable(); self.productFinderUrl ko.computed(function() { var searchTerm self.productFinderSearchTerm(); var search2 ofConfig.productFinderSearchstring.replace(/__query__/g, searchTerm); return bulk_atc.asp?find_product1&s + searchTerm + &search2 + search2; }); self.showRemoveLink function(data){ if(!ofConfig.allowProductRemoves){ return false; }/* // EJ - replaced the below if statement with the the code below to account for SU setting // all but one detail line on an order / quote to disallow delete. // I believe this was supposed to handle instanced items, but Im not entirely certain // Leaving the code here in case Im wrong if( _.filter(viewModel.detailLines(),function(detail) { return detail.removeType() ! hide} ).length 1 ){ return false; }*/ var instanceKeys viewModel.detailLines().reduce(function(instanceKeys, line) { if(instanceKeys.indexOf(line.instance()) -1) { instanceKeys.push(line.instance()); } return instanceKeys; }, ); if(!ofConfig.allowRemoveLastItem && instanceKeys.length 2) { return false; } if(data.removeType() hide){ return false; } return true; }; self.breadcrumbMarkup function(){ if(self.recordType() cart) { return ofConfig.sPaymentHeaderLabel; } else if (self.recordType() recurring) { return ul classbreadcrumb breadcrumb-cart>li classactive>Recurring Order # + self.referenceId() + span classdivider>i classicon-chevron-right>/i>/span>/li>; } else { return ul classbreadcrumb breadcrumb-cart>li classactive> + ofConfig.SavedCartLabel + # + self.referenceId() + span classdivider>i classicon-chevron-right>/i>/span>/li>li>i classicon-ok>/i> Order Placed/li>/ul> } }(); self.expirationDate ko.observable(function() { return new moment(self.quoteExpirationDate()).format(MM/DD/YYYY); }()); self.expirationDate.subscribe(function(newExpirationDate) { self.buildOrderHeaderFields(QuoteExpirationDate); }); runHook(orderModelBottom, { self: self, order: self }); } // end of var Order blah blah blah //This code was running on other pages and causing errors. if(default.asp payment.asp && isExistingOrder){ var shippingAddresses processShippingAddresses(); if(shippingAddresses().length 1){ //redirect to bill-ship because the user has no shipping addresses var sUrl account.asp?fromct&errno-shiptos&o_key + utils.getParameter(o_key) + (ofConfig.isModal ? &modal1 : ); document.location sUrl; } } function processShippingAddresses(data){ var addressArray data; var newshippingAddresses; if(Array.isArray(addressArray)) { newshippingAddresses addressArray.map(function(item, index, arr) { address new addressInfo(); address.name(item.sha_nm); address.company(item.s_company || ); address.attention(item.attention || ); address.address1(item.s_add1 || ); address.address2(item.s_add2 || ); address.address3(item.s_add3 || ); address.address4(item.s_add4 || ); address.address5(item.s_add5 || ); address.country(item.s_country || USA); address.city(item.s_city || ); address.state(item.s_state || undefined); address.zipCode(item.s_zip || ); address.phone(item.s_phone || ); address.email(item.em || ); address.global(item.globaladdress || 0); address.key(item.sha_key); address.editing(false); return address; }); } /* Changing to an observable array (was an obeservable object that contained an array) */ var observableAryOfSHA ko.observableArray(); newshippingAddresses.forEach(function(obj){ observableAryOfSHA.push(ko.mapping.fromJS(obj, shippingAddressMappingOptions)); }); return observableAryOfSHA; //ko.mapping.fromJS(newshippingAddresses, shippingAddressMappingOptions); } var orderMapping { create: function(options) { var newOrder new Order(options.data); return newOrder; // new Order(options.data); } } //Build Json for order header field and optional additional tables. //Pass the Json to the Post Logic Ajax function var postOrderHeaderField function(sOrderField, viewModelProperty, extraTablesJson, callbacks) { var postData {}; var order ; order { o_key : ofConfig.OKey }; order0sOrderField viewModelProperty; postData { Tables: { TableName : orders, TableKeyField : o_key, UserKeyField : o_key, UserKeyIsPrimaryKey : True, Data : order } }; //Optional additional tables on the order if (!!extraTablesJson) { postDataTables.push(extraTablesJson); } self.postLogicJsonAjax(postData, false, callbacks); }; var postOrderDetailFields function(sOrderDetailKey, sDetailFields, viewModelProperties, callbacks) { var postData {}; var orderLine ; orderLines { od_key : sOrderDetailKey }; for(var i 0; i sDetailFields.length; i++){ orderLines0sDetailFieldsi viewModelPropertiesi; } postData { Tables: { TableName : order_detail, TableKeyField : od_key, UserKeyField : od_key, UserKeyIsPrimaryKey : True, Data : orderLines } }; self.postLogicJsonAjax(postData, false, callbacks); }; //Posts Json directly to table(s) using Post Logic //Should be used for fields that do not affect other properties in the ViewModel (i.e. text areas) //No actions on success. var postLogicJsonAjax function(postData, getOrderJSON, callbacks) { callbacks callbacks || {}; jQuery.ajax({ url: payment.asp + ?o_key + ofConfig.OKey + &getorderJSON + getOrderJSON + &ajaxtrue&pageactionpostLogicJSON&randomnum + new Date().getTime(), data: postLogicJSON + encodeURIComponent(JSON.stringify(postData)), cache: false, type: POST, dataType: json, success: callbacks.success, error: function(jqXHR, textStatus, errorThrown) { if (typeof callbacks.error function) { callbacks.error(jqXHR, textStatus, errorThrown); } else { alert(Error posting to + (postDataTables0TableName || postLogicJsonAjax) + .); } }, complete: callbacks.complete }); }; var postInfo function(ajaxOptions, pageAction, scrollToId, model) { if(!model) { model viewModel; } model.activeAjaxRequestCount(model.activeAjaxRequestCount() + 1); model.processing(true); model.errorMessages.removeAll(); var existingSuccess ajaxOptions.success; var existingError ajaxOptions.error; var existingComplete ajaxOptions.complete; if(!ajaxOptions.url) { ajaxOptions.url orderInfoPostUrl + ?o_key + viewModel.orderKey() + &ajaxtrue&pageaction + pageAction; } if(!ajaxOptions.type) { ajaxOptions.type POST; } ajaxOptions.success function(data) { var response JSON.parse(data); if(Array.isArray(response) && Object.keys(response0.Errors).length > 0) { for (var msg in response0.Errors) { if(response0.Errors.hasOwnProperty(msg)) { scrollToId errorList; model.errorMessages.push( { errorType: msg, message: response0.Errorsmsg } ); } } } ko.mapping.fromJS(response1, orderMapping, model); model.updateOrderAccess(); if(typeof existingSuccess function) { existingSuccess(data); } if(scrollToId) { model.showConfirmationMessage(true); scrollToSection(# + scrollToId); } }; ajaxOptions.error function(data) { if(typeof existingError function) { existingError(data); } }; ajaxOptions.complete function() { runHook(postInfoAjaxCompleteFunction, { model: model }); if(typeof existingComplete function) { existingComplete(); } model.activeAjaxRequestCount(model.activeAjaxRequestCount() - 1); if(model.activeAjaxRequestCount() 1) { model.processing(false); /* EJ - 2016-11-14 Ugly hack to get around ko.mapping not initializing the Account property correctly when re-mapping on existing object. I think it may have to do with manually converting the Account property to a validatedObservable the first time through. */ fixUpNulls(model.Account()); } }; $.ajax(ajaxOptions); } var fixUpNulls function(account) { for(var prop in account) { if(account.hasOwnProperty(prop) && typeof accountprop function) { if(accountprop() null || accountprop() null) { accountprop(); } } } } var postPayPal function(orderActionKey) { viewModel.processing(true); jQuery.ajax({ url: payment.asp + ?paypal_order_submit1&oa_id + orderActionKey + &o_key + viewModel.orderKey() + &randomnum + new Date().getTime() , data: o_key + viewModel.orderKey() , cache: false , type: POST , dataType: json , success: function(data){ if(!data.status && data.message ! ){ viewModel.errorMessages.push( { errorType: payment_methods, message: data.message } ); viewModel.processing(false); } else if(data.url ! ){ document.location data.url; } } , error: function(data) { alert(Error attempting PayPal checkout); viewModel.processing(false); } , complete: function(data) { } }); } var addFromProductFinder function(productInfo) { viewModel.productFinderSearchTerm(); var productInfo { productKey: productInfo.key, productSku: productInfo.sku, parentChildType: productInfo.parent_child_type, parentProductId: productInfo.parent_p_id } viewModel.loadProductForEdit(productInfo, ); } $(function() { if(getOriginalPageName() ! bulk_atc.asp) { addGlobalModalCompletionHandler($(#find_product), addFromProductFinder); } });/script>script typetext/javascript> function handleSkuSubmission(sku, state) { var sku _.trim(viewModel.productFinderSearchTerm()); //var $sku $(#sku_entry); //var sku _.trim($sku.val()); if (sku) { var request new ProductRequest(page_entry, { sku: sku, state: state }); return processProductRequests(request); } else { return $.when(); } } function processProductRequests(requests) { var def $.Deferred(); loadProducts(requests) .done(function () { if(!requests0.product) { openProductFinder(requests0.sku); } else { var productInfo { productKey: requests0.product.p_key, productSku: requests0.product.sku, parentChildType: requests0.product.parent_child_type, parentProductId: requests0.product.parent_p_id || }; viewModel.loadProductForEdit(productInfo, ); } }) .fail(_.bindKey(def, reject)); return def.promise(); } function loadProductsByAjax(pageaction, prop, requests) { var def; if (requests.length) { def $.Deferred(); $.ajax({ url: bulk_atc.asp?modal1, dataType: JSON, data: { pageaction: pageaction, items: _.pluck(requests, prop) } }) .done(function (data) { if (data.items) { def.resolve(data.items); } else { def.reject(); } }) .fail(function () { def.reject(); }); def.fail(function () { console.error(Failed to fetch product info.); }); } else { def $.when(); } return def.promise(); } function openProductFinder(searchTerm) { var $btn $(#find_product); // Trigger the global modal handler. $btn.click(); } function loadProducts(requests) { var requestPartitions _.partition(requests, key); var requestsWithKey requestPartitions0; var requestsWithoutKey requestPartitions1; var def $.Deferred(); toggleLoadingWidget(true); $.when( loadProductsByAjax(products_by_key, key, requestsWithKey), loadProductsByAjax(products_by_sku, sku, requestsWithoutKey) ) .done(function (productsFromKeys, productsFromSkus) { var products productsFromKeys.concat(productsFromSkus); _.each(requests, function (request) { request.product _.find(products, _.bindKey(request, matchesProduct)); }); toggleLoadingWidget(false); def.resolve(products) }) .fail(_.bindKey(def, reject)); return def.promise(); } // Represents a request to add a product to the table. // The data argument must contain a product property or a sku property. function ProductRequest(source, data) { use strict; var self this; self.matchesProduct function(product) { return self.key ? product.p_key self.key : product.sku.toLowerCase() self.sku.toLowerCase(); }; self.source source; self.product data.product; self.state data.state; self.price data.price; self.sku self.product ? self.product.sku : data.sku; self.key self.product ? self.product.p_key : data.key; } // Represents the result of processing a ProductRequest. function ProductResponse(request, prompt, error) { use strict; var self this; self.request request; self.prompt prompt; self.error error; } var loadSkusFromPrefix _.memoize(function(prefix) { return $.ajax({ url: bulk_atc.asp, dataType: JSON, data: { pageaction: sku_list, prefix: prefix } }) .then(function (data) { return data.items; }); }); function getSkuList(query, process) { var prefix query.slice(0, 1); loadSkusFromPrefix(prefix).done(process); } function initSkuAutocomplete($input) { var source getSkuList; $input.typeahead({ items: 8, minLength: 1, source: source, // Contrary to the docs, the default sorter does not put exact matches first. sorter: function (items) { var lowerQuery this.query.toLowerCase(); return _.sortBy(items, function (item) { var lowerItem item.toLowerCase(); if (lowerItem lowerQuery) { return 0; } else if (!lowerItem.indexOf(lowerQuery)) { return 1; } else { return 2; } }); }, updater: function (sku) { // Delay the form submission until the input is updated. An event listener is // required since that update utilizes the return value of this function. $input.one(change, function () { $(#add_item_form).submit(); }); return sku; } }); } ko.bindingHandlers.autocompleteSku { init: function(element, valueAccessor, allBindingsAccessor) { var $el $(element); initSkuAutocomplete($el); } }; ko.bindingHandlers.executeOnEnter { init: function (element, valueAccessor, allBindings, viewModel) { var callback valueAccessor(); $(element).keypress(function (event) { var keyCode (event.which ? event.which : event.keyCode); if (keyCode 13) { callback.call(viewModel); return false; } return true; }); } };/script>script typetext/html idcart.billingSection> !-- ko template: cart.superUserOrderFormButton-->!-- /ko --> div data-bindcss: { hide: viewModel.completed() }, html: viewModel.breadcrumbMarkup>/div> !-- ko template: { name: cart.confirmation} -->!-- /ko --> div idcheckout_billing classcheckout-section active completed data-bindwith: viewModel> div classcheckout-section-heading> h3 classcheckout-section-heading__text>Billing i classicon-ok-sign text-success data-bindvisible: viewModel.billingSectionValid>/i>/h3> /div> div classcheckout-section-body> div classcheckout-section-inner> !-- ko template: { name: cart.billingSummary } --> !-- /ko --> !-- ko template: { name: cart.billingForm } --> !-- /ko --> /div> /div> div classcheckout-section-footer data-bindvisible: showBillingEdit() && !orderPlaced()> button typebutton idbtn_continue_shipping classbtn btn-primary pull-right data-targetcheckout_shipping data-bind click: toggleShowBillingEdit, attr: { disabled: !viewModel.billingSectionValid() } > Continue Checkout /button> /div> /div> !-- ko template: { name: credits, if: viewModel.showCredits } -->!-- /ko -->/script>script typetext/html idcart.printButton> div classprint-hide data-bindif: viewModel.completed()> button typebutton classbtn btn-primary pull-right onclickwindow.print();> i classicon-print>/i> Print /button> /div>/script>script typetext/html idcart.superUserOrderFormButton> !-- ko if: ofConfig.isSuperUserSession && ofConfig.superUserShowViewModeButton --> button typebutton classbtn btn-secondary pull-right data-bindclick: viewModel.toggleSuperUserMode> View as span data-bindif: viewModel.superUserOrderFormMode()>Normal User/span>span data-bindifnot: viewModel.superUserOrderFormMode()>Super User/span> /button> !-- /ko --> !-- ko if: ofConfig.isModal --> div classpull-right> button typebutton classbtn btn-primary data-bindclick: viewModel.returnToPendingOrders> i classicon-chevron-left>/i> Return to span data-bindtext: ofConfig.SavedCartLabel>/span>s /button> /div> !-- /ko -->/script>script typetext/html idcart.detailSection> div idcheckout_details classcheckout-section active completed> div classcheckout-section-heading> h3 classcheckout-section-heading__text>Items & Shipping i classicon-ok-sign text-success data-bindvisible: viewModel.shippingComplete>/i>/h3> button typebutton classbtn checkout-btn-edit pull-right data-targetcheckout_shipping data-bind click: function() { viewModel.shippingComplete(false) }, visible: viewModel.shippingComplete() && !viewModel.completed() >Edit/button> /div> div classcheckout-section-body> div idshipping_address_summary > !-- ko template: { name: cart.shippingSummary, data: shipments(), if : (viewModel.shippingComplete() || viewModel.completed()) && shipments().length > 0 } --> !-- /ko --> !-- ko template: { name: cart.shippingActions, if: !viewModel.shippingComplete() } --> !-- /ko --> !-- ko template: { name: cart.assignItemsToShipTos, data: itemsOnOrder, if : ofConfig.amazonView && viewModel.useMultiShipEditUI() && !viewModel.shippingComplete() && !viewModel.completed() } --> !-- /ko --> !-- ko template: { name: cart.itemsOnOrderSelection, data: itemsOnOrder, if : ofConfig.invView & viewModel.useMultiShipEditUI() && !viewModel.shippingComplete() && !viewModel.completed() } --> !-- /ko --> !-- ko template: { name: cart.itemShipToMapPreview, data: itemShipToMap, if : ofConfig.invView & viewModel.useMultiShipEditUI() && !viewModel.shippingComplete() && !viewModel.completed() } --> !-- /ko --> !-- ko template: { name: cart.selectShipTo, data: $data, if : !viewModel.useMultiShipEditUI() && !viewModel.shippingComplete() && !viewModel.completed() }--> !-- /ko --> /div> /div> div classalert alert-info data-bindvisible: $data.detailLines().length 0, html: Please add products to the + oConfig.labels.savedCarts + to continue>/div> div classcheckout-section-footer data-bindvisible: !orderPlaced() && !viewModel.shippingComplete()> button typebutton idbtn_continue_shipping classbtn btn-primary pull-right data-targetcheckout_shipping data-bindclick: allocateShipments, attr: { disabled: !viewModel.billingSectionValid() || $data.detailLines().length 0 }> Continue Checkout /button> /div> /div>/script>script typetext/html idcart.shippingActions> ul classnav nav-tabs> !-- ko if: ofConfig.allowUserCreatedShipments && detailLines().length > 0--> li data-bindcss: { active: !viewModel.useMultiShipEditUI() }> a href# data-bindclick: viewModel.useMultiShipEditUI() ? viewModel.toggleMultiShip : null>Singlespan classhidden-xs> Address/span>/a> /li> li data-bindcss: { active: viewModel.useMultiShipEditUI() }> a href# data-bindclick: viewModel.useMultiShipEditUI() ? null : viewModel.toggleMultiShip>Multiplespan classhidden-xs> Addresses/span>/a> /li> !-- /ko --> !-- ko if: ofConfig.bAllowShipToAdds && detailLines().length > 0 --> li> !-- ko template: cart.addAddressButton -->!-- /ko --> li> !-- /ko --> !-- ko if: viewModel.allowProductAdds() && ofConfig.showProductAddDropdown --> !-- ko template: cart.addProductButton-->!-- /ko --> !-- /ko --> /ul>/script>script typetext/html idcart.productQuickAdd> div classproduct-select> div classform-buttons input-append> input typetext idsku_entry data-bindtextInput: productFinderSearchTerm, autocompleteSku, executeOnEnter: handleSkuSubmission namesku classspan8 placeholderAdd Product autocompleteoff autocapitalizeoff autocorrectoff> button idsku_submit data-bindclick: handleSkuSubmission classbtn tabindex-1>i classicon-plus>/i>/button> button idfind_product data-bindaddModalHandler: { element : $(button#find_product), handler : addFromProductFinder }, attr: { data-url: productFinderUrl } classbtn global-modal typebutton tabindex-1 data-titleFind a Product data-sizelarge>i classicon-search>/i>/button> /div> /div> div classwell stylemax-width:450px; data-bind visible: viewModel.mainProduct() && !!!viewModel.mainProduct().configuratorEditData, if: viewModel.mainProduct() && !!!viewModel.mainProduct().configuratorEditData > strong data-bindhtml: viewModel.mainProduct().selectedProduct().name() || viewModel.mainProduct().name()>/strong> !-- ko template: { name: catalog.detail_info, data:viewModel.mainProduct } -->!-- /ko --> div data-bindif: viewModel.mainProduct classdetail-child-selector> span data-bindtemplate: { name: catalog.child_selectors, if: viewModel.mainProduct().childSelectors, data: viewModel.mainProduct().childSelectors }>/span> /div> !-- ko template: { name:catalog.atc_full, data:viewModel.mainProduct().selectedProduct, if:viewModel.mainProduct } -->!-- /ko --> div styleclear:both;>/div> /div>/script>script typetext/html idcart.shippingSection> div idcheckout_shipping classcheckout-section active completed data-bindwith: viewModel> div classcheckout-section-heading> h3 classcheckout-section-heading__text>Finalize & Placespan classhidden-xs> Order/span> i classicon-ok-sign text-success data-bindvisible: completed()>/i>/h3> /div> !-- ko template: { name: cart.errorList, data: _.filter(errorMessages(), function (error) { return error.errorType ship_vias || error.errorType shipment; } ) } -->!-- /ko --> !-- ko if: viewModel.shippingComplete --> div classcheckout-section-body> div classcheckout-section-inner> div idcheckout_review classrow-fluid> div classspan8> !-- ko template: { name: cart.productQuickAdd, if: viewModel.allowProductAdds() && ofConfig.showProductQuickAddInFinalStep } -->!-- /ko --> !-- ko template: { name: cart.shipmentList, if: viewModel.allowShipViaEdits() } --> !-- /ko --> !-- ko template: { name: cart.shipmentSummaryList, if: !viewModel.allowShipViaEdits() } --> !-- /ko --> !-- ko if: viewModel.shippingComplete() --> !-- ko template: { name: cart.couponEntry, if: ofConfig.showCoupon && ofConfig.showCouponEntryInline && viewModel.allowPayMethodEdits() } -->!-- /ko --> !-- ko template: { name: cart.giftCertificateEntry, if: ofConfig.showGiftCertificate && ofConfig.showGiftCertificateEntryInline && viewModel.allowPayMethodEdits() } -->!-- /ko --> fieldset classcheckout-review__fieldset idpayment_methods data-bindvisible: !!$data.selectedOrderAction && $data.selectedOrderAction().showPaymentMethods()> legend classcheckout-review__fieldset-content data-bindvisible: !orderPlaced() && allItemsAllocated()> i classicon-lock icon-fixed-width>/i> Secure Payment Methods /legend> !-- ko template: { name: cart.errorList, data: _.filter(errorMessages() , function (error) { return error.errorType payment_methods; }) } -->!-- /ko --> div classform-horizontal checkout-review__fieldset-content data-bind if: viewModel.allowPayMethodEdits() && viewModel.payMethods().length> !-- ko template: { name: cart.paymentMethods, afterRender: initCCForm } -->!-- /ko --> /div> div classalert alert-warning data-bindvisible: !viewModel.payMethods().length> div data-bindhtml: ofConfig.sPaymentMethodMissingError>/div> div data-bindif: ofConfig.bIsValidIp || ofConfig.isSuperUserSession> No Payment Methods Found. /div> /div> !-- ko if: !viewModel.allowPayMethodEdits() && !viewModel.completed() --> div classwell checkout-review__fieldset-content> !-- ko template: cart.paymentMethodSummary -->!-- /ko --> /div> !-- /ko --> /fieldset> fieldset classcheckout-review__fieldset idcontrolgroup_quoteinfo data-bindif: (recordType() ! cart && ofConfig.showExpirationDate) && ((superUserOrderFormMode() && ofConfig.superUserAllowExpirationDateEdits) || viewModel.isValidDate(expirationDate()))> legend classcheckout-review__fieldset-content> i classicon-pencil icon-fixed-width>/i> Quote Information /legend> div classform-horizontal checkout-review__fieldset-content> !-- ko template: { name: cart.expirationDate, if: recordType() ! cart && ofConfig.showExpirationDate } -->!-- /ko --> /div> /fieldset> fieldset classcheckout-review__fieldset idcontrolgroup_recurring data-bindif: !completed() && ((selectedOrderAction() && selectedOrderAction().showRecurringOrderSettings()) || viewModel.recordType() recurring ) > div classcheckout-review__fieldset-content> !-- ko template: { name: cart.recurringDetails } -->!-- /ko --> /div> /fieldset> fieldset classcheckout-review__fieldset data-bindif: ofConfig.showOrderActionsInline> legend classcheckout-review__fieldset-content data-bindif: viewModel.allowPlaceOrder() && shippingComplete() && paymentMethodID(), visible: orderActions().length > 1> i classicon-cog icon-fixed-width>/i> Choose an Order Action /legend> !-- ko if : ofConfig.showOrderActionsInline && !viewModel.completed() --> !-- ko template: { name: cart.orderActions, if: shippingComplete() && paymentMethodID() && orderActions().length > 0 } -->!-- /ko --> div classcheckout-review__fieldset-content data-bindif: orderActions().length 0 && shippingComplete() && paymentMethodID()> div classalert alert-info>There are no actions available at this time./div> /div> !-- /ko --> /fieldset> !--ko template: { name: cart.noteBookNotes, if : viewModel.noteBook().notes().length > 0 } -->!-- /ko --> !-- /ko --> /div> !-- ko if: ofConfig.showPricingOrderEntry --> div classspan4> div classsticky data-bindStickyfill> !-- ko template: { name: cart.checkoutSummary } -->!-- /ko --> /div> /div> !-- /ko --> /div> /div> /div> !-- /ko --> /div>/script>script typetext/html idcart.couponEntry> div idcoupon_entry classcontrol-group data-bindif: !orderPlaced() && billingSectionValid() && shipmentsSectionsValid()> form classwell> label forcouponcode classcontrol-label> b>Have a coupon?/b> /label> div classcontrols> !-- ko ifnot: couponCode --> div classinput-append> input typetext namecouponcode idcouponcode classinput-medium data-bindvalue: newCouponCode placeholderEnter code> button classbtn btn-success data-bindclick: function() { SetCouponCode(newCouponCode()); newCouponCode(); }>Apply/button> /div> !-- /ko --> !-- ko if: couponCode --> div classalert alert-success> strong>span data-bindtext: couponCode>/span>/strong> applied. i stylecursor: pointer classicon-remove text-error titleRemove Coupon data-bindclick: function() { SetCouponCode(); }>/i> /div> !-- /ko --> /div> /form> !-- ko template: { name: cart.errorList, data: _.filter(errorMessages() , function (error) { return error.errorType coupon; }) } -->!-- /ko --> /div>/script>script typetext/html idcart.giftCertificateEntry> div idgiftCertificateEntry classcontrol-group data-bindif: !orderPlaced() && billingSectionValid() && shipmentsSectionsValid()> form classwell> label forgiftCertCode classcontrol-label> b>Have a gift certificate?/b> /label> div classcontrols> !-- ko ifnot: giftCertCode --> div classinput-append> input typetext namegiftCertCode idgiftCertCode classinput-medium data-bindvalue: newGiftCertificate placeholderEnter code> button classbtn btn-success data-bindclick: function() { SetGiftCertificate(newGiftCertificate()); newGiftCertificate(); }>Apply/button> /div> !-- /ko --> !-- ko if: giftCertCode --> div classalert alert-success> strong>span data-bindtext: giftCertCode>/span>/strong> applied. i stylecursor: pointer classicon-remove text-error titleRemove Gift Certificate data-bindclick: function() { SetGiftCertificate(); }>/i> /div> !-- /ko --> /div> /form> !-- ko template: { name: cart.errorList, data: _.filter(errorMessages() , function (error) { return error.errorType coupon; }) } -->!-- /ko --> /div>/script>script typetext/html idcart.orderActions> div data-bindvisible: !processing() > div idrestriction_message_container data-bindif : $data.restrictionMessages().length > 0> !-- ko template: cart.restrictionMessages-->!-- /ko --> /div> div data-bindvisible: orderActions().length > 1 classwell order-actions__well> div classrow-fluid order-actions__row> div classspan6 order-actions__span data-bindvisible: orderActions().length > 1> div classorder-actions__header idorder_actions_header> div classorder-actions__wrapper data-bindforeach: orderActions> label classradio order-actions__radio> input typeradio nameradio data-bind attr: { id: $data.refId }, checked: viewModel.selectedOrderActionRefId, value: $data.refID > b data-bind html: $data.name>/b> p data-bind html: $data.customerDescription>/p> /label> /div> /div> /div> div classspan6 order-actions__span> ul data-bindforeach: orderActions classunstyled> li data-bindvisible: $data.refID() (viewModel.selectedOrderAction() && viewModel.selectedOrderActionRefId()) || $parent.orderActions().length 1> div idcontrolgroup_nickname data-bindif: $data.showNickname() || viewModel.nickname()> label fornickname classcontrol-label> Name of Order small classmuted>(optional)/small> /label> input typetext classinput-block-level namenickname idnickname data-bindvalue: viewModel.nickname> /div> div idadd_comments_container data-bindif : $data.showComments> !-- ko template: cart.noteBookComments-->!-- /ko --> /div> /li> /ul> /div> /div> /div> div classform-actions data-bindforeach: orderActions> !-- ko template: { name: cart.termsAndConditions } -->!-- /ko --> button classbtn btn-large btn-primary data-bind html: function() { if($data.showComments() && viewModel.customerComment() ! ){ return Send Comment & + $data.buttonLabel(); }else{ return $data.buttonLabel; } }(), attr: { id : $data.refID, disabled: ( (($parent.paymentMethod.paymentType() cc && $parent.ccn_id() ) && (placeOrderActionType() place || placeOrderActionType() validate)) || ($data.requireTermsAndConditions() && !$parent.termsAgreement()) ) }, click: viewModel.processOrderAction, visible: ($data.refID() (viewModel.selectedOrderAction() && viewModel.selectedOrderActionRefId()) || $parent.orderActions().length 1) && ($data.showButton()) >/button> /div> /div>/script>script typetext/html idcart.termsAndConditions> label fortermsAgreement classcheckbox data-bindvisible: ($data.refID() (viewModel.selectedOrderAction() && viewModel.selectedOrderActionRefId()) || $parent.orderActions().length 1) && $data.requireTermsAndConditions()> input typecheckbox classrequired data-bindchecked: $parent.termsAgreement idtermsAgreement>/input> By placing this order, you agree to our a data-bindattr: { href: page.asp?modal1&p_key + ofConfig.termsAndConditionsPageKey } classglobal-modal data-titleTerms and Conditions>terms and conditions/a>. Please check to indicate that you have read them. /label>/script>script typetext/html idcart.restrictionMessages> div classwell> b>Important Order Information/b> p classtext-warning data-bindforeach: restrictionMessages> span data-bind html: $data>/span> /p> /div>/script>script typetext/html idcart.checkoutSummary> !-- ko template: { name: cart.couponEntry, if: ofConfig.showCoupon && !ofConfig.showCouponEntryInline } -->!-- /ko --> !-- ko template: { name: cart.giftCertificateEntry, if: ofConfig.showGiftCertificate && !ofConfig.showGiftCertificateEntryInline } -->!-- /ko --> div idcheckout_summary classpanel panel-default data-bindwith: viewModel> div classpanel-heading> b>Order Summary/b> /div> table classtable> tbody> tr data-bindvisible: ofConfig.showEffectiveOrderDate && viewModel.isValidDate(effective_order_date())> td>Effective Order Date/td> td idorder_date classcell-right data-bindtext: moment(effective_order_date()).format(MM/DD/YYYY) >/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() productTotal()> td data-bindhtml: ofConfig.productSubtotalLabel>/td> td idp_total classcell-right>span data-bindhtml: utils.formatMoney(productTotal())>/span>/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() ! productTotal()> td data-bindhtml: ofConfig.productSubtotalBeforeDiscountLabel>/td> td idp_coupon_total classcell-right>span data-bindhtml: utils.formatMoney(productSubTotalBeforeDiscount())>/span>/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() ! productTotal()> td>span data-bindhtml: ofConfig.productDiscountTotalLabel>/span> (span data-bindtext: session.TradeAdjustment>/span>%)/td> td idp_coupon_total classcell-right deduction>span data-bindhtml: utils.formatMoney(productDiscountTotal())>/span>/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() ! productTotal()> td data-bindhtml: ofConfig.productSubtotalAfterDiscountLabel>/td> td idp_coupon_total classcell-right>span data-bindhtml: utils.formatMoney(productTotal())>/span>/td> /tr> tr data-bindvisible: giftCertCode> td data-bindhtml: ofConfig.giftCertificateTotalLabel>/td> td idp_coupon_total classcell-right deduction>span data-bindhtml: utils.formatMoney(giftCertAmount())>/span>/td> /tr> tr data-bindvisible: couponCode> td data-bindhtml: ofConfig.couponSubtotalLabel>/td> td idp_coupon_total classcell-right deduction>span data-bindhtml: utils.formatMoney(couponDiscountTotals.totalDiscount())>/span>/td> /tr> tr data-bindif: ofConfig.bShowShipTotal && ofConfig.bUsingShipping> td data-bindhtml: ofConfig.shippingTotalLabel>/td> !-- ko if: shipmentsSectionsValid() --> td ids_total classcell-right> !-- ko if : ofConfig.bShowShipTotalMessage --> span data-bindtext: ofConfig.sShipTotalText>/span> !-- /ko --> !-- ko ifnot: ofConfig.bShowShipTotalMessage --> !-- ko if: ofConfig.bShowPriceText && shippingTotal() 0 --> span data-bindtext: ofConfig.sShipTotalText>/span> !-- /ko --> !-- ko if: !ofConfig.bShowPriceText || shippingTotal() > 0 --> span data-bindhtml: utils.formatMoney(shippingTotal())>/span> !-- /ko --> !-- /ko --> /td> !-- /ko --> !-- ko if: !shipmentsSectionsValid() --> td ids_total classcell-right >TBD/td> !-- /ko --> /tr> tr data-bindif: ofConfig.showTaxTotal> td data-bindhtml: ofConfig.taxTotalLabel>/td> !-- ko if: shipmentsSectionsValid() --> td idt_total classcell-right>span data-bindhtml: utils.formatMoney(taxTotal())>/span>/td> !-- /ko --> !-- ko if: !shipmentsSectionsValid() --> td idt_total classcell-right>TBD/td> !-- /ko --> /tr> tr classsuccess text-large> td classtext-success>b>span data-bindhtml: ofConfig.orderTotalLabel>/span>/b>/td> td classcell-right text-success>b>span data-bindhtml: utils.formatMoney(orderBalance())>/span>/b>/td> /tr> /tbody> /table> !-- ko if : !ofConfig.showOrderActionsInline && !viewModel.completed() --> !-- ko template: { name: cart.orderActions, if: shippingComplete() && paymentMethodID() && orderActions().length > 0 } -->!-- /ko --> div data-bindif: orderActions().length 0 && shippingComplete() && paymentMethodID()> div classalert alert-info>There are no actions available at this time./div> /div> !-- /ko --> /div>/script>script typetext/html idcart.noteBookComments> div classconvolog-comments> div idexternal_comments_wrapper> label forexternal_comments> Comments small classmuted>(optional)/small> /label> textarea idexternal_comments classinput-block-level rows3 autocompleteoff data-bindtextInput: viewModel.customerComment> /textarea> p data-bindvisible: viewModel.customerComment() ! >a classbtn btn-small btn-block data-bindevent : { click : viewModel.saveCustomerComment }>Post Comments/a>/p> p classhelp-block text-small data-bindhtml: ofConfig.orderCommentHelpText>/p> /div> /div>/script>script typetext/html idcart.noteBookNotes> div idconversation_log_detail> div nameconversation_detail_template> h3>Comments for this order:/h3> div classconvolog-entries> ul classlist-group data-bindforeach: $data.noteBook().notes()> li classlist-group-item> div> p data-bindhtml: $data.externalNotes>/p> small classmuted>i classicon-user>/i> span data-bindhtml: $data.postedByName + at + $data.createDate>/span>/small> /div> /li> /ul> /div> /div>/div>/script>script typetext/html idcart.paymentMethodSummary> ul classunstyled> li>b>Payment/b>/li> li data-bindtext: paymentMethod.name>/li> !-- ko if: paymentMethod.paymentType() cc --> li>strong data-bindtext: vaultedPayment.cardType>/strong> ending in strong data-bindtext: vaultedPayment.last4>/strong>/li> li classpayment-method-summary__expiration>Expires strong>span data-bindtext: vaultedPayment.expMonth>/span>/span data-bindtext: vaultedPayment.expYear>/span>/strong>/li> !-- /ko --> /ul> input typehidden idponumber data-bindvalue: poNumber/>/script>script typetext/html idcart.confirmation> div idcheckout_confirmation classcheckout-section data-bindvisible: !viewModel.errorMessages().length && viewModel.showConfirmationMessage() > div classcheckout-section-body> div classcheckout-section-inner> !-- ko if: viewModel.selectedLifecycleStage().confirmationMessage() ! --> div data-bindattr: { class: confirmation-alert-box + selectedLifecycleStage().displayClass() }> i classicon-3x pull-left>/i> h3 data-bindhtml: selectedLifecycleStage().confirmationMessage()>/h3> /div> !-- /ko --> !-- ko if: viewModel.selectedLifecycleStage().confirmationMessage() --> div classalert data-bind css: { alert-error: viewModel.lifecycleStage() cancelled, alert-success: function(){ return (completed() || (viewModel.lifecycleStage() pending || viewModel.recordType() recurring) ) || (!completed() && viewModel.lifecycleStage() ! cancelled) } }, > i classicon-ok-sign icon-3x pull-left>/i> h3 classtext-success data-bindvisible: completed() && viewModel.lifecycleStage() ! cancelled>Thank you for your order!/h3> h3 classtext-success data-bindvisible: !completed() && viewModel.recordType() recurring >Recurring Order Saved./h3> h3 classtext-success data-bindvisible: !completed() && viewModel.lifecycleStage() pending >This order is pending approval./h3> h3 classtext-success data-bindvisible: !completed() && viewModel.lifecycleStage() ! pending && viewModel.lifecycleStage() ! recurring && viewModel.lifecycleStage() ! cancelled >This order has been saved./h3> h3 classtext-error data-bindvisible: viewModel.lifecycleStage() cancelled >This order was rejected./h3> /div> !-- /ko --> !-- ko template: cart.printButton-->!-- /ko --> !-- ko if: completed() && orderNumber() --> h3>Your order number is span data-bindtext: ofConfig.orderNumberPrefix>/span>span data-bindtext: orderNumber>/span>/h3> !-- /ko --> div classrow-fluid checkout-section__row> div classspan6 well checkout-section__span> !-- ko template: cart.paymentMethodSummary -->!-- /ko --> /div> div classspan6 checkout-section__span data-bindcss: { well: poNumber() || comments() }> div idcontrolgroup_invoice_ponumber_summary classcontrol-group checkout-section__summary-wrapper data-bindif: poNumber> div classcheckout-section__summary> label forponumber_summary classcontrol-label> strong data-bindhtml: ofConfig.POLabel>/strong> /label> div classcontrols> strong>span idponumber_summary class data-bindtext: poNumber>/span>/strong> /div> /div> /div> div idcontrolgroup_invoice_comments_summary classcontrol-group checkout-section__summary-wrapper data-bindif: comments> div classcheckout-section__summary> label fororder_comments_summary classcontrol-label> strong data-bindtext: ofConfig.fulfillmentCommentsText>/strong> /label> div classcontrols> div idorder_comments_summary data-bindtext: comments>/div> /div> /div> /div> /div> /div> /div> /div> /div>/script>script typetext/html idcart.errorList> div iderrorList> !-- ko if: $data.length > 0 && !viewModel.completed() --> div classalert alert-error> ul classunstyled data-bindforeach: $data> li>strong>span data-bindtext: message>/span>/strong>/li> /ul> /div> !-- /ko --> /div>/script>script typetext/html idcart.allocationNotComleteMessage> div classalert alert-warning> h3 classtext-warning>i classicon-warning-sign>/i> Your shipments arent complete./h3> p>All items on your order must be allocated to shipments before you can complete the order./p> /div>/script>!-- bound -->script typetext/html idcart.billingForm> !-- ko if: showBillingEdit --> div idbilling_address_form classform-horizontal> !-- ko template: { name: cart.orderContact, data: viewModel.customer } --> !-- /ko --> !-- ko template: { name: cart.billingAddress, data: viewModel.account } --> !-- /ko --> /div> !-- /ko -->/script>!-- bound -->script typetext/html idcart.orderContact> fieldset> legend>Order Contact/legend> div classcontrol-group data-bindvalidationElement: $data.firstName> label forbill_f_nm classcontrol-label>First Name/label> div classcontrols> input typetext idbill_f_nm data-bindvalue: $data.firstName> /div> /div> div classcontrol-group data-bindvalidationElement: $data.lastName> label forbill_l_nm classcontrol-label>Last Name/label> div classcontrols> input typetext idbill_l_nm data-bindvalue: $data.lastName> /div> /div> div classcontrol-group data-bindvalidationElement: $data.email> label forbill_em classcontrol-label>Email/label> div classcontrols> input typetext idbill_em data-bindvalue: $data.lastName> /div> /div> div classcontrol-group data-bindvalidationElement: $data.phone> label forbill_phone classcontrol-label>Phone/label> div classcontrols> input typetext idbill_phone data-bindvalue: $data.phone> div classhelp-inline text-small>Format: span idgc-number-1 classgc-cs-link titleCall with Google Voice>888-555-1234/span> xxxx/div> /div> /div> /fieldset>/script>script typetext/html idcart.billingAddress> fieldset> legend>Billing Address/legend> !-- ko template: { name: cart.addressInfo } -->!-- /ko --> /fieldset>/script>!-- bound -->script typetext/html idcart.billingSummary> !-- ko ifnot: showBillingEdit --> div idbilling_address_summary classrow-fluid billing-address-summary__row> div classspan6 billing-address-summary__span> div classwell billing-address-summary__well> b>Order Contact/b> button typebutton idcontact-address classbtn btn-link btn-mini global-modal data-bind attr: { href: account.asp?modalactioneditcontact&modal1&o_key + viewModel.orderKey() }, visible: viewModel.allowContactEdits(), addModalHandler: { element : $(#contact-address), handler : function() { location.reload() }} data-titleEdit Contact Information data-sizefull > Change /button> !-- ko template: { name: cart.orderContactSummary, data: customer } --> !-- /ko --> /div> /div> div classspan6 billing-address-summary__span> div classwell billing-address-summary__well> b>Billing Address/b> button typebutton idbilling-address classbtn btn-link btn-mini global-modal data-bind attr: { href: account.asp?modalactioneditaccount&modal1&o_key + viewModel.orderKey() }, visible: viewModel.allowAccountEdits(), addModalHandler: { element : $(#billing-address), handler : function() { location.reload() } } data-titleEdit Billing Information data-sizefull > Change /button> !-- ko template: { name: cart.billingAddressSummary, data: billToAccount } -->!-- /ko --> /div> /div> /div> !-- /ko -->/script>!-- bound -->script typetext/html idcart.orderContactSummary> ul classunstyled> li>span data-bindtext: $data.firstName>/span> span data-bindtext: $data.lastName>/span>/li> li data-bindtext: $data.email>/li> li data-bindtext: $data.phone>/li> /ul>/script>!-- bound -->script typetext/html idcart.billingAddressSummary> ul classunstyled> li data-bindtext: $data.company>/li> li data-bindtext: $data.address1, visible: !!$data.address1()>/li> li data-bindtext: $data.address2, visible: !!$data.address2()>/li> li data-bindtext: $data.address3, visible: !!$data.address3()>/li> li data-bindtext: $data.address4, visible: !!$data.address4()>/li> li data-bindtext: $data.address5, visible: !!$data.address5()>/li> li data-bindvisible: $data.city || $data.state || $data.zipCode>span data-bindtext: $data.city>/span>span data-bindvisible: $data.city >, /span>span data-bindtext: $data.state>/span> span data-bindtext: $data.zipCode>/span>/li> li data-bindtext: $data.country, visible: $data.country>/li> /ul>/script>script typetext/html idcart.shipmentMethodSelector> div classradiogroup data-bindforeach: shipViaChoices> !-- ko if: eligible --> label classradio clearfix data-bindattr: { for: $parentContext.$index() + single_sm_0 + $context.$index() }, css: { active: $parent.selectedShipVia.shipViaChoiceID() shipViaChoiceKey() }> input classship-via-radio typeradio data-bindattr: { disabled: viewModel.orderPlaced, name: $parentContext.$index() + single_sm_0 + $context.$index(), id: $parentContext.$index() + single_sm_0 + $context.$index() }, checked: $parent.selectedShipViaChoice, value: $data>span data-bindhtml: name>/span> !-- ko if: ofConfig.bShowShipViaPrice && ofConfig.showPricingOrderEntry --> span classsv-price pull-right data-bindifnot: viewModel.superUserOrderFormMode() && ofConfig.superUserAllowShippingPriceEdits> !-- ko if : ofConfig.bShowShipTotalMessage --> span data-bindtext: ofConfig.sShipTotalText>/span> !-- /ko --> !-- ko ifnot: ofConfig.bShowShipTotalMessage --> !-- ko if: ofConfig.bShowPriceText && total() 0 --> span data-bindtext: ofConfig.sShipTotalText>/span> !-- /ko --> !-- ko if: !ofConfig.bShowPriceText || total() > 0 --> span data-bindhtml: utils.formatMoney(total())>/span> !-- /ko --> !-- /ko --> /span> div classsu-sv-inputs pull-right data-bindif: viewModel.superUserOrderFormMode() && ofConfig.superUserAllowShippingPriceEdits> button typebutton classbtn btn-mini btn-link su-price-reset data-bindvisible: priceCalcType() fixed,event: { click: viewModel.resetSuperUserShippingPrice } > span data-bindhtml: ofConfig.superUserResetPriceHelpText>/span> /button> div classinput-prepend> span classadd-on>$/span> input typetext classinput-mini text-right data-bindvalue: total().toFixed(2), event: { change: viewModel.superUserSetShipViaPrice }> /div> /div> !-- /ko --> !-- ko if: !ofConfig.showPricingOrderEntry --> div classsv-hidden-price pull-right data-bindhtml: utils.drawHidePriceMessage()>/div> !-- /ko --> /label> !-- /ko --> /div> !-- ko if: shipViaChoices().length 0 || !(shipViaChoices().find(function(item) { return item.eligible() })) --> span classalert alert-error>No Shipping Methods Available/span> !-- /ko --> !-- ko if: ofConfig.ShowShipViaDS && selectedShipVia.description --> div idshipping-ds0 classalert alert-info alert-block without-close shipping-ds data-bindhtml: selectedShipVia.description> /div> !-- /ko -->/script>script typetext/html idcart.shipperAccountSelector> !-- ko if: selectedShipVia.collectShippingAccount() --> div classalert alert-info alert-block without-close shipping-account-info data-bindattr: { id : shipping-account-info + parseInt($context.$index() + 1) }> p> i classicon-info-sign>/i> span data-bindattr: { id : sv-collect-info-msg + parseInt($context.$index() + 1) }>This shipping method requires that you provide your own shipper account number to cover the shipping charges./span> /p> div classinput-append shipping-account-select data-bindattr: { id : shipping-account-select + parseInt($context.$index() + 1) }> select classinput-xlarge selShipAcct data-bind attr: { id : selShipAcct + parseInt($context.$index() + 1), name : selShipAcct + parseInt($context.$index() + 1) }, options: selectedShipVia.shippingAccounts, optionsText: function(item){ if( ko.unwrap(item.name) ! ){ return ko.unwrap(item.name) + ( + ko.unwrap(item.number) + ); }else{ return ko.unwrap(item.carrier) + ( + ko.unwrap(item.number) + ); } }, value: selectedShipVia.shippingAccountId, optionsValue: shippingAccountKey, optionsCaption: Select an account..., validationOptions: { messageTemplate: null, insertMessages: true } >/select> !-- ko if: ofConfig.superUserAllowShipperAccountEdits && selectedShipVia.shippingAccounts().length > 0 && selectedShipVia.shippingAccountId() ! undefined --> a idbtnEditShipAcct1 data-selshipacct_idselShipAcct1 classbtn btnEditShipAcct global-modal data-bind html: ofConfig.sShipAccountEditButtonText, attr: { href : sf_shipping_account_ae.asp?modal1&key + selectedShipVia.shippingAccountId() }, addModalHandler: { element : $(.btnEditShipAcct.global-modal), handler : viewModel.genericModalComplete } >/a> !-- /ko --> /div> !-- ko if : ofConfig.superUserAllowShipperAccountAdds --> a classbtn btn-link btnAddShipAcct global-modal hrefsf_shipping_account_ae.asp?modal1 data-bind html : ofConfig.sShipAccountAddbuttonText, addModalHandler: { element : $(.btnAddShipAcct.global-modal), handler : viewModel.genericModalComplete }, attr : { id : btnAddShipAcct + parseInt($context.$index() + 1 } >/a> !-- /ko --> div data-bindif: !selectedShipVia.shippingAccountId.isValid() && selectedShipVia.shippingAccounts().length > 0> p classalert alert-error>Please select a shipping account/p> /div> /div> !-- /ko -->/script>script typetext/html idcart.shipmentGiftOptions> div classcontrol-group> label forgift_msg classcontrol-label data-bind html : ofConfig.sShipmentCommentLabel>/label> div classcontrols> div classtext-small gift-msg-help> span data-bind html : ofConfig.sShipmentCommentHelpText>/span> /div> textarea classgift_msg__textarea rows3 maxlength250 autocompleteoff data-bindvalue: comments, attr: { readonly: viewModel.orderPlaced }>/textarea> span classhelp-block text-small>Up to 250 characters/span> /div> /div>/script>script typetext/html idcart.shipmentGiftOptionsSummary>/script>script typetext/html idcart.productLeadTimes> !-- ko if: ofConfig.bShowProductLeadTimes && ofConfig.productLeadTimesText ! && leadTimeDays() > 0 --> div classtext-small text-info stylemargin-bottom: 5px; data-bindhtml: ofConfig.productLeadTimesText.replace(days>, leadTimeDays() ) > /div> !-- /ko -->/script>script typetext/html idcart.expectedShipDate> span data-bindhtml: ofConfig.expectedShipDate.replace(date>, moment(expectedShipDate()).format(MM/DD/YYYY) )>/span>/script>!-- bound -->script typetext/html idcart.requestedShipDate> div classcontrol-group data-bindvisible: selectedShipVia> label classcontrol-label data-bindhtml: ofConfig.requestedShipDateLabel>/label> div classcontrols> div classinput-append> input typetext classinput-medium stylebackground-color: white;cursor: pointer readonlyreadonly data-bindattr: { disabled: viewModel.orderPlaced, id: selectedShipVia.shipViaChoiceID } , datepicker: requestedShipDate , datepickerOptions: { minDate: new Date(earliestShipDate()), maxDate: moment(new Date()).add(120, days).toDate(), //most quote systems only go out 120 days (after that, rates are not available) constrainInput: true, showOn:both, buttonText: i class\icon-calendar\>/i>, beforeShowDay: function (date) { return isValidRequestedDate(date); } }> button typebutton classbtn data-bindattr: { disabled: viewModel.orderPlaced }, click: function(shipment) { $(# + shipment.selectedShipVia.shipViaChoiceID()).datepicker(show) }, clickBubble: false> i classicon-calendar>/i> /button> /div> /div> /div>/script>script typetext/html idcart.requestedShipDateSummary> div classcontrol-group> label classcontrol-label>Ship On/label> div classcontrols> div classuneditable-text data-bindtext: requestedShipDate>/div> /div> /div>/script>!-- bound -->script typetext/html idcart.addressInfo> div classcontrol-group data-bindvalidationElement: $data.company> label fors_company classcontrol-label>Name/Company/label> div classcontrols> input typetext ids_company classinput-xlarge data-bindvalue: $data.company> span classhelp-inline text-small>(optional)/span> /div> /div> div classcontrol-group data-bindvalidationElement: $data.address1> label fors_add1 classcontrol-label>Street Address/label> div classcontrols> input typetext ids_add1 classinput-xlarge data-bindvalue: $data.address1> /div> /div> div classcontrol-group data-bindvalidationElement: $data.address2> label fors_add2 classcontrol-label>Address 2/label> div classcontrols> input typetext ids_add2 data-bindvalue: $data.address2> span classhelp-inline text-small>(optional)/span> div classhelp-block text-small>Apartment, Suite, Building, Floor, etc./div> /div> /div> div classcontrol-group data-bindvalidationElement: $data.country> label fors_country classcontrol-label>Country/label> div classcontrols> select ids_country data-bindvalue: $data.country, options: countries, optionsText: countryName, optionsValue: iso3, optionsCaption: Select a country..., change: $data.loadStates> /select> /div> /div> div classcontrol-group data-bindvalidationElement: $data.city> label fors_city classcontrol-label>City/label> div classcontrols> input typetext ids_city data-bindvalue: $data.city> /div> /div> div classcontrol-group data-bindvalidationElement: $data.state> label fors_state classcontrol-label>State / Province/label> div classcontrols> select ids_state data-bindvalue: $data.state, options: $data.stateChoices, optionsText: name, optionsValue: code, optionsCaption: Select a state...> /select> /div> /div> !-- div classcontrol-group data-bindvalidationElement: $data.County> label fors_county classcontrol-label>County/label> div classcontrols> input typetext ids_county data-bindvalue: $data.County> /div> /div --> div classcontrol-group data-bindvalidationElement: $data.zipCode> label fors_zip classcontrol-label>ZIP / Postal Code/label> div classcontrols> input typetext ids_zip classinput-small data-bindvalue: $data.zipCode> /div> /div> div classcontrol-group data-bindvisible: $data.hasOwnProperty(phone)> label fors_phone classcontrol-label>Phone/label> div classcontrols> input typetext ids_phone data-bindvalue: $data.phone> div classhelp-block text-small>Format: span idgc-number-2 classgc-cs-link titleCall with Google Voice>888-555-1234/span> xxxx/div> /div> /div>/script>script typetext/html idcart.shippingSummary> !-- ko if: $data.length > 0 --> !-- div classcheckout-section-body --> div> div classcheckout-section-inner> div classwell> p data-bindvisible : viewModel.useMultiShipEditUI>Your order is being shipped to multiple locations./p> !-- ko ifnot : viewModel.useMultiShipEditUI --> !-- ko template : { name: cart.addressSummaryInfo, data: $data0.shipTo }-->!-- /ko--> !-- /ko --> /div> /div> /div> !-- /ko -->/script>script typetext/html idcart.addressSummaryInfo> p data-bind forEach: $data classaddress-summary> !-- ko if: attention --> span data-bindtext: attention() + , >/span> !-- /ko --> !-- ko if: company --> span data-bindtext: company() + , >/span> !-- /ko --> !-- ko if: firstName() || lastName() --> span data-bindtext: firstName() + + lastName() + , >/span> !-- /ko --> span data-bindtext: address1() + ,, visible: address1>/span> span data-bindtext: address2() + ,, visible: address2>/span> span data-bindtext: address3() + ,, visible: address3>/span> span data-bindtext: address4() + ,, visible: address4>/span> span data-bindtext: address5() + ,, visible: address5>/span> span data-bindvisible: city || state || zipCode> span data-bindtext: city>/span>span data-bindvisible: city>, /span>span data-bindtext: state>/span> span data-bindtext: zipCode>/span> /span> span data-bindtext: country; visible: country>/span> /p>/script>script typetext/html idcart.shipmentItemListSummary> !-- ko if: details().length > 0 --> !-- ko foreach: details --> div classcheckout-multiship-item media> img data-bindattr : { alt: orderDetail.sku() + - + orderDetail.name(), src: utils.buildImagePath(orderDetail.thumbnail()) } classmedia-object onerrorutils.handleImageError(this)> div classmedia-heading> span data-bindtext: orderDetail.sku>/span> - span data-bindhtml: orderDetail.name>/span> !-- ko template: { name :cart.productLeadTimes, data: orderDetail} -->!-- /ko --> /div> small>Qty: span data-bindtext: qtyToShip>/span> of span data-bindtext: orderDetail.qty>/span> !-- ko if:ofConfig.showUom --> span classuom data-bindtext: orderDetail.uom>/span> !-- /ko --> /small> /div> !-- /ko --> !-- /ko -->/script>script typetext/html idcart.shipmentItemList> !-- ko if: details().length > 0 --> div data-bindforeach: details> div classmedia> img data-bindvisible: !oConfig.fastTrack, attr : { alt: orderDetail.sku() + - + orderDetail.name(), src: utils.buildImagePath(orderDetail.thumbnail()) } classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classmedia-body> !-- div classcart-item-sku data-bindtext: orderDetail.sku>/div> --> p classcart-item-name> span data-bindhtml: orderDetail.name>/span> !-- ko template: { name: cart.backorderMessage, data: orderDetail, if: ofConfig.showBackorderMessage } -->!-- /ko --> !-- ko template: { name :cart.productLeadTimes, data: orderDetail} -->!-- /ko --> !-- ko template: { name: cart.softgoods, data: orderDetail, if: ofConfig.showSoftGoodAuthorizations } -->!-- /ko --> !-- ko if: orderDetail.promoID --> span classpromo-icon data-bindattr: { title : orderDetail.promoDescription() } >P/span> !-- /ko --> /p> p>span data-bindhtml: utils.formatMoney(orderDetail.instanceUnitPrice())>/span>/p> div classcart-item-total-qty> span classbadge data-bindtext: qtyToShip()>/span> !-- ko if:ofConfig.showUom --> span classuom data-bindtext: orderDetail.uom>/span> !-- /ko --> on shipment /div> /div> /div> /div> !-- /ko -->/script>script typetext/html idcart.shipmentItemTable> !-- ko if: details().length > 0 --> !-- ko template: { afterRender: function() { $(document).trigger(enhance.tablesaw); } } --> table classtablesaw cart-table data-tablesaw-modestack> thead> th classcart-desc__th data-bindtext: ofConfig.labels.cartDesc>/th> th classcart-qty__th data-bindtext: ofConfig.labels.cartQty>/th> !-- ko if: ofConfig.showPricingOrderEntry --> th classcart-price__th data-bindtext: ofConfig.labels.cartItemPrice>/th> !-- /ko --> !-- ko if: ofConfig.showPricingOrderEntry --> th classcart-total__th data-bindtext: ofConfig.labels.cartTotal>/th> !-- /ko --> !-- ko if: ofConfig.allowProductEditInFinalStep && viewModel.recordType() ! recurring --> th>/th> !-- /ko --> /thead> tbody classcart-row-std data-bindforeach: details> !-- ko if: orderDetail.parentProductID().trim() || !orderDetail.hasParentInCart() --> tr> td> div classmedia> img data-bindvisible: !oConfig.fastTrack, attr : { alt: orderDetail.sku() + - + orderDetail.name(), src: utils.buildImagePath(orderDetail.thumbnail()) }, css: { print-hide: !ofConfig.showProductImagesWhenPrinting } classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classmedia-body> div classcart-item-sku data-bindtext: orderDetail.sku, visible: !orderDetail.parentProductID().trim() || !orderDetail.hasParentInCart()>/div> div classcart-item-name > span data-bindhtml: orderDetail.name>/span> !-- ko template: { name: cart.backorderMessage, data: orderDetail, if: ofConfig.showBackorderMessage } -->!-- /ko --> !-- ko template: { name :cart.productLeadTimes, data: orderDetail} -->!-- /ko --> !-- ko template: { name: cart.softgoods, data: orderDetail, if: ofConfig.showSoftGoodAuthorizations } -->!-- /ko --> !-- ko if: viewModel.recordType() recurring --> div classrecurring-summary data-bindhtml: viewModel.getRecurringLabel($data)>/div> !-- /ko --> !-- ko if: orderDetail.promoID --> span classpromo-icon data-bindattr: { title : orderDetail.promoDescription() } >P/span> !-- /ko --> /div> p data-bindif: ofConfig.AllowWarehouse && orderDetail.productWarehouse> span data-bindhtml: ofConfig.warehouseLabel + + orderDetail.productWarehouse.name()>/span> /p> !-- ko if : ofConfig.bShowCartOptions && orderDetail.cartOption --> p data-bindtext: orderDetail.cartOption>/p> !-- /ko --> !-- ko template: { name: cart.configOptions, data: orderDetail } -->!-- /ko --> !-- ko template: { name: cart.additionalDetailLineInfo, data: orderDetail } -->!-- /ko --> /div> /div> /td> td classinstance-qty-ship__td> span data-bindtext: qtyToShip>/span>span data-bindif: ofConfig.showTotalQtyOnShipment> of span data-bindtext: orderDetail.qty>/span>/span> !-- ko if:ofConfig.showUom --> span classuom data-bindtext: orderDetail.uom>/span> !-- /ko --> /td> !-- ko if: ofConfig.showPricingOrderEntry --> td classinstance-unit-price__td> span data-bindhtml: utils.formatMoney(orderDetail.instanceUnitPrice())>/span> /td> td classinstance-ext-price__td> span data-bindhtml: utils.formatMoney(orderDetail.instanceExtPrice())>/span> /td> !-- /ko --> !-- ko if: !ofConfig.showPricingOrderEntry --> td classinstance-hidden-price__td data-bindhtml: utils.drawHidePriceMessage()>/td> !-- /ko --> !-- ko if: ofConfig.allowProductEditInFinalStep && viewModel.recordType() ! recurring --> td classrecurring__td> !-- ko template: { name: cart.productInlineEditLinks, data: orderDetail } -->!-- /ko --> /td> !-- /ko --> /tr> !-- ko if:orderDetail.editing() && viewModel.mainProduct() --> tr> td colspan5> div classdetail-child-selector> span data-bindtemplate: { name: catalog.child_selectors, if: viewModel.mainProduct().childSelectors, data: viewModel.mainProduct().childSelectors }>/span> /div> !-- ko template: { name:catalog.atc_full, data:viewModel.mainProduct().selectedProduct, if:viewModel.mainProduct } -->!-- /ko --> /td> /tr> !-- /ko --> !-- /ko --> /tbody> /table> !-- /ko --> !-- /ko -->/script>script typetext/html idcart.additionalDetailLineInfo>/script>script typetext/html idcart.configOptions> !-- ko if : configuratorJson.choices --> div classconfig-options stylemargin:0;padding-bottom:0;border: 1px solid #ddd;> div classconfig-options__title stylebackground-color: #ddd; padding:5px 10px; margin: 0 0 5px 0;float:none;> span classconfig-options__type stylefont-weight: bold; data-bindtext: configuratorJson.configType() cartoptions ? Options : Configuration Options>/span> span classpull-right config-options__details data-bindvisible: configuratorJson.configType() ! cartoptions> !-- ko template: { name: cart.productEditLink, data: { title: Edit Configuration, linkText: Edit, detailLine: $data } } -->!-- /ko --> /span> /div> ul classconfigOptions config-options__group data-bindforeach: configuratorJson.choices> li classconfig-options__item>strong>span data-bindtext: questionText>/span>/strong> span data-bindtext: answerText>/span>/li> /ul> !-- ko if: instanceChildren.length > 0 --> table classtablesaw cart-table config-options__cart-table> thead classconfig-options__thead> th classconfig-options__qty-title>Qty/th> th classconfig-options__price-title>Item Price/th> th classconfig-options__desc-title>Description/th> /thead> tbody classcart-row-std config-options__tbody data-bindforeach: instanceChildren> tr> td classconfig-options__qty-text data-bindtext: qty>/td> td classconfig-options__price-text>span data-bindhtml: utils.formatMoney( (priceBeforeAdjustment() || price()) )>/span>/td> td classconfig-options__desc-text data-bindhtml: name>/td> /tr> /tbody> /table> !-- /ko --> /div> !-- /ko -->/script>script typetext/html idcart.addAddressButton> a typebutton classglobal-modal data-sizefull data-titleAdd Shipping Address data-bind visible: ofConfig.bAllowShipToAdds, attr: { href : account.asp?modalactionaddshipto&modal1&o_key + viewModel.orderKey() }, addModalHandler: { element : $(#shipping_address_summary .global-modal), handler : addAddressHandler }> i classicon-plus-sign icon-fixed-width>/i>Add span classhidden-xs hidden-sm>a new/span> span classhidden-xs>address/span> /a>/script>script typetext/html idcart.addProductButton> li classdropdown pull-right hide> a typebutton classadd-product dropdown-toggle data-toggledropdown> i classicon-plus-sign icon-fixed-width>/i>Add Products span classcaret>/span>/a> /a> ul classdropdown-menu> li> a classglobal-modal add-bulk data-sizefull data-titleAdd Products data-bind attr: { href : bulk_atc.asp?modalactionaddProduct&modal1&o_key + viewModel.orderKey() }, addModalHandler: { element : $(.add-bulk), handler : viewModel.genericModalComplete }, click: function() { utils.setActiveQuote(viewModel.orderKey()); return true; } >Quick Add/a> /li> li> a classglobal-modal add-browse data-sizefull data-titleAdd Products data-bind attr: { href : pc_combined_results.asp?modalactionaddProduct&modal1&o_key + viewModel.orderKey() }, addModalHandler: { element : $(.add-browse), handler : viewModel.genericModalComplete }, click: function() { utils.setActiveQuote(viewModel.orderKey()); return true; } >Browse/a> /li> li> a classglobal-modal add-from-fave data-sizefull data-titleAdd Products data-bind attr: { href : favorite_lists_man.asp?modalactionaddProduct&modal1&o_key + viewModel.orderKey() }, addModalHandler: { element : $(.add-from-fave), handler : viewModel.genericModalComplete }, click: function() { utils.setActiveQuote(viewModel.orderKey()); return true; } >From Favorites/a>/li> li>a classglobal-modal add-from-so data-sizefull data-titleAdd Products data-bind attr: { href : erp_manage_sales_orders.asp?modalactionaddProduct&modal1&o_key + viewModel.orderKey()}, addModalHandler: { element : $(.add-from-so), handler : viewModel.genericModalComplete }, click: function() { utils.setActiveQuote(viewModel.orderKey()); return true; } >From Sales Order/a>/li> /ul> /li>/script>style typetext/css> .media.noborder, .tablesaw-stack tbody tr.noborder, .item-list .media.noborder { border-bottom:0; margin-bottom:0; padding-bottom:0; border-top: 0; display: none; } .tablesaw tbody tr, .item-list .media { border-top: 1px solid #dfdfdf; border-bottom: 0; } .item-list .media { padding-top: 10px; } .configOptions { list-style-type: none; margin-right: 10px; }/style>script typetext/html idcart.itemCard> img data-bindattr : { alt: sku() + - + name(), src: utils.buildImagePath(commodity.pic.thumb()) }, visible: !oConfig.fastTrack && (!parentProductID().trim() || !hasParentInCart() ) classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classpull-left cart-item-pic data-bindvisible: !oConfig.fastTrack && parentProductID().trim() && hasParentInCart()> /div> div classmedia-body> div classmedia-heading> b data-bindhtml: name>/b> !-- ko if : promoID --> span classpromo-icon data-bindattr: { title : promoDescription() } >P/span> !-- /ko --> p classtext-xsmall muted data-bindtext: sku, visible: !parentProductID().trim() || !hasParentInCart()>/p> !-- ko template: { name: cart.backorderMessage, if: ofConfig.showBackorderMessage } -->!-- /ko --> !-- ko template: cart.productLeadTimes -->!-- /ko --> !-- ko template: { name: cart.softgoods, if: ofConfig.showSoftGoodAuthorizations } -->!-- /ko --> div data-bindif: ofConfig.AllowWarehouse && $data.productWarehouse> span data-bindhtml: ofConfig.warehouseLabel + + $data.productWarehouse.name()>/span> span data-bindif: viewModel.allowWarehouseSelection() && !viewModel.useMultiShipEditUI()> !-- ko template: { name: cart.productEditLink, data: { title: Change Warehouse, linkText: (Change Warehouse), detailLine: $data } } -->!-- /ko --> /span> /div> !-- ko if : ofConfig.bShowCartOptions && cartOption --> p data-bindtext: cartOption>/p> !-- /ko --> !-- ko template: { name: cart.configOptions, data: $data } -->!-- /ko --> !-- ko template: { name: cart.additionalDetailLineInfo, data: $data } -->!-- /ko --> /div> !-- ko if:$data.editing() && viewModel.mainProduct() --> div stylemax-width: 300px;> !-- ko template: { name: catalog.detail_info, data:viewModel.mainProduct } -->!-- /ko --> div classdetail-child-selector> span data-bindtemplate: { name: catalog.child_selectors, if: viewModel.mainProduct().childSelectors, data: viewModel.mainProduct().childSelectors }>/span> /div> !-- ko template: { name:catalog.atc_full, data:viewModel.mainProduct().selectedProduct } -->!-- /ko --> /div> !-- /ko --> !-- ko if : viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits && $data.qtyDisplayType() input && !$data.editing() && ofConfig.showPricingOrderEntry --> div classcart-item-price> p classinput-prepend input-append> span classadd-on>$/span> input typenumber classinput-small step.01 data-bind value: price, attr: { id : price- + orderDetailKey() }, event: { change: viewModel.setItemShipToMapPrice($data) } > !-- ko if: priceCalculationType() fixed --> a href#0 classadd-on data-bindevent: { click: viewModel.resetSuperUserPriceOverride }, html: ofConfig.superUserResetPriceHelpText> /a> !-- /ko --> /p> span classhelp-block data-bindif: viewModel.superUserRestrictMinPrice() & superUserMinPrice() ! null>Min: span data-bindhtml: utils.formatMoney(superUserMinPrice())>/span>/span> !-- ko if: ofConfig.showSUPriceControls && (commodity.cost() || commodity.retailPrice()) --> !-- ko template: cart.priceHelper -->!-- /ko --> !-- /ko --> /div> !-- /ko --> !-- ko if : (!(viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits) || $data.qtyDisplayType() text) && !$data.editing() && ofConfig.showPricingOrderEntry --> div classcart-item-price data-bindhtml: utils.formatMoney(instanceUnitPrice())>/div> !-- /ko --> !-- ko if : !ofConfig.showPricingOrderEntry --> div classcart-item-hiddenprice data-bindhtml: utils.drawHidePriceMessage()>/div> !-- /ko --> !-- ko if : viewModel.useMultiShipEditUI() || $data.qtyDisplayType() text || !viewModel.allowProductAdds() && !$data.editing() --> div classcart-item-qty> label> input typetext classqty-input disabled data-bindattr: { value: viewModel.getTotalQty(instance()) }> !-- ko if:ofConfig.showUom --> span classuom data-bindtext: $data.uom>/span> !-- /ko --> on span classorder data-bindvisible:!viewModel.useMultiShipEditUI()>order/span>span classshipment data-bindvisible: viewModel.useMultiShipEditUI()>shipment/span> /label> !-- ko if : viewModel.allowQtyControls() --> !-- ko template: cart.qtyControlSettings -->!-- /ko --> !-- /ko --> /div> !-- /ko --> !-- ko if : !viewModel.useMultiShipEditUI() && $data.qtyDisplayType() input && viewModel.allowProductAdds() && !$data.editing()--> div classcart-item-qty> label> input typenumber classqty-input data-bind value: qty, attr: { id : qty-ship- + orderDetailKey(), min : minQty(), step : qtyIncrement() || 1, max : maxQty() || undefined }, validateQty > span data-bind attr: { data-key : orderDetailKey() }, visible: minQty() > 1 || maxQty() > 1 || qtyIncrement() > 1> a href#0 data-triggerhover data-htmltrue data-placementtop data-bindpopover, attr: { data-content: oConfig.labels.minQty + : + minQty() + br> + oConfig.labels.step + : + qtyIncrement() + br> + oConfig.labels.maxQty + : + maxQty() }> i classicon-question-sign>/i> /a> /span> !-- ko if:ofConfig.showUom --> span classuom data-bindtext: $data.uom>/span> !-- /ko --> on order /label> !-- ko if : viewModel.allowQtyControls() --> !-- ko template: cart.qtyControlSettings -->!-- /ko --> !-- /ko --> /div> !-- /ko --> !-- div classtext-small muted data-bindattr: { data-key : orderDetailKey() } > div idqty_controls_msg > span data-bindif: minQty() > 0> span data-bindtext: oConfig.labels.minQty>/span>: span data-bindtext: minQty()>/span>br> /span> span data-bindif: maxQty() > 0> span data-bindtext: oConfig.labels.maxQty>/span>: span data-bindtext: maxQty()>/span>br> /span> span data-bindif: qtyIncrement() && qtyIncrement() ! 1> span data-bindtext: oConfig.labels.step>/span>: span data-bindtext: qtyIncrement()>/span>br> /span> /div> /div> --> div classproduct-delete-edit-wrap> !-- ko if: viewModel.showRemoveLink($data) --> span classproduct-delete> a href data-bindevent: { click: viewModel.removeProduct }, visible: !editing() titleRemove this item from your Order? classtext-xsmall> i classicon icon-small icon-remove>/i> span classvisible-lg>remove/span> /a> /span> br /> !-- /ko --> !-- ko if: viewModel.allowProductAdds() && ofConfig.allowProductEditInEditView --> !-- ko template: { name: cart.productInlineEditLinks } -->!-- /ko --> !-- /ko --> /div> !-- ko if: viewModel.recordType() recurring && !editing()--> div classorder-items-recurring> div classorder-items-label visible-xs visible-sm>Schedule/div> !-- ko template: { name: cart.recurringLineDetails } -->!-- /ko --> /div> !-- /ko --> /div>/script>script typetext/html idcart.productInlineEditLinks> span classproduct-edit> a href styledisplay: block data-bindevent: { click: viewModel.editProduct }, visible: !editing() titleEdit this line item classtext-xsmall> i classicon icon-small icon-edit>/i> span classvisible-lg>edit/span> /a> a href styledisplay: block; wrap: none; data-bindevent: { click: viewModel.cancelEditProduct }, visible: editing titleCancel edits classtext-xsmall> i classicon icon-small icon-remove>/i> span classvisible-lg>cancel/span> /a> /span>/script>script typetext/html idcart.productEditLink> a classglobal-modal productEditLink data-bindattr: { href: pc_product_detail.asp?key + detailLine.productID() + &od_key + detailLine.orderDetailKey(), data-title: title }, text: linkText, addModalHandler: { element : $(.productEditLink), handler : viewModel.genericModalComplete }, click: function() { utils.setActiveQuote(viewModel.orderKey()); return true; }, visible: !viewModel.completed() && viewModel.allowProductAdds() data-sizelarge>/a>/script>script typetext/html idcart.selectShipTo> !-- ko if: ofConfig.useProductSummaryTableView --> div classrow-fluid checkout-multiship-row single-ship table-view> div classship-to-select data-bindif: shipments().length > 0 > div classaddress-select> label>Ship to this address:/label> div classinput-append data-bindwith: shipments()0> !-- ko template: cart.shipToSelectOptGroups-->!-- /ko --> /div> /div> /div> p> /p> !-- ko template: { name: cart.productQuickAdd, if: viewModel.allowProductAdds() && ofConfig.showProductQuickAddInEditView } -->!-- /ko --> p> /p> div classitems-on-order> label>Items on Order:/label> div classitem-list> div data-bindforeach: $data.itemsOnOrder> !-- ko if: parentProductID().trim() || !hasParentInCart() --> div classmedia data-bindtemplate: cart.itemCard>/div> !-- /ko --> /div> /div> /div> /div> !-- /ko --> !-- ko ifnot: ofConfig.useProductSummaryTableView --> div classrow-fluid checkout-multiship-row single-ship> div classship-to-select span6 data-bindif: shipments().length > 0 > div classaddress-select> label>Ship to this address:/label> div classinput-append data-bindwith: shipments()0> !-- ko template: cart.shipToSelectOptGroups-->!-- /ko --> /div> /div> /div> div classitems-on-order span6> label>Items on Order:/label> div classitem-list> div data-bindforeach: $data.itemsOnOrder> !-- ko if: parentProductID().trim() || !hasParentInCart() --> div classmedia data-bindtemplate: cart.itemCard>/div> !-- /ko --> /div> /div> /div> /div> !-- /ko -->/script>script typetext/html idcart.shipToSelect> select classinput-auto data-bind options: availableAddresses, optionsText: function(item){ return item.name(); }, value: shipTo > /select>/script>script typetext/html idcart.shipToSelectOptGroups> select classinput-auto data-bind foreach: viewModel.addressTypes(), value: shipTo > optgroup data-bindattr: {label: $data.label }, foreach: $parent.availableAddresses> !-- ko if: $data.global() $parent.global --> option data-bind value: $data, text: $data.name()>/option> !-- /ko --> /optgroup> /select> span classadd-on data-bindvisible: $data.shipTo().global() 0 && viewModel.allowShaEdits()> a classedit-shipto global-modal data-sizefull data-bind addModalHandler: { element : $(#shipping_address_summary .global-modal), handler : function(data){ apiGetShippingAddresses(data); } }, attr: { href: account.asp?modalactioneditshipto&modal1&o_key + viewModel.orderKey() + &sha_id + $data.shipTo().key() }, visible: viewModel.allowShaEdits() >Edit/a> /span>/script>script typetext/html idcart.assignItemsToShipTos> div data-bindforeach: $data> !-- ko if: parentProductID().trim() || !hasParentInCart() --> div classrow-fluid checkout-multiship-row> div classspan5> div classmedia data-bindtemplate: { name: cart.itemCard }>/div> /div> div classspan7> !-- div data-bindforeach: viewModel.itemShipToMap().filter(function(shipToMap){ return shipToMap.instance() instance() }) --> div data-bindforeach: viewModel.itemShipToMap().filter(function(shipToMap){ return shipToMap.orderDetailKey orderDetailKey() }) > div classinput-prepend input-append> input typenumber classqty-input data-bind value: qty, attr: { id : qty-ship- + orderDetailKey, min : $parent.minQty(), step : $parent.qtyIncrement() || 1, max : $parent.maxQty() || undefined }, disable: $parent.qtyDisplayType() text, validateQty > !-- ko template: cart.shipToSelectOptGroups-->!-- /ko --> !-- ko if: $index() ! 0 --> span classadd-on> a classremove-shipto href# data-bindclick: removeItemToShipToMap, attr: { data-index : $index}>Remove/a> /span> !-- /ko --> /div> p> button classbtn btn-link btn-small split-this typebutton data-bind attr : { data-split : parseFloat(qty()) }, visible: qty() > minQty() && (parseFloat(qty()) > parseFloat(qtyIncrement() * 2)) && $parent.qtyDisplayType() input, text: ofConfig.splitThisItemText, click: moveItemToNewShipTo > /button> /p> /div> /div> /div> !-- /ko --> /div>/script>script typetext/html idcart.itemShipToMapPreview> table classtablesaw data-tablesaw-modestack> thead> th>#/th> th>Ship to address/th> th>Items in shipment/th> th> /th> /thead> tbody data-bindforeach: _.uniq(_.invoke(viewModel.itemShipToMap(),shipTo))> tr> td> !-- ko template: { name: cart.addressSummaryInfo, data: $data } -->!-- /ko --> /td> td> span class data-bindforeach: viewModel.itemShipToMap().filter(function(shipToMap){ return shipToMap.shaKey() $data.key() }) > ul classunstyled data-bindforeach: viewModel.itemsOnOrder().filter(function(item){ return item.orderDetailKey() orderDetailKey })> li>span classbadge data-bindtext: qty>/span> span data-bindhtml : name>/span>/li> /div> /span> /td> td classcell-center> button classbtn btn-inverse>i classicon-trash>/i>/button> /td> /tr> /tbody> /table>/script>script typetext/html idcart.itemsList> table classtablesaw table cart-table tablesaw-stack data-tablesaw-modestack> !-- ko if: viewModel.useMultiShipEditUI() && !viewModel.allItemsAllocated() --> thead> th>/th> th> Description /th> th> Qty /th> th> Item Price /th> th> Total /th> /thead> !-- /ko --> !-- ko if: viewModel.allItemsAllocated() || !viewModel.useMultiShipEditUI() --> thead> th> Description /th> th> Qty /th> th> Item Price /th> th> Total /th> /thead> !-- /ko --> tbody classcart-row-std data-bindforeach: $data> !-- ko if: parentProductID().trim() || !hasParentInCart() --> tr data-bindcss: { alert alert-warning: viewModel.useMultiShipEditUI() && allocatedQty() ! qty() }> !-- ko if: viewModel.useMultiShipEditUI() && !viewModel.allItemsAllocated() --> td> span data-bindif: qty() ! allocatedQty()>i classicon-warning-sign>/i> span data-bindtext: qty() - allocatedQty()>/span> unallocated/span> /td> !-- /ko --> td classmedia> img data-bindvisible: !oConfig.fastTrack,attr : { alt: sku() + - + name(), src: utils.buildImagePath(commodity.pic.thumb()) } classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classmedia-body> div classcart-item-sku data-bindtext: sku>/div> !-- ko if : ofConfig.bShowCartOptions && cartOption --> p data-bindtext: cartOption>/p> !-- /ko --> !-- ko template: { name: cart.configOptions, data: $data } -->!-- /ko --> !-- ko template: { name: cart.additionalDetailLineInfo, data: $data } -->!-- /ko --> !-- ko if: viewModel.recordType() recurring --> div classflex-table-column order-items-recurring> div classorder-items-label visible-xs visible-sm>Schedule/div> !-- ko template: { name: cart.recurringLineDetails } -->!-- /ko --> /div> !-- /ko --> div classcart-item-name > span data-bindhtml: name>/span> !-- ko if: promoID --> span classpromo-icon data-bindattr: { title : promoDescription() } >P/span> !-- /ko --> /div> /div> /td> td> span data-bindtext: qty>/span> !-- ko if: viewModel.useMultiShipEditUI --> (span data-bindtext: allocatedQty>/span> assigned) !-- /ko --> /td> td> span data-bindhtml: utils.formatMoney(priceBeforeAdjustment() || price())>/span> /td> td> span data-bindhtml: utils.formatMoney((priceBeforeAdjustment() || price()) * qty())>/span> /td> /tr> !-- /ko --> /tbody> /table>/script>script typetext/html idcart.priceHelper> a data-bindvisible: ofConfig.collapsePriceControls href#0 onclick$(this).next(.collapse).toggleClass(in); return false;> Pricing Controls i classicon-angle-down>/i> /a> span data-bindcss: { collapse: ofConfig.collapsePriceControls } stylemargin-top: 5px;display:block;> !-- ko if: commodity.cost() --> label> div classinput-append> input typenumber classqty-input step1 data-bind value: markupPercent, attr: { id : markupPercent- + orderDetailKey(), min: minMarkupPercent }, event: { change: viewModel.setItemShipToMapPrice($data) } > span classadd-on>%/span> /div> Markup /label> !-- /ko --> !-- ko if: commodity.retailPrice() --> label> div classinput-append> input typenumber classqty-input step1 data-bind value: discountPercent, attr: { id : discountPercent- + orderDetailKey(), max: maxDiscountPercent }, event: { change: viewModel.setItemShipToMapPrice($data) } > span classadd-on>%/span> /div> Discount /label> !-- /ko --> !-- ko if: commodity.cost() --> label> div classinput-append> input typenumber classqty-input step1 data-bind value: grossMarginPercent, attr: { id : grossMarginPercent- + orderDetailKey(), min: minGrossMarginPercent }, event: { change: viewModel.setItemShipToMapPrice($data) } > span classadd-on>%/span> /div> Gross margin /label> !-- /ko --> !-- ko if: commodity.cost() --> label> div classinput-prepend> span classadd-on>$/span> input typenumber classqty-input step.01 data-bind value: grossMarginAmount, attr: { id : grossMarginAmount- + orderDetailKey(), min: minGrossMarginAmount }, event: { change: viewModel.setItemShipToMapPrice($data) } > /div> Gross margin /label> !-- /ko --> /span>/script>script typetext/html idcart.qtyControlSettings> a data-bindvisible: ofConfig.collapseQtyControls href#0 onclick$(this).next(.collapse).toggleClass(in); return false;> Qty Controls i classicon-angle-down>/i> /a> p data-bindcss: { collapse: ofConfig.collapseQtyControls, well: !ofConfig.collapseQtyControls } stylemargin-top: 5px;> !-- ko if: $data.qtyDisplayType() input --> label> input typenumber min1 classqty-input data-bind value: suMinQty, attr: { id : minQty + orderDetailKey() } > Min Qty /label> label> input typenumber min0 classqty-input data-bind value: suMaxQty, attr: { id : maxQty + orderDetailKey() } > Max Qty /label> label> input typenumber min1 classqty-input data-bind value: suQtyIncrement, attr: { id : qtyIncrement + orderDetailKey() } > Qty Increment /label> !-- /ko --> !-- TODO: Do we need to hide if original removeType hide? --> label classcheckbox> input typecheckbox data-bindchecked: allowDeletes, attr: { id: allowDeletes- + orderDetailKey() }> Allow deletes /label> /p>/script>script typetext/html idcart.paymentMethodList_radio> div classpaymentmethods --radio control-group> div classcontrol-label>strong>Select Payment Method/strong>/div> div classcontrols data-bindforeach: payMethods> label classpaymentmethod> input typeradio nameshipmethod data-bindvalue: $data.paymentMethodKey(), checked: $parent.paymentMethod.paymentMethodKey(), click: $parent.setPaymentMethod> span data-bindtext: name>/span> /label> /div> /div>/script>script typetext/html idcart.paymentMethodList_tabs> ul classnav nav-tabs data-bindforeach: payMethods> li data-bind css: { active: $parent.paymentMethod.paymentMethodKey() $data.paymentMethodKey() } > a data-bindattr: { id: paymentMethodKey, data-content: description, href: #method_ + paymentType() }, text: name, click: $parent.setPaymentMethod, clickBubble: true data-togglepill relpopover data-triggerhover data-placementtop>/a> /li> /ul>/script>script typetext/html idcart.paymentMethods> !-- ko template: { name: cart.paymentMethodList_ + ofConfig.payMethodDisplayType } -->!-- /ko --> div classtab-content> div idmethod_cc: classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() cc }> div data-bindtemplate : { name: cart.creditCardForm }>/div> /div> div idmethod_billme classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() billme }> /div> div idmethod_ach-check classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() ach-check }> h3>-- ACH is not implemented yet, but would go here --/h3> !-- drawAchCheckForm --> /div> div idmethod_paypal classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() paypal }> /div> div idcontrolgroup_invoice_ponumber classcontrol-group data-bindif: paymentMethodID && paymentMethod.collectPO()> hr> label forponumber classcontrol-label data-bindhtml: ofConfig.POLabel>/label> div classcontrols> input typetext nameponumber idponumber data-bindvalue: poNumber, attr: { maxlength: ofConfig.POMaxLength, required: viewModel.paymentMethod.poRequired() true ? required : null } /> input typehidden idponum_required value0 data-bindif: !viewModel.paymentMethod.poRequired()/> !-- ko if: !viewModel.paymentMethod.poRequired() --> p idponum_help classhelp-block text-small data-bindhtml: ofConfig.POLabelHelp>/p> !-- /ko --> input typehidden idponum_required value1 data-bindif: viewModel.paymentMethod.poRequired()/> p idponum_help classhelp-block text-small data-bindif: viewModel.paymentMethod.poRequired()>(required)/p> /div> /div> div idcontrolgroup_invoice_comments classcontrol-group data-bindif: ofConfig.showFulfillmentcomments> hr> label fororder_comments classcontrol-label> strong data-bindtext: ofConfig.fulfillmentCommentsText>/strong> /label> div classcontrols> textarea typetext nameorder_comments idorder_comments autocompleteoff data-bindvalue: comments, attr: { maxlength: ofConfig.fulfillmentcommentsMaxLength }>/textarea> p classhelp-block text-small>(optional)/p> /div> /div> /div>/script>script typetext/html idcart.productSelectList>!-- ko if: $data --> div idmodal_add_prods classmodal fade hide data-backdropstatic data-max-height400> div classmodal-header> h3>Select Items to Ship/h3> /div> div classmodal-body> div classlist-group list-group-flex js-shipItemSelect data-bindif: detailsMap> !-- ko foreach: detailsMap --> span data-forasdfcheckout_item_1 classlist-group-item> !-- was a label, changed to span to keep checkbox from being erroneously changed as you click other elements in the list item, will drive check box off of qty, and set qty to 0 if checkbox is un-checked by user --> div classflex-item checkbox> input typecheckbox idcheckout_item_1 data-bindchecked: toggleItemSelect, attr : { disabled: unallocatedQty() 0 && qtyToShip() 0} /> /div> div classflex-item flex-item-grow media checkout-multiship-item> img data-bindattr : { alt: detailLine.sku() + - + detailLine.name(), src: utils.buildImagePath(detailLine.commodity.pic.thumb()) } classmedia-object pull-left onerrorutils.handleImageError(this) /> div classmedia-body> div classmedia-heading> div classtext-trim stylemax-width: 20em; data-bindattr: { title: detailLine.sku() + - + detailLine.name() }> span data-bindtext: detailLine.sku>/span> - span data-bindtext: detailLine.name>/span> /div> /div> table classtable table-condensed text-xsmall> tbody> tr> td>Total Qty/td> td classcell-right data-bindtext: totalOrderQty>/td> /tr> tr> td>Currently included in this shipment/td> td classcell-right> span data-bindtext: qtyToShip>/span> !-- ko if:ofConfig.showUom --> span classuom data-bindtext: detailLine.uom>/span> !-- /ko --> /td> /tr> tr> td>Included in all shipments/td> td classcell-right data-bindtext: qtyInAllShipments>/td> /tr> tr> td>Remaining/td> td classcell-right data-bindtext: unallocatedQty>/td> /tr> /tbody> /table> /div> /div> div classflex-item> label formulti_prod_qty_1>Include/label> input typenumber idmulti_prod_qty_1 classqty-input min0 data-bindattr: { max: Number(unallocatedQty()) + Number(qtyToShip()) } , value: qtyToShip, restrictedQty /> /div> /span> !-- /ko --> /div> /div> div classmodal-footer> button typebutton classbtn btn-link data-dismissmodal>Cancel/button> button typebutton idbtn_add_to_shipment classbtn btn-primary data-bindclick: selectItemsComplete, clickBubble: false>Update shipment/button> /div> /div>!-- /ko -->/script>script typetext/html idcart.shipmentSummaryList> !-- ko foreach: shipments --> div classlist-group> div classlist-group-item data-bindvisible: $parent.useMultiShipEditUI> h5> !-- ko template: { name: cart.addressSummaryInfo, data: shipTo } -->!-- /ko --> /h5> /div> div classlist-group-item> !-- ko template: { name: cart.shipmentItemTable } -->!-- /ko --> div classlist-group-item__content-row row-fluid> div classlist-group-item__content-span span4 data-bindif: selectedShipVia> div classlist-group-item__content> b>Shipping Method:/b> div> span data-bindtext: selectedShipVia.name>/span> !-- ko if : ofConfig.bShowShipTotalMessage --> (span data-bindtext: ofConfig.sShipTotalText>/span>) !-- /ko --> !-- ko ifnot: ofConfig.bShowShipTotalMessage --> !-- ko if: ofConfig.bShowPriceText && selectedShipVia.total() 0 --> (span data-bindtext: ofConfig.sShipTotalText>/span>) !-- /ko --> !-- ko if: !ofConfig.bShowPriceText || selectedShipVia.total() > 0 --> (span data-bindhtml: utils.formatMoney(selectedShipVia.total())>/span>) !-- /ko --> !-- /ko --> /div> /div> /div> div classlist-group-item__content-span span4 data-bindif: ofConfig.UseRequestedDay> div classlist-group-item__content> b>Will be shipped on: /b> div data-bindtext: requestedShipDate>/div> /div> /div> div classlist-group-item__content-span span4 data-bindif: !ofConfig.UseRequestedDay && ofConfig.bUseExpectedShipDate> div classlist-group-item__content> b>Will be shipped on: /b> div data-bindtext: expectedShipDate>/div> /div> /div> !-- ko if : ofConfig.bShowShipmentComment --> div classlist-group-item__content-span span4> div classlist-group-item__content> b data-bind html : ofConfig.sShipmentCommentTitle + :>/b> div data-bind html : comments() ? comments : No + ofConfig.sShipmentCommentTitle>/div> /div> /div> !-- /ko --> /div> /div> /div> !-- /ko -->/script>script typetext/html idcart.shipmentList> !-- ko foreach: shipments --> div classrow-fluid shipment-list data-bindattr: { id: key }> div classlist-group shipment-list__group> div classlist-group-item clearfix shipment-list__item> div data-bindif : $parent.shipments().length > 1 classshipment-title pull-left> !-- ko template: { name: cart.addressSummaryInfo, data: shipTo, if: !showShippingAddressEdit() && shipToValid() } -->!-- /ko --> !-- ko template: { name: cart.shipmentSplitByDisplay } -->!-- /ko --> /div> div classpull-right shipment-list__text> a classshipment-list__link href#0 data-bindclick: function() { viewModel.shippingComplete(false) }, html: ofConfig.sEditShipmentText>/a> i classicon-large icon-question-sign shipment-help shipment-list__link-icon data-triggerhover data-placementleft data-bindpopover, attr: { data-content: function(){ if(utils.getCookie(activequote) && utils.getCookie(activequote).length 32){ return ofConfig.shipmentListEditBtnHelpTextQuote; }else{ return ofConfig.shipmentListEditBtnHelpText; } }(), title: ofConfig.shipmentListEditBtnHelpTitleText }> /i> /div> /div> !-- ko if : ofConfig.useProductSummaryTableView --> div classlist-group-item> div classrow-fluid> !-- ko template: { name: cart.shipmentItemTable } -->!-- /ko --> /div> /div> div classlist-group-item> div classrow-fluid> div data-bindif: ofConfig.bUsingShipping, css: { span7: ofConfig.bShowShipmentComment || ofConfig.UseRequestedDay || ofConfig.bUseExpectedShipDate }> div classwell > label data-bindhtml: ofConfig.shipmentListChooseMethodLabel>/label> !-- ko template: { name: cart.shipmentMethodSelector } -->!-- /ko --> /div> !-- ko template: { if : ofConfig.CollectShipAccount, name: cart.shipperAccountSelector }-->!-- /ko --> /div> div classspan5 data-bindif: ofConfig.bShowShipmentComment || ofConfig.UseRequestedDay || ofConfig.bUseExpectedShipDate> h5 data-bind html : ofConfig.sShipmentCommentTitle>/h5> !-- ko template: { if: ofConfig.bShowShipmentComment, name: cart.shipmentGiftOptions } -->!-- /ko --> !-- ko template: { if: ofConfig.UseRequestedDay, name: cart.requestedShipDate } --> !-- /ko --> !-- ko template: { if: ofConfig.bUseExpectedShipDate, name: cart.expectedShipDate } -->!-- /ko --> /div> /div> /div> !-- /ko --> !-- ko if : !ofConfig.useProductSummaryTableView --> div classlist-group-item> div classrow-fluid> div classspan5> !-- ko template: { name: cart.shipmentItemList } -->!-- /ko --> /div> div classspan7> label data-bindhtml: ofConfig.shipmentListChooseMethodLabel>/label> !-- ko template: { name: cart.shipmentMethodSelector } -->!-- /ko --> !-- ko template: { if: ofConfig.bShowShipmentComment, name: cart.shipmentGiftOptions } -->!-- /ko --> !-- ko template: { if: ofConfig.UseRequestedDay, name: cart.requestedShipDate } --> !-- /ko --> !-- ko template: { if: ofConfig.bUseExpectedShipDate, name: cart.expectedShipDate } -->!-- /ko --> /div> /div> /div> !-- /ko --> /div> /div> !-- /ko -->/script>script typetext/html idcart.shipmentSplitByDisplay> div classship-from data-bindhtml: $data.shipFrom.name>/div>/script>script typetext/html idcart.errorMessage> p classhelp-inline data-bindvisible: field.isModified() && !field.isValid(), text: field.error>/p>/script>script typetext/html idcart.processingOverlay> div idappLoadingWidget classapp-loading> svg idappLoadingSpinner classapp-loading-spinner version1.1 xmlnshttp://www.w3.org/2000/svg xmlns:xlinkhttp://www.w3.org/1999/xlink x0px y0px width170px height170px viewBox-220 312 170 170 enable-backgroundnew -220 312 170 170 xml:spacepreserve> g classapp-loading-spinner-svg> path fill#AAAAAA dM-67.6,398.2l13.5-4c-0.3-5.9-1.1-11.6-2.4-17l-14-0.3c-0.5-1.6-1.1-3-1.6-4.6l10.8-8.9 c-2.4-5.1-5.4-10.2-8.6-14.8l-13.2,5.1c-1.1-1.3-2.2-2.4-3.2-3.5l6.5-12.4c-4.3-3.8-8.9-7.3-13.8-10.2l-10,9.7 c-1.3-0.8-3-1.3-4.3-2.2l1.3-14c-5.4-1.9-10.8-3.5-16.7-4.3l-5.7,12.9c-1.6-0.3-3.2-0.3-4.9-0.3l-4-13.5c-5.9,0.3-11.6,1.1-17,2.4 l-0.3,14c-1.6,0.5-3,1.1-4.6,1.6l-8.9-10.8c-5.1,2.4-10.2,5.4-14.8,8.6l5.1,13.2c-1.3,1.1-2.4,2.2-3.5,3.2l-12.4-6.5 c-3.8,4.3-7.3,8.9-10.2,13.8l9.7,10c-0.8,1.3-1.3,3-2.2,4.3l-14-1.3c-1.9,5.4-3.5,10.8-4.3,16.7l12.9,5.7c-0.3,1.6-0.3,3.2-0.3,4.9 l-13.5,4c0.3,5.9,1.1,11.6,2.4,17l14,0.3c0.5,1.6,1.1,3,1.6,4.6l-10.8,8.9c2.4,5.1,5.4,10.2,8.6,14.8l13.2-5.1 c1.1,1.3,2.2,2.4,3.2,3.5l-6.5,12.4c4.3,3.8,8.9,7.3,13.8,10.2l10-9.7c1.3,0.8,3,1.3,4.3,2.2l-1.3,14c5.4,1.9,10.8,3.5,16.7,4.3 l5.7-12.9c1.6,0.3,3.2,0.3,4.9,0.3l4,13.5c5.9-0.3,11.6-1.1,17-2.4l0.3-14c1.6-0.5,3-1.1,4.6-1.6l8.9,10.8 c5.1-2.4,10.2-5.4,14.8-8.6l-5.1-13.5c1.3-1.1,2.4-2.2,3.5-3.2l12.4,6.5c3.8-4.3,7.3-8.9,10.2-13.8l-9.7-10c0.8-1.3,1.3-3,2.2-4.3 l14,1.3c1.9-5.4,3.5-10.8,4.3-16.7l-12.9-5.7C-67.9,401.4-67.6,399.8-67.6,398.2z M-135,437.3c-22.4,0-40.4-18.1-40.4-40.4 c0-22.4,18.1-40.4,40.4-40.4s40.4,18.1,40.4,40.4C-94.6,419.2-112.7,437.3-135,437.3z>/path> /g> image classapp-loading-spinner-img srctemplates/gfx/loading/loading.gif altLoading...>/image> /svg> /div>/script>script typetext/html idcart.expirationDate> div classcontrol-group data-bindif: (superUserOrderFormMode() && ofConfig.superUserAllowExpirationDateEdits) || viewModel.isValidDate(expirationDate())> label classcontrol-label>Expires On/label> div classcontrols> !-- ko if: superUserOrderFormMode() && ofConfig.superUserAllowExpirationDateEdits --> div classinput-append> input typetext classinput-medium idExpirationDate stylebackground-color: white;cursor: pointer readonlyreadonly data-bindattr: { disabled: viewModel.orderPlaced } , datepicker: expirationDate , datepickerOptions: { minDate: (new Date(expirationDate())) new Date() ? new Date(expirationDate()) : new Date(), maxDate: moment(new Date()).add(ofConfig.maxExpirationDays, days).toDate(), //TODO: this should be configurable constrainInput: true, showOn:both, buttonText: i class\icon-calendar\>/i>, beforeShowDay: function (date) { var currentExpiration (new Date(expirationDate())).getTime(); var checkDate date.getTime(); var todayDate (new Date()); todayDate.setHours(0,0,0,0); var today todayDate.getTime(); validDate checkDate currentExpiration || checkDate > today; return validDate; } }> button typebutton classbtn data-bindattr: { disabled: viewModel.orderPlaced }, click: function(shipment) { $(#ExpirationDate).datepicker(show) }, clickBubble: false> i classicon-calendar>/i> /button> /div> !-- /ko --> !-- ko if: !superUserOrderFormMode() || !ofConfig.superUserAllowExpirationDateEdits --> span data-bindtext: expirationDate>/span> !-- /ko --> /div> /div>/script>script typetext/html idcart.softgoods> !-- ko if: $data.orderFlags.indexOf(create_softgoods_auth) > 0 --> span data-bindtext: oConfig.labels.softgoods>/span> !-- /ko -->/script>script typetext/html idcart.backorderMessage> !-- ko if: (qty() - Math.max(0, commodity.qtyAvailable() - commodity.qtyBuffer())) > 0 --> div classtext-small text-warning>i classicon-warning-sign icon-large>/i> b>span data-bindtext:qty() - Math.max(0, commodity.qtyAvailable() - commodity.qtyBuffer())>/span>/b> on back order. b>span data-bindtext: Math.max(0, commodity.qtyAvailable() - commodity.qtyBuffer())>/span>/b> will ship./div> !-- /ko -->/script>script typetext/html idcart.recurringDetails> legend > i classicon icon-repeat icon-fixed-width>/i> Schedule Details /legend> !-- ko if: viewModel.lifecycleStage() recurring-preprocessed --> div classalert alert-warning>This order has recently been preprocessed and changes made here could affect the order being processed./div> !-- /ko --> !-- ko if: viewModel.lifecycleStage() recurring-pending --> div classalert alert-error>This order has recently been cloned and changes made here will not be reflected on the current order being processed./div> !-- /ko --> !-- ko if: viewModel.lifecycleStage() recurring-disabled --> div classalert alert-info>This order is currently disabled and will not be processed on the date selected./div> !-- /ko --> div idrecurring_details classform-horizontal checkout-payment-form > div classcontrol-group input-append> label classcontrol-label forro_rundate>strong>Next order date:/strong>/label> div classcontrols> input typetext idro_rundate classinput-medium stylebackground-color: white;cursor: pointer readonlyreadonly data-binddatepicker: roRunDate, value: moment(roRunDate()).format(MM/DD/YYYY) , datepickerOptions: { minDate: viewModel.getMinimumRecurringOrderDate(), constrainInput: true, showOn:both, buttonText: i class\icon-calendar\>/i> }> /div> /div> div classcontrol-group> label classcontrol-labelforro_rec_qty> strong>Place order every: /strong>/label> div classcontrols> input idro_rec_qty classqtyinput data-bindvalue: roRecQty typenumber min1> select idro_rec_case classinput-medium data-bindvalue: roRecCase> option valueday>Day(s)/option> option valueweek>Week(s)/option> option valuemonth>Month(s)/option> option valueyear>Year(s)/option> /select> /div> /div> /div> hr>/script>script typetext/html idcart.recurringLineDetails> span classro-actions> select idro_actions data-bindvalue: selectedRoAction, event:{ change: viewModel.updateRecurringType }> option valuerecurring data-bindtext: ofConfig.roRecurringSelectText>/option> option valuefixed data-bindtext: ofConfig.roOneTimeSelectText>/option> option valueskipnext data-bindtext: ofConfig.roSkipSelectText>/option> /select> /span>/script>/div>!-- include files here -->script typetext/html idcatalog.product_title_custom> div classpage-header detail-title> h1 data-bindhtml: selectedProduct().name() || name()>/h1> p classproduct__tagline>ESTABLISH THE BENCHMARK, RAISE THE BAR, REPEAT! span classtrademark>™/span>/p> !-- template: catalog.product_links --> /div>/script>script typetext/html idcatalog.atc_form_submit_custom> div classmedia atc-large> !-- ko if: atcErrorText() ! --> div classalert alert-error data-bindhtml:atcErrorText>/div> !-- /ko --> div classpull-left data-bindtemplate: catalog.product_quantity>/div> div classmedia-body> div classbtn-group> button typebutton classbtn btn-primary btn-large button product-detail-atc__button data-bind click: addToCart, html: atcButtonText() >/button> /div> div data-bindtemplate: { name: catalog.saved_cart_form_submit, if: oConfig.useSavedCarts }>/div> /div> /div> !-- ko template: { afterRender: function() { PayPalService(0); } } --> div idpaypal-button-container data-bindhtml: unitPrice() >/div> !-- /ko -->/script>script typetext/html idcart.paymentMethods_custom> !-- ko template: { name: cart.paymentMethodList_ + ofConfig.payMethodDisplayType } -->!-- /ko --> div classtab-content> div idmethod_cc: classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() cc }> div data-bindtemplate : { name: cart.creditCardForm }>/div> /div> div idmethod_billme classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() billme }> /div> div idmethod_ach-check classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() ach-check }> h3>-- ACH is not implemented yet, but would go here --/h3> !-- drawAchCheckForm --> /div> div idmethod_paypal classtab-pane data-bindcss: { active: paymentMethodID() && paymentMethod.paymentType() paypal }> img stylemargin-bottom:10px; srchttps://www.paypalobjects.com/webstatic/en_US/i/buttons/buy-logo-medium.png altBuy now with PayPal /> div data-bindhtml: payPalHtml>/div> /div> div idcontrolgroup_invoice_ponumber classcontrol-group data-bindif: paymentMethodID && paymentMethod.collectPO()> hr> label forponumber classcontrol-label data-bindhtml: ofConfig.POLabel>/label> div classcontrols> input typetext nameponumber idponumber data-bindvalue: poNumber, attr: { maxlength: ofConfig.POMaxLength, required: viewModel.paymentMethod.poRequired() true ? required : null } /> input typehidden idponum_required value0 data-bindif: !viewModel.paymentMethod.poRequired()/> !-- ko if: !viewModel.paymentMethod.poRequired() --> p idponum_help classhelp-block text-small data-bindhtml: ofConfig.POLabelHelp>/p> !-- /ko --> input typehidden idponum_required value1 data-bindif: viewModel.paymentMethod.poRequired()/> p idponum_help classhelp-block text-small data-bindif: viewModel.paymentMethod.poRequired()>(required)/p> /div> /div> div idcontrolgroup_invoice_comments classcontrol-group data-bindif: ofConfig.showFulfillmentcomments> hr> label fororder_comments classcontrol-label> strong data-bindtext: ofConfig.fulfillmentCommentsText>/strong> /label> div classcontrols> textarea typetext nameorder_comments idorder_comments autocompleteoff data-bindvalue: comments, attr: { maxlength: ofConfig.fulfillmentcommentsMaxLength }>/textarea> p classhelp-block text-small>(optional)/p> /div> /div> /div>/script>script> /* Documentation on paypal pay later service :: https://developer.paypal.com/docs/business/checkout/pay-later-messaging/advanced/#configure-using-javascript */ function PayPalService(price){ $( document ).ready(function() { console.log(paypalservice); if(price 0) { price $( #paypal-button-container ).html(); } $( #paypal-button-container ).html(); PayPalSDK.Messages({ amount: price, style: { layout: text, logo: { type: primary, position: top }, }, }).render(#paypal-button-container); }); }; registerHook({ name: addToCartSuccessHandler, func: function (oArgs) { details oArgs.details; sku details0.sku(); qty details0.selectedQty(); unitPrice details0.unitPrice(); totalPrice qty * unitPrice; try { fbq(track, AddToCart, { value: totalPrice, currency: USD, content_ids: sku, content_type: product }); } catch(error) { console.error(error); } } }); registerHook({ name: orderModelBottom, func: function (oArgs) { var order oArgs.self; var self oArgs.self; var postLogicTrackedJsonAjax function(postData, orderKey) { jQuery.ajax({ url: payment.asp + ?o_key + orderKey + &ajaxtrue&pageactionpostLogicJSON&randomnum + new Date().getTime() , data: postLogicJSON + encodeURIComponent(JSON.stringify(postData)) , cache: false , type: POST , dataType: json , success: function(data,status,request){ } , error: function(data) { alert(Error posting to + (postDataTables0TableName || postLogicJsonAjax) + .); } , complete: function(data) { } }); }; var postOrderTrackedField function(sOrderField, viewModelProperty, viewModel) { var postData {}; var order ; order { o_key : viewModel.orderKey() }; order0sOrderField viewModelProperty; postData { Tables: { TableName : orders, TableKeyField : o_key, UserKeyField : o_key, UserKeyIsPrimaryKey : True, Data : order } }; postLogicTrackedJsonAjax(postData, viewModel.orderKey()); }; order.postOrderToFB function (){ try { var ProductsOrdered ; for(var i 0; i order.detailLines().length; i++) { var line order.detailLines()i; ProductsOrdered.push({ id: line.sku(), quantity: line.qty() }); } fbq(track, Purchase, { value: order.orderTotal(), currency: USD, content_ids: ProductsOrdered, content_type: product }); } catch(error) { console.error(error); } } if(order.completed()) { order.postOrderToFB(); } order.payPalHtml function(){ PayPalService(order.orderTotal()); return div idpaypal-button-container>/div>; }(); self.opt5 ko.observable(function(){ if(self.opt5() ! undefined && self.opt5() ! ) { return self.opt5() } else { return null; } }()); self.orderPlaced.subscribe(function(){ self.postOrderToGA4(); postOrderHeaderField(opt5, 1); self.opt5(1); }) if (self.completed() && self.opt5() ! 1 ) { self.postOrderToGA4(); postOrderHeaderField(opt5, 1); self.opt5(1); } self.postOrderToGA4 function() { if (self.completed() && self.opt5() ! 1 ) { try { var items ; var line_total 0; for(var i 0; i self.detailLines().length; i++) { var line self.detailLines()i; var item { item_id: line.sku(), item_name: line.name(), currency: USD, price: line.price(), quantity: Number(line.qty()), index: i } items.push(item); } if (items.length > 1) { window.dataLayer window.dataLayer || ; function gtag(){dataLayer.push(arguments);} gtag(event, purchase, { transaction_id: self.orderNumber(), affiliation: ofConfig.t_tracking_company, value: self.orderTotal(), tax: self.taxTotal(), shipping: self.shippingTotal(), currency: USD, coupon: self.couponCode(), items: items }); } } catch(err) { console.log(err); } } } } }); registerHook({ name: productModelBottom, func: function (oArgs) { self oArgs.self; self.priceDisplay ko.observable(function () { var template catalog.details_link; var userPriceGroup M; if (self.requireInfoForAtc() && self.childStartingPrice && userPriceGroup M) { template catalog.price_start_at } else if (!self.requireInfoForAtc()) { template catalog.selected_product_price_display; } else { template catalog.breaks_off; } return template; }()); } });/script>div classgtm-tracking> script typetext/javascript> window.dataLayer.push({ CIMpageName : default.asp, CIMorderFrontURL : https://www.nitrousexpress.com, CIMcustomerUsername : , CIMaccountKey : , CIMcustomerKey : , CIMsessionOrderKey : 0184CDF83ABA456188F53CAFE0D8ACC8, CIMsessionIP : 52.40.234.105 }); /script> /div>!-- .gtm-tracking --> div classga-ecommerce-tracking> !-- START Tracking/Analytics Code --> !-- END Tracking/Analytics Code -->/div>!--.ga-ecommerce-tracking --> /body>/html>
Subdomains
Date
Domain
IP
powersports.nitrousexpress.com
2024-09-14
104.21.6.188
www.nitrousexpress.com
2024-11-19
216.59.42.221
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]