Help
RSS
API
Feed
Maltego
Contact
Domain > www.beaverresearch.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
Whois
Property
Value
NameServer
K2.ISERV.NET
Created
1997-11-26 00:00:00
Changed
2015-11-02 00:00:00
Expires
2016-11-25 00:00:00
Registrar
TUCOWS DOMAINS INC.
DNS Resolutions
Date
IP Address
2024-11-19
67.23.168.210
(
ClassC
)
Port 443
HTTP/1.1 200 OKcache-control: no-storecontent-type: text/htmlexpires: Mon, 18 Nov 2024 04:41:46 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&SessionPriceGroupBLANK&sc%5Fid8DF8F5079A4648E39B9E6B9492D50079&l%5Fws%5FidA17844F2149949B7B76F24CBAC064BCF&a%5Fnum&c%5Fid&s%5Fkey8B2F7EC82A814B4697576043058C1500&CurrencySymbol&a%5Fid&sitefrontTrue&url%5Fid&managerfrontFalse; path/set-cookie: customer%5FlogonsitefrontTrue&managerfrontFalse&username&custid&c%5Fid&parent%5Fc%5Fid; path/set-cookie: ASPSESSIONIDASADABBALLAGPLGBODOPJAKIGFHBKPEE; path/access-control-allow-credentials: trueaccess-control-allow-origin: http://www.beaverresearch.comdate: Tue, 19 Nov 2024 04:41:46 GMTcontent-length: 627710 !DOCTYPE html>!--if IE>!endif-->!--if IE 9> html classno-js ie9 lt-ie10> !endif-->!--if gt IE 9>!--> html classno-js> !--!endif-->head> meta http-equivContent-Type contenttext/html; charsetutf-8 /> meta nameviewport contentwidthdevice-width, initial-scale1, minimum-scale1, maximum-scale1> title>Beaver Research Company/title> meta namedescription contentFor the finest in specialty chemicals and maintenance systems, call on Beaver Research Company. From hand care to grounds care, greases to degreasing products, we carry some of the industries best formulated chemicals and natural compounds to achieve a “job well done.”> meta namekeywords contentBeaver Research, Specialty Chemicals, Chemicals, Industrial Chemicals, Beaver Research Company, Detergents, Degreasers, Water Treatment, Industrial Aerosols, Greases, Insecticides, Disinfectants, Floor Care, beaver hats, msds sheets> link relcanonical hrefhttps://www.beaverresearch.com/ /> link hrefhttps://fonts.googleapis.com/css?familyUbuntu:300,400,400i,500,700 relstylesheet>link relstylesheet hreftemplates/fa/css/font-awesome.min.css> !-- Favicon --> link relshortcut icon typeimage/x-icon hrefgfx/favicon/favicon.ico> link relapple-touch-icon-precomposed sizes57x57 hrefgfx/favicon/apple-touch-icon-57x57.png /> link relapple-touch-icon-precomposed sizes114x114 hrefgfx/favicon/apple-touch-icon-114x114.png /> link relapple-touch-icon-precomposed sizes72x72 hrefgfx/favicon/apple-touch-icon-72x72.png /> link relapple-touch-icon-precomposed sizes144x144 hrefgfx/favicon/apple-touch-icon-144x144.png /> link relapple-touch-icon-precomposed sizes60x60 hrefgfx/favicon/apple-touch-icon-60x60.png /> link relapple-touch-icon-precomposed sizes120x120 hrefgfx/favicon/apple-touch-icon-120x120.png /> link relapple-touch-icon-precomposed sizes76x76 hrefgfx/favicon/apple-touch-icon-76x76.png /> link relapple-touch-icon-precomposed sizes152x152 hrefgfx/favicon/apple-touch-icon-152x152.png /> link relicon typeimage/png hrefgfx/favicon/favicon-196x196.png sizes196x196 /> link relicon typeimage/png hrefgfx/favicon/favicon-96x96.png sizes96x96 /> link relicon typeimage/png hrefgfx/favicon/favicon-32x32.png sizes32x32 /> link relicon typeimage/png hrefgfx/favicon/favicon-16x16.png sizes16x16 /> link relicon typeimage/png hrefgfx/favicon/favicon-128.png sizes128x128 /> meta nameapplication-name contentBeaver Research Company /> meta namemsapplication-TileColor content#FFFFFF /> meta namemsapplication-TileImage contentgfx/favicon/mstile-144x144.png /> meta namemsapplication-square70x70logo contentgfx/favicon/mstile-70x70.png /> meta namemsapplication-square150x150logo contentgfx/favicon/mstile-150x150.png /> meta namemsapplication-wide310x150logo contentgfx/favicon/mstile-310x150.png /> meta namemsapplication-square310x310logo contentgfx/favicon/mstile-310x310.png /> link relstylesheet href../css/bootstrap-retail.css?122e9b3> link relstylesheet href../css/retail.css?122e9b3>script srccode/js_hooks.asp?122e9b3>/script>script>// This function is needed for JS hooks.function getOriginalPageName() { return default.asp;}/script>script>var pendoData { visitor: { id: -beaver, key: , package: 3, template: , firstName: , lastName: , email: , companyName: , companyNum: , role: standard }, account: { id: beaver, key: A17844F2149949B7B76F24CBAC064BCF, package: 3 }, 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?122e9b3aa42d1d869f206d242ff5d4e4e3ba780d >/script>/head>body classhome retail t-ui-phase-4 site-type-3 loggedout t-ui-phase-4 home loggedout site-type-3> noscript classnoscript-padding>/noscript>header idretail-header-0 classretail-header-0> div classbeaver-topbar> div classcontainer-fluid topbar__desktop> a hreftel:18005440133> i classicon-phone>/i> span classhide-980>Call us at /span> span classtext-underline>800-544-0133/span> span classhide-980> to order!/span> /a> div classtopbar__right-menu> ul idtopbar__links classtopbar__links linkset click-persist horizontal js-click-outside-to-close topbar__links__ul-1> li classtopbar__links__li-1 data-key37BE3000106D4657A1E2038B097E2993>a hrefabout-us classtopbar__links__a-1>About Us/a>/li> li classtopbar__links__li-1 data-key8B355DFABCE94C7A8066FE5BE2155B39>a hrefcareers classtopbar__links__a-1>Careers/a>/li> li classtopbar__links__li-1 data-key60C18B55B5FC4D018FA0FB59C7D25CCB>a hrefcontact_us.asp classtopbar__links__a-1>Contact Us/a>/li>/ul> ul idheader__signin classtopbar__links topbar__signin linkset horizontal> li class> a idtopbar__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-user>/i> Customer Portal /a> /li> /ul> ul classtopbar__links topbar__signup linkset horizontal> li>a hrefbecome-customer/>Become a Customer/a>/li> /ul> /div> /div> div classtopbar__mobile> ul idtopbar__mobile__wrap classlinkset click-persist topbar__mobile__wrap js-click-outside-to-close> li> a classhamburger-toggle hrefjavascript:void(0);>i classicon-reorder>/i>/a> ul classtopbar__mobile__linksets__wrap> li> ul idmobile-logo-bar-links classlinkset click-persist mobile-logo-bar-links js-click-outside-to-close mobile-logo-bar-links__ul-1> li classlink-parent prodcat mobile-logo-bar-links__li-1 data-key34BDB716736F4CE5861903F91234EC1F>a hrefjavascript:void(0); classmobile-logo-bar-links__a-1>Products/a> ul classmobile-logo-bar-links mobile-logo-bar-links__ul-2>li classmobile-logo-bar-links__li-2>a href/category/industrial-maintenance-and-cleaning classmobile-logo-bar-links__a-2 data-parent-href/category/industrial-maintenance-and-cleaning data-parent-nameIndustrial Maintenance and Cleaning data-keyB786CE9DD04C4F5F94766CDD4988F796>Industrial Maintenance and Cleaning/a>/li>li classmobile-logo-bar-links__li-2>a href/category/janitorial-and-sanitation-supplies classmobile-logo-bar-links__a-2 data-parent-href/category/janitorial-and-sanitation-supplies data-parent-nameJanitorial and Sanitation Supplies data-key264A31962A1843B2A6F302D683D47C00>Janitorial and Sanitation Supplies/a>/li>li classmobile-logo-bar-links__li-2>a href/category/building-and-grounds-maintenance classmobile-logo-bar-links__a-2 data-parent-href/category/building-and-grounds-maintenance data-parent-nameBuilding and Grounds Maintenance data-keyDFE1E3BC230B487E84C1306E2F5F51E5>Building and Grounds Maintenance/a>/li>li classmobile-logo-bar-links__li-2>a href/category/production-and-process-chemicals classmobile-logo-bar-links__a-2 data-parent-href/category/production-and-process-chemicals data-parent-nameProduction and Process Chemicals data-key4F4F582A96B24A14B3F8F8604987D0CA>Production and Process Chemicals/a>/li>li classmobile-logo-bar-links__li-2>a href/category/water-treatment classmobile-logo-bar-links__a-2 data-parent-href/category/water-treatment data-parent-nameWater Treatment data-key6F1300D74FD54F708AB1EE949FD7CF66>Water Treatment/a>/li>li classmobile-logo-bar-links__li-2>a href/category/market-segments classmobile-logo-bar-links__a-2 data-parent-href/category/market-segments data-parent-nameMarket Segments data-key68A7603E4A1D4C8A900C22B563104EEF>Market Segments/a>/li>li classmobile-logo-bar-links__li-2>a href/category/application-specific classmobile-logo-bar-links__a-2 data-parent-href/category/application-specific data-parent-nameApplication Specific data-key6E49BD084C264E4EA723F1176ADCBAEC>Application Specific/a>/li>li classmobile-logo-bar-links__li-2 >a href/category/private-branding classmobile-logo-bar-links__a-2 data-parent-href/category/private-branding data-parent-namePrivate Branding data-keyF7FCC0A7277F4843A4DC017D334C2DAA>Private Branding/a>/li>/ul>/li> li classmobile-logo-bar-links__li-1 data-keyFE48FB6F953944CDB5BDAF82E4530166>a href# classmobile-logo-bar-links__a-1>Market Segments/a> ul classmobile-logo-bar-links__ul-2> li classmobile-logo-bar-links__li-2 data-keyF024E422535C42D79F0E10BF130243DC>a hrefcategory/environmental-services classmobile-logo-bar-links__a-2>Environmental Services/a>/li> li classmobile-logo-bar-links__li-2 data-key8BFF1396EE8447ADB39A7A6434BD24DA>a hrefcategory/facilities-maintenance classmobile-logo-bar-links__a-2>Facilities Maintenance/a>/li> li classmobile-logo-bar-links__li-2 data-key807F967BF7E94E4CB3C3482A0180E628>a hrefcategory/food-beverage-processing classmobile-logo-bar-links__a-2>Food/Beverage Processing/a>/li> li classmobile-logo-bar-links__li-2 data-keyC944408D91A949B6B6F8FEBA1C945634>a hrefcategory/government classmobile-logo-bar-links__a-2>Government/a>/li> li classmobile-logo-bar-links__li-2 data-key8C74582B48384450BB1C762B64DA0D93>a hrefcategory/hospitality classmobile-logo-bar-links__a-2>Hospitality/a>/li> li classmobile-logo-bar-links__li-2 data-key14BBA923887944E7B43AB1D72D32AEF4>a hrefcategory/industrial-manufacturing classmobile-logo-bar-links__a-2>Industrial Manufacturing/a>/li> li classmobile-logo-bar-links__li-2 data-key4EE0041065F54724B16A0F1454E26442>a hrefcategory/janitorial-services classmobile-logo-bar-links__a-2>Janitorial Services/a>/li> li classmobile-logo-bar-links__li-2 data-key5BAD88CFF2F64290ACCF71E6A8611382>a hrefcategory/oil-gas classmobile-logo-bar-links__a-2>Oil & Gas/a>/li> li classmobile-logo-bar-links__li-2 data-keyFB43E53AF1734E8F86E207D3805DFC63>a hrefcategory/outdoor-and-grounds classmobile-logo-bar-links__a-2>Outdoor & Grounds/a>/li> li classmobile-logo-bar-links__li-2 data-key7928053A7EB5420FBEECE2F4516F9B4B>a hrefcategory/safety classmobile-logo-bar-links__a-2>Safety/a>/li> /ul>/li> li classmobile-logo-bar-links__li-1 data-key077BB24ED12D4B0094F285492A8AEC0C>a href# classmobile-logo-bar-links__a-1>Applications/a> ul classmobile-logo-bar-links__ul-2> li classmobile-logo-bar-links__li-2 data-key918FB3EE4C1E42D79715E37FD704045D>a hrefcategory/automotive-fleet-products classmobile-logo-bar-links__a-2>Automotive/Fleet Products/a>/li> li classmobile-logo-bar-links__li-2 data-key2D51806B8F164FD99B76FA487A35DE00>a hrefcategory/aerosol-products classmobile-logo-bar-links__a-2>Aerosol Products/a>/li> li classmobile-logo-bar-links__li-2 data-key1D133B57F418426D9AE800EE66C97EAF>a hrefcategory/bowl-cleaners classmobile-logo-bar-links__a-2>Bowl Cleaners/a>/li> li classmobile-logo-bar-links__li-2 data-key8351CA8492D345BD947A62A26A410BEF>a hrefcategory/carpet-care classmobile-logo-bar-links__a-2>Carpet Care/a>/li> li classmobile-logo-bar-links__li-2 data-key0F071A9D39154D468C017E7345191A6C>a hrefcategory/coatings classmobile-logo-bar-links__a-2>Coatings/a>/li> li classmobile-logo-bar-links__li-2 data-key036EBFFF344743CDA2B250D9F41B7375>a hrefcategory/deodorizers classmobile-logo-bar-links__a-2>Deodorizers/a>/li> li classmobile-logo-bar-links__li-2 data-key7BF4E0043C38490F9F4AF76030B21A16>a hrefcategory/descalers classmobile-logo-bar-links__a-2>Descalers/a>/li> li classmobile-logo-bar-links__li-2 data-key8CA148C10F5B43FB8DD5F8BCB43035AA>a hrefcategory/disinfectants classmobile-logo-bar-links__a-2>Disinfectants/a>/li> li classmobile-logo-bar-links__li-2 data-key57FB23725DA34CFAA8A84F3C5AFA31A4>a hrefcategory/degreasers classmobile-logo-bar-links__a-2>Degreasers/a>/li> li classmobile-logo-bar-links__li-2 data-key4D1CEAD4AFF7463C8CA9EF1D3A08820A>a hrefcategory/detergents classmobile-logo-bar-links__a-2>Detergents/a>/li> li classmobile-logo-bar-links__li-2 data-key354477AC540141B6A65E9DC677A6E0DA>a hrefcategory/dish-and-pot classmobile-logo-bar-links__a-2>Dish & Pot/a>/li> li classmobile-logo-bar-links__li-2 data-key69B9C1A174A847FBA7C6FE6233F81C9B>a hrefcategory/electronics-cleaner classmobile-logo-bar-links__a-2>Electronics Cleaner/a>/li> li classmobile-logo-bar-links__li-2 data-key6602B72945A949B193B6EA92497809C1>a hrefcategory/floor-care classmobile-logo-bar-links__a-2>Floor Care/a>/li> li classmobile-logo-bar-links__li-2 data-key3629EC9BFF084641A1428D36B7E0591F>a hrefcategory/glass-cleaner classmobile-logo-bar-links__a-2>Glass Cleaner/a>/li> li classmobile-logo-bar-links__li-2 data-keyCA30D00EC86842CD841E4DD8105590A1>a hrefcategory/greases classmobile-logo-bar-links__a-2>Greases/a>/li> li classmobile-logo-bar-links__li-2 data-key36F93461B34E4A159CC76CF521D6B05F>a hrefcategory/grounds-care classmobile-logo-bar-links__a-2>Grounds Care/a>/li> li classmobile-logo-bar-links__li-2 data-keyBBE1D6B13783412881E2B3CDAB5CD699>a hrefcategory/hand-cleaner classmobile-logo-bar-links__a-2>Hand Cleaner/a>/li> li classmobile-logo-bar-links__li-2 data-key0054D41BBA3E4D5AB557672F89FCA04F>a href# classmobile-logo-bar-links__a-2>Hard Goods/a> ul classmobile-logo-bar-links__ul-3> li classmobile-logo-bar-links__li-3 data-key6121F47CF88B4F2B91F11C5AC2949D58>a hrefcategory/broom-and-brush classmobile-logo-bar-links__a-3>Broom & Brush/a>/li> li classmobile-logo-bar-links__li-3 data-key78CF609F921144C4A4785D1FEADBA6EA>a hrefcategory/bucket-and-wringer classmobile-logo-bar-links__a-3>Bucket & Wringer/a>/li> li classmobile-logo-bar-links__li-3 data-keyD6F5479523264B55B57FF841AE3D8399>a hrefcategory/cleaning-pad classmobile-logo-bar-links__a-3>Cleaning Pad/a>/li> li classmobile-logo-bar-links__li-3 data-key334C63CA777B41A4B4B2672CC960BA21>a hrefcategory/can-liners classmobile-logo-bar-links__a-3>Can Liners/a>/li> li classmobile-logo-bar-links__li-3 data-key531A346EB26147C4AC5D7892C6588D6B>a hrefcategory/deodorant-dispensers classmobile-logo-bar-links__a-3>Deodorant Dispensers/a>/li> li classmobile-logo-bar-links__li-3 data-keyC0B0BD6F02FB49B4BCFCBE4F83E0BEA7>a hrefcategory/drum-pumps-and-accessories classmobile-logo-bar-links__a-3>Drum Pumps & Accessories/a>/li> li classmobile-logo-bar-links__li-3 data-key915949E63D264E33BEF001E3C481CBF5>a hrefpc_combined_results.asp?pc_idEA7745ABCE0C4CECA8BAFB850940D04E classmobile-logo-bar-links__a-3>Food Service/a>/li> li classmobile-logo-bar-links__li-3 data-key17CE1479C7184ED99F8F54A8F36C5E48>a hrefcategory/floor-accessories classmobile-logo-bar-links__a-3>Floor Accessories/a>/li> li classmobile-logo-bar-links__li-3 data-key168B65686E2743C6A144B8773255FB5A>a hrefcategory/foamers-sprayers-proportioners classmobile-logo-bar-links__a-3>Foamers/Sprayers/Proportioners/a>/li> li classmobile-logo-bar-links__li-3 data-key15B8F19AA6814EAC8C4265D617DB8CBF>a hrefcategory/gloves classmobile-logo-bar-links__a-3>Gloves/a>/li> li classmobile-logo-bar-links__li-3 data-key24EB72B36851495DA303F007CE572D09>a hrefcategory/hand-pads classmobile-logo-bar-links__a-3>Hand Pads/a>/li> li classmobile-logo-bar-links__li-3 data-key0BB431E2483C4AF7825BD9A14E7F0F22>a hrefcategory/microfiber-accessories classmobile-logo-bar-links__a-3>Microfiber Accessories/a>/li> li classmobile-logo-bar-links__li-3 data-key24D5514FAF41481E8D9F05675FC00DBB>a hrefcategory/mop-handles classmobile-logo-bar-links__a-3>Mop Handles/a>/li> li classmobile-logo-bar-links__li-3 data-keyFC05FEF2CF6F47D9AFFA81ED5FC714B6>a hrefcategory/mop-heads classmobile-logo-bar-links__a-3>Mop Heads/a>/li> li classmobile-logo-bar-links__li-3 data-key21D6D80D819F42CC99C7E94E05CBA5AB>a hrefcategory/multi-product-kits classmobile-logo-bar-links__a-3>Multi-Product Kits/a>/li> li classmobile-logo-bar-links__li-3 data-keyCE9876DCF8534EAB8DFFE1BA52A70800>a hrefcategory/parts-washer-parts classmobile-logo-bar-links__a-3>Parts Washer/Parts/a>/li> li classmobile-logo-bar-links__li-3 data-keyF74CD6A5DE7541328143791CBD82FD7F>a hrefcategory/polish classmobile-logo-bar-links__a-3>Polishes/a>/li> li classmobile-logo-bar-links__li-3 data-key4B383B75A9184F31A2EB421B12DA4A9A>a hrefcategory/specialty-lubricants classmobile-logo-bar-links__a-3>Specialty Lubricants/a>/li> li classmobile-logo-bar-links__li-3 data-key230596CD178846A3A5702E5085EE79C2>a hrefcategory/sprayers classmobile-logo-bar-links__a-3>Sprayers/a>/li> li classmobile-logo-bar-links__li-3 data-key4F7AD2A01A244B53BFEAA4602BD5233B>a hrefcategory/tugs classmobile-logo-bar-links__a-3>Tugs/a>/li> li classmobile-logo-bar-links__li-3 data-keyA94902EC201645B4B5B139E7C3094120>a hrefcategory/test-kits classmobile-logo-bar-links__a-3>Test Kits/a>/li> li classmobile-logo-bar-links__li-3 data-keyB6D34C3DD52C4E35A5F2AC24C761110D>a hrefcategory/water-treatment-equipment classmobile-logo-bar-links__a-3>Water Treatment Equipment/a>/li> /ul>/li> li classmobile-logo-bar-links__li-2 data-keyF26F34830E364837B9E3D57EC5BCC940>a hrefcategory/laundry classmobile-logo-bar-links__a-2>Laundry/a>/li> li classmobile-logo-bar-links__li-2 data-key7F2748A6A9454A17A971265BE8FF45D2>a hrefcategory/manufacturing-commodities classmobile-logo-bar-links__a-2>Manufacturing/Commodities/a>/li> li classmobile-logo-bar-links__li-2 data-keyD88A6E6AC6B64C8B9BC81D767E1E5B85>a hrefcategory/metal-working-fluids classmobile-logo-bar-links__a-2>Metal Working Fluids/a>/li> li classmobile-logo-bar-links__li-2 data-key4682F26251B749DF8FF786502550DCC1>a hrefcategory/paint-stripper classmobile-logo-bar-links__a-2>Paint Stripper/a>/li> li classmobile-logo-bar-links__li-2 data-keyFE125D6C9AC04605AA7BA70714742B87>a hrefcategory/paper-products classmobile-logo-bar-links__a-2>Paper Products/a>/li> li classmobile-logo-bar-links__li-2 data-key05EAC778BF1840AAA06BD26C1A152F2D>a hrefcategory/sewer classmobile-logo-bar-links__a-2>Sewer/a>/li> li classmobile-logo-bar-links__li-2 data-keyF3824F173C6743169F95DA14374AC01D>a hrefcategory/silicones-sealants classmobile-logo-bar-links__a-2>Silicones/Sealants/a>/li> li classmobile-logo-bar-links__li-2 data-key4FE1736AFB4444E0A63FBA822AE20AEB>a hrefcategory/specialty-chemicals classmobile-logo-bar-links__a-2>Specialty Chemicals/a>/li> li classmobile-logo-bar-links__li-2 data-key06426525C86343AE9CDB15E38084CF9F>a hrefcategory/special-order-non-stock classmobile-logo-bar-links__a-2>Special Order/Non-Stock/a>/li> li classmobile-logo-bar-links__li-2 data-key0EC45D4586934196A2D882E6A6111A6A>a hrefcategory/process-water-treatment classmobile-logo-bar-links__a-2>Water Treatment/a>/li> li classmobile-logo-bar-links__li-2 data-key2CE232F7D305400AA58F6A86226DAB6F>a hrefcategory/winter-products classmobile-logo-bar-links__a-2>Winter Products/a>/li> /ul>/li> li classmobile-logo-bar-links__li-1 data-keyEA3C70585AFB44DEBBDEDB37035D47BD>a hrefdownload-catalog.asp classmobile-logo-bar-links__a-1 target_blank>Download Catalog/a>/li>/ul>ul idmobile-topbar-links classlinkset click-persist mobile-topbar-links js-click-outside-to-close mobile-topbar-links__ul-1> li classmobile-topbar-links__li-1 data-key37BE3000106D4657A1E2038B097E2993>a hrefabout-us classmobile-topbar-links__a-1>About Us/a>/li> li classmobile-topbar-links__li-1 data-key8B355DFABCE94C7A8066FE5BE2155B39>a hrefcareers classmobile-topbar-links__a-1>Careers/a>/li> li classmobile-topbar-links__li-1 data-key60C18B55B5FC4D018FA0FB59C7D25CCB>a hrefcontact_us.asp classmobile-topbar-links__a-1>Contact Us/a>/li>/ul> /li> /ul> /li> /ul> a classmobile-phone hreftel:18005440133> i classicon-phone>/i> span classhide-xs>Call us at /span> span classtext-underline>800-544-0133/span> span classhide-xs> to order!/span> /a> a classmobile-login hrefsecurity_logon.asp>i classicon-user>/i>/a> /div> /div> div idlogo-bar classlogo-bar> div classcontainer-fluid> div classlogo-bar__logo> !-- Call getTemplateLogo() --> a hrefhttps://www.beaverresearch.com classlogo> img srcimages/br-logo-main.png altLogo> /a> /div> div classlogo-bar__right> nav classlogo-bar__menu> ul idbeaver-logo-bar-menu classbeaver-logo-bar-menu linkset click-persist horizontal js-click-outside-to-close beaver-logo-bar-menu__ul-1> li classlink-parent prodcat beaver-logo-bar-menu__li-1 data-key34BDB716736F4CE5861903F91234EC1F>a hrefjavascript:void(0); classbeaver-logo-bar-menu__a-1>Products/a> ul classbeaver-logo-bar-menu beaver-logo-bar-menu__ul-2>li classbeaver-logo-bar-menu__li-2>a href/category/industrial-maintenance-and-cleaning classbeaver-logo-bar-menu__a-2 data-parent-href/category/industrial-maintenance-and-cleaning data-parent-nameIndustrial Maintenance and Cleaning data-keyB786CE9DD04C4F5F94766CDD4988F796>Industrial Maintenance and Cleaning/a>/li>li classbeaver-logo-bar-menu__li-2>a href/category/janitorial-and-sanitation-supplies classbeaver-logo-bar-menu__a-2 data-parent-href/category/janitorial-and-sanitation-supplies data-parent-nameJanitorial and Sanitation Supplies data-key264A31962A1843B2A6F302D683D47C00>Janitorial and Sanitation Supplies/a>/li>li classbeaver-logo-bar-menu__li-2>a href/category/building-and-grounds-maintenance classbeaver-logo-bar-menu__a-2 data-parent-href/category/building-and-grounds-maintenance data-parent-nameBuilding and Grounds Maintenance data-keyDFE1E3BC230B487E84C1306E2F5F51E5>Building and Grounds Maintenance/a>/li>li classbeaver-logo-bar-menu__li-2>a href/category/production-and-process-chemicals classbeaver-logo-bar-menu__a-2 data-parent-href/category/production-and-process-chemicals data-parent-nameProduction and Process Chemicals data-key4F4F582A96B24A14B3F8F8604987D0CA>Production and Process Chemicals/a>/li>li classbeaver-logo-bar-menu__li-2>a href/category/water-treatment classbeaver-logo-bar-menu__a-2 data-parent-href/category/water-treatment data-parent-nameWater Treatment data-key6F1300D74FD54F708AB1EE949FD7CF66>Water Treatment/a>/li>li classbeaver-logo-bar-menu__li-2>a href/category/market-segments classbeaver-logo-bar-menu__a-2 data-parent-href/category/market-segments data-parent-nameMarket Segments data-key68A7603E4A1D4C8A900C22B563104EEF>Market Segments/a>/li>li classbeaver-logo-bar-menu__li-2>a href/category/application-specific classbeaver-logo-bar-menu__a-2 data-parent-href/category/application-specific data-parent-nameApplication Specific data-key6E49BD084C264E4EA723F1176ADCBAEC>Application Specific/a>/li>li classbeaver-logo-bar-menu__li-2 >a href/category/private-branding classbeaver-logo-bar-menu__a-2 data-parent-href/category/private-branding data-parent-namePrivate Branding data-keyF7FCC0A7277F4843A4DC017D334C2DAA>Private Branding/a>/li>/ul>/li> li classbeaver-logo-bar-menu__li-1 data-keyFE48FB6F953944CDB5BDAF82E4530166>a href# classbeaver-logo-bar-menu__a-1>Market Segments/a> ul classbeaver-logo-bar-menu__ul-2> li classbeaver-logo-bar-menu__li-2 data-keyF024E422535C42D79F0E10BF130243DC>a hrefcategory/environmental-services classbeaver-logo-bar-menu__a-2>Environmental Services/a>/li> li classbeaver-logo-bar-menu__li-2 data-key8BFF1396EE8447ADB39A7A6434BD24DA>a hrefcategory/facilities-maintenance classbeaver-logo-bar-menu__a-2>Facilities Maintenance/a>/li> li classbeaver-logo-bar-menu__li-2 data-key807F967BF7E94E4CB3C3482A0180E628>a hrefcategory/food-beverage-processing classbeaver-logo-bar-menu__a-2>Food/Beverage Processing/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyC944408D91A949B6B6F8FEBA1C945634>a hrefcategory/government classbeaver-logo-bar-menu__a-2>Government/a>/li> li classbeaver-logo-bar-menu__li-2 data-key8C74582B48384450BB1C762B64DA0D93>a hrefcategory/hospitality classbeaver-logo-bar-menu__a-2>Hospitality/a>/li> li classbeaver-logo-bar-menu__li-2 data-key14BBA923887944E7B43AB1D72D32AEF4>a hrefcategory/industrial-manufacturing classbeaver-logo-bar-menu__a-2>Industrial Manufacturing/a>/li> li classbeaver-logo-bar-menu__li-2 data-key4EE0041065F54724B16A0F1454E26442>a hrefcategory/janitorial-services classbeaver-logo-bar-menu__a-2>Janitorial Services/a>/li> li classbeaver-logo-bar-menu__li-2 data-key5BAD88CFF2F64290ACCF71E6A8611382>a hrefcategory/oil-gas classbeaver-logo-bar-menu__a-2>Oil & Gas/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyFB43E53AF1734E8F86E207D3805DFC63>a hrefcategory/outdoor-and-grounds classbeaver-logo-bar-menu__a-2>Outdoor & Grounds/a>/li> li classbeaver-logo-bar-menu__li-2 data-key7928053A7EB5420FBEECE2F4516F9B4B>a hrefcategory/safety classbeaver-logo-bar-menu__a-2>Safety/a>/li> /ul>/li> li classbeaver-logo-bar-menu__li-1 data-key077BB24ED12D4B0094F285492A8AEC0C>a href# classbeaver-logo-bar-menu__a-1>Applications/a> ul classbeaver-logo-bar-menu__ul-2> li classbeaver-logo-bar-menu__li-2 data-key918FB3EE4C1E42D79715E37FD704045D>a hrefcategory/automotive-fleet-products classbeaver-logo-bar-menu__a-2>Automotive/Fleet Products/a>/li> li classbeaver-logo-bar-menu__li-2 data-key2D51806B8F164FD99B76FA487A35DE00>a hrefcategory/aerosol-products classbeaver-logo-bar-menu__a-2>Aerosol Products/a>/li> li classbeaver-logo-bar-menu__li-2 data-key1D133B57F418426D9AE800EE66C97EAF>a hrefcategory/bowl-cleaners classbeaver-logo-bar-menu__a-2>Bowl Cleaners/a>/li> li classbeaver-logo-bar-menu__li-2 data-key8351CA8492D345BD947A62A26A410BEF>a hrefcategory/carpet-care classbeaver-logo-bar-menu__a-2>Carpet Care/a>/li> li classbeaver-logo-bar-menu__li-2 data-key0F071A9D39154D468C017E7345191A6C>a hrefcategory/coatings classbeaver-logo-bar-menu__a-2>Coatings/a>/li> li classbeaver-logo-bar-menu__li-2 data-key036EBFFF344743CDA2B250D9F41B7375>a hrefcategory/deodorizers classbeaver-logo-bar-menu__a-2>Deodorizers/a>/li> li classbeaver-logo-bar-menu__li-2 data-key7BF4E0043C38490F9F4AF76030B21A16>a hrefcategory/descalers classbeaver-logo-bar-menu__a-2>Descalers/a>/li> li classbeaver-logo-bar-menu__li-2 data-key8CA148C10F5B43FB8DD5F8BCB43035AA>a hrefcategory/disinfectants classbeaver-logo-bar-menu__a-2>Disinfectants/a>/li> li classbeaver-logo-bar-menu__li-2 data-key57FB23725DA34CFAA8A84F3C5AFA31A4>a hrefcategory/degreasers classbeaver-logo-bar-menu__a-2>Degreasers/a>/li> li classbeaver-logo-bar-menu__li-2 data-key4D1CEAD4AFF7463C8CA9EF1D3A08820A>a hrefcategory/detergents classbeaver-logo-bar-menu__a-2>Detergents/a>/li> li classbeaver-logo-bar-menu__li-2 data-key354477AC540141B6A65E9DC677A6E0DA>a hrefcategory/dish-and-pot classbeaver-logo-bar-menu__a-2>Dish & Pot/a>/li> li classbeaver-logo-bar-menu__li-2 data-key69B9C1A174A847FBA7C6FE6233F81C9B>a hrefcategory/electronics-cleaner classbeaver-logo-bar-menu__a-2>Electronics Cleaner/a>/li> li classbeaver-logo-bar-menu__li-2 data-key6602B72945A949B193B6EA92497809C1>a hrefcategory/floor-care classbeaver-logo-bar-menu__a-2>Floor Care/a>/li> li classbeaver-logo-bar-menu__li-2 data-key3629EC9BFF084641A1428D36B7E0591F>a hrefcategory/glass-cleaner classbeaver-logo-bar-menu__a-2>Glass Cleaner/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyCA30D00EC86842CD841E4DD8105590A1>a hrefcategory/greases classbeaver-logo-bar-menu__a-2>Greases/a>/li> li classbeaver-logo-bar-menu__li-2 data-key36F93461B34E4A159CC76CF521D6B05F>a hrefcategory/grounds-care classbeaver-logo-bar-menu__a-2>Grounds Care/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyBBE1D6B13783412881E2B3CDAB5CD699>a hrefcategory/hand-cleaner classbeaver-logo-bar-menu__a-2>Hand Cleaner/a>/li> li classbeaver-logo-bar-menu__li-2 data-key0054D41BBA3E4D5AB557672F89FCA04F>a href# classbeaver-logo-bar-menu__a-2>Hard Goods/a> ul classbeaver-logo-bar-menu__ul-3> li classbeaver-logo-bar-menu__li-3 data-key6121F47CF88B4F2B91F11C5AC2949D58>a hrefcategory/broom-and-brush classbeaver-logo-bar-menu__a-3>Broom & Brush/a>/li> li classbeaver-logo-bar-menu__li-3 data-key78CF609F921144C4A4785D1FEADBA6EA>a hrefcategory/bucket-and-wringer classbeaver-logo-bar-menu__a-3>Bucket & Wringer/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyD6F5479523264B55B57FF841AE3D8399>a hrefcategory/cleaning-pad classbeaver-logo-bar-menu__a-3>Cleaning Pad/a>/li> li classbeaver-logo-bar-menu__li-3 data-key334C63CA777B41A4B4B2672CC960BA21>a hrefcategory/can-liners classbeaver-logo-bar-menu__a-3>Can Liners/a>/li> li classbeaver-logo-bar-menu__li-3 data-key531A346EB26147C4AC5D7892C6588D6B>a hrefcategory/deodorant-dispensers classbeaver-logo-bar-menu__a-3>Deodorant Dispensers/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyC0B0BD6F02FB49B4BCFCBE4F83E0BEA7>a hrefcategory/drum-pumps-and-accessories classbeaver-logo-bar-menu__a-3>Drum Pumps & Accessories/a>/li> li classbeaver-logo-bar-menu__li-3 data-key915949E63D264E33BEF001E3C481CBF5>a hrefpc_combined_results.asp?pc_idEA7745ABCE0C4CECA8BAFB850940D04E classbeaver-logo-bar-menu__a-3>Food Service/a>/li> li classbeaver-logo-bar-menu__li-3 data-key17CE1479C7184ED99F8F54A8F36C5E48>a hrefcategory/floor-accessories classbeaver-logo-bar-menu__a-3>Floor Accessories/a>/li> li classbeaver-logo-bar-menu__li-3 data-key168B65686E2743C6A144B8773255FB5A>a hrefcategory/foamers-sprayers-proportioners classbeaver-logo-bar-menu__a-3>Foamers/Sprayers/Proportioners/a>/li> li classbeaver-logo-bar-menu__li-3 data-key15B8F19AA6814EAC8C4265D617DB8CBF>a hrefcategory/gloves classbeaver-logo-bar-menu__a-3>Gloves/a>/li> li classbeaver-logo-bar-menu__li-3 data-key24EB72B36851495DA303F007CE572D09>a hrefcategory/hand-pads classbeaver-logo-bar-menu__a-3>Hand Pads/a>/li> li classbeaver-logo-bar-menu__li-3 data-key0BB431E2483C4AF7825BD9A14E7F0F22>a hrefcategory/microfiber-accessories classbeaver-logo-bar-menu__a-3>Microfiber Accessories/a>/li> li classbeaver-logo-bar-menu__li-3 data-key24D5514FAF41481E8D9F05675FC00DBB>a hrefcategory/mop-handles classbeaver-logo-bar-menu__a-3>Mop Handles/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyFC05FEF2CF6F47D9AFFA81ED5FC714B6>a hrefcategory/mop-heads classbeaver-logo-bar-menu__a-3>Mop Heads/a>/li> li classbeaver-logo-bar-menu__li-3 data-key21D6D80D819F42CC99C7E94E05CBA5AB>a hrefcategory/multi-product-kits classbeaver-logo-bar-menu__a-3>Multi-Product Kits/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyCE9876DCF8534EAB8DFFE1BA52A70800>a hrefcategory/parts-washer-parts classbeaver-logo-bar-menu__a-3>Parts Washer/Parts/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyF74CD6A5DE7541328143791CBD82FD7F>a hrefcategory/polish classbeaver-logo-bar-menu__a-3>Polishes/a>/li> li classbeaver-logo-bar-menu__li-3 data-key4B383B75A9184F31A2EB421B12DA4A9A>a hrefcategory/specialty-lubricants classbeaver-logo-bar-menu__a-3>Specialty Lubricants/a>/li> li classbeaver-logo-bar-menu__li-3 data-key230596CD178846A3A5702E5085EE79C2>a hrefcategory/sprayers classbeaver-logo-bar-menu__a-3>Sprayers/a>/li> li classbeaver-logo-bar-menu__li-3 data-key4F7AD2A01A244B53BFEAA4602BD5233B>a hrefcategory/tugs classbeaver-logo-bar-menu__a-3>Tugs/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyA94902EC201645B4B5B139E7C3094120>a hrefcategory/test-kits classbeaver-logo-bar-menu__a-3>Test Kits/a>/li> li classbeaver-logo-bar-menu__li-3 data-keyB6D34C3DD52C4E35A5F2AC24C761110D>a hrefcategory/water-treatment-equipment classbeaver-logo-bar-menu__a-3>Water Treatment Equipment/a>/li> /ul>/li> li classbeaver-logo-bar-menu__li-2 data-keyF26F34830E364837B9E3D57EC5BCC940>a hrefcategory/laundry classbeaver-logo-bar-menu__a-2>Laundry/a>/li> li classbeaver-logo-bar-menu__li-2 data-key7F2748A6A9454A17A971265BE8FF45D2>a hrefcategory/manufacturing-commodities classbeaver-logo-bar-menu__a-2>Manufacturing/Commodities/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyD88A6E6AC6B64C8B9BC81D767E1E5B85>a hrefcategory/metal-working-fluids classbeaver-logo-bar-menu__a-2>Metal Working Fluids/a>/li> li classbeaver-logo-bar-menu__li-2 data-key4682F26251B749DF8FF786502550DCC1>a hrefcategory/paint-stripper classbeaver-logo-bar-menu__a-2>Paint Stripper/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyFE125D6C9AC04605AA7BA70714742B87>a hrefcategory/paper-products classbeaver-logo-bar-menu__a-2>Paper Products/a>/li> li classbeaver-logo-bar-menu__li-2 data-key05EAC778BF1840AAA06BD26C1A152F2D>a hrefcategory/sewer classbeaver-logo-bar-menu__a-2>Sewer/a>/li> li classbeaver-logo-bar-menu__li-2 data-keyF3824F173C6743169F95DA14374AC01D>a hrefcategory/silicones-sealants classbeaver-logo-bar-menu__a-2>Silicones/Sealants/a>/li> li classbeaver-logo-bar-menu__li-2 data-key4FE1736AFB4444E0A63FBA822AE20AEB>a hrefcategory/specialty-chemicals classbeaver-logo-bar-menu__a-2>Specialty Chemicals/a>/li> li classbeaver-logo-bar-menu__li-2 data-key06426525C86343AE9CDB15E38084CF9F>a hrefcategory/special-order-non-stock classbeaver-logo-bar-menu__a-2>Special Order/Non-Stock/a>/li> li classbeaver-logo-bar-menu__li-2 data-key0EC45D4586934196A2D882E6A6111A6A>a hrefcategory/process-water-treatment classbeaver-logo-bar-menu__a-2>Water Treatment/a>/li> li classbeaver-logo-bar-menu__li-2 data-key2CE232F7D305400AA58F6A86226DAB6F>a hrefcategory/winter-products classbeaver-logo-bar-menu__a-2>Winter Products/a>/li> /ul>/li> li classbeaver-logo-bar-menu__li-1 data-keyEA3C70585AFB44DEBBDEDB37035D47BD>a hrefdownload-catalog.asp classbeaver-logo-bar-menu__a-1 target_blank>Download Catalog/a>/li>/ul> /nav> div classlogo-bar__search> form idfrmUnivSearch classu-search-form methodpost action> span classu-search-group u-search-text> input typetext nameu_search_text idu_search_text classinput-search placeholderSearch for products value autocompleteoff autocorrectoff autocapitalizeoff spellcheckfalse /> /span> span classu-search-group u-search-droplist> select nameu_search_type idu_search_type class hide> option valuepc_combined_results.asp?search_prod((searchlike~p.sku~keyword>|Or|searchlike~p.nm~keyword>|Or|searchlike~p.ds~keyword>|Or|searchlike~p.search_terms~keyword>|Or|searchlike~p.searchfield1~keyword>|Or|searchlike~p.searchfield5~keyword>|Or|searchlike~pa.sku_alias~keyword>|Or|searchlike~pa.nm_alias~keyword>|Or|searchlike~pa.ds_alias~keyword>)|Or|searchlike~p.child_rollup_search_terms~keyword>|Or|searchlike~p.search_terms~keyword>)&search_keywordkeyword>>Products/option>option valueerp_manage_sales_orders.asp?search2(searchlike~order_date~keyword>|OR|searchlike~eosoh.order_number~keyword>|OR|searchlike~eosoh.status~keyword>|OR|searchlike~grand_total~keyword>|OR|searchlike~po_number~keyword>|OR|searchlike~expected_ship_date~keyword>)&skeyword>&sfieldsearchall>Orders/option>option valueback_order_report.asp?eosoh.order_date_date_from&eosoh.order_date_date_to&group&skeyword>&sfieldsearchall&rpp50&ddtloaded1&pagesize50&search2((searchlike~p.nm~keyword>%7COR%7Csearchlike~p.sku~keyword>%7COR%7Csearchlike~eosoh.order_number~keyword>%7COR%7Csearchlike~eosoh.po_number~keyword>%7COR%7Csearchlike~eosod.qty_backordered~keyword>%7COR%7Csearchlike~eosod.unit_price~keyword>))&page1&ddt1>Backorders/option>option valueerp_manage_shipments.asp?ship_date_date_from&ship_date_date_to&group&skeyword>&sfieldsearchall&rpp50&ddtloaded1&pagesize50&search2((searchlike~ship_date~keyword>%7COR%7Csearchlike~eos.ship_via~keyword>%7COR%7Csearchlike~eos.tracking_num~keyword>%7COR%7Csearchlike~eos.sales_order_number~keyword>%7COR%7Csearchlike~eoih.ref_id~keyword>%7COR%7Csearchlike~eosoh.po_number~keyword>%7COR%7Csearchlike~eos.notes~keyword>))&page1&ddt1>Shipments/option>option valueerp_manage_invoices.asp?search2(searchlike~eoih.ref_id~keyword|OR|searchlike~invoice_date~keyword>|OR|searchlike~eoih.status~keyword>|OR|searchlike~po_number~keyword>|OR|searchlike~eoih.sales_order_number~keyword>|OR|searchlike~invoice_due~keyword>)&skeyword>&sfieldsearchall>Invoices/option>option valuemy_addresses.asp?skeyword>&sfieldsearchall&rpp50&ddtloaded1&pagesize50&search2((searchlike~sha.nm~keyword>%7COR%7Csearchlike~sha.s_add1~keyword>%7COR%7Csearchlike~sha.s_city~keyword>%7COR%7Csearchlike~sha.s_state~keyword>%7COR%7Csearchlike~sha.s_zip~keyword>%7COR%7Csearchlike~sha.s_country~keyword>))&page1&ddt1>My Addresses/option>option valueerp_manage_payments.asp?sortbydate_received&sortorderdesc&skeyword>&sfieldsearchall&pagesize100&search2((searchlike~date_received~keyword>|OR|searchlike~eop.invoice_number~keyword>|OR|searchlike~amount~keyword>|OR|searchlike~payment_type~keyword>|OR|searchlike~reference_info~keyword>))>Payments/option>option valueproduct_stock_ddt.asp?skeyword>&sfieldsearchall&search2((searchlike~p.nm~keyword>%7COR%7Csearchlike~p.sku~keyword>%7COR%7Csearchlike~p.retail_price~keyword>))>Price List/option>option valuefavorite_lists_man.asp?skeyword>&sfieldsearchall&search2((searchlike~fl.nm~keyword>))>Favorite Lists/option> /select> /span> span classu-search-group u-search-btn> button typesubmit nameu_search_submit idu_search_submit classbtn> i classicon-search>/i> /button> /span>input typehidden namesearch_tip_url idsearch_tip_url value /> /form> script typeapplication/javascript> // Execute when DOM ready $(function(){ // Form post $(#frmUnivSearch).on(submit, function(e){ e.preventDefault(); fncProcessUniversalSearch(); }); }); /* Boolean Vars */ /* * Add the STOREFRONTURL to the page being redirected to * @author johns * @since 6/28/2012 * @var bool */ var bAddStoreFrontUrlToPost true; /* * Log the keyword search * @author johns * @since 6/28/2012 * @var bool */ var bUseKeywordSearchLogging true; /* * Create searchstring by the splitting the terms on spaces * @author johns * @since 6/28/2012 * @var bool */ var bUseSplitTermSearching true; /* * Use Auto Suggestions when searching * @author johns * @since 07/26/2012 * @var bool */ var bUseAutoSuggestions true; /* * Add Categories to the Searchstring * @author johns * @since 07/26/2012 * @var bool */ var bUseCategories false; /* * Add modal1 to redirect url * @author ejohnston * @since 10/02/2017 * @var bool */ var bUseModal false; /* String Vars */ /* * VBScript variable for STOREFRONTURL * @author johns * @since 6/28/2012 * @var string * Updated 2017-10-03 EJ - Used order front url to avoid SSL mixed content errors */ var sStoreFrontUrl https://www.beaverresearch.com; /* * Name of the current page loaded * @author johns * @since 6/28/2012 * @var string * Updated 201-11-15 EJ - Changed var name to avoid conflict */ var searchPageName i_i_u_search.asp; /* * List of product fields to check for a product search * @author johns * @since 6/28/2012 * @var string */ var sProductFieldsToCheck p.sku, p.nm, p.ds, p.search_terms, p.child_rollup_search_terms, p.child_skus, p.child_nms, child_ds; /* * List of fields to check for a website search * @author johns * @since 6/28/2012 * @var string */ var sWebsiteFieldsToCheck p.nm,p.ds,staticpages.se_pagetitle,staticpages.se_ds,staticpages.se_keywords; /* * Name of the page to redirect to for product searches * @author johns * @since 6/28/2012 * @var string */ var sProductSearchPage pc_combined_results.asp; /* * Name of the page to redirect to for website searches * @author johns * @since 6/28/2012 * @var string */ var sWebsiteSearchPage search_results.asp; /* * List of category fields to check for a product search * @author johns * @since 07/26/2012 * @var string */ var sCategoryFieldsToCheck pc.nm,pc.ds; //- these are for the search tips ajax call redirect /* * Page the search is being performed on * @author johns * @since 07/26/2012 * @var string */ var sInitPage /Default.asp; /* * Website name * @author johns * @since 07/26/2012 * @var string */ var sSitename beaver; var sProductSearchTerm products; var bTrimSearchTerm false; /** * This function handles the form submission. * * @author seanm * @since ?? * * @author johns * @modified 6/28/2012 * * @return void */ function fncProcessUniversalSearch() { var sPrepopValues ; var sDelimiter ?; var sNewSearchPage ; var sSearchType ; var sRedirectUrl ; var sSearchTerm jQuery(#u_search_text).val() if (bTrimSearchTerm) sSearchTerm $.trim(sSearchTerm); sSearchTerm encodeURIComponent(sSearchTerm); sSearchType jQuery(#u_search_type option:selected).text().toLowerCase(); if ( bUseSplitTermSearching && sSearchType sProductSearchTerm ) { sNewSearchPage fncBuildSplitTermSearchPage ( sSearchTerm, sSearchType ); } else { sNewSearchPage jQuery(#u_search_type option:selected).val().replace(/keyword>/ig, sSearchTerm); } /* * If theres already a ?, we need to make sure we dont add another. */ if ( sNewSearchPage.indexOf(?) > 0 ) { sDelimiter &; } /* * PMH #134437 * Added search_keyword to query string regardless of whether splitting is in use. That allows * the search textbox to always populate. */ if ( bUseSplitTermSearching && sSearchType sProductSearchTerm ) { sPrepopValues sDelimiter + search_keyword + sSearchTerm; } else { if (sNewSearchPage.indexOf(search_keyword) -1) sPrepopValues sDelimiter + search_keyword + sSearchTerm + sDelimiter + u_search_type + jQuery(#u_search_type option:selected).text(); else sPrepopValues sDelimiter + u_search_type + jQuery(#u_search_type option:selected).text(); } if ( sNewSearchPage.indexOf(u_search_type) > 0 ) { sPrepopValues ; } if ( bAddStoreFrontUrlToPost ) { sNewSearchPage sStoreFrontUrl + / + sNewSearchPage; } if ( bUseAutoSuggestions ) { fncCheckSearchSuggestions(); sRedirectUrl jQuery(#search_tip_url).val(); } //- if ( bUseAutoSuggestions ) if ( sRedirectUrl ) { sRedirectUrl sNewSearchPage + sPrepopValues; } if ( bUseKeywordSearchLogging ) { fncLogKeywordSearch(sSearchType, sSearchTerm, sRedirectUrl) } if(bUseModal) { sRedirectUrl + &modal1; } window.location sRedirectUrl; } //- function fncProcessUniversalSearch() /** * This function fires an ajax call to log the keyword search. * * @author johns * @since 6/28/2012 * * @param sType (string): type of search submitted * @param sKeyword (string): keyword(s) searching for * @param sUrl (string): url redirected to see the results * of the search * * @return void */ function fncLogKeywordSearch ( sType, sKeyword, sUrl ) { jQuery.ajax({ url: searchPageName + ?pageactionlogsearch&SearchFormAjax1, data: search_type + sType + &search_term + sKeyword + &search_url + sUrl + &r_id + new Date().getTime(), type: POST, dataType: text, beforeSend: , success: function () { return; } }); } //- function fncLogKeywordSearch ( sType, sKeyword, sUrl ) /** * This function builds a searchstring from phrases (denoted * by single or double quotes) and other search terms. * * @author johns * @since 6/28/2012 * * @param sSearchType (string): type of search submitted * @param sSearchTerms (string): phrases or words searching for * * @return string (page used to redirect to with the appropriate searchstring) */ function fncBuildSplitTermSearchPage ( sSearchTerms, sSearchType ) { /* * array variables */ var aNewSearchTerms; var aFieldsToCheck; var aTerms; /* * string variables */ var sTerms ; var aNewSearchTerms ; var sResult ; var sSearchStringQSVar ; /* * determine which list of fields to use and which * page we need to redirect to based on search * type */ switch (sSearchType) { case website: sSearchPage sWebsiteSearchPage; sFieldsToCheck sWebsiteFieldsToCheck; sSearchStringQSVar search_website; break; case sProductSearchTerm: sSearchPage sProductSearchPage; sFieldsToCheck sProductFieldsToCheck; if ( bUseCategories ) aCategoryFieldsToCheck sCategoryFieldsToCheck.split(,); sSearchStringQSVar search_prod; sCategorySearchStringQSVar search_cat; break; } /* * build an array from a list of fields to check in the extended search * by splitting the list on , */ aFieldsToCheck sFieldsToCheck.split(,); aNewSearchTerms decodeURIComponent(sSearchTerms).split(/\s+/); sSearchTerms encodeURIComponent(sSearchTerms); if (1 1) { sSearchPage sSearchPage + ? + sSearchStringQSVar + + fncBuildSearchString(aNewSearchTerms, aFieldsToCheck); if (bUseCategories && sSearchType sProductSearchTerm) { sSearchPage sSearchPage + & + sCategorySearchStringQSVar + + fncBuildSearchString(aNewSearchTerms, aCategoryFieldsToCheck); } } return sSearchPage; } // fncBuildSplitTermSearchPage function fncCheckSearchSuggestions () { var sSearchTerm ; try { /* * if it is blank, ge the value of term being searched * for */ sSearchTerm jQuery(#u_search_text).val(); sSearchTerm sSearchTerm.toLowerCase(); /* * loop through the json object build by the ajax call * to build the search tips list */ for ( var i 0, goTo window.oSearch.terms.length; i goTo; i++ ) { /* * get the term value of json object */ sTerm window.oSearch.termsi; sOriginalTerm sTerm; sTerm sTerm.toLowerCase(); /* * see if the term matches the word being searched for */ if ( sTerm sSearchTerm ) { /* * check the term that matched an suggested term * has an specific url to redirect to */ fncGetSearchTermRedirectUrl ( window.oSearchsOriginalTerm ); /* * if a specific redirect url has been found then exit the terms for loop */ if ( jQuery(#search_tip_url).val() ! ) break; } //- if ( sTerm sSearchTerm ) } //- for ( var i 0, goTo window.oSearch.terms.length; i goTo; i++ ) } catch ( oError ) { //alert(oError.message); } //- try return } //- function fncGetSearchSuggestionUrl () /** * AJAX Call to get search term suggestions * * @author johns * @since 4/15/2010 * * @return void */ function fncGetSuggestions ( text ) { try { //- check to see if the ajax call should be fired again //- run it again, if length of the search term 0 if ( text.length 1 ) { window.bGetSuggestions false; } //- if ( text.length 1 ) if ( ! window.bGetSuggestions ) { if ( text.length > 1 ) { //- set it to true once inside the ajax call so it does not fire again window.bGetSuggestions true; text text.substr(0,1); jQuery.ajax({ url: i_i_pc_search_form.asp , data: ({ searchformaction : ajaxcall , searchformactiontype : getsearchtips , firstchar : text , ajax: new Date().getTime() }) , cache: false , dataType: json , error: function(jqXHR, textStatus, errorThrown) { console.log(error - + errorThrown); } , success: fncLoadSuggestions }); } //- if ( text.length > 1 ) } //- if ( ! window.bGetSuggestions ) } catch ( oError ) { //alert(oError.message); } //- try }// function fncGetSuggestions() /** * AJAX callback function to load search * term suggestions * * @author johns * @since 4/15/2010 * * @return void */ function fncLoadSuggestions ( oData ) { window.oSearch oData; jQuery(#u_search_text) .autocomplete(oData.terms,{ select: function ( event, ui ) { /* * get the search term selected from the auto complete list (json object) */ oResult window.oSearchui.item.label; /* * check the term that matched an suggested term * has an specific url to redirect to */ fncGetSearchTermRedirectUrl ( oResult ); } }); } //- function fncLoadSuggestions ( oData ) /** * This function determines if the term that matched an * suggested term has an specific url to redirect to. * * @author johns * @since 7/30/2012 * * @param oResult (json object): term in the json object * that matched the term entered by the user * * @return void */ function fncGetSearchTermRedirectUrl ( oResult ) { /* * if the term matching the word being searched for * has action link and the url is not blank then * set the hidden input field for the search tip url * to the url of the current term index */ if ( oResult.action link && oResult.url ! ) { /* * get the length of the name of the site currently on(needed * to see if the sitename/virtualweb needs to be * stripped off) */ iLenSitename sSitename.length; /* * if on an admin server strip off the /sitename/virtualweb/ off the * current page name (pulled from the Request.ServerVariables(SCRIPT_NAME) */ if ( sInitPage.substr(0,iLenSitename + 13) / + sSitename + /virtualweb/ ) { sInitPage sInitPage.substr(iLenSitename + 13); } //- if ( sInitPage.substr(0,iLenSitename + 13) / + sSitename + /virtualweb/ ) /* * check to see if the static page is located in * a directory (only assuming one directory deep off the root * since static pages are only one directory deep * off the root) */ if ( sInitPage.indexOf(/) > 0 ) { sResultUrl ../ + oResult.url; } else { sResultUrl oResult.url; } //- if ( sInitPage.indexOf(/) > 0 ) /* * set the hidden input field to the url of the matched term */ jQuery(#search_tip_url).val(sResultUrl); } //- if ( oResult.action link && oResult.url ! ) } //- function fncGetSearchTermRedirectUrl ( oResult ) /** * This function builds a searchstring based on the list of * split search terms and the list of fields to check. * * @author johns * @since 7/30/2012 * * @param aSearchTerms (array): list of search terms * @param aFieldsToCheck (array): list of fields to check * * @return string (WSP formatted searchstring) */ function fncBuildSearchString ( aSearchTerms, aFieldsToCheck ) { /* * string variables */ /* * New Search String Built * @author johns * @since 08/15/2012 * @var string */ var sNewSearchString ; /* * boolean variables */ /* * Is this the First Field in the list of fields * to check in split term searching? * @author johns * @since 08/14/2012 * @var bool */ var bFirstField true; /* * loop through the search terms split on whitespace */ for ( var iTermCounter 0, iTermGoTo aSearchTerms.length - 1; iTermCounter iTermGoTo; iTermCounter++ ) { /* * loop through the fields to search list with the current search term */ for ( var iFieldCounter 0, iFieldGoTo aFieldsToCheck.length - 1; iFieldCounter iFieldGoTo; iFieldCounter++ ) { /* * check to see if we are at the first field * if so, add the opening parantheses */ if ( bFirstField ) { sNewSearchString + (; } //- if ( bFirstField ) /* * check to see if the searchstring var has assigned to anything yet * if so, concatentate |Or| to the end of the string */ if ( sNewSearchString ! && ! bFirstField ) { sNewSearchString + |Or|; } //- if ( sNewSearchString ! && ! bFirstField ) /* * build the searchstring with the current search term and field based * on the search type */ sNewSearchString + searchlike~ + aFieldsToCheckiFieldCounter + ~ + encodeURIComponent(aSearchTermsiTermCounter); /* * set the var to false that signals we are on the first field the next time * through the loop */ bFirstField false; } //- for ( var iFieldCounter 0, iFieldGoTo aFieldsToCheck.length - 1; iFieldCounter iFieldGoTo; iFieldCounter++ ) /* * after looping through the fields to search with the current search term, * reset the var that signals we are on the first field the next time we * loop through them */ bFirstField true; /* * after looping through the fields to search with the current search term, * check to see if we just looped through the last search term */ if ( iTermCounter > iTermGoTo ) { /* * if we are at the last search term, add the closing parantheses to * the current search term */ sNewSearchString + ); } else { /* * if we are not at the last search term, add the closing parantheses * to the current search term and concatenate |And| to the end of * the searchstring */ sNewSearchString + )|And|; } //- if ( iTermCounter > iTermGoTo ) } //- for ( var iTermCounter 0, iTermGoTo aSearchTerms.length - 1; iTermCounter iTermGoTo; iTermCounter++ ) return sNewSearchString } //- function fncBuildSearchString ( aSearchTerms, aFieldsToCheck ) jQuery(function() { jQuery(#u_search_text).keyup(function() { if ( bUseAutoSuggestions ) { fncGetSuggestions(this.value); } //- if ( bUseAutoSuggestions ) }); if (bUseAutoSuggestions) { jQuery(#search_keyword).autocomplete(); } }); /script> /div> /div> /div> /div> /header>div idpageMain classpage-main> div classhome-hero stylebackground-image: url(images/beaver-homepage-hero.jpg);>div classcontainer-fluid home-hero__wrap>div classhome-hero__content>h1>Bringing You Quality Specialty Chemicals For Over 50 Years/h1>p>You deserve quality products that keep the planet, your people and budget safe. Over the past 50 years, we’ve helped 15,000+ organizations, across every major sector, do just that. Contact us today to learn more about our environmentally safe, quality products./p>a classhome-hero__button hrefbecome-customer/>Become a Customer/a>/div>/div>/div>script> /** * Rating Stars * - gets score from data attribute on container * @author jonr * @since 1/31/2014 */ jQuery(function(){ jQuery(.raty) .raty({ path: templates/gfx/, space: false, readOnly: true, width: 90, hints: Bad, Poor, Good, Very Good, Excellent, score: function() { return jQuery(this).attr(data-score); } }); }); /script> div classcontainer-fluid> div classhome-feature-products>h2>We Have A Variety Of Products To Suit Your Needs/h2>div classowl-carousel home-feature-products-carousel>div classitem>a hrefpc_combined_results.asp?pc_idB786CE9DD04C4F5F94766CDD4988F796>img srcimages/industrialmaintenance.jpg alt />h4>Industrial Maintenance and Cleaning/h4>/a>/div>div classitem>a hrefpc_combined_results.asp?pc_id264A31962A1843B2A6F302D683D47C00>img srcimages/JanSanProducts.jpg alt />h4>Janitorial and Sanitation Supplies/h4>/a>/div>div classitem>a hrefpc_combined_results.asp?pc_idDFE1E3BC230B487E84C1306E2F5F51E5>img srcimages/building-and-grounds.jpg alt />h4>Building and Grounds Maintenance/h4>/a>/div>/div>a classhome-feature-products__view-all-btn hrefcategories.asp>View All Product Categories/a>/div>script> /** * Rating Stars * - gets score from data attribute on container * @author jonr * @since 1/31/2014 */ jQuery(function(){ jQuery(.raty) .raty({ path: templates/gfx/, space: false, readOnly: true, width: 90, hints: Bad, Poor, Good, Very Good, Excellent, score: function() { return jQuery(this).attr(data-score); } }); }); /script>div classhome__core-values>h2>We Believe In Strong Core Values/h2>div classcontainer-fluid>div classcore-values__item1>img srcimages/core-values-people.png alt />h3>People/h3>p>We value and respect our customers, suppliers, employees and global community./p>/div>div classcore-values__item2>img srcimages/core-values-integrity.png alt />h3>Integrity/h3>p>We are committed to doing what’s right forever, rather than what’s right for right now./p>/div>div classcore-values__item3>img srcimages/core-values-quality.png alt />h3>Quality/h3>p>We are dedicated to providing safer, more efficient products that really work for your needs./p>/div>div classcore-values__item4>img srcimages/core-values-innovation.png alt />h3>Innovation/h3>p>We strive to develop the processes and products that contribute to sustainability of our environment./p>/div>div classcore-values__item5>img srcimages/core-values-environment.png alt />h3>Environment/h3>p>We care for our planet and the people, plants and animals that call it home./p>/div>/div>/div>script> /** * Rating Stars * - gets score from data attribute on container * @author jonr * @since 1/31/2014 */ jQuery(function(){ jQuery(.raty) .raty({ path: templates/gfx/, space: false, readOnly: true, width: 90, hints: Bad, Poor, Good, Very Good, Excellent, score: function() { return jQuery(this).attr(data-score); } }); }); /script>div classbuy-from-us>h1>Buying From Us Is Easy!/h1>p>Simply fill out the form below and let us know which of our quality products you would like ot learn more about./p>script charsetutf-8 typetext/javascript src//js.hsforms.net/forms/shell.js>/script>script> hbspt.forms.create({ portalId: 7231516, formId: 6eb89594-4fc1-4442-800e-95b82cfc57df});/script>/div>script> /** * Rating Stars * - gets score from data attribute on container * @author jonr * @since 1/31/2014 */ jQuery(function(){ jQuery(.raty) .raty({ path: templates/gfx/, space: false, readOnly: true, width: 90, hints: Bad, Poor, Good, Very Good, Excellent, score: function() { return jQuery(this).attr(data-score); } }); }); /script> a nametop idtop>/a> /section> !-- wpc-fw-title --> div classwpc_container> /ul> /div>!--/#wpc_container-->script> /** * Rating Stars * - gets score from data attribute on container * @author jonr * @since 1/31/2014 */ jQuery(function(){ jQuery(.raty) .raty({ path: templates/gfx/, space: false, readOnly: true, width: 90, hints: Bad, Poor, Good, Very Good, Excellent, score: function() { return jQuery(this).attr(data-score); } }); }); /script> /div> /div>/div>footer idpageFooter classpage-foot print-hide> div classcontainer-fluid> div classrow-fluid> div classcolumn1> address> strong>Beaver Research Company/strong>br> 3700 E. Kilgore Rd.br>Portage, Michigan 49002br>Toll Free: 800.544.0133br>Phone: 269.382.0133br>Fax: 269.382.0214 /address> /div> div classcolumn2> ul idfooter-column-2 classfooter-column-2 linkset footer-column-2__ul-1> li classfooter-column-2__li-1 data-keyFD471EFF2800424680B6951F21A26463>a hrefcareers classfooter-column-2__a-1>Careers/a>/li> li classfooter-column-2__li-1 data-keyEF4A55E59C644814AA8986A96B0183F0>a hrefabout-us classfooter-column-2__a-1>About/a>/li> li classfooter-column-2__li-1 data-key739B8C8761974A0F84D860E643B9ACE1>a hrefcontact_us.asp classfooter-column-2__a-1>Contact/a>/li> li classfooter-column-2__li-1 data-key7CCB7DE625804C15A4AE93716177ED9D>a href/security_logon.asp classfooter-column-2__a-1>Customer Portal/a>/li>/ul> /div> div classcolumn3> ul idfooter-column-3 classfooter-column-3 linkset footer-column-3__ul-1> li classfooter-column-3__li-1 data-key2CED692906B64CFE849D2FAF423AD4D9>a hrefcategories.asp classfooter-column-3__a-1>Products/a>/li> li classfooter-column-3__li-1 data-key7047AE2CA5894331A8C9AC260FDF09B1>a hrefdownload-catalog.asp classfooter-column-3__a-1 targetblank>Download Catalog/a>/li> li classfooter-column-3__li-1 data-keyC5C3B0FAA3414AC08CE337954FE53596>a hrefcreate_login_and_account.asp classfooter-column-3__a-1>Become a Customer/a>/li>/ul> /div> div classcolumn4> div>img classseal src../templates/images/AWT_logo.png altAWT Logo /> img classseal src../templates/gfx/issa-badge.png altISSA Member /> img classseal src../templates/images/NSF_logo.png altNSF Logo />/div>script> /** * Rating Stars * - gets score from data attribute on container * @author jonr * @since 1/31/2014 */ jQuery(function(){ jQuery(.raty) .raty({ path: templates/gfx/, space: false, readOnly: true, width: 90, hints: Bad, Poor, Good, Very Good, Excellent, score: function() { return jQuery(this).attr(data-score); } }); }); /script> /div> /div> /div> div classcolophon> div classcontainer-fluid> div classrow-fluid> div classspan6> ©2024 Beaver Research Company. /div> div classspan6 text-right> Ecommerce & ERP Integration by a hrefhttp://www.websitepipeline.com relnofollow target_blank>CIMcloud/a>. /div> /div> /div> /div>/footer>div classglobal-body-append> div classga-tracking> !-- START Tracking/Analytics Code --> !-- END Tracking/Analytics Code -->/div>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.beaverresearch.com; var jsConfig { static_pages: { content_key: , content_type: } } /script> script srccode/global_modal_js.asp?122e9b3>/script> script src../hooks/js_custom_functions.asp?122e9b3>/script> script srcjs/vendor/stretchy.min.js?122e9b3 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?122e9b3aa42d1d869f206d242ff5d4e4e3ba780d >/script> script src../js/retail.js?122e9b3>/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 { localStorage.setItem(breadcrumbs, JSON.stringify(obj)); } catch(e) { // nothing to do if it didnt work console.error(failed to save breadcrumbs); } }; 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(int100) { // in this case, we have to track a +1 to add to the result because 100 sliced down to 2 places loses info 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() { 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 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); } } 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.requireInfoForAtc ko.computed(function () { return !!(self.childDisplayType() || 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(); 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.isParent function() { if (self.type.toLowerCase() parent){ 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() ! 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 propertyitemListElement typeofListItem data-bindcss: { active: !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 ? : name >/span> meta propertyposition data-bindattr: { content : $index() + 1 }> /li> !-- /ko --> !-- /ko --> !-- ko ifnot: oConfig.activeBreadcrumb && oConfig.activeBreadcrumb.length > 0 --> !-- ko foreach: $data --> li propertyitemListElement typeofListItem data-bindcss: { active: !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 ? : 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: name, data-key: key }> img data-bindattr: { src: utils.buildImagePath(pic2) }/> /a> /div> div classprod-info> div classprod-desc> div classprod-nm> a data-bindattr: { href: link, title: 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 > !-- 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: oConfig.labels.favLink, data-title: oConfig.labels.favLink, href: add_product_to_favorites.asp?p_id + key() }, tooltip data-iconheart data-sizesmall> i classicon-heart>/i> /a> !-- /ko --> !-- ko if: !oConfig.showFavLink && oConfig.useSavedCarts --> button typebutton classbtn data-bindattr: { title: 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: 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: 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: 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: 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: 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: 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: (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: 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: 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: name, data-key: key }, html: name>/a> /script> script typetext/html idcatalog.image_link> a classdetail_link data-bindattr: { href: link, title: thumbAltText() || name(), data-key: key }> img data-bind attr: { src: utils.buildImagePath(thumb()), alt: 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: 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>, Order); } $(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 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: pc_combined_results.asp } ); 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 : , t_tracking_company : , t_tracking_id : , t_gtm : false, t_gtm_id : , sessionData : { sc_id : AAF10E0B498B407DA3208A3D704B35D0, sessionKey : 8B2F7EC82A814B4697576043058C1500, storefrontUrl : https://www.beaverresearch.com, orderfrontUrl : https://www.beaverresearch.com, cdnUrl: https://dej7787zuxy4a.cloudfront.net, isSuperUserSession : false }, detailConfig : { productKey : , useAdvancedTabs : true, useRelatedProducts : true, useSecondRelatedProducts : false, useAlsoBoughtProducts : true, useRecentlyViewedProducts : true, useAliases : false, selectChildProductOnLoad : false, 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 : 25,50,100, showSort : true, productSort : { field : p.orderby,p.sku, direction : asc, display : - }, productSortOptions : { field : p.orderby,p.sku, direction : asc, display : - },{ 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) }, showDownload : false, gridListViewRowClass : , gridListViewATCColumnClass : , showDescription : true, labels : { layout : , sort : Sort by, rpp : per page, firstPage : , maxPage : , prevPage : < Prev, nextPage : Next >, favListRemoveColumnHeader : , searchResultsHeader : Search Results, 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.beaverresearch.com/i_i_add_to_cart.asp, isLoggedIn : false, showChildrenSelection: false, usePromos : false, useIdp : false, useUom : (true || 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 : true, showEmailFriend : true, showFavLink : false, showRFQLink : false, showProductHistory : false, showProductHistoryResults: false, showWarehouses : false, showProdYouSave : true, allowWarehouseSelection : false, useWarehousesTable : false, defaultWarehouse : , hazmatLink : , allowChildATC : true, showListViewATC : false, showNameCol : false, showImgCol : true, preventATCInvalidQty : false, showZeroPriceMessage : true, 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 : Order, 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 : 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 add a review, reviewsAddText : Add a Review }, mapBehaviorMessages : { showMessage : Call for Price, requireLoginMessage : div>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> span style\color: #444;\>to see price and purchase/span>/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 : , title : Page 1, pic : test_flag1_n.jpg, 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? }; 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(); }) || 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.postGoogleAnalytics function() { 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({ customerCity : self.account.city() }); dataLayer.push({ customerState : self.account.state() }); dataLayer.push({ customerCountry : self.account.country() }); dataLayer.push({ couponCode : self.couponCode() }); dataLayer.push({ couponAmount : self.couponDiscountTotals.totalDiscount() }); dataLayer.push({ paymentMethod : self.paymentMethod.name() }); // 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: EEtransaction, 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; } } 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); }); // Used for Google Analytics and Tag Manager, etc self.completed.subscribe(function(completed){ if(completed) { self.postGoogleAnalytics(); } }); 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 : viewModel.orderKey() }; 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 + viewModel.orderKey() + &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 --> h3 data-bindif: completed() && orderNumber() >Your order number is span data-bindtext: ofConfig.orderNumberPrefix>/span>span data-bindtext: orderNumber>/span>/h3> 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>/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> //These are defined in cim_dashboard.asp in coresite. utils.templateExists function(name){ return document.getElementById(name); }; utils.getTemplateName function(template){ if(utils.templateExists(template + _custom)){ return template + _custom; }else{ return template; } }; registerHook({ //Task#: 152245 name: SUAccountAddEdit, func: function(oArgs) { function validateAcctNum() { var accountRefId $(#division).val() ! ? $(#division).val() + - + $(#num).val() : $(#num).val(); if (accountRefId ! ) { $.ajax({ url: Default.asp, data: ajaxactioncheckacctnum&refid + accountRefId + &r_id + new Date().getTime(), type: GET, dataType: text, beforeSend: , success: function (sData) { handleValidation (sData); } }); } } function handleValidation(sData) { if (sData 0) { if ($(#invalid_acct_num).length 1) $(#num_answer_container).append(div idinvalid_acct_num classmgrfront-error>Account Number is already taken/div>); } else { $(#invalid_acct_num).remove(); } } $(#num).focusout(function() { validateAcctNum() }); } }); registerHook({ name: productSearchResultsAfterConfig, func: function(oArgs){ var self oArgs.self; if(viewModel && viewModel.category) { if(oConfig.pageName pc_combined_results.asp && viewModel.category.top_level 1) { $(body).addClass(top-level-category); } else { $(body).addClass(child-category); } } oConfig.siteTemplateType retail; } }); registerHook({ name: productModelBottom, func: function(oArgs){ var self oArgs.self; 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; }); } //default to sales uom for super users if it exists if(!uom && oConfig.sessionData.isSuperUserSession) { uom _.find(self.uomPrice(), function (price) { return price.uom() uom_sales; }); } 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; })()); self.showYouSave ko.computed(function () { if(!self.selectedUom()) { return false; } 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.uomTemplate ko.computed(function(){ if (oConfig.sessionData.isSuperUserSession && self.selectedProduct() && self.selectedProduct().uomPrice().length > 1) { return utils.getTemplateName(catalog.uom_select) } else { return utils.getTemplateName(catalog.uom_input); } }); //Task 232770 if(viewModel && viewModel.category) { if(oConfig.pageName ! pc_combined_results.asp && viewModel.category.top_level 1) { $(body).addClass(top-level-categories); } } } }); registerHook({ name: orderModelBottom, func: function(oArgs){ var self oArgs.self; //initialize opt1 if(self.opt1() ){ self.opt1(order); } if(self.opt2() ){ self.opt2(0); } //subscribe to opt1 and opt2 self.opt1.subscribe(function(newValue){ postOrderHeaderField(opt1, newValue); }); self.opt2.subscribe(function(newValue){ postOrderHeaderField(opt2, newValue); }); self.useLocalShipping ko.computed({ read: function(){ return self.opt2() 1 ? true : false; }, write: function(newValue){ self.opt2(newValue ? 1 : 0); } }); self.orderType ko.computed({ read: function(){ return self.opt1() || order; }, write: function(newValue){ self.opt1(newValue); } }); } });/script>script typetext/html idcart.shipToSelectOptGroups_custom> 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.address1() + + $data.address2() + , + $data.city() + , + $data.state() + , + $data.zipCode() + + $data.country()>/option> !-- /ko --> /optgroup> /select> span classadd-on data-bindvisible: $data.shipTo().global() 0> 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 idcatalog.detail_info_container_custom> !-- template: { name: catalog.product_title, data: selectedProduct } --> div classdetail_info_container_sku> p>span data-bindhtml: oConfig.labels.sku>/span> span itempropsku data-bindtext: selectedProduct().sku>/span>/p> /div> div classdetail-product-info> span data-bindtemplate: catalog.rating_detail>/span> !-- template: catalog.product_links --> span data-bindtemplate: { name: catalog.product_description, data: selectedProduct }>/span> 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> !-- ko if: oConfig.isLoggedIn --> div classprivate-docs data-bindtemplate: { name: catalog.private_documents, data: selectedProduct().private_documents() }>/div> !-- /ko --> div data-bind template: { name: promotions.descriptions, if: promoDescriptions && promoDescriptions.length, data: { title: Item on Promotion, descriptions: promoDescriptions, selectedProduct: selectedProduct } } > /div> div classdetail-child-selector> span data-bindtemplate: { name: catalog.child_selectors, if: $data.childSelectors, data: $data.childSelectors }>/span> /div> div data-bindtemplate: catalog.share_code>/div> div idatcform> div data-bindtemplate: { name: catalog.atc_full, data: selectedProduct }>/div> /div> /div>/script>script typetext/html idcatalog.private_documents> ul classdoc_downloads unstyled> !-- ko if: $data.length > 0 --> li>DSS Documents:/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.selected_product_price_display_custom> span data-bindif: unitPrice() 0 && oConfig.showZeroPriceMessage && showPrice && !oConfig.sessionData.isSuperUserSession> ul classunstyled prod-pricing__wrap> li classretail> span data-bindtext: oConfig.zeroPriceMessage>/span> /li> li classtext-small data-bindtemplate: { name: catalog.qty_breaks, if: oConfig.useBreaks }>/li> /ul> /span> span data-bindif: !(unitPrice() 0 && oConfig.showZeroPriceMessage) && showPrice && uomPrice() || (oConfig.sessionData.isSuperUserSession && showPrice)> ul classunstyled> !-- ko if: priceTrace --> li classtext-small> div classalert alert-info data-bindhtml: priceTrace().replace(/\n/gi,br>) >/div> /li> !-- /ko --> li classretail> b data-bindtext: utils.formatPrice(unitPrice())>/b> span classprod-uom data-bindtemplate: catalog.uom>/span> /li> !-- ko if: showYouSave --> li classsretail> del data-bindtext: utils.formatPrice(suggestedPrice())>/del> span classyousave data-bindspacedtext: oConfig.labels.youSaveLabel + + youSavePercent()>/span> /li> !-- /ko --> li classtext-small data-bindtemplate: { name: catalog.qty_breaks, if: oConfig.useBreaks }>/li> /ul> /span> !-- ko if: (!showPrice || !showAtc) && oConfig.pageName pc_product_detail.asp --> div classretail data-bindhtml: $data.mapPriceMessage>/div> !-- /ko -->/script>script typetext/html idZcart.addProductButtonZ_custom> li classdropdown pull-right> 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-browse data-sizefull data-titleAdd Products data-bind attr: { href : pc_combined_results.asp?modalactionaddProduct&modal1 }, 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> /ul> /li>/script>script typetext/html idZcatalog.uom_input_custom> !-- 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: _.find(uomPrice(), function(price) { return price.isDefault() true }).description()> small>/ span data-bindhtml: _.find(uomPrice(), function(price) { return price.isDefault() true }).description()>/span>/small> !-- /ko -->/script>script typetext/html idcart.shipmentList_custom> !-- ko foreach: shipments --> div classrow-fluid data-bindattr: { id: key }> div classlist-group> div classlist-group-item clearfix> 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> a href#0 data-bindclick: function() { viewModel.shippingComplete(false) }, html: ofConfig.sEditShipmentText>/a> i classicon-large icon-question-sign shipment-help data-triggerhover data-placementleft titleEdit This Shipment data-bindpopover, attr: {data-content: function(){ if(utils.getCookie(activequote) && utils.getCookie(activequote).length 32){ return Click here to change shipping addresses, edit item quantities, add items, or set item prices; }else{ return Click here to change shipping addresses or edit item quantities; } }() }> /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>Choose a shipping method:/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 template: { name: cart.local_shipping_charge, if: oConfig.sessionData.isSuperUserSession } -->!-- /ko --> !-- /ko --> !-- ko if : !ofConfig.useProductSummaryTableView --> div classlist-group-item> div classrow-fluid> div classspan5> !-- ko template: { name: cart.shipmentItemList } -->!-- /ko --> /div> div classspan7> label>Choose a shipping method:/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.paymentMethods_custom> 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> 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> PO Number /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()/> p idponum_help classhelp-block text-small data-bindif: !viewModel.paymentMethod.poRequired()>(optional)/p> 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> !-- ko template: { name: cart.order_type, if: ofConfig.isSuperUserSession } -->!--/ko --> 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>/textarea> p classhelp-block text-small>(optional)/p> /div> /div> /div>/script>script typetext/html idcart.local_shipping_charge> div classrow-fluid> div classlist-group-item styleborder-top:0 !important;> input typecheckbox idopt2 nameopt2 data-bindchecked: viewModel.useLocalShipping> label for opt2>Add local shipping charge?/label>br> /div> /div>/script>script typetext/html idcart.order_type> div classcontrol-group> label classcontrol-label>Order Type/label> div idcontrolgroup_ordertype classcontrols> label classradio inline> input typeradio nameopt1 valueorder data-bindchecked: viewModel.orderType> Order /label> label classradio inline> input typeradio nameopt1 valuequote data-bindchecked: viewModel.orderType> Quote /label> /div> /div> span data-bindvisible: orderType.hasError, text: orderType.validationMessage> /span>/script>script typetext/html idZcart.itemCard_custom> img data-bindattr : { alt: sku() + - + name(), src: commodity.pic.thumb }, visible: !parentProductID().trim() classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classpull-left cart-item-pic data-bindvisible: parentProductID().trim()> /div> div classmedia-heading> b data-bindtext: 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()>/p> p> !-- ko template: { name: cart.productEditLink, data: { title: Change Warehouse, linkText: Change Warehouse, detailLine: $data}, if: viewModel.allowWarehouseSelection && !viewModel.useMultiShipEditUI } -->!-- /ko --> /p> !-- ko if : ofConfig.bShowCartOptions && cartOption --> p data-bindtext: cartOption>/p> !-- /ko --> !-- ko template: { name: cart.configOptions, data: $data } -->!-- /ko --> /div> !-- ko if : viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits && $data.qtyDisplayType() input --> div classcart-item-price> div classinput-prepend> span classadd-on>$/span> input typenumber classinput-small step.01 data-bind value: price, attr: { id : price- + orderDetailKey() }, event: { change: viewModel.setItemShipToMapPrice($data) } > /div> span classbtn btn-link text-xsmall data-bind if: priceCalculationType() fixed, event: { click: viewModel.resetSuperUserPriceOverride } > span data-bindhtml: ofConfig.superUserResetPriceHelpText>/span> /span> /div> !-- /ko --> !-- ko if : !(viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits) || $data.qtyDisplayType() text --> div classcart-item-price data-bindtext: $ + instanceUnitPrice().toFixed(2)>/div> !-- /ko --> !-- ko if : viewModel.useMultipleShipments() || $data.qtyDisplayType() text--> div classcart-item-qty> span classbadge data-bindtext: viewModel.getTotalQty(instance())>/span> on span classorder data-bindvisible:!viewModel.useMultipleShipments()>order/span>span classshipment data-bindvisible: viewModel.useMultipleShipments()>shipment/span> /div> !-- /ko --> !-- ko if : !viewModel.useMultipleShipments() && $data.qtyDisplayType() input--> div classcart-item-total-qty> div classinput-prepend input-append> span classadd-on>Qty/span> input typenumber classqty-input data-bind value: qty, attr: { id : qty-ship- + orderDetailKey(), min : minQty(), step : qtyIncrement() || 1, max : maxQty() || undefined }, validateQty > span classadd-on 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.maxQty + : + maxQty() + br> + oConfig.labels.step + : + qtyIncrement() }> i classicon-question-sign>/i> /a> /span> /div> !-- ko if : viewModel.superUserOrderFormMode() --> !-- ko template: cart.qtyControlSettings -->!-- /ko --> !-- ko template: cart.uomEdits -->!-- /ko --> !-- /ko --> /div> !-- /ko --> !-- ko if: viewModel.showRemoveLink($data) --> span classproduct-delete> a href data-bindevent: { click: viewModel.removeProduct } titleRemove this item from your Order? classtext-xsmall> i classicon icon-small icon-remove>/i> span classvisible-lg>remove/span> /a> /span> !-- /ko -->/script>script typetext/html idZcart.uomEdits> !-- ko template: { name: cart.productEditLink, data: { title: Change UOM, linkText: Change UOM, detailLine: $data }, if: viewModel.allowWarehouseSelection && !viewModel.useMultiShipEditUI } -->!-- /ko -->/script>script typetext/html idZcart.shipmentItemTable_custom> !-- ko if: details().length > 0 --> table classtablesaw cart-table data-tablesaw-modestack> thead> th data-bindtext: ofConfig.labels.cartDesc>/th> th data-bindtext: ofConfig.labels.cartQty>/th> th data-bindtext: ofConfig.labels.cartItemPrice>/th> th data-bindtext: ofConfig.labels.cartTotal>/th> /thead> tbody classcart-row-std data-bindforeach: details> !-- ko if: orderDetail.parentProductID().trim() || !orderDetail.hasParentInCart() --> tr> td> div classmedia> img data-bindattr : { alt: orderDetail.sku() + - + orderDetail.name(), src: images/ + orderDetail.thumbnail() } 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 if: orderDetail.promoID --> span classpromo-icon data-bindattr: { title : orderDetail.promoDescription() } >P/span> !-- /ko --> br> !-- ko if: ofConfig.isSuperUserSession --> small data-bindtext: UOM: + orderDetail.uom()>/small> !-- /ko --> /div> p data-bindif: viewModel.allowWarehouseSelection && !viewModel.useMultiShipEditUI> !-- ko template: { name: cart.productEditLink, data: { title: Change Warehouse, linkText: Change Warehouse, detailLine: orderDetail } } -->!-- /ko --> /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> span data-bindtext: qtyToShip>/span>span data-bindif: ofConfig.showTotalQtyOnShipment> of span data-bindtext: orderDetail.qty>/span>/span> /td> td> $span data-bindtext: orderDetail.instanceUnitPrice().toFixed(2)>/span> /td> td> $span data-bindtext: orderDetail.instanceExtPrice().toFixed(2)>/span> /td> /tr> !-- /ko --> /tbody> /table> !-- /ko --> /script>script typetext/html idZcart.billingSummary_custom> !-- ko ifnot: showBillingEdit --> div idbilling_address_summary classrow-fluid> div classspan6> div classwell> b>Order Contact/b> button typebutton idcontact-address classbtn btn-link btn-mini global-modal hrefaccount.asp?modalactioneditcontact&modal1&o_key+ viewModel.orderKey() data-bind visible: viewModel.allowContactEdits(), addModalHandler: { element : $(#contact-address), handler : function() { location.reload() }}, attr:{ href: account.asp?modalactioneditcontact&modal1&o_key + viewModel.orderKey() } data-titleEdit Contact Information data-sizefull > Edit /button> !-- ko template: { name: cart.orderContactSummary, data: customer } --> !-- /ko --> /div> /div> div classspan6> div classwell> b>Billing Address/b> button typebutton idbilling-address classbtn btn-link btn-mini global-modal hrefaccount.asp?modalactioneditaccount&modal1&o_key + viewModel.orderKey() data-bind visible: viewModel.allowAccountEdits(), addModalHandler: { element : $(#billing-address), handler : function() { location.reload() } }, attr:{ href: account.asp?modalactioneditaccount&modal1&o_key + viewModel.orderKey() } data-titleEdit Billing Information data-sizefull > Edit /button> !-- ko template: { name: cart.billingAddressSummary, data: account } -->!-- /ko --> /div> /div> /div> !-- /ko -->/script>script typetext/html idZcart.itemCard> img data-bindattr : { alt: sku() + - + name(), src: commodity.pic.thumb }, visible: !parentProductID().trim() || !hasParentInCart() classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classpull-left cart-item-pic data-bindvisible: 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> p data-bindif: viewModel.allowWarehouseSelection && !viewModel.useMultiShipEditUI> !-- ko template: { name: cart.productEditLink, data: { title: Change Warehouse, linkText: Change Warehouse, detailLine: $data } } -->!-- /ko --> /p> !-- 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 : viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits && $data.qtyDisplayType() input --> 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-bindtext: superUserMinPrice().toFixed(2)>/span>/span> !-- ko if: commodity.cost() || commodity.retailPrice() --> !-- ko template: cart.priceHelper -->!-- /ko --> !-- /ko --> /div> !-- /ko --> !-- ko if : !(viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits) || $data.qtyDisplayType() text --> div classcart-item-price data-bindtext: $ + instanceUnitPrice().toFixed(2)>/div> !-- /ko --> !-- ko if : viewModel.useMultiShipEditUI() || $data.qtyDisplayType() text--> div classcart-item-qty> label> input typetext classqty-input disabled data-bindattr: { value: viewModel.getTotalQty(instance()) }> 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--> 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> 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> --> !-- ko if: viewModel.showRemoveLink($data) --> span classproduct-delete> a href data-bindevent: { click: viewModel.removeProduct } titleRemove this item from your Order? classtext-xsmall> i classicon icon-small icon-remove>/i> span classvisible-lg>remove/span> /a> /span> !-- /ko --> /div>/script>script typetext/html idZcart.checkoutSummary_custom> !-- 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: productSubTotalBeforeDiscount() productTotal()> td>Items/td> td idp_total classcell-right>$span data-bindtext: productTotal().toFixed(2)>/span>/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() ! productTotal()> td>Items before discount/td> td idp_coupon_total classcell-right>$span data-bindtext: productSubTotalBeforeDiscount().toFixed(2)>/span>/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() ! productTotal()> td>Product Discount (span data-bindtext: session.TradeAdjustment>/span>%)/td> td idp_coupon_total classcell-right deduction>$span data-bindtext: productDiscountTotal().toFixed(2)>/span>/td> /tr> tr data-bindvisible: productSubTotalBeforeDiscount() ! productTotal()> td>Items after discount/td> td idp_coupon_total classcell-right>$span data-bindtext: productTotal().toFixed(2)>/span>/td> /tr> tr data-bindvisible: giftCertCode> td>Gift Certificate Amount/td> td idp_coupon_total classcell-right deduction>$span data-bindtext: giftCertAmount().toFixed(2)>/span>/td> /tr> tr data-bindvisible: couponCode> td>Coupon Adjustment/td> td idp_coupon_total classcell-right deduction>$span data-bindtext: couponDiscountTotals.totalDiscount().toFixed(2)>/span>/td> /tr> tr data-bindif: ofConfig.bUsingShipping> td>Shipping/td> !-- ko if: shipmentsSectionsValid() --> td ids_total classcell-right> !-- ko ifnot : oConfig.sessionData.isSuperUserSession --> span data-bindtext: ofConfig.sShipTotalText>/span> !-- /ko --> !-- ko if: oConfig.sessionData.isSuperUserSession --> $span data-bindtext: shippingTotal().toFixed(2)>/span> !-- /ko --> /td> !-- /ko --> !-- ko if: !shipmentsSectionsValid() --> td ids_total classcell-right >TBD/td> !-- /ko --> /tr> tr> td>Taxes/td> !-- ko if: shipmentsSectionsValid() --> td idt_total classcell-right>$span data-bindtext: taxTotal().toFixed(2)>/span>/td> !-- /ko --> !-- ko if: !shipmentsSectionsValid() --> td idt_total classcell-right>TBD/td> !-- /ko --> /tr> tr classsuccess text-large> td classtext-success>b>Order Total/b>/td> td classcell-right text-success>b>$span data-bindtext: orderBalance().toFixed(2)>/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.confirmation_custom> div idcheckout_confirmation classcheckout-section data-bindvisible: viewModel.showConfirmationMessage > div classcheckout-section-body> div classcheckout-section-inner> 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 && orderType() ! quote>Thank you for your order!/h3> h3 classtext-success data-bindvisible: completed && viewModel.lifecycleStage() ! cancelled && orderType() quote>Quote submitted to Sage/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 template: cart.printButton-->!-- /ko --> h3 data-bindif: completed && orderType() ! quote>Your order number is span data-bindtext: ofConfig.orderNumberPrefix>/span>span data-bindtext: orderNumber>/span>/h3> h3 data-bindif: completed && orderType() quote>Your quote number is span data-bindtext: ofConfig.orderNumberPrefix>/span>span data-bindtext: orderNumber>/span>/h3> 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/javascript> utils.ZaddToCart function (details, cart) { function getQueryStringParameters() { var params { type : v200add, sc_id : 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 ; _.forEach(details, function (item) { var product item.selectedProduct(); var productKey product.key(); var minQty product.minQty() || 1; var uom ko.toJS(product.selectedUom()); dataqty_ + productKey product.selectedQty() || minQty; datauom_ + productKey uom.description; if(uom.uom uom_std){ datauom_conversion_ + productKey 1.00; } if(uom.hasOwnProperty(UomId)) { datauom_id_ + productKey uom.UomId; dataqty_display_type_ + productKey uom; //for cart display (Cart Post Logic will override this if it needs to) } datapw_id_ + productKey product.selectedWarehouse().key || oConfig.defaultWarehouse; _.assign(data, buildConfiguratorPostData(productKey)); if (minQty ! 1) datamin_order_qty_ + productKey minQty; if(product.selectedUom().minQty() > 1) { dataminqty_ + productKey product.selectedUom().minQty() } else if(product.configuratorEditData && product.configuratorEditData.minQty) { dataminqty_ + productKey product.configuratorEditData.minQty; } if(product.selectedUom().maxQty() > 1) { datamaxqty_ + productKey product.selectedUom().maxQty() } else if(product.configuratorEditData && product.configuratorEditData.maxQty) { datamaxqty_ + productKey product.configuratorEditData.maxQty; } if(product.selectedUom().step() > 1) { dataqty_increment_ + productKey product.selectedUom().step() } else if(product.configuratorEditData && product.configuratorEditData.qtyIncrement) { dataqty_increment_ + productKey product.configuratorEditData.qtyIncrement; } if(product.configuratorEditData && product.configuratorEditData.removeType) { dataremove_type_ + productKey product.configuratorEditData.removeType; } if(product.configuratorEditData && product.configuratorEditData.priceCalcType) { dataprice_calc_type_ + productKey product.configuratorEditData.priceCalcType; if(product.configuratorEditData.priceCalcType fixed) { dataprice_ + productKey product.configuratorEditData.price; } } runHook(getPostDataBeforeReturn, { self: self, data: data, product: product }); productKeys.push(productKey); }); data.keys productKeys.join(,); return data; } function getAjaxConfig() { return { url: i_i_add_to_cart.asp? + $.param(getQueryStringParameters()), type: POST, data: $.param(getPostData()), 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) { fncReloadCartWindow(); 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); 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 ); } 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 }; if(details.length > 0 && details0.useConfigurator()){ if(!eval(formValidation + oConfig.formValidationKey).check()){ bPass false; } }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; } };/script>script typetext/html idzzzcart.itemCard_custom> img data-bindattr : { alt: sku() + - + name(), src: commodity.pic.thumb }, visible: !parentProductID().trim() || !hasParentInCart() classmedia-object pull-left cart-item-pic onerrorutils.handleImageError(this)> div classpull-left cart-item-pic data-bindvisible: 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: cart.productLeadTimes -->!-- /ko --> p data-bindif: viewModel.allowWarehouseSelection && !viewModel.useMultiShipEditUI> !-- ko template: { name: cart.productEditLink, data: { title: Change Warehouse, linkText: Change Warehouse, detailLine: $data } } -->!-- /ko --> /p> !-- 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() --> 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-bindtext: superUserMinPrice().toFixed(2)>/span>/span> !-- ko if: commodity.cost() || commodity.retailPrice() --> !-- ko template: cart.priceHelper -->!-- /ko --> !-- /ko --> /div> !-- /ko --> !-- ko if : (!(viewModel.superUserOrderFormMode() && ofConfig.superUserAllowProductPriceEdits) || $data.qtyDisplayType() text) && !$data.editing() --> div classcart-item-price data-bindtext: $ + instanceUnitPrice().toFixed(2)>/div> !-- /ko --> !-- ko if : viewModel.useMultiShipEditUI() || $data.qtyDisplayType() text && !$data.editing() --> div classcart-item-qty> label> input typetext classqty-input disabled data-bindattr: { value: viewModel.getTotalQty(instance()) }> 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 && !$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> 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> !-- /ko --> !-- ko if: ofConfig.allowProductEditInEditView --> !-- ko template: { name: cart.productInlineEditLinks } -->!-- /ko --> !-- /ko --> /div> /div>/script>script typetext/html idcatalog.category_list_custom> 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: name }> img data-bindattr: { src: utils.buildImagePath(pic2) }/> /a> /div> div classprod-info> div classprod-desc> div classprod-nm> a data-bindattr: { href: link, title: name }, html: name>/a> /div> div classprod-ds data-bindhtml: description>/div> a classtop-prodcat-btn data-bindattr: { href: link, title: name }>View Products/a> /div> /div> /div> /div>/script>script typetext/html idcatalog.advanced_parent_layout_custom> div idproduct_view classproduct_view product_view--custom data-bindattr: { class: oConfig.detailConfig.gridRowClass }> div data-bindattr: { class: oConfig.detailConfig.gridLeftColumnClass }> div idproduct_images data-bindtemplate: { name: catalog.image_gallery, data: selectedProduct }>/div> /div> div data-bindattr: { class: oConfig.detailConfig.gridRightColumnClass }> span classproduct_view__rating-detail data-bindtemplate: catalog.rating_detail>/span> !-- template: catalog.product_links --> span classproduct_view__detail-info data-bindtemplate: catalog.detail_info >/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> span data-bindtemplate: { name: catalog.product_description, data: selectedProduct }>/span> div classproduct_view__share-code data-bindtemplate: catalog.share_code>/div> 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.product_view_custom> div idproduct_view classrow-fluid product_view product_view--custom> div data-bindattr: { class: oConfig.detailConfig.gridLeftColumnClass }> !-- 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 }> !-- 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.additional_sections_custom> span data-bindtemplate: { name: catalog.also_bought, data: alsoBought }>/span> span data-bindifnot: selectedProduct().useTabs(), attr: { data-layout : oConfig.detailConfig.pageLayoutMode } > 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.recently_viewed, data: $parent.recentlyViewed }>/span>/script>script typetext/html idcatalog.product_title_custom> div classpage-header detail-title> h1 data-bindhtml: selectedProduct().name() || name()>/h1> /div>/script>script typetext/html idcatalog.detail_info_custom> dl classprod-searchfields> !-- ko if: oConfig.pageName payment.asp --> !-- template: catalog.sku_label --> !-- /ko --> !-- template: { name: catalog.searchfields, foreach: _.values(selectedProduct().searchfields) } --> /dl>/script>script typetext/html idcatalog.results-landing> !-- 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.results-landing_category-header, data: category } : catalog.page_title >/div> /div> /div> !-- /ko -->/script>script typetext/html idcatalog.results-landing_category-header> !-- template: { name: catalog.results-landing_category-list, data: children, if: children.length > 0 } -->/script>script typetext/html idcatalog.results-landing_category-list> div classcategory-listings results-landing_category-list data-layoutgallery data-bindforeach: $data> div classprod-card> div classprod-thumb> a data-bindattr: { href: link, title: name }> img data-bindattr: { src: utils.buildImagePath(pic2) }/> /a> /div> div classprod-info> div classprod-desc> div classprod-nm> a data-bindattr: { href: link, title: name }, html: name>/a> /div> div classprod-ds data-bindhtml: description>/div> a classtop-prodcat-btn data-bindattr: { href: link, title: name }>View Products/a> /div> /div> /div> /div>/script>script typetext/html idcatalog.product_card_custom> div classprod-card> !-- ko if: isActiveLayout(gallery) || oConfig.pageName pc_product_detail.asp --> div classprod-thumb data-bindvisible: !oConfig.fastTrack> span classprod-thumb-img data-bindtemplate: catalog.image_link>/span> span classprod-thumb-flags data-bindtemplate: catalog.flags>/span> /div> div classprod-info> div classprod-desc> div classprod-nm> !-- template: catalog.name_link --> /div> !-- Custom removed ratings and added sku --> div classdetail_info_container_sku> p>span data-bindhtml: oConfig.labels.sku>/span> span itempropsku data-bindtext: selectedProduct().sku>/span>/p> /div> /div> div classprod-idp data-bindtemplate: catalog.inventory>/div> div classprod-pricing data-bindtemplate: catalog.selected_product_price_display>/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> span classprod-thumb-img data-bindtemplate: catalog.image_link>/span> span classprod-thumb-flags data-bindtemplate: catalog.flags>/span> /div> div classprod-info> div classprod-desc> div classprod-nm> !-- template: catalog.name_link --> /div> !-- Custom removed ratings and added sku --> div classdetail_info_container_sku> p>span data-bindhtml: oConfig.labels.sku>/span> span itempropsku data-bindtext: selectedProduct().sku>/span>/p> /div> div classprod-ds data-bind html: selectedProduct().description, visible: !oConfig.fastTrack && selectedProduct().description()> /div> 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: catalog.selected_product_price_display>/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.category_header_custom> !-- template: { name: catalog.breadcrumbs, data: breadcrumbs } --> !-- ko if: pic && oConfig.siteTemplateType retail --> h1 classhead_title head_title--bg data-bindhtml: name, style: { backgroundImage: url( + utils.buildImagePath(pic) + ) }>/h1> !-- /ko --> !-- ko if: !pic || oConfig.siteTemplateType dashboard --> h1 classhead_title head_title--nobg data-bindhtml: name>/h1> !-- /ko --> !-- 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>div classga-ecommerce-tracking> !-- START Tracking/Analytics Code --> !-- END Tracking/Analytics Code -->/div> /body>/html>
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
]