
<!DOCTYPE html>

<!--[if IE]><![endif]-->
<!--[if IE 9]> <html class="no-js ie9 lt-ie10" lang="en"> <![endif]-->
<!--[if gt IE 9]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<!-- include files here -->

        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", function () {
                // Locate all links inside #mainMenu
                var mainMenu = document.getElementById("mainMenu");
                if (mainMenu) {
                    var links = mainMenu.querySelectorAll("a[href]");
                    links.forEach(function (link) {
                    if (link.getAttribute("href").toLowerCase().includes("spend_allowance_tracking_man.asp")) {
                        var li = link.closest("li");
                        if (li) {
                            li.style.display = "none";
                        }
                    }
                    });
                }
            });
        </script>
    

<head>
    
<link rel="preconnect" href="https://fonts.gstatic.com/" />

  <link href="https://fonts.googleapis.com/css?family=Lato:400,500,700&display=swap" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'"/>  	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=2">
	
	

	<title>Electro-Medical Equipment, Inc.</title>
	<meta name="description" content="">
	<meta name="keywords" content="">
    <link rel="canonical" href="https://electro-medical.com/" />
<link rel="stylesheet" href="templates/fa/css/custom-font-awesome.min.css">
	<link rel="shortcut icon" type="image/x-icon" href="https://d29eekna00jloo.cloudfront.net/images/favicon.png?v=3975201667">
	<link rel="icon" type="image/png" href="images/favicon.png" sizes="16x16" />
	<link rel="icon" type="image/png" href="images/favicon.png" sizes="32x32" />
	<link rel="icon" type="image/png" href="" sizes="48x48" />
		<link rel="preload" href="../css/bootstrap-retail.css?aec323c" as="style" onload="this.onload=null;this.rel='stylesheet'">
	    <link rel="preload" href="../css/retail.css?aec323c" as="style" onload="this.onload=null;this.rel='stylesheet'">
		<link rel="preload" href="../css/focus.css?aec323c" as="style" onload="this.onload=null;this.rel='stylesheet'">
	

    <style>

        /* 
        ### Skins CSS Overrides
        */

                /* Retail Template
                --------------------------------------------------------------- */
                h1, h2, h3, h4, h5, h6,
                input, button, select, textarea,
                body, body.retail {
                    font-family: Lato
                }

                html,
                body,
                p {
                    color: #333333;
                }
                
                a { 
                    color: #c14e59; 
                }

                .text-warning,
                a.text-warning {
                    color: #8a6d3b;
                }

                .text-warning:hover,
                a.text-warning:hover {
                    color: #66512c;
                }

                .text-danger,
                a.text-danger {
                    color: #a94442;
                }

                .text-danger:hover,
                a.text-danger:hover {
                    color: #843534;
                }

                .text-success,
                a.text-success {
                    color: #3c763d;
                }

                .text-success:hover,
                a.text-success:hover {
                    color: #2b542c;
                }

                .text-info,
                a.text-info {
                    color: #31708f;
                }

                .text-info:hover,
                a.text-info:hover {
                    color: #245269;
                }

                a:hover,
                a:focus { 
                    color: rgb(218,104,114); 
                }

                h1, h2, h3, h4, h5, h6, 
                .formblock-heading, 
                legend, 
                .checkout-section-heading, 
                .checkout-section.active .checkout-section-heading { 
                    color: #444444; 
                }

                .pace .pace-progress {
                    background: #c14e59;
                }

                /* Retail Topbar
                --------------------------------------------------------------- */

                [class*="retail-header"] .topbar {
                    background-color: #444444;
                }

                /* Retail Buttons
                --------------------------------------------------------------- */

                .btn-link {
                    color: #c14e59;
                }

                .btn-link:not([disabled]):hover, 
                .btn-link:not([disabled]):focus, 
                .btn-link:not([disabled]):active, 
                .btn-link:not([disabled]).active {
                    color: rgb(218,104,114);
                }

                /* Primary buttons */
                .btn-primary, .btn-primary.button {
                    background-color: #c14e59;
                    border-color: #c14e59;
                    color: #FFFFFF;
                }

                .btn-primary:not([disabled]):hover, 
                .btn-primary:not([disabled]):focus, 
                .btn-primary:not([disabled]):active, 
                .btn-primary:not([disabled]).active, 
                .btn-primary:not([disabled]).button:hover, 
                .btn-primary:not([disabled]).button:focus, 
                .btn-primary:not([disabled]).button:active, 
                .btn-primary:not([disabled]).button.active {
                    background-color: rgb(218,104,114);
                    border-color: rgb(218,104,114);
                    color: #FFFFFF;
                }

                /* Secondary buttons */
                .btn:not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info), 
                .btn:not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button {
                    background-color: #f6edc4;
                    border-color: #f6edc4;
                    color: #222222;
                }

                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info):hover, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info):focus, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info):active, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).active, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button:hover, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button:focus, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button:active, 
                .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button.active {
                    background-color: rgb(255,255,222);
                    border-color: rgb(255,255,222);
                    color: #222222;
                }

                .list-group-item.active, 
                .list-group-item.active:hover, 
                .list-group-item.active:focus {
                    color: #FFFFFF !important;
                    border-color: #c14e59 !important;
                    background-color: #c14e59 !important;
                }

                /************* 
                ** Unused button settings
                .btn-secondary,
                .btn-inverse {
                    color: #222222;
                    border-color: #f6edc4;
                    background-color: #f6edc4;
                }

                .btn-secondary:hover,
                .btn-secondary:focus,
                .btn-inverse:hover,
                .btn-inverse:focus {
                    background-color: rgb(255,255,222);
                    border-color: rgb(255,255,222);
                }

                .btn-secondary:active,
                .btn-inverse:active {
                    background-color: rgb(255,252,211);
                    border-color: rgb(255,252,211);
                } 

                .btn-success {
                    color: #468847;
                    border-color: #468847;
                    background-color: #468847;
                }

                .btn-success:hover,
                .btn-success:focus {
                    background-color: rgb(96,162,96);
                    border-color: rgb(96,162,96);
                }

                .btn-success:active {
                    background-color: rgb(85,151,86);
                    border-color: rgb(85,151,86);
                }

                .btn-danger {
                    color: #FFFFFF;
                    border-color: #B94A48;
                    background-color: #B94A48;
                }

                .btn-danger:hover,
                .btn-danger:focus {
                    background-color: rgb(210,100,98);
                    border-color: rgb(210,100,98);
                }

                .btn-danger:active {
                    background-color: rgb(200,89,87);
                    border-color: rgb(200,89,87);
                }
                *************/

                .toast-success {
                    background-color: #c14e59;
                }


                /* Breadcrumbs
                --------------------------------------------------------------- */

                body.retail.focus-mode:not(.account) .breadcrumb.breadcrumb-cart li.active {
                    background: #c14e59;
                    color: #FFFFFF;
                }

                 body.retail.focus-mode:not(.account) .breadcrumb.breadcrumb-cart li.active:after {
                    border-color: transparent;
                    border-left-color: #c14e59;
                    border-width: 20px;
                }


                /* Retail Template 1
                --------------------------------------------------------------- */

                /* Topbar */
                .topbar #retail-topbar-left-menu>li>a:hover, 
                .topbar #retail-topbar-left-menu>li>a:focus, 
                .topbar #retail-topbar-left-menu>li.open>a {
                    background-color: rgb(94,94,94);
                    color: #FFFFFF;
                }

                @media (max-width: 980px) {
                    .topbar #retail-topbar-left-menu>li>a:hover, 
                    .topbar #retail-topbar-left-menu>li>a:focus, 
                    .topbar #retail-topbar-left-menu>li.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }
                }

                .topbar #retail-topbar-left-menu>li ul {
                    background-color: #FFFFFF;
                }

                .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1 {
                    color: #FFFFFF !important;
                }

                @media (max-width: 1024px) {
                    .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1 {
                        color: #333333 !important;
                    }
                }

                .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:hover, 
                .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:focus {
                    color: #FFFFFF !important;
                }

                @media (max-width: 1024px) {
                    .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:hover, 
                    .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:focus {
                        color: #FFFFFF !important;
                        background: #c14e59 !important;
                    }
                 }


                .topbar #retail-topbar-left-menu>li ul a:hover, 
                .topbar #retail-topbar-left-menu>li ul a:focus {
                    background-color: rgb(230,230,230);
                }

                @media (max-width: 980px) {
                    .topbar #retail-topbar-left-menu {
                        background-color: #FFFFFF;
                    }
                }

                /* Header */
                
                .focus-header,
                [class*="retail-header"] .logo-bar {
                    background-color: #FFFFFF;
                }

                .focus-header__exit-wrapper {
                    border-color: rgb(230,230,230);
                }

                .focus-header__exit {
                    color: #222222;
                }
                
                .focus-header__exit:focus,
                .focus-header__exit:active,
                .focus-header__exit:hover {
                    color: #222222 !important;
                    background-color:  rgb(230,230,230);
                }


                [class*="retail-header"] .header__prodcat__toggle,
                [class*="retail-header"] .header__signin-open {
                    color: #222222 !important;
                }

                [class*="retail-header"] #header__user-menu>li.link-parent ul,
                [class*="retail-header"] #header__prodcat>li.link-parent ul {
                    background-color: #FFFFFF;
                }

                [class*="retail-header"] .topbar__menu-toggle a,
                [class*="retail-header"] .logo-bar__right .linkset > li > a {
                    color: #222222 !important;
                }

                [class*="retail-header"] .topbar__menu-toggle a:hover,
                [class*="retail-header"] .topbar__menu-toggle a:focus {
                    background: rgb(42,42,42) !important;
                }

                @media (max-width: 980px) {
                    [class*="retail-header"] .logo-bar__right .linkset > li > a {
                        background-color: #444444;
                        color: #FFFFFF !important;
                    }
                }

                [class*="retail-header"] .logo-bar__right .linkset > li > a:hover, 
                [class*="retail-header"] .logo-bar__right .linkset > li > a:active {
                    color: rgb(60,60,60) !important;
                }
                @media (max-width: 980px) {
                    [class*="retail-header"] .logo-bar__right .linkset > li > a:hover, 
                    [class*="retail-header"] .logo-bar__right .linkset > li > a:focus, 
                    [class*="retail-header"] .logo-bar__right .linkset > li > a:active {
                         color: #FFFFFF !important;
                         background: rgb(42,42,42) !important;
                    }
                }

                [class*="retail-header"] .logo-bar__right .linkset ul>li>a:hover, 
                [class*="retail-header"] .logo-bar__right .linkset ul>li>a:focus {
                    background-color: rgb(230,230,230);
                }

                [class*="retail-header"] #header__prodcat>li.link-parent li.link-parent.open>a {
                    background-color: #c14e59;
                    color: #FFFFFF;
                }

                [class*="retail-header"] #header__prodcat>li>ul {
                    border-top: 1px solid #c14e59;
                }

                [class*="retail-header"] #header__prodcat>li>ul ul {
                    border-left: 5px solid #c14e59;
                }

                [class*="retail-header"] .header__hero-search {
                    background-image: url('https://d29eekna00jloo.cloudfront.net/images/physical%20therapy_hero.jpg?v=3975201667');
                }

                /* Introduction */

                .home-description {
                    background-color: #c14e59;
                    color: #FFFFFF;
                }

                .home-description:after {
                    border-color: #c14e59 transparent transparent transparent;
                }


                /* Featured */

                .trending-products__title:after {
                        background-color: #c14e59;
                }

                /* Reseller */

                .footer-reseller__col-1 {
                    background-image: url('https://d29eekna00jloo.cloudfront.net/images/homecx4.jpg?v=3975201667');
                }
                
                .footer-reseller__col-2 {
                    background-color: #c14e59;
                }

                .footer-reseller__col-2:before {
                    border-color: transparent #c14e59 transparent transparent;
                }

                .footer-reseller__wrap,
                .footer-reseller__wrap p {
                    color: #FFFFFF;
                }

                .footer-reseller h2:after {
                    background-color: #f6edc4;
                }

                /* Retail Products
                --------------------------------------------------------------- */

                .prod-info {
                    color: #333333;
                }

                .prod-desc {
                    color: #c14e59;
                }
                
                .prod-desc p {
                    color: #c14e59;
                }
                
                .specials_nm {
                    color: #c14e59;
                }

                .specials_nm:hover,
                .specials_nm:focus {
                    color: rgb(218,104,114);
                }

                /* Retail Footer
                --------------------------------------------------------------- */

                [class*="retail-footer"] {
                    color: #222222; 
                    background-color: #FFFFFF; 
                }

                [class*="retail-footer"] .bottom-bar {
                    color: #FFFFFF; 
                    background-color: #444444; 
                }

                [class*="retail-footer"] .bottom-bar__colophon a:hover {
                    color: rgba(255,255,255,0.8); 
                }
        
                

                 /* Retail Template 2
                --------------------------------------------------------------- */

                /* Header */

                .retail-header-2 .header__prodcat__container {
                    background-color: #444444;
                }

                .retail-header-2 .header__prodcat .header__prodcat__toggle,
                .retail-header-2 .header__user-menu .header__user-menu__toggle,
                .retail-header-2 .header__signin .header__signin-open,
                .retail-header-2 .header__cart-preview .header__cart-preview__toggle {
                    color: #444444 !important;
                }

                @media (min-width: 981px) {

                    .retail-header-2 .header__prodcat__container .link-parent>ul>li>a {
                        color: #FFFFFF;
                    }

                    .retail-header-2 .header__prodcat__container .link-parent>ul>li ul {
                        background-color: #FFFFFF;
                    }

                    .retail-header-2 .header__prodcat__container .link-parent>ul>li li a {
                        color: #222222;
                    }

                    .retail-header-2 .header__prodcat__container .link-parent>ul>li li a:hover,
                    .retail-header-2 .header__prodcat__container .link-parent>ul>li li a:focus,
                    .retail-header-2 .header__prodcat__container .link-parent>ul>li li.link-parent.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }
                }

                @media (max-width: 980px) {
                    .retail-header-2 .header__prodcat__container .link-parent ul {
                        background-color: #FFFFFF;
                    }

                    .retail-header-2 .header__prodcat__container .link-parent ul li a {
                        color: #222222;
                    }

                    .retail-header-2 .header__prodcat__container .link-parent ul li.link-parent.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }

                    .retail-header-2 .header__user-menu .link-parent ul,
                    .retail-header-2 .header__cart-preview .link-parent ul,
                    .retail-header-2 .header__prodcat>.link-parent>ul {
                        border-top: 1px solid #c14e59;
                    }
                }

                 /* Retail Template 3
                --------------------------------------------------------------- */

                .retail-header-3 .header__prodcat .header__prodcat__toggle,
                .retail-header-3 .header__user-menu .header__user-menu__toggle,
                .retail-header-3 .header__signin .header__signin-open,
                .retail-header-3 .header__cart-preview .header__cart-preview__toggle {
                    color: #444444 !important;
                }

                @media (min-width: 981px) {                    
                    .retail-header-3 .header__prodcat .link-parent>ul li a:hover,
                    .retail-header-3 .header__prodcat .link-parent>ul li a:focus,
                    .retail-header-3 .header__prodcat .link-parent>ul li.link-parent.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }
                }

                @media (max-width: 980px) {                   

                    .retail-header-3 .header__user-menu .link-parent ul,
                    .retail-header-3 .header__cart-preview .link-parent ul,
                    .retail-header-3 .header__prodcat>.link-parent>ul {
                        border-top: 1px solid #c14e59;
                    }

                    .retail-header-3 .header__prodcat li li.link-parent.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }
                }

                 /* Retail Template 4
                --------------------------------------------------------------- */

                /* Header */

               
                .retail-header-4 .header__prodcat__container.--desktop {
                    background-color: #444444;
                }

                .retail-header-4 .header__prodcat__container.--all-screens .header__prodcat>.link-parent ul ul {
                        background: #FFFFFF;
                    }

                .retail-header-4 .header__prodcat__container.--all-screens .header__prodcat>.link-parent ul ul li>a:hover,
                .retail-header-4 .header__prodcat__container.--all-screens .header__prodcat>.link-parent ul ul li>a:focus,
                .retail-header-4 .header__prodcat__container.--all-screensl .header__prodcat>.link-parent ul ul li.link-parent.open>a,
                .retail-header-4 .header__user-menu .link-parent ul li a:hover,
                .retail-header-4 .header__user-menu .link-parent ul li a:focus {
                    background-color: #c14e59;
                    color: #FFFFFF;
                }

                .retail-header-4 .header__prodcat .header__prodcat__toggle,
                .retail-header-4 .header__user-menu .header__user-menu__toggle,
                .retail-header-4 .header__signin .header__signin-open,
                .retail-header-4 .header__cart-preview .header__cart-preview__toggle {
                    color: #444444 !important;
                }


                @media (min-width: 981px) {

                    .retail-header-4 .header__prodcat__container.--all-screens .header__prodcat>li>ul>li>a {
                        color: #444444 !important;
                    }

                    /* Horizontal Product Menu Styling */

                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul>li>a,
                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul .prodcat>ul>li>a {
                        color: #FFFFFF;
                    }

                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul>li ul {
                        background: #FFFFFF;
                    }

                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul>li ul li>a:hover,
                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul>li ul li>a:focus,
                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul>li ul li.link-parent.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }

                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul .prodcat>ul>li>a:hover,
                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul .prodcat>ul>li>a:focus,
                    .retail-header-4 .header__prodcat__container.--horizontal .header__prodcat>.link-parent>ul .prodcat>ul>li.link-parent.open>a {
                        background-color: transparent;
                        color: #FFFFFF;
                    }
                    
                    .retail-header-4 .header__prodcat__container.--horizontal.--mega-menu .header__prodcat>.link-parent>ul>li ul ul .link-parent>a:hover,
                    .retail-header-4 .header__prodcat__container.--horizontal.--mega-menu .header__prodcat>.link-parent>ul>li ul ul .link-parent>a:focus,
                    .retail-header-4 .header__prodcat__container.--horizontal.--mega-menu .header__prodcat>.link-parent>ul>li ul ul .link-parent.open>a {
                        background-color: transparent;
                        color:  #c14e59;
                    }

                    /* Vertical Product Menu Styling */

                    .retail-header-4 .header__prodcat__container.--vertical .header__prodcat>.link-parent>ul>li>a {
                        color: #FFFFFF;
                    }

                    .retail-header-4 .header__prodcat__container.--vertical .header__prodcat>.link-parent ul ul {
                        background: #FFFFFF;
                    }

                    .retail-header-4 .header__prodcat__container.--vertical .header__prodcat>.link-parent ul ul li>a:hover,
                    .retail-header-4 .header__prodcat__container.--vertical .header__prodcat>.link-parent ul ul li>a:focus,
                    .retail-header-4 .header__prodcat__container.--vertical .header__prodcat>.link-parent ul ul li.link-parent.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }

                }

                .retail-header-4 .top-bar {
                    background-color: #444444;
                    color: #FFFFFF;
                }

                .retail-header-4 .top-bar .top-bar__menu-toggle,
                .retail-header-4 .top-bar .top-bar__left>ul>li>ul>li>a {
                    color: #FFFFFF;
                }

                .retail-header-4 .top-bar .top-bar__left>ul>li>ul ul {
                    background-color: #FFFFFF;
                }

                @media (max-width: 980px) {
                    .retail-header-4 .top-bar .top-bar__left>ul>li>ul li>a {
                        color: #222222;
                    }
                    .retail-header-4 .top-bar .top-bar__left>ul .link-parent>ul .link-parent.open>a {
                        background: #c14e59;
                        color: #FFFFFF;
                    }
                    .retail-header-4 .top-bar .top-bar__left>ul>li ul,
                    .retail-header-4 .header__prodcat__container .header__prodcat>.link-parent>ul {
                        background-color: #FFFFFF;
                    }
                    .retail-header-4 .header__user-menu .link-parent ul,
                    .retail-header-4 .header__cart-preview .link-parent ul,
                    .retail-header-4 .header__prodcat>.link-parent>ul {
                        border-top: 1px solid #c14e59;
                    }
                    .retail-header-4 .header__prodcat>.link-parent>ul li a:hover,
                    .retail-header-4 .header__prodcat>.link-parent>ul li a:focus,
                    .retail-header-4 .header__prodcat>.link-parent>ul li.open>a {
                        background-color: #c14e59;
                        color: #FFFFFF;
                    }
                }
                
        
        
    </style>

<script>
    // This function is needed for JS hooks.
    function getOriginalPageName() {
        return 'default.asp';
    }

    function getUrlPath() {
        return '/Default.asp';
    }

    function getUrl() {
        return '/Default.asp?';
    }

    function handleImageError(img, noImagePath){
        if(!noImagePath) {
            noImagePath = 'images/no-image.png';
        }
        if ($(img).attr('src') !== noImagePath) {
            $(img).attr('src', noImagePath);
        }    
    }
    var sitename = "electromed2";
    var isWorkerDomain = false;
    var processPageTitle = isWorkerDomain && !false;
    var bValidIp = true;
    var sOfUrl   = 'https://electro-medical.com';
</script>

        <!-- Google Tag Manager -->
        <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
        })(window,document,'script','dataLayer','GTM-PCS3LQ3S');</script>
        <!-- End Google Tag Manager -->
        <!-- Latest Google Analytics (GA4) -->
        <!-- Global site tag (gtag.js) - Google Analytics -->
        <script async src="https://www.googletagmanager.com/gtag/js?id=G-FTTLVTT8RR"></script>
        <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', 'G-FTTLVTT8RR',{'debug_mode':true});
        </script>
        <script src="https://www.google.com/recaptcha/api.js?render=6LdLF-MrAAAAAMp-NkW_5PYJKNmMku12_HydqjmR"></script>
        <style>
            .grecaptcha-badge { visibility: hidden; }
        </style>

<script>
    var utils = {};

    utils.isCrossOriginFrame = function (parentContext) {
        try {
            if(!parentContext) parentContext = window;
            if (parentContext === window) return false;

            return (document.location.hostname !== parentContext.location.hostname);
        } catch (e) {
            return true;
        }
    }

    utils.getParameter = function (param, context) {
        var value;
        if(!context) context = window;
        
        // return empty string if cross origin (can't access params)
        if(utils.isCrossOriginFrame(context)) return '';

        var parameters = context.location.search.replace('?', '');

        if (parameters) {
            var pattern = new RegExp('\\b' + param + '=([^;&]+)', 'gi');
            value = parameters.split(pattern)[1];
        }

        return value || '';
    };

    utils.urlEncodePath = function(url) {
        if(!url) return '';
        var encodedUrl = url;
        var pathPortionRegex = /^(https:\/\/[^\/]+\/|\/)?([^?\n]+)(\?[^\n]*)?$/gi;
        var pathPortionArray = Array.from(url?.matchAll(pathPortionRegex) ?? []);
        var pathPortion = '';

        if(Array.isArray(pathPortionArray)
            && pathPortionArray.length > 0
            && Array.isArray(pathPortionArray[0])
            && pathPortionArray[0].length > 2) {
                pathPortion = pathPortionArray[0][2];
        }

        if(pathPortion) {
            var urlEncodedPathPortion = encodeURIComponent(utils.htmlDecode(pathPortion))?.replace(/%2f/gi, '/');
            encodedUrl = encodedUrl.replace(pathPortion, urlEncodedPathPortion);
        }

        return encodedUrl;
    };

    utils.buildImagePath = function(image){
        if(image && image.indexOf("http") > -1){
            imageUrl = image.replace(/http:/i, 'https:');
        }else{
            image = image.replace(oConfig.storefrontUrl, oConfig.sessionData.cdnUrl).toLowerCase();
            if(!image){
                imageUrl = oConfig.noImagePath || oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/images/' + oConfig.defaultImage.replace(/^\/+/, '');
            }
            else if(image.indexOf("/") > -1){
                imageUrl = oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/' + image.replace(/^\/+/, '');
            }
            else{
                imageUrl = oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/images/' + image.replace(/^\/+/, '');
            }
        }

        imageUrl = utils.urlEncodePath(imageUrl);

        cacheBustingPrefix = '?';
        if(imageUrl.includes('?')) cacheBustingPrefix = '&';
        return imageUrl + cacheBustingPrefix + 'v=3975201667';
    };

    utils.pageUrl = location.href.replace(/.+\//, '');
    utils.loginUrl = 'security_logon.asp?autopage=' + encodeURIComponent(utils.pageUrl);

    utils.pageName = function(){
        return "default.asp";
    }

    utils.pageType = function(){
        var pageType = "";
        if(utils.pageUrl == '' && pageType == ''){
            pageType = 'home';
        }else if(pageType != ''){
            switch(pageType){
                case 'prodcat':
                case 'product':
                    pageType = 'catalog';
                    break;
                case 'page-section':
                case 'webpage':
                    pageType = 'content';
                    break;
                default:
                    pageType = 'other';
                    break;
            }
        }else{
            switch(getOriginalPageName()){
                case 'pc_product_detail.asp':
                case 'pc_combined_results.asp':
                case 'largest_spend_products.asp':
                case 'largest_qty_ordered_products.asp': 
                case 'recently_ordered_products.asp': 
                case 'frequently_ordered_products.asp':
                    pageType = 'catalog';
                    break;
                case 'showcart.asp':
                case 'account.asp':
                    pageType = 'checkout';
                    break;
                default:
                    pageType = 'other';
                    break;

            }
        }
        return pageType;
    }

    utils.htmlEncode = function(value){
        return $('<textarea/>').text(value).html();
    }

    utils.htmlDecode = function(value){
        return $("<textarea/>").html(value).text();
    }

    utils.pageSubType = function(){
        pageSubType = "default";
        if("" != ''){
            pageSubType = "";
        }
        return pageSubType;
    }

    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: $(element[0]).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.popToastr = function(title, subtext, config) {

        var confirmToastrConfig = config ? config : {
            'closeButton': true,
            'newestOnTop': true,
            'positionClass': 'toast-top-right',
            'preventDuplicates': false,
            'showDuration': 500,
            'hideDuration': 1000,
            'tapToDismiss': false,
            'timeOut': 5000,
            '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': 500,
            'hideDuration': 1000,
            'tapToDismiss': true,
            'timeOut': 5000,
            'extendedTimeOut': 1000
        }

        $.extend(errorToastrConfig, config);

        toggleLoadingWidget(false);

        toastr.error(
            subtext,
            title,
            errorToastrConfig
        );
    }

    utils.decimalPlacesOnUnitPrices = parseInt(2) || 2;
    utils.decimalPlacesOnTotals = parseInt('2') || 2;
    utils.decimalPlacesAllowedOnProductQty = 0;
    utils.defaultQtyIncrement = 1;

    /*
     * 2024-06-07 - Client-side version (Server-side in Global Functions)
     * Standard implementation of quantity validation
     * calculation logic.
     * This assumes all values passed in already account
     * for the uom conversion factor if applicable.
     */
     utils.getValidProductQty = function(inputQty, minQty, maxQty, step, allowZeroValue) {

        // init as success result
        var qtyValidationResult = {
            inputQty: inputQty,
            validQty: inputQty,
            error: ''
        }

        if(typeof allowZeroValue === 'undefined') allowZeroValue = false;

        //- set defaults
        if(typeof step === 'undefined') step = utils.defaultQtyIncrement; //- Defined in site_config_overrides.asp
        if(typeof minQty === 'undefined') minQty = step;
        if(typeof maxQty === 'undefined') maxQty = 0;

        //- Ensure all values are numeric
        inputQty = parseFloat(inputQty);
        minQty = parseFloat(minQty);
        maxQty = parseFloat(maxQty);
        step = parseFloat(step);

        //- zero is valid when validating qty inputs elements
        //- when zero indicates the product is not selected
        //- for add to cart, like on input-qty view with a single
        //- add to cart button
        if(inputQty == 0 && allowZeroValue) {
            return qtyValidationResult;
        }

        //- retun min if inputQty is not passed in, is 0 or less than minQty.
        if( !inputQty || (minQty > 0 && inputQty < minQty)){
            qtyValidationResult.validQty = minQty;
            qtyValidationResult.error = 'min';
            return qtyValidationResult;
        }

        //- DecimalPlacesAllowedOnProductQty defined in site_config_overrides.asp
        //- and assigned to utils.decimalPlacesAllowedOnProductQty in global_scripts_top.asp
        //- It can be 0 so we add 1 to it so we have a multiplier of at least 10.
        //- floatFixMultiplier is used to account for precision issues with floating point
        //- arithmatic on base-10 decimal numbers.
        var floatFixMultiplier = Math.pow(10, (parseFloat(utils.decimalPlacesAllowedOnProductQty) + 1));

        var PadDifferenceFromMin = ( (inputQty * floatFixMultiplier) - (minQty * floatFixMultiplier) );
        var padStep = step * floatFixMultiplier;
        var padMinQty = minQty * floatFixMultiplier;
        var padMaxQty = maxQty * floatFixMultiplier;

        //- Force max to valid value
        if(maxQty < minQty) maxQty = 0;
        if(maxQty > 0) {
            var maxStepMod = (padMaxQty - padMinQty) % padStep;
            if(maxStepMod != 0) {
                var maxAdjust = Math.floor( (padMaxQty - padMinQty) / padStep ) * padStep;

                maxQty = (padMinQty + maxAdjust) / floatFixMultiplier;
            }
        }

        //- return max if inputQty is greater than max
        if(maxQty > 0 && inputQty > maxQty){
            qtyValidationResult.validQty = maxQty;
            qtyValidationResult.error = 'max';
            return qtyValidationResult;
        }

        // 1 isn't a valid default for qty when using
        // fractional quantities without a defined increment
        // or if it's off when it's simple sales uom, so
        // we set increment/step to 0
        var stepMod = step ? ( parseFloat( PadDifferenceFromMin % padStep ) / floatFixMultiplier ) : 0;

        if(stepMod != 0){

            padValidQty = (Math.ceil( PadDifferenceFromMin / padStep ) * padStep) + padMinQty

            var validQty = Math.round(padValidQty) / floatFixMultiplier;

            qtyValidationResult.validQty = validQty;
            if(maxQty > 0 && validQty > maxQty) qtyValidationResult.validQty = maxQty;
            if(validQty < minQty) qtyValidationResult.validQty = minQty;
            qtyValidationResult.error = 'inc';
            return qtyValidationResult;
        }

        return qtyValidationResult;
    }

</script>
<script>
    var cimcloud = {
        helpers: {
            url: getUrl,
            urlPath: getUrlPath,
            loginUrl: utils.loginUrl,
            pageType: utils.pageType,
            pageSubType: utils.pageSubType,
            pageName: utils.pageName,
            pageKey: '',
            urlParameter: utils.getParameter,
            buildImagePath: utils.buildImagePath,
            environment: "production"
        },
        session: {
            key: "022507AF5A994426A3DFC3B29B01E852",
            accountKey: "",
            customerKey: "",
            orderKey: "75C67D9955EF4D619AD72B3087D9C082",
            accountNumber: "",
            accountName: "",
            username: "",
            email: "",
            firstName: "",
            lastName: "",
            sitename: "electromed2",
            isLoggedIn: false,
            isImpersonation: false,
            parentSession: {
                username: "",
                email: "",
                firstName: "",
                lastName: ""
            },
            sessionKey: "022507AF5A994426A3DFC3B29B01E852",
            appliedRights: "ELECTROMED2-CUSTOM-SETTINGS,SEARCH-FIELDS,APPLICATION-DEFAULTS-SHOW-CREATE-USER-SETTINGS,COUPON-TO-ERP-USE-FIXED-ITEM,COUPON-TO-ERP-USE-FIXED-ITEM,PAY-INVOICES-100,PAY-INVOICES-100,APPLICATION-DEFAULTS-ALLOW-ADD-USER-TO-EXISTING-ACCOUNT-SETTINGS,APPLICATION-DEFAULTS-PC-IMAGE-ICONS-SETTINGS,APPLICATION-DEFAULTS-MODIFICATIONS-SETTINGS,BASE-ORDER_COMMENTS,PRODUCT-IMAGES,SHIPPING-SETTINGS,S100-CIMCLOUD-B2B-A,APPLICATION-DEFAULTS-SHOW_BROWSER_MESSAGING-SETTINGS,COUPON2,COUPON2,APPLICATION-DEFAULTS-CART-CHECKOUT-SETTINGS-SETTINGS,PC-IMAGE-ICONS,APPLICATION-DEFAULTS-POWER-CUSTOMERS-SETTINGS,ADV-PRICE-DISPLAY-SETTINGS,ADV-PRICE-DISPLAY-SETTINGS,APPLICATION-DEFAULTS-SHOW_FREIGHT_INVOICE_DETAIL-SETTINGS,BASE_INVOICES,BASE_INVOICES,DS-SHIPVIA,DS-SHIPVIA,COUPON3,ENABLE-SHIPPING-EDITS,ENABLE-SHIPPING-EDITS,SHOW-PRICE-BREAKS,EMAIL-A-FRIEND,MODIFICATIONS,ENABLE-SHIPPING-ADDS,ENABLE-SHIPPING-ADDS,PRODUCT-CATEGORIES,QUOTES-WITH-CONV-LOGS,ELECTROMED2-DEFAULTS-PRODUCT-GALLERY-SETTINGS,APPLICATION-DEFAULTS-CATALOG-ALLOW-ATC-SETTINGS,APPLICATION-DEFAULTS-MODIFICATIONS-WORKER-SETTINGS,APPLICATION-DEFAULTS-USE_TERMS_DISCOUNT_ON_INVOICES-SETTINGS,QUOTES-SAVED-CARTS,QUOTES-SAVED-CARTS,ELECTROMED2-DEFAULTS-BASE_INVOICES-SETTINGS,SHOW-RESIDENTIAL-ON-ADDRESS-EDIT,APPLICATION-DEFAULTS-BASE_INVOICES-WORKERS-SETTINGS,ELECTROMED2-DEFAULTS-SHOW_FREIGHT_INVOICE_DETAIL-SETTINGS,ELECTROMED2-DEFAULTS-BASE-ADVANCED_CUSTOMER_PRICE_SETTINGS-SETTINGS,APPLICATION-DEFAULTS-PRODUCT-GALLERY-SETTINGS,PAYMENT_METHOD_SETTINGS,APPLICATION-DEFAULTS-S100-CIMCLOUD-B2B-A-SETTINGS,ELECTROMED2-DEFAULTS-BASE_ORDERS-AND-SHIPMENTS-SETTINGS,CANADA,ELECTROMED2-DEFAULTS-ALLOW-ADD-USER-TO-EXISTING-ACCOUNT-SETTINGS,PRODUCT-DESC,APPLICATION-DEFAULTS-BASE-SHOW_SHIPPING_ADDRESSES-SETTINGS,APPLICATION-CUSTOM-SETTINGS,UPLOAD-ATC,APPLICATION-DEFAULTS-PAY-INVOICES-100-SETTINGS,ADVANCED-TABS,20220714-415479,RECENTLY-VIEWED-PRODUCTS,WEB-PAGE-ONLY,ALLOW-CREATE-NEW-ACCOUNT,COUPON,COUPON,CART-OPTIONS,SHOW_BROWSER_SUPPORT_MESSAGING,PRODUCT-PRICE-LIST,PRODUCT-DOCS,ELECTROMED2-DEFAULTS-PAY-INVOICES-100-SETTINGS,APPLICATION-DEFAULTS-CATALOG-ENABLE-PRODUCT-DISPLAY-FIELDS-SETTINGS,APPLICATION-DEFAULTS-PRODUCT-CATEGORIES-SETTINGS,APPLICATION-DEFAULTS-GOOGLEFEED-SETTINGS,BASE-SHIPPING_ADDRESSES,BASE_PAYMENTS-AND-CREDITS,BASE_PAYMENTS-AND-CREDITS,ALLOW-ADD-USER-TO-EXISTING-ACCOUNT,ALLOW-ADD-USER-TO-EXISTING-ACCOUNT,ELECTROMED2-DEFAULTS-BASE-PAYMENT_METHOD_SETTINGS-SETTINGS,BASE_ORDERS-AND-SHIPMENTS,BASE_ORDERS-AND-SHIPMENTS,ELECTROMED2-DEFAULTS-SHOW-CREATE-USER-SETTINGS,PC-CHILD-SEARCH-ROLLUP,RELATED-PRODUCTS,20200226-783995,APPLICATION-DEFAULTS-BASE-ADVANCED_CUSTOMER_PRICE_SETTINGS-SETTINGS,SITEMAPGEN,ELECTROMED2-DEFAULTS-BASE-ORDER_COMMENTS-SETTINGS,ELECTROMED2-DEFAULTS-ALLOW-CREATE-NEW-ACCOUNT-SETTINGS,APPLICATION-DEFAULTS-ADVANCED-TABS-SETTINGS,USE_TERMS_DISCOUNTS_ON_INVOICES,BULK-ADD-TO-CART,BULK-ADD-TO-CART,APPLICATION-DEFAULTS-BASE_INVOICES-SETTINGS,ENABLE-BILLING-EDITS,ENABLE-BILLING-EDITS,POWER-CUSTOMERS-IMPERSONATE,APPLICATION-DEFAULTS-BASE_ORDERS-AND-SHIPMENTS-SETTINGS,POWER-CUSTOMERS,TAXEXEMPT-C1,SHOW_FREIGHT_INVOICE_DETAIL,SHOW_FREIGHT_INVOICE_DETAIL,BASE-SHOW_PRODUCT_ACCOUNT_HISTORY,BASE-SHOW_PRODUCT_ACCOUNT_HISTORY,CART-CHECKOUT-SETTINGS,GOOGLEFEED,PRODUCT-GALLERY,PRODUCT-GALLERY,CATALOG-ALLOW-ATC,ELECTROMED2-DEFAULTS-SHIPPING-SETTINGS-SETTINGS,DS-PCAT,ELECTROMED2-DEFAULTS-SHOW-CREATE-ACCOUNT-SETTINGS".split(',')
        },
        catalog: {},
        webPage: {
            sections: {}
        },        
        report: {
            // This function is used to get the report builder results as JSON.
            getReportBuilderResults: function(rb_key, searchstring = "") {
                const url = '/report_builder_results.asp?ajax=true&key=' + rb_key + '&searchstring=' + searchstring;

                return new Promise((resolve, reject) => {
                    $.ajax({
                            url: url,
                            method: 'GET',
                            dataType: 'json'
                        })
                        .done(function(response) {
                            resolve(response);
                        })
                        .fail(function() {
                            reject(new Error("Report not found"));
                        });
                });
            }
        }
    }

    var viewModels = viewModels || {};
</script>



<script src="/js/bundles/coreTop.js?aec323c1b0473b6ea6a440505731c7fc33b81ae3" ></script>


<script src="/js/bundles/corePlugins.js?aec323c1b0473b6ea6a440505731c7fc33b81ae3" ></script>


<script src="/js/bundles/coreVendors.js?aec323c1b0473b6ea6a440505731c7fc33b81ae3" ></script><script id="mcjs">!function(c,h,i,m,p){m=c.createElement(h),p=c.getElementsByTagName(h)[0],m.async=1,m.src=i,p.parentNode.insertBefore(m,p)}(document,"script","https://chimpstatic.com/mcjs-connected/js/users/057959f85432ae9a2a0aa0d4d/b4fbc824c9e9838b8b4f63c08.js");</script>

</head>

<body class="home retail t-ui-phase-4 site-type-4 loggedout  t-ui-phase-4 home loggedout site-type-4 production electromed2">

	      
        <!-- Google Tag Manager (noscript) -->
        <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PCS3LQ3S" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
        <!-- End Google Tag Manager (noscript) -->
     

    <noscript class="noscript-padding"></noscript>

    

<header id="retail-header-1" class="retail-header-1">
        <div id="topbar" class="topbar print-hide">
        <div class="container-fluid">
            <nav class="topbar__left">
                <ul class="topbar__left__menu linkset click-persist js-click-outside-to-close">
                    <li>
                        <a class="topbar__menu-toggle" href="#0">
                            <i class="icon-reorder"></i> Menu
                        </a>
                        <ul id="retail-topbar-left-menu" class="horizontal retail-topbar-left-menu retail-topbar-left-menu__ul-1">
	<li class="retail-topbar-left-menu__li-1" data-key='8D783EDB6C114EDB87C2446C6F5C8288'><a href="content/AboutUs.asp" class="retail-topbar-left-menu__a-1">About Us</a></li>
	<li class="retail-topbar-left-menu__li-1" data-key='9A3CC3AAEA3E49718BD2628F0955F2ED'><a href="contact_us.asp" class="retail-topbar-left-menu__a-1">Contact</a></li>
	<li class="retail-topbar-left-menu__li-1" data-key='50541D1FAA7D408B9F60CF842112B892'><a href="/PPE-Supplies/" class="retail-topbar-left-menu__a-1">PPE Products</a></li>
	<li class="retail-topbar-left-menu__li-1" data-key='DD952DC06B314BE4A4AD78148FD13A39'><a href="/page.asp?p_key=8451A1BA2C114DC18FB5E13B2C9C5595" class="retail-topbar-left-menu__a-1">Price Match</a></li>
</ul>
                    </li>
                </ul>
            </nav>
            <div class="topbar__right">
                
            </div>
        </div>
    </div>

<div id="logo-bar" class="logo-bar">
    <div class="container-fluid">
        <div class="logo-bar__logo">
            
		<a href="https://electro-medical.com" class="logo hidden-xs">
		<img src="https://d29eekna00jloo.cloudfront.net/images/logo.jpg?v=3975201667&v=3975201667" alt="Electro-Medical Equipment Logo">
		</a>
	
		<a href="https://electro-medical.com" class="logo visible-xs">
		<img src="https://d29eekna00jloo.cloudfront.net/images/logo.jpg?v=3975201667&v=3975201667" alt="Electro-Medical Equipment Logo">
		</a>
	
        </div>
        <nav class="logo-bar__right">
            

<ul id="header__prodcat" class="header__prodcat linkset click-persist js-click-outside-to-close">
    <li class="link-parent products__link-parent">
        <a class="header__prodcat__toggle" href="#0">
            <i class="icon-tags"></i> Products
        </a>

			<ul class="prodcat prodcat__ul-1"><li class="prodcat__li-1"><a href="/Cearance/" class="prodcat__a-1" data-parent-href="/Cearance/" data-parent-name="Clearance Items" data-key="C186AB17CA694071A678424CC45A5813"><span class=cat-nm>Clearance Items</span></a></li><li class="prodcat__li-1 "><a href="/Clinical-Equipment/" class="prodcat__a-1" data-parent-href="/Clinical-Equipment/" data-parent-name="Clinical Equipment" data-key="55D6DF274A034B0AAB67C6F6EE337FA2"><span class=cat-nm>Clinical Equipment</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/AED-DEFIBRILLATOR/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/AED-DEFIBRILLATOR/" data-parent-name="Clinical Equipment|AED DEFIBRILLATOR" data-key="936DB5AFFDA54749B8E6D2FF0DC7B338"><span class=cat-nm>AED DEFIBRILLATOR</span></a></li><li class="prodcat__li-2"><a href="/Blood-Pressure-Sphygmomanometers/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Blood-Pressure-Sphygmomanometers/" data-parent-name="Clinical Equipment|Blood Pressure /  Sphygmomanometers" data-key="49F75F0C063F4DF0A1FBCFF92A3707DD"><span class=cat-nm>Blood Pressure /  Sphygmomanometers</span></a></li><li class="prodcat__li-2"><a href="/Game-Ready-Compression/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Game-Ready-Compression/" data-parent-name="Clinical Equipment|Game Ready & Compression" data-key="7119EDB99B314677956BACF18C3B7074"><span class=cat-nm>Game Ready & Compression</span></a></li><li class="prodcat__li-2"><a href="/Hawk-Grips/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Hawk-Grips/" data-parent-name="Clinical Equipment|HawkGrip IASTM Tools" data-key="443380554BB84CBCAF39D3F4BE4749C9"><span class=cat-nm>HawkGrip IASTM Tools</span></a></li><li class="prodcat__li-2"><a href="/Hot-Pack-Units/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Hot-Pack-Units/" data-parent-name="Clinical Equipment|Hot Pack Units" data-key="F8EBC5B49C6D4A69A33CDFFEF1FE1684"><span class=cat-nm>Hot Pack Units</span></a></li><li class="prodcat__li-2"><a href="/Lotion-Warmers/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Lotion-Warmers/" data-parent-name="Clinical Equipment|Lotion Warmers" data-key="2DCBB1A47F704446B6EBF7FCC6B529EF"><span class=cat-nm>Lotion Warmers</span></a></li><li class="prodcat__li-2"><a href="/Parallel-Bars/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Parallel-Bars/" data-parent-name="Clinical Equipment|Parallel Bars" data-key="2A17C55583034946A8D3DD79ADFEB3A1"><span class=cat-nm>Parallel Bars</span></a></li><li class="prodcat__li-2"><a href="/Posture-Mirrors/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Posture-Mirrors/" data-parent-name="Clinical Equipment|Posture Mirrors" data-key="D78F94A335A7488C88BF7999427C9C30"><span class=cat-nm>Posture Mirrors</span></a></li><li class="prodcat__li-2"><a href="/Rebounders/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Rebounders/" data-parent-name="Clinical Equipment|Rebounders" data-key="9C9966BFDC2A447B9B44E303B2FE87C7"><span class=cat-nm>Rebounders</span></a></li><li class="prodcat__li-2"><a href="/Rehab-Weight-Racks-and-Weights/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Rehab-Weight-Racks-and-Weights/" data-parent-name="Clinical Equipment|Rehab Weight Racks and Weights" data-key="C1A7F33727F047CDB488BD50F83D7822"><span class=cat-nm>Rehab Weight Racks and Weights</span></a></li><li class="prodcat__li-2"><a href="/Splinting-Equipment/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Splinting-Equipment/" data-parent-name="Clinical Equipment|Splinting Equipment" data-key="4B6560A37D9840A0B7BFA2B88CF26857"><span class=cat-nm>Splinting Equipment</span></a></li><li class="prodcat__li-2"><a href="/Therapy-Stairs-Steps/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Therapy-Stairs-Steps/" data-parent-name="Clinical Equipment|Therapy Stairs & Steps" data-key="3CFB008035124AFAAC1D34913A7CE4D5"><span class=cat-nm>Therapy Stairs & Steps</span></a></li><li class="prodcat__li-2"><a href="/Treatment-Curtains-Privacy-Screens/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Treatment-Curtains-Privacy-Screens/" data-parent-name="Clinical Equipment|Treatment Curtains / Privacy Screens" data-key="49FCA2C86A0D462AA5D9BE6431A5EA6D"><span class=cat-nm>Treatment Curtains / Privacy Screens</span></a></li><li class="prodcat__li-2"><a href="/Work-Hardening/" class="prodcat__a-2" data-parent-href="/Clinical-Equipment/|/Work-Hardening/" data-parent-name="Clinical Equipment|Work Hardening" data-key="17DB6670B3CC4BAB980B655B3FACFA4C"><span class=cat-nm>Work Hardening</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Clinical-Supplies/" class="prodcat__a-1" data-parent-href="/Clinical-Supplies/" data-parent-name="Clinical Supplies" data-key="F917871B51164B7EABC25B44EE186BCB"><span class=cat-nm>Clinical Supplies</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Anatomical-Charts-and-Models/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Anatomical-Charts-and-Models/" data-parent-name="Clinical Supplies|Anatomical Charts and Models" data-key="02F3C69CA6A94C76B768DC60E658E893"><span class=cat-nm>Anatomical Charts and Models</span></a></li><li class="prodcat__li-2"><a href="/Bandages-and-Dressings/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Bandages-and-Dressings/" data-parent-name="Clinical Supplies|Bandages and Dressings" data-key="2E3EA3C97A6F4210BAD09FAE603AFC22"><span class=cat-nm>Bandages and Dressings</span></a></li><li class="prodcat__li-2"><a href="/Disinfectant-Cleaning-Products-Wipes/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Disinfectant-Cleaning-Products-Wipes/" data-parent-name="Clinical Supplies|Disinfectant Cleaning Products & Wipes" data-key="D6308480CA574FF8B92C9C41D1143409"><span class=cat-nm>Disinfectant Cleaning Products & Wipes</span></a></li><li class="prodcat__li-2"><a href="/Dry-Needling/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Dry-Needling/" data-parent-name="Clinical Supplies|Dry Needling" data-key="87A5F2D12B6E4898BFA618600B1FBD3A"><span class=cat-nm>Dry Needling</span></a></li><li class="prodcat__li-2"><a href="/Electrodes/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Electrodes/" data-parent-name="Clinical Supplies|Electrodes" data-key="BAAFB6A2FF9744389755ED3232BCA8E5"><span class=cat-nm>Electrodes</span></a></li><li class="prodcat__li-2"><a href="/Gait-Belts/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Gait-Belts/" data-parent-name="Clinical Supplies|Gait Belts" data-key="822D060AD8644A9B975B82A096DA3478"><span class=cat-nm>Gait Belts</span></a></li><li class="prodcat__li-2"><a href="/Gloves-Clinical-Exam/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Gloves-Clinical-Exam/" data-parent-name="Clinical Supplies|Gloves / Clinical Exam" data-key="430A36F949D44773A9E4A1718F1725E1"><span class=cat-nm>Gloves / Clinical Exam</span></a></li><li class="prodcat__li-2"><a href="/Iontophoresis/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Iontophoresis/" data-parent-name="Clinical Supplies|Iontophoresis" data-key="2DF8CF43C14347EF98F335822879AF11"><span class=cat-nm>Iontophoresis</span></a></li><li class="prodcat__li-2"><a href="/Medical-Paper-Supplies/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Medical-Paper-Supplies/" data-parent-name="Clinical Supplies|Medical Paper Supplies" data-key="0F66BCE83EA64BC99851371D302CA98B"><span class=cat-nm>Medical Paper Supplies</span></a></li><li class="prodcat__li-2"><a href="/Mobilization/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Mobilization/" data-parent-name="Clinical Supplies|MOBILIZATION" data-key="0A67038BCFF84F1685EF12F04048626E"><span class=cat-nm>MOBILIZATION</span></a></li><li class="prodcat__li-2"><a href="/Patient-Gowns/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Patient-Gowns/" data-parent-name="Clinical Supplies|Patient Gowns" data-key="90C0F03A269449B29CCE24B5FC9588CC"><span class=cat-nm>Patient Gowns</span></a></li><li class="prodcat__li-2"><a href="/Patient-Positioning-Foam-Rollers/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Patient-Positioning-Foam-Rollers/" data-parent-name="Clinical Supplies|Patient Positioning & Foam Rollers" data-key="B2B7CCD3573C42889CE775F3AC6C5164"><span class=cat-nm>Patient Positioning & Foam Rollers</span></a></li><li class="prodcat__li-2"><a href="/Physical-Therapy-Education/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Physical-Therapy-Education/" data-parent-name="Clinical Supplies|Physical Therapy Education" data-key="756AB7F9F2D341A2A33A3513C9354DFB"><span class=cat-nm>Physical Therapy Education</span></a></li><li class="prodcat__li-2"><a href="/Resistance-Bands/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Resistance-Bands/" data-parent-name="Clinical Supplies|Resistance Bands" data-key="76AF7AB556CE4CE784F5B9642D0F4F5A"><span class=cat-nm>Resistance Bands</span></a></li><li class="prodcat__li-2"><a href="/Tape-and-Taping-Supplies/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Tape-and-Taping-Supplies/" data-parent-name="Clinical Supplies|Tape and Taping Supplies" data-key="8356613279D3455F982FBC60DC7EEF96"><span class=cat-nm>Tape and Taping Supplies</span></a></li><li class="prodcat__li-2"><a href="/Timers/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Timers/" data-parent-name="Clinical Supplies|Timers" data-key="1B35D0ECBAAE44BCA01CC379EC8C80D8"><span class=cat-nm>Timers</span></a></li><li class="prodcat__li-2"><a href="/Topical-Pain-Relief-/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Topical-Pain-Relief-/" data-parent-name="Clinical Supplies|Topical Analgesics & Pain Relief Products" data-key="CA6163AA6B4A4555B6317FCB261CF77B"><span class=cat-nm>Topical Analgesics & Pain Relief Products</span></a></li><li class="prodcat__li-2"><a href="/Towels-and-Clinical-Linens/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Towels-and-Clinical-Linens/" data-parent-name="Clinical Supplies|Towels and Clinical Linens" data-key="3DE680314FD64A41BBD6D1D7A9F80DF8"><span class=cat-nm>Towels and Clinical Linens</span></a></li><li class="prodcat__li-2"><a href="/Ultrasound-Gels-Lotions/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Ultrasound-Gels-Lotions/" data-parent-name="Clinical Supplies|Ultrasound Gels & Lotions" data-key="8208000BCA06426A92723540ACFE8031"><span class=cat-nm>Ultrasound Gels & Lotions</span></a></li><li class="prodcat__li-2"><a href="/Wound-Care-Products/" class="prodcat__a-2" data-parent-href="/Clinical-Supplies/|/Wound-Care-Products/" data-parent-name="Clinical Supplies|Wound Care Products" data-key="F15E114D500F4AF6BC3D63139ABFF532"><span class=cat-nm>Wound Care Products</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Daily-Living-Aids/" class="prodcat__a-1" data-parent-href="/Daily-Living-Aids/" data-parent-name="Daily Living Aids" data-key="8948305881064D05934861318C7D5483"><span class=cat-nm>Daily Living Aids</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Bathroom-Products/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Bathroom-Products/" data-parent-name="Daily Living Aids|Bathroom Products" data-key="6BA92900CDC144F998B179619CA22178"><span class=cat-nm>Bathroom Products</span></a></li><li class="prodcat__li-2"><a href="/Bedside-Commodes/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Bedside-Commodes/" data-parent-name="Daily Living Aids|Bedside Commodes" data-key="B1EA14D4D5BB41419CA7B342657BA8D1"><span class=cat-nm>Bedside Commodes</span></a></li><li class="prodcat__li-2"><a href="/Blood-Pressure-Monitors/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Blood-Pressure-Monitors/" data-parent-name="Daily Living Aids|Blood Pressure Monitors" data-key="9196904D5F484E3FAA54CB890A196560"><span class=cat-nm>Blood Pressure Monitors</span></a></li><li class="prodcat__li-2"><a href="/Crutches/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Crutches/" data-parent-name="Daily Living Aids|Crutches" data-key="A99496AF630E4345B569A23682A7F34A"><span class=cat-nm>Crutches</span></a></li><li class="prodcat__li-2"><a href="/Dining-Assistance/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Dining-Assistance/" data-parent-name="Daily Living Aids|Dining Assistance" data-key="655049E8092147F0A9AE5F3F273BFF90"><span class=cat-nm>Dining Assistance</span></a></li><li class="prodcat__li-2"><a href="/Dressing-Aids/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Dressing-Aids/" data-parent-name="Daily Living Aids|Dressing Aids" data-key="16F0367BFE984FD78BF54FF65086A0F0"><span class=cat-nm>Dressing Aids</span></a></li><li class="prodcat__li-2"><a href="/Gait-Belts/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Gait-Belts/" data-parent-name="Daily Living Aids|Gait Belts" data-key="822D060AD8644A9B975B82A096DA3478"><span class=cat-nm>Gait Belts</span></a></li><li class="prodcat__li-2"><a href="/Home-Exercise-Equipment/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Home-Exercise-Equipment/" data-parent-name="Daily Living Aids|Home Exercise Equipment" data-key="C35E8102D88F4AC28CCB12C183D23DC3"><span class=cat-nm>Home Exercise Equipment</span></a></li><li class="prodcat__li-2"><a href="/Home-Pedal-Exercisers/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Home-Pedal-Exercisers/" data-parent-name="Daily Living Aids|Home Pedal Exercisers" data-key="2C69DC9E06D14DB4900EC946304E99CC"><span class=cat-nm>Home Pedal Exercisers</span></a></li><li class="prodcat__li-2"><a href="/Home-Traction-Devices/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Home-Traction-Devices/" data-parent-name="Daily Living Aids|Home Traction Devices" data-key="783FBBBAAEAC4F7581B4CC7DBC34F795"><span class=cat-nm>Home Traction Devices</span></a></li><li class="prodcat__li-2"><a href="/Patient-Assistance/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Patient-Assistance/" data-parent-name="Daily Living Aids|Patient Assistance" data-key="F0C4100B57664E62A29B3AE7D2321CDE"><span class=cat-nm>Patient Assistance</span></a></li><li class="prodcat__li-2"><a href="/Patient-Education/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Patient-Education/" data-parent-name="Daily Living Aids|Patient Education" data-key="159C94A7F6DF4F1E9E1D1C8D78002A99"><span class=cat-nm>Patient Education</span></a></li><li class="prodcat__li-2"><a href="/Pedometers/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Pedometers/" data-parent-name="Daily Living Aids|Pedometers" data-key="BD24272336AC4B3F8556A616B63F2230"><span class=cat-nm>Pedometers</span></a></li><li class="prodcat__li-2"><a href="/Walkers-and-Accessories/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Walkers-and-Accessories/" data-parent-name="Daily Living Aids|Walkers and Accessories" data-key="87E5DB7968054531AD9997F6A0B91241"><span class=cat-nm>Walkers and Accessories</span></a></li><li class="prodcat__li-2"><a href="/Walking-Canes/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Walking-Canes/" data-parent-name="Daily Living Aids|Walking Canes" data-key="BFEFE491B5E649D589D8673197EA55B2"><span class=cat-nm>Walking Canes</span></a></li><li class="prodcat__li-2"><a href="/Wheelchairs/" class="prodcat__a-2" data-parent-href="/Daily-Living-Aids/|/Wheelchairs/" data-parent-name="Daily Living Aids|Wheelchairs" data-key="938783DB11CC44CFA8197F49DE1ADD0C"><span class=cat-nm>Wheelchairs</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Hand-Therapy/" class="prodcat__a-1" data-parent-href="/Hand-Therapy/" data-parent-name="Hand Therapy" data-key="54A6D0AFB9F04F99B84BE500295D5C2E"><span class=cat-nm>Hand Therapy</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Arthritic--Supports/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Arthritic--Supports/" data-parent-name="Hand Therapy|Arthritic  Supports" data-key="8C5967BA4BA545B2BC5D0B228D87E929"><span class=cat-nm>Arthritic  Supports</span></a></li><li class="prodcat__li-2"><a href="/Electrotherapy-UltraSound-Units/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Electrotherapy-UltraSound-Units/" data-parent-name="Hand Therapy|Electrotherapy UltraSound Units" data-key="AD20EEB39E7C4EAFB20BF10D7D8DA2A4"><span class=cat-nm>Electrotherapy UltraSound Units</span></a></li><li class="prodcat__li-2"><a href="/Fluidotherapy-Machines/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Fluidotherapy-Machines/" data-parent-name="Hand Therapy|Fluidotherapy Machines" data-key="F2C2EB860DD043E78293AEEB4CFDBC92"><span class=cat-nm>Fluidotherapy Machines</span></a></li><li class="prodcat__li-2"><a href="/Hand-and-Finger-Splints/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Hand-and-Finger-Splints/" data-parent-name="Hand Therapy|Hand and Finger Splints" data-key="CFFB13E37EEF4EB580ABBC62BD0A4209"><span class=cat-nm>Hand and Finger Splints</span></a></li><li class="prodcat__li-2"><a href="/hand-therapy/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/hand-therapy/" data-parent-name="Hand Therapy|Hand and Wrist Exercise Devices" data-key="3C918F5508F74532BE05F2AC6CD57DCA"><span class=cat-nm>Hand and Wrist Exercise Devices</span></a></li><li class="prodcat__li-2"><a href="/Hand-Therapy-Tables/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Hand-Therapy-Tables/" data-parent-name="Hand Therapy|Hand Therapy Tables" data-key="3DB2414924A04369B77811DC11AEE8A9"><span class=cat-nm>Hand Therapy Tables</span></a></li><li class="prodcat__li-2"><a href="/OT_WORK-_TABLES" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/OT_WORK-_TABLES" data-parent-name="Hand Therapy|OT Work Tables" data-key="77C49315521447E2B7D8D63E9AB33883"><span class=cat-nm>OT Work Tables</span></a></li><li class="prodcat__li-2"><a href="/Paraffin-Baths/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Paraffin-Baths/" data-parent-name="Hand Therapy|Paraffin Baths" data-key="07E015F5D1B34C4F8FC9DF0522E4B3EB"><span class=cat-nm>Paraffin Baths</span></a></li><li class="prodcat__li-2"><a href="/Splinting-Equipment/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Splinting-Equipment/" data-parent-name="Hand Therapy|Splinting Equipment" data-key="4B6560A37D9840A0B7BFA2B88CF26857"><span class=cat-nm>Splinting Equipment</span></a></li><li class="prodcat__li-2"><a href="/Splinting-Material/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Splinting-Material/" data-parent-name="Hand Therapy|Splinting Material" data-key="9D3939F3C71045C5953CD2016C2A7BAA"><span class=cat-nm>Splinting Material</span></a></li><li class="prodcat__li-2"><a href="/Wound-Care-Products/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Wound-Care-Products/" data-parent-name="Hand Therapy|Wound Care Products" data-key="F15E114D500F4AF6BC3D63139ABFF532"><span class=cat-nm>Wound Care Products</span></a></li><li class="prodcat__li-2"><a href="/Wrist-Supports/" class="prodcat__a-2" data-parent-href="/Hand-Therapy/|/Wrist-Supports/" data-parent-name="Hand Therapy|Wrist Supports" data-key="61B0F4F753714D338BD85FB0624A1D56"><span class=cat-nm>Wrist Supports</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Hot-Cold-Therapy/" class="prodcat__a-1" data-parent-href="/Hot-Cold-Therapy/" data-parent-name="Hot and Cold Therapy" data-key="097E2E8486FE40339CF581C179D106F1"><span class=cat-nm>Hot and Cold Therapy</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Cold-Packs/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Cold-Packs/" data-parent-name="Hot and Cold Therapy|Cold Packs" data-key="3873DB4396E24B18B6727498D23026FE"><span class=cat-nm>Cold Packs</span></a></li><li class="prodcat__li-2"><a href="/Fluidotherapy-Machines/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Fluidotherapy-Machines/" data-parent-name="Hot and Cold Therapy|Fluidotherapy Machines" data-key="F2C2EB860DD043E78293AEEB4CFDBC92"><span class=cat-nm>Fluidotherapy Machines</span></a></li><li class="prodcat__li-2"><a href="/Freezers-Cold-Pack/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Freezers-Cold-Pack/" data-parent-name="Hot and Cold Therapy|Freezers / Cold Pack" data-key="146A8CFCF6754E3B9B3AF1746754FA18"><span class=cat-nm>Freezers / Cold Pack</span></a></li><li class="prodcat__li-2"><a href="/Game-Ready-Compression/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Game-Ready-Compression/" data-parent-name="Hot and Cold Therapy|Game Ready & Compression" data-key="7119EDB99B314677956BACF18C3B7074"><span class=cat-nm>Game Ready & Compression</span></a></li><li class="prodcat__li-2"><a href="/Hot-Pack-Units/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Hot-Pack-Units/" data-parent-name="Hot and Cold Therapy|Hot Pack Units" data-key="F8EBC5B49C6D4A69A33CDFFEF1FE1684"><span class=cat-nm>Hot Pack Units</span></a></li><li class="prodcat__li-2"><a href="/Hot-Packs-Covers-Moist-Heat/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Hot-Packs-Covers-Moist-Heat/" data-parent-name="Hot and Cold Therapy|Hot Packs & Covers  (Moist Heat)" data-key="F892ABFADC2142CA9E6250B7D674304A"><span class=cat-nm>Hot Packs & Covers  (Moist Heat)</span></a></li><li class="prodcat__li-2"><a href="/Hot-Cold-Packs/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Hot-Cold-Packs/" data-parent-name="Hot and Cold Therapy|Hot/Cold Packs" data-key="59A28EF03F3B41AF93852D80EBE9DFD0"><span class=cat-nm>Hot/Cold Packs</span></a></li><li class="prodcat__li-2"><a href="/Paraffin-Baths/" class="prodcat__a-2" data-parent-href="/Hot-Cold-Therapy/|/Paraffin-Baths/" data-parent-name="Hot and Cold Therapy|Paraffin Baths" data-key="07E015F5D1B34C4F8FC9DF0522E4B3EB"><span class=cat-nm>Paraffin Baths</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Massage-Therapy-Equipment/" class="prodcat__a-1" data-parent-href="/Massage-Therapy-Equipment/" data-parent-name="Massage Therapy Equipment" data-key="6568BB78D6084A8498F963F2B26418EE"><span class=cat-nm>Massage Therapy Equipment</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Hawk-Grips/" class="prodcat__a-2" data-parent-href="/Massage-Therapy-Equipment/|/Hawk-Grips/" data-parent-name="Massage Therapy Equipment|HawkGrip IASTM Tools" data-key="443380554BB84CBCAF39D3F4BE4749C9"><span class=cat-nm>HawkGrip IASTM Tools</span></a></li><li class="prodcat__li-2"><a href="/Ice-Massage/" class="prodcat__a-2" data-parent-href="/Massage-Therapy-Equipment/|/Ice-Massage/" data-parent-name="Massage Therapy Equipment|Ice Massage" data-key="31BEC26044C84D88A65EA0625954B75F"><span class=cat-nm>Ice Massage</span></a></li><li class="prodcat__li-2"><a href="/Massage-Lotions-Creams-Waxes-Oils/" class="prodcat__a-2" data-parent-href="/Massage-Therapy-Equipment/|/Massage-Lotions-Creams-Waxes-Oils/" data-parent-name="Massage Therapy Equipment|Massage Lotions, Creams, Waxes & Oils" data-key="A36AE724BB2545E6BE1C16F57B8207C8"><span class=cat-nm>Massage Lotions, Creams, Waxes & Oils</span></a></li><li class="prodcat__li-2"><a href="/Massage-Tables/" class="prodcat__a-2" data-parent-href="/Massage-Therapy-Equipment/|/Massage-Tables/" data-parent-name="Massage Therapy Equipment|Massage Tables" data-key="3AEFDDD91A3C4AC7A50A66DA371ABA95"><span class=cat-nm>Massage Tables</span></a></li><li class="prodcat__li-2"><a href="/Massagers-and-Tools/" class="prodcat__a-2" data-parent-href="/Massage-Therapy-Equipment/|/Massagers-and-Tools/" data-parent-name="Massage Therapy Equipment|Massagers and Tools" data-key="7E9F451E40774D7399321C3C59DAE78C"><span class=cat-nm>Massagers and Tools</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Medical-Diagnostic-Equipment/" class="prodcat__a-1" data-parent-href="/Medical-Diagnostic-Equipment/" data-parent-name="Medical Diagnostic Equipment" data-key="C61D86960A1A4658BAE064FF15589EA9"><span class=cat-nm>Medical Diagnostic Equipment</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Aesthesiometers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Aesthesiometers/" data-parent-name="Medical Diagnostic Equipment|Aesthesiometers" data-key="4F8407F4F86B418C9C9E2371FD3F5F56"><span class=cat-nm>Aesthesiometers</span></a></li><li class="prodcat__li-2"><a href="/Blood-Pressure-Sphygmomanometers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Blood-Pressure-Sphygmomanometers/" data-parent-name="Medical Diagnostic Equipment|Blood Pressure /  Sphygmomanometers" data-key="49F75F0C063F4DF0A1FBCFF92A3707DD"><span class=cat-nm>Blood Pressure /  Sphygmomanometers</span></a></li><li class="prodcat__li-2"><a href="/Body-Fat-Analyzers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Body-Fat-Analyzers/" data-parent-name="Medical Diagnostic Equipment|Body Fat Analyzers" data-key="FD90A26FB100471580EE2CAFE82BECAF"><span class=cat-nm>Body Fat Analyzers</span></a></li><li class="prodcat__li-2"><a href="/Dexterity-Tests/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Dexterity-Tests/" data-parent-name="Medical Diagnostic Equipment|Dexterity Tests" data-key="8A2A952398374627ABE64FD2F2828E90"><span class=cat-nm>Dexterity Tests</span></a></li><li class="prodcat__li-2"><a href="/Dynamometers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Dynamometers/" data-parent-name="Medical Diagnostic Equipment|Dynamometers" data-key="A0D08E79EDB04690B7BA1DCEE23DA927"><span class=cat-nm>Dynamometers</span></a></li><li class="prodcat__li-2"><a href="/Goniometers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Goniometers/" data-parent-name="Medical Diagnostic Equipment|Goniometers" data-key="32DDB6FBC2EB4E14919D8E351E306BB1"><span class=cat-nm>Goniometers</span></a></li><li class="prodcat__li-2"><a href="/Heart-Rate-Oximeters/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Heart-Rate-Oximeters/" data-parent-name="Medical Diagnostic Equipment|Heart Rate / Oximeters" data-key="4860E5EBBF104F8BB8AC8A0DB1B80D88"><span class=cat-nm>Heart Rate / Oximeters</span></a></li><li class="prodcat__li-2"><a href="/Inclinometers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Inclinometers/" data-parent-name="Medical Diagnostic Equipment|Inclinometers" data-key="7608F64B490F4FA4B5FF6988BB427A7F"><span class=cat-nm>Inclinometers</span></a></li><li class="prodcat__li-2"><a href="/Measuring-Devices-and-Flexibility-Tests/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Measuring-Devices-and-Flexibility-Tests/" data-parent-name="Medical Diagnostic Equipment|Measuring Devices and Flexibility Tests" data-key="3F300C7361FD4DBCB16CEAA0CF2CE646"><span class=cat-nm>Measuring Devices and Flexibility Tests</span></a></li><li class="prodcat__li-2"><a href="/Medical-Tuning-Forks/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Medical-Tuning-Forks/" data-parent-name="Medical Diagnostic Equipment|Medical Tuning Forks" data-key="BF0479206F0048C9950F012F7189C264"><span class=cat-nm>Medical Tuning Forks</span></a></li><li class="prodcat__li-2"><a href="/Physician-Scales/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Physician-Scales/" data-parent-name="Medical Diagnostic Equipment|Physician Scales" data-key="749BAE9F1A7E40D99FA93AA1853F5DE7"><span class=cat-nm>Physician Scales</span></a></li><li class="prodcat__li-2"><a href="/Pinch-Gauges/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Pinch-Gauges/" data-parent-name="Medical Diagnostic Equipment|Pinch Gauges" data-key="627A5314998A4613A7F2FF11168373D1"><span class=cat-nm>Pinch Gauges</span></a></li><li class="prodcat__li-2"><a href="/Push-Pull-Dynamometers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Push-Pull-Dynamometers/" data-parent-name="Medical Diagnostic Equipment|Push/Pull Dynamometers" data-key="33A8BAEDCFCD42F6A7CC69999048BD55"><span class=cat-nm>Push/Pull Dynamometers</span></a></li><li class="prodcat__li-2"><a href="/Sensory-Evaluation/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Sensory-Evaluation/" data-parent-name="Medical Diagnostic Equipment|Sensory Evaluation" data-key="70A1A22BDEF7472F987C006456B8652B"><span class=cat-nm>Sensory Evaluation</span></a></li><li class="prodcat__li-2"><a href="/Skinfold-Calipers/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Skinfold-Calipers/" data-parent-name="Medical Diagnostic Equipment|Skinfold Calipers" data-key="EBA6124ADDD24F63A38410EABF3116C4"><span class=cat-nm>Skinfold Calipers</span></a></li><li class="prodcat__li-2"><a href="/Stethoscopes/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Stethoscopes/" data-parent-name="Medical Diagnostic Equipment|Stethoscopes" data-key="7C9A574E483A4EB79EE2B3D68B650652"><span class=cat-nm>Stethoscopes</span></a></li><li class="prodcat__li-2"><a href="/Volumetric-Measuring-Devices/" class="prodcat__a-2" data-parent-href="/Medical-Diagnostic-Equipment/|/Volumetric-Measuring-Devices/" data-parent-name="Medical Diagnostic Equipment|Volumetric Measuring Devices" data-key="3668A45F3CA74A6DAFA558D58DF86FE3"><span class=cat-nm>Volumetric Measuring Devices</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Medical-Exercise-Equipment/" class="prodcat__a-1" data-parent-href="/Medical-Exercise-Equipment/" data-parent-name="Medical Exercise Equipment" data-key="0D9BC9B41994493893491FE28C5B33B0"><span class=cat-nm>Medical Exercise Equipment</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Balance-Trainers/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Balance-Trainers/" data-parent-name="Medical Exercise Equipment|Balance Trainers" data-key="8D70B65FCE9541058C11AABF33FC2B8D"><span class=cat-nm>Balance Trainers</span></a></li><li class="prodcat__li-2"><a href="/Blood-Flow-Resistance/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Blood-Flow-Resistance/" data-parent-name="Medical Exercise Equipment|Blood Flow Resistance" data-key="985D1913B6D14DB3952B57EC06055E5C"><span class=cat-nm>Blood Flow Resistance</span></a></li><li class="prodcat__li-2"><a href="/Bungie-Therapy/Training/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Bungie-Therapy/Training/" data-parent-name="Medical Exercise Equipment|Bungie Therapy/Training" data-key="7B1796407B6D479C9A9C9E596BFC73E4"><span class=cat-nm>Bungie Therapy/Training</span></a></li><li class="prodcat__li-2 "><a href="/Clinical-Exercise-Units/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units" data-key="F0F450B1CB7740DAA483C276DD213ADA"><span class=cat-nm>Clinical Exercise Units</span></a><ul class="prodcat__ul-3"><li class="prodcat__li-3"><a href="/Clinical-Functional-Trainers/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Clinical-Functional-Trainers/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Clinical Functional Trainers" data-key="F7B77AA737F04C87B2BA0CA474AD3572"><span class=cat-nm>Clinical Functional Trainers</span></a></li><li class="prodcat__li-3"><a href="/Ellipticals/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Ellipticals/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Ellipticals" data-key="F2131940E7294197B2CCA2637AAFBDDA"><span class=cat-nm>Ellipticals</span></a></li><li class="prodcat__li-3"><a href="/Matrix-Exercise-Equipment/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Matrix-Exercise-Equipment/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Matrix Medical Exercise Equipment" data-key="4B4589800E2E41B39179E0E27C77AA6E"><span class=cat-nm>Matrix Medical Exercise Equipment</span></a></li><li class="prodcat__li-3"><a href="/Medical-Treadmills/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Medical-Treadmills/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Medical Treadmills" data-key="22AC04CF4855428FA794E6F73776431E"><span class=cat-nm>Medical Treadmills</span></a></li><li class="prodcat__li-3"><a href="/Recumbent-Upright-Exercise-Bikes/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Recumbent-Upright-Exercise-Bikes/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Recumbent & Upright Exercise Bikes" data-key="0FC395173E3C4C2285FA2C086AD2A681"><span class=cat-nm>Recumbent & Upright Exercise Bikes</span></a></li><li class="prodcat__li-3"><a href="/Rehab-Pro-Pulley/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Rehab-Pro-Pulley/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Rehab Pro Pulley" data-key="3912A1B2885A4E638B20FA2DD3181B9D"><span class=cat-nm>Rehab Pro Pulley</span></a></li><li class="prodcat__li-3"><a href="/Rowers/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Rowers/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|ROWERS" data-key="5D3104A0DE784F299C5312A38C9D19F4"><span class=cat-nm>ROWERS</span></a></li><li class="prodcat__li-3"><a href="/Shuttle-Systems/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Shuttle-Systems/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Shuttle Systems" data-key="EE794C4D29C742F79F9F8793EA80724A"><span class=cat-nm>Shuttle Systems</span></a></li><li class="prodcat__li-3"><a href="/Stepper-Machines/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/Stepper-Machines/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Stepper Machines" data-key="33928C97311C4F20B1ACD0B200343782"><span class=cat-nm>Stepper Machines</span></a></li><li class="prodcat__li-3"><a href="pc_combined_results.asp?pc_id=9963C21C4CCF4C4B8556E2F8D0ECEF0A" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|pc_combined_results.asp?pc_id=9963C21C4CCF4C4B8556E2F8D0ECEF0A" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|Total Gym Systems " data-key="9963C21C4CCF4C4B8556E2F8D0ECEF0A"><span class=cat-nm>Total Gym Systems </span></a></li><li class="prodcat__li-3"><a href="pc_combined_results.asp?pc_id=C1A3CF636BCB4448ABC8C3295AF5FB2E" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|pc_combined_results.asp?pc_id=C1A3CF636BCB4448ABC8C3295AF5FB2E" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|TRUE Gravity Exercise Equipment " data-key="C1A3CF636BCB4448ABC8C3295AF5FB2E"><span class=cat-nm>TRUE Gravity Exercise Equipment </span></a></li><li class="prodcat__li-3"><a href="/UBE-Upper-Body-Ergometers/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Clinical-Exercise-Units/|/UBE-Upper-Body-Ergometers/" data-parent-name="Medical Exercise Equipment|Clinical Exercise Units|UBE  Upper Body / Ergometers" data-key="1272E3D7E7DC485A8E0ADFBFF63D7700"><span class=cat-nm>UBE  Upper Body / Ergometers</span></a></li></ul></li><li class="prodcat__li-2 "><a href="/Exercise-Products/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/" data-parent-name="Medical Exercise Equipment|Exercise Products" data-key="401ED9A245F44301A507D8CAE2AF58AA"><span class=cat-nm>Exercise Products</span></a><ul class="prodcat__ul-3"><li class="prodcat__li-3"><a href="/Exercise-Balls/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Exercise-Balls/" data-parent-name="Medical Exercise Equipment|Exercise Products|Exercise Balls" data-key="A96DDAA26EB1428C8CE67CE53F51D142"><span class=cat-nm>Exercise Balls</span></a></li><li class="prodcat__li-3"><a href="/Exercise-Bars/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Exercise-Bars/" data-parent-name="Medical Exercise Equipment|Exercise Products|Exercise Bars" data-key="D814108DE6324990B80C66FBDC49E741"><span class=cat-nm>Exercise Bars</span></a></li><li class="prodcat__li-3"><a href="/Exercise-Mats/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Exercise-Mats/" data-parent-name="Medical Exercise Equipment|Exercise Products|Exercise Mats" data-key="7D7F6E4FEB3148549F995AEA13EDEC32"><span class=cat-nm>Exercise Mats</span></a></li><li class="prodcat__li-3"><a href="/Exercise-Tubing/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Exercise-Tubing/" data-parent-name="Medical Exercise Equipment|Exercise Products|Exercise Tubing" data-key="9C140572EC6D436F884055B20386DD14"><span class=cat-nm>Exercise Tubing</span></a></li><li class="prodcat__li-3"><a href="/Medicine-Balls/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Medicine-Balls/" data-parent-name="Medical Exercise Equipment|Exercise Products|Medicine Balls" data-key="B03FC21459A74DBE8BCC8A548549F2DC"><span class=cat-nm>Medicine Balls</span></a></li><li class="prodcat__li-3"><a href="/Pulleys-Exercise/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Pulleys-Exercise/" data-parent-name="Medical Exercise Equipment|Exercise Products|Pulleys / Exercise" data-key="9E4FCD9AE48B4ED7827AC6A4002ABC39"><span class=cat-nm>Pulleys / Exercise</span></a></li><li class="prodcat__li-3"><a href="/Resistance-Bands/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Resistance-Bands/" data-parent-name="Medical Exercise Equipment|Exercise Products|Resistance Bands" data-key="76AF7AB556CE4CE784F5B9642D0F4F5A"><span class=cat-nm>Resistance Bands</span></a></li><li class="prodcat__li-3"><a href="/Stretching-Equipment-Straps/" class="prodcat__a-3" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Products/|/Stretching-Equipment-Straps/" data-parent-name="Medical Exercise Equipment|Exercise Products|Stretching Equipment  & Straps" data-key="2BEBA220045A4726BD8BE495B8B5ECAA"><span class=cat-nm>Stretching Equipment  & Straps</span></a></li></ul></li><li class="prodcat__li-2"><a href="/Exercise-Rail-Systems/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Exercise-Rail-Systems/" data-parent-name="Medical Exercise Equipment|Exercise Rail Systems" data-key="06B56E5510B34FF09849A77123786786"><span class=cat-nm>Exercise Rail Systems</span></a></li><li class="prodcat__li-2"><a href="/Matrix-Exercise-Equipment/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Matrix-Exercise-Equipment/" data-parent-name="Medical Exercise Equipment|Matrix Medical Exercise Equipment" data-key="4B4589800E2E41B39179E0E27C77AA6E"><span class=cat-nm>Matrix Medical Exercise Equipment</span></a></li><li class="prodcat__li-2"><a href="/Protonics_MD/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Protonics_MD/" data-parent-name="Medical Exercise Equipment|Protonics System" data-key="F3D2F8FFD2034FDC842685BA2DC5CAD2"><span class=cat-nm>Protonics System</span></a></li><li class="prodcat__li-2"><a href="/Rebounders/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Rebounders/" data-parent-name="Medical Exercise Equipment|Rebounders" data-key="9C9966BFDC2A447B9B44E303B2FE87C7"><span class=cat-nm>Rebounders</span></a></li><li class="prodcat__li-2"><a href="/Water-Aquatic-Therapy/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Water-Aquatic-Therapy/" data-parent-name="Medical Exercise Equipment|Water / Aquatic Therapy" data-key="95536974036E4E528C5C80745D974D3B"><span class=cat-nm>Water / Aquatic Therapy</span></a></li><li class="prodcat__li-2"><a href="/Yoga-and-Pilates/" class="prodcat__a-2" data-parent-href="/Medical-Exercise-Equipment/|/Yoga-and-Pilates/" data-parent-name="Medical Exercise Equipment|Yoga and Pilates" data-key="FE3AF2B970BD4E758889D6D6574099FC"><span class=cat-nm>Yoga and Pilates</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Modalities/" class="prodcat__a-1" data-parent-href="/Modalities/" data-parent-name="Modalities" data-key="D474FB3021DE4AD0B9253AF868906587"><span class=cat-nm>Modalities</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Diathermy-Machines/" class="prodcat__a-2" data-parent-href="/Modalities/|/Diathermy-Machines/" data-parent-name="Modalities|Diathermy Machines" data-key="853D22450BC546DD81F70509932E5461"><span class=cat-nm>Diathermy Machines</span></a></li><li class="prodcat__li-2"><a href="/Electrotherapy-Combo-Units/" class="prodcat__a-2" data-parent-href="/Modalities/|/Electrotherapy-Combo-Units/" data-parent-name="Modalities|Electrotherapy Combo Units" data-key="8FCFF2EF272C480C87A16C0BA2D0E7DC"><span class=cat-nm>Electrotherapy Combo Units</span></a></li><li class="prodcat__li-2"><a href="/Electrotherapy-Stim-Units/" class="prodcat__a-2" data-parent-href="/Modalities/|/Electrotherapy-Stim-Units/" data-parent-name="Modalities|Electrotherapy Stim Units" data-key="6634B6EEB6AA4C02821C0469FB28ECEC"><span class=cat-nm>Electrotherapy Stim Units</span></a></li><li class="prodcat__li-2"><a href="/Electrotherapy-UltraSound-Units/" class="prodcat__a-2" data-parent-href="/Modalities/|/Electrotherapy-UltraSound-Units/" data-parent-name="Modalities|Electrotherapy UltraSound Units" data-key="AD20EEB39E7C4EAFB20BF10D7D8DA2A4"><span class=cat-nm>Electrotherapy UltraSound Units</span></a></li><li class="prodcat__li-2"><a href="/EMG-Biofeedback-Units/" class="prodcat__a-2" data-parent-href="/Modalities/|/EMG-Biofeedback-Units/" data-parent-name="Modalities|EMG / Biofeedback Units" data-key="C9A2D27222EF49099F98A06550BC46ED"><span class=cat-nm>EMG / Biofeedback Units</span></a></li><li class="prodcat__li-2"><a href="/Fluidotherapy-Machines/" class="prodcat__a-2" data-parent-href="/Modalities/|/Fluidotherapy-Machines/" data-parent-name="Modalities|Fluidotherapy Machines" data-key="F2C2EB860DD043E78293AEEB4CFDBC92"><span class=cat-nm>Fluidotherapy Machines</span></a></li><li class="prodcat__li-2"><a href="/Iontophoresis/" class="prodcat__a-2" data-parent-href="/Modalities/|/Iontophoresis/" data-parent-name="Modalities|Iontophoresis" data-key="2DF8CF43C14347EF98F335822879AF11"><span class=cat-nm>Iontophoresis</span></a></li><li class="prodcat__li-2"><a href="/Laser-Therapy-Equipment/" class="prodcat__a-2" data-parent-href="/Modalities/|/Laser-Therapy-Equipment/" data-parent-name="Modalities|Laser Therapy  " data-key="01D53D4A280E46DF85601CC49DAFC011"><span class=cat-nm>Laser Therapy  </span></a></li><li class="prodcat__li-2"><a href="/Lead-Wire-and-Adaptors-Electrotherapy-Accessories/" class="prodcat__a-2" data-parent-href="/Modalities/|/Lead-Wire-and-Adaptors-Electrotherapy-Accessories/" data-parent-name="Modalities|Lead Wire and Adaptors / Electrotherapy Accessories" data-key="C498EB44E4BB4FB1A5A4A4EAD48BE15A"><span class=cat-nm>Lead Wire and Adaptors / Electrotherapy Accessories</span></a></li><li class="prodcat__li-2"><a href="/Medical-Carts/" class="prodcat__a-2" data-parent-href="/Modalities/|/Medical-Carts/" data-parent-name="Modalities|Medical Carts" data-key="B609F99E97304FCF823E213C4E6257F0"><span class=cat-nm>Medical Carts</span></a></li><li class="prodcat__li-2"><a href="/Portable-Electrotherapy/" class="prodcat__a-2" data-parent-href="/Modalities/|/Portable-Electrotherapy/" data-parent-name="Modalities|Portable Electrotherapy" data-key="0A6C9C0A0DB645E9BD8E8230D918A3FF"><span class=cat-nm>Portable Electrotherapy</span></a></li><li class="prodcat__li-2"><a href="/Richmar-Products/" class="prodcat__a-2" data-parent-href="/Modalities/|/Richmar-Products/" data-parent-name="Modalities|Richmar Products" data-key="6D65AE4D0F4F40E189D7AC0D02B2430E"><span class=cat-nm>Richmar Products</span></a></li><li class="prodcat__li-2"><a href="/Deep-Oscillation/" class="prodcat__a-2" data-parent-href="/Modalities/|/Deep-Oscillation/" data-parent-name="Modalities|Richmar THERADOT&reg; - Deep Oscillation Therapy Device" data-key="09632882CFF54901B0BFD08D8F13B3CB"><span class=cat-nm>Richmar THERADOT&reg; - Deep Oscillation Therapy Device</span></a></li><li class="prodcat__li-2"><a href="pc_combined_results.asp?pc_id=F8D11A393A8C45608AC1E348710B1A60" class="prodcat__a-2" data-parent-href="/Modalities/|pc_combined_results.asp?pc_id=F8D11A393A8C45608AC1E348710B1A60" data-parent-name="Modalities|Shockwave Units " data-key="F8D11A393A8C45608AC1E348710B1A60"><span class=cat-nm>Shockwave Units </span></a></li><li class="prodcat__li-2"><a href="/Tens-Electrodes/" class="prodcat__a-2" data-parent-href="/Modalities/|/Tens-Electrodes/" data-parent-name="Modalities|TENS Units" data-key="4EED92A28BD14CED9F59AB43075A3224"><span class=cat-nm>TENS Units</span></a></li><li class="prodcat__li-2"><a href="/Traction/" class="prodcat__a-2" data-parent-href="/Modalities/|/Traction/" data-parent-name="Modalities|Traction" data-key="75F13348092F4FE7B24DC9E0BB70543A"><span class=cat-nm>Traction</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Orthopedic-Supports/" class="prodcat__a-1" data-parent-href="/Orthopedic-Supports/" data-parent-name="Orthopedic Supports" data-key="F3E3426484DC42E3A241CDF2116B4801"><span class=cat-nm>Orthopedic Supports</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2 "><a href="/Ankle-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Ankle-Supports/" data-parent-name="Orthopedic Supports|Ankle Supports" data-key="DF1BCBB3DC854A1BBA8633E745D03CA7"><span class=cat-nm>Ankle Supports</span></a><ul class="prodcat__ul-3"><li class="prodcat__li-3"><a href="/Lace-Up-Ankle-Supports/" class="prodcat__a-3" data-parent-href="/Orthopedic-Supports/|/Ankle-Supports/|/Lace-Up-Ankle-Supports/" data-parent-name="Orthopedic Supports|Ankle Supports|Lace Up Ankle Supports" data-key="5BC77A3401F944C68E0B979CB57692EB"><span class=cat-nm>Lace Up Ankle Supports</span></a></li></ul></li><li class="prodcat__li-2"><a href="/Arm-Slings/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Arm-Slings/" data-parent-name="Orthopedic Supports|Arm Slings" data-key="B76E4CF0C90E4F2787AC5D4E8BEA4517"><span class=cat-nm>Arm Slings</span></a></li><li class="prodcat__li-2"><a href="/Arthritic--Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Arthritic--Supports/" data-parent-name="Orthopedic Supports|Arthritic  Supports" data-key="8C5967BA4BA545B2BC5D0B228D87E929"><span class=cat-nm>Arthritic  Supports</span></a></li><li class="prodcat__li-2"><a href="/Athletic-Taping-Supplies/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Athletic-Taping-Supplies/" data-parent-name="Orthopedic Supports|Athletic Taping Supplies" data-key="ECE5EF9636F94765883494DBE9C3660B"><span class=cat-nm>Athletic Taping Supplies</span></a></li><li class="prodcat__li-2"><a href="/Back-Lumbar-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Back-Lumbar-Supports/" data-parent-name="Orthopedic Supports|Back / Lumbar Supports" data-key="06AD5B9A660B4AF2924CE24030D02D27"><span class=cat-nm>Back / Lumbar Supports</span></a></li><li class="prodcat__li-2"><a href="/Back-Cushions/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Back-Cushions/" data-parent-name="Orthopedic Supports|Back Cushions" data-key="1D991FDBEC0D4CC2A1A74868628B7FEF"><span class=cat-nm>Back Cushions</span></a></li><li class="prodcat__li-2"><a href="/Cervical-Collars/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Cervical-Collars/" data-parent-name="Orthopedic Supports|Cervical Collars" data-key="F9A1C6D8277A4ADCAADE4DD2BBE4E3F2"><span class=cat-nm>Cervical Collars</span></a></li><li class="prodcat__li-2"><a href="/Elbow-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Elbow-Supports/" data-parent-name="Orthopedic Supports|Elbow Supports" data-key="DC4911850A0F4A3D827F087A078A4AB1"><span class=cat-nm>Elbow Supports</span></a></li><li class="prodcat__li-2"><a href="/Foam-Rollers/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Foam-Rollers/" data-parent-name="Orthopedic Supports|Foam Rollers" data-key="EA6BA8B2CF2A418A88DB7C6C50E0B2F7"><span class=cat-nm>Foam Rollers</span></a></li><li class="prodcat__li-2"><a href="/Hand-and-Finger-Splints/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Hand-and-Finger-Splints/" data-parent-name="Orthopedic Supports|Hand and Finger Splints" data-key="CFFB13E37EEF4EB580ABBC62BD0A4209"><span class=cat-nm>Hand and Finger Splints</span></a></li><li class="prodcat__li-2"><a href="/Kinesiology-Tapes/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Kinesiology-Tapes/" data-parent-name="Orthopedic Supports|Kinesiology Tapes" data-key="8E38F65DFBB5481E88D169CCCFD21E72"><span class=cat-nm>Kinesiology Tapes</span></a></li><li class="prodcat__li-2 "><a href="/Knee-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Knee-Supports/" data-parent-name="Orthopedic Supports|Knee Supports" data-key="DB3F4F378F054565BC74324924EED96D"><span class=cat-nm>Knee Supports</span></a><ul class="prodcat__ul-3"><li class="prodcat__li-3"><a href="/Open-Patella-Knee-Supports/" class="prodcat__a-3" data-parent-href="/Orthopedic-Supports/|/Knee-Supports/|/Open-Patella-Knee-Supports/" data-parent-name="Orthopedic Supports|Knee Supports|Open Patella Knee Supports" data-key="FA299B07549841F8BA93AF23F554F07C"><span class=cat-nm>Open Patella Knee Supports</span></a></li><li class="prodcat__li-3"><a href="/Specialty--Knee-Braces/" class="prodcat__a-3" data-parent-href="/Orthopedic-Supports/|/Knee-Supports/|/Specialty--Knee-Braces/" data-parent-name="Orthopedic Supports|Knee Supports|Specialty  Knee Braces" data-key="EC2C09972F904EF08994CF2AE1835176"><span class=cat-nm>Specialty  Knee Braces</span></a></li></ul></li><li class="prodcat__li-2"><a href="/Lumbar-Rolls/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Lumbar-Rolls/" data-parent-name="Orthopedic Supports|Lumbar Rolls" data-key="BCDAD37AF144434094A44D9F5C405689"><span class=cat-nm>Lumbar Rolls</span></a></li><li class="prodcat__li-2"><a href="/Orthotics-Vasyli/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Orthotics-Vasyli/" data-parent-name="Orthopedic Supports|Orthotics / Vasyli" data-key="598BC49C4D3343B584D16851C794FFE1"><span class=cat-nm>Orthotics / Vasyli</span></a></li><li class="prodcat__li-2"><a href="/Patella-Taping-Products/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Patella-Taping-Products/" data-parent-name="Orthopedic Supports|Patella Taping Products" data-key="B7F37035C9014569AD4AE8523CB0F9DF"><span class=cat-nm>Patella Taping Products</span></a></li><li class="prodcat__li-2"><a href="/Shoulder-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Shoulder-Supports/" data-parent-name="Orthopedic Supports|Shoulder Supports" data-key="913E0F6EEC8742779EA78D4E6CE1CB43"><span class=cat-nm>Shoulder Supports</span></a></li><li class="prodcat__li-2 "><a href="/Specialty-Cervical-Pillows/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Specialty-Cervical-Pillows/" data-parent-name="Orthopedic Supports|Specialty Cervical Pillows" data-key="ED20D56230B34ECDAD1A1C8AE60DFC62"><span class=cat-nm>Specialty Cervical Pillows</span></a></li><li class="prodcat__li-2"><a href="/Thigh-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Thigh-Supports/" data-parent-name="Orthopedic Supports|Thigh Supports" data-key="2B9157DD5854486CB24819FBF9CF060E"><span class=cat-nm>Thigh Supports</span></a></li><li class="prodcat__li-2"><a href="/Wrist-Supports/" class="prodcat__a-2" data-parent-href="/Orthopedic-Supports/|/Wrist-Supports/" data-parent-name="Orthopedic Supports|Wrist Supports" data-key="61B0F4F753714D338BD85FB0624A1D56"><span class=cat-nm>Wrist Supports</span></a></li></ul></li><li class="prodcat__li-1 "><a href="/Sports-Medicine/" class="prodcat__a-1" data-parent-href="/Sports-Medicine/" data-parent-name="Sports Medicine" data-key="AEDCE978214D4B3386B9CCF4A74CAD45"><span class=cat-nm>Sports Medicine</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2 "><a href="/Athletic-Taping-Supplies/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Athletic-Taping-Supplies/" data-parent-name="Sports Medicine|Athletic Taping Supplies" data-key="ECE5EF9636F94765883494DBE9C3660B"><span class=cat-nm>Athletic Taping Supplies</span></a><ul class="prodcat__ul-3"><li class="prodcat__li-3"><a href="/Medical-Tape/" class="prodcat__a-3" data-parent-href="/Sports-Medicine/|/Athletic-Taping-Supplies/|/Medical-Tape/" data-parent-name="Sports Medicine|Athletic Taping Supplies|Medical Tape" data-key="0D31AA87F33445228DF24DF306C04DAC"><span class=cat-nm>Medical Tape</span></a></li></ul></li><li class="prodcat__li-2"><a href="/Bungie-Therapy/Training/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Bungie-Therapy/Training/" data-parent-name="Sports Medicine|Bungie Therapy/Training" data-key="7B1796407B6D479C9A9C9E596BFC73E4"><span class=cat-nm>Bungie Therapy/Training</span></a></li><li class="prodcat__li-2"><a href="/Dry-Needling/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Dry-Needling/" data-parent-name="Sports Medicine|Dry Needling" data-key="87A5F2D12B6E4898BFA618600B1FBD3A"><span class=cat-nm>Dry Needling</span></a></li><li class="prodcat__li-2"><a href="/Game-Ready-Compression/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Game-Ready-Compression/" data-parent-name="Sports Medicine|Game Ready & Compression" data-key="7119EDB99B314677956BACF18C3B7074"><span class=cat-nm>Game Ready & Compression</span></a></li><li class="prodcat__li-2"><a href="/Kinesiology-Tapes/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Kinesiology-Tapes/" data-parent-name="Sports Medicine|Kinesiology Tapes" data-key="8E38F65DFBB5481E88D169CCCFD21E72"><span class=cat-nm>Kinesiology Tapes</span></a></li><li class="prodcat__li-2"><a href="/Rebounders/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Rebounders/" data-parent-name="Sports Medicine|Rebounders" data-key="9C9966BFDC2A447B9B44E303B2FE87C7"><span class=cat-nm>Rebounders</span></a></li><li class="prodcat__li-2"><a href="/Deep-Oscillation/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Deep-Oscillation/" data-parent-name="Sports Medicine|Richmar THERADOT&reg; - Deep Oscillation Therapy Device" data-key="09632882CFF54901B0BFD08D8F13B3CB"><span class=cat-nm>Richmar THERADOT&reg; - Deep Oscillation Therapy Device</span></a></li><li class="prodcat__li-2"><a href="/Sports-Medicine-Whirlpools/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Sports-Medicine-Whirlpools/" data-parent-name="Sports Medicine|Sports Medicine Whirlpools" data-key="00773F3D036746EB89B7315ADBC31429"><span class=cat-nm>Sports Medicine Whirlpools</span></a></li><li class="prodcat__li-2"><a href="/HomeTeam-Training-Room-Tables" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/HomeTeam-Training-Room-Tables" data-parent-name="Sports Medicine|TRAINING ROOM " data-key="596721D3F7954BF899C60EA6D27A8523"><span class=cat-nm>TRAINING ROOM </span></a></li><li class="prodcat__li-2"><a href="/Wound-Care-Products/" class="prodcat__a-2" data-parent-href="/Sports-Medicine/|/Wound-Care-Products/" data-parent-name="Sports Medicine|Wound Care Products" data-key="F15E114D500F4AF6BC3D63139ABFF532"><span class=cat-nm>Wound Care Products</span></a></li></ul></li><li class="prodcat__li-1"><a href="/Whirlpools-Accessories/" class="prodcat__a-1" data-parent-href="/Whirlpools-Accessories/" data-parent-name="Whirlpools and Accessories" data-key="6C3451C809884C27BF97A79E397F7BD7"><span class=cat-nm>Whirlpools and Accessories</span></a></li><li class="prodcat__li-1 "><a href="/PPE-Supplies/" class="prodcat__a-1" data-parent-href="/PPE-Supplies/" data-parent-name="PPE Products" data-key="EEF970E1C80643AC9D1C4B324CBB3BE2"><span class=cat-nm>PPE Products</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2"><a href="/Disinfectant-Cleaning-Products-Wipes/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Disinfectant-Cleaning-Products-Wipes/" data-parent-name="PPE Products|Disinfectant Cleaning Products & Wipes" data-key="D6308480CA574FF8B92C9C41D1143409"><span class=cat-nm>Disinfectant Cleaning Products & Wipes</span></a></li><li class="prodcat__li-2"><a href="/Gloves-Clinical-Exam/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Gloves-Clinical-Exam/" data-parent-name="PPE Products|Gloves / Clinical Exam" data-key="430A36F949D44773A9E4A1718F1725E1"><span class=cat-nm>Gloves / Clinical Exam</span></a></li><li class="prodcat__li-2"><a href="/Hand-Sanitizers/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Hand-Sanitizers/" data-parent-name="PPE Products|Hand Sanitizers" data-key="A066EB6382554F1A87E64829ABB0481C"><span class=cat-nm>Hand Sanitizers</span></a></li><li class="prodcat__li-2"><a href="/Medical-Paper-Supplies/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Medical-Paper-Supplies/" data-parent-name="PPE Products|Medical Paper Supplies" data-key="0F66BCE83EA64BC99851371D302CA98B"><span class=cat-nm>Medical Paper Supplies</span></a></li><li class="prodcat__li-2"><a href="/Patient-Gowns/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Patient-Gowns/" data-parent-name="PPE Products|Patient Gowns" data-key="90C0F03A269449B29CCE24B5FC9588CC"><span class=cat-nm>Patient Gowns</span></a></li><li class="prodcat__li-2"><a href="/Protective-Masks/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Protective-Masks/" data-parent-name="PPE Products|Protective Masks" data-key="3E8F74868C6C4C16A7049602A8C9F2B1"><span class=cat-nm>Protective Masks</span></a></li><li class="prodcat__li-2"><a href="/Towels-and-Clinical-Linens/" class="prodcat__a-2" data-parent-href="/PPE-Supplies/|/Towels-and-Clinical-Linens/" data-parent-name="PPE Products|Towels and Clinical Linens" data-key="3DE680314FD64A41BBD6D1D7A9F80DF8"><span class=cat-nm>Towels and Clinical Linens</span></a></li></ul></li><li class="prodcat__li-1"><a href="/Preferred-Products/" class="prodcat__a-1" data-parent-href="/Preferred-Products/" data-parent-name="Preferred Products" data-key="4FF8E666311F483CA2D18E4CD2E02C01"><span class=cat-nm>Preferred Products</span></a></li><li class="prodcat__li-1"><a href="/Promo/" class="prodcat__a-1" data-parent-href="/Promo/" data-parent-name="Promotions" data-key="98EA39B56E8B42069AC136D8CD4D3084"><span class=cat-nm>Promotions</span></a></li><li class="prodcat__li-1 "><a href="/Physical-Therapy-Tables/" class="prodcat__a-1" data-parent-href="/Physical-Therapy-Tables/" data-parent-name="Physical Therapy Tables" data-key="06F7802A1F214D44A7C34B3460691E63"><span class=cat-nm>Physical Therapy Tables</span></a><ul class="prodcat__ul-2"><li class="prodcat__li-2 "><a href="/ASSIST-hi-lo-tables/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/ASSIST-hi-lo-tables/" data-parent-name="Physical Therapy Tables|ASSIST Hi-Low Tables" data-key="F4B038F8FD314FF5947F1AA094AD3023"><span class=cat-nm>ASSIST Hi-Low Tables</span></a><ul class="prodcat__ul-3"><li class="prodcat__li-3"><a href="/Assist-Clinical-Tables" class="prodcat__a-3" data-parent-href="/Physical-Therapy-Tables/|/ASSIST-hi-lo-tables/|/Assist-Clinical-Tables" data-parent-name="Physical Therapy Tables|ASSIST Hi-Low Tables|Clinical Line" data-key="1C124A449FA74ACAB4B7809A2EFC96AC"><span class=cat-nm>Clinical Line</span></a></li><li class="prodcat__li-3"><a href="/Assist-Table-Accessories" class="prodcat__a-3" data-parent-href="/Physical-Therapy-Tables/|/ASSIST-hi-lo-tables/|/Assist-Table-Accessories" data-parent-name="Physical Therapy Tables|ASSIST Hi-Low Tables|Accessories" data-key="A5E58EC075D0462F8C1FC971C4E52C3E"><span class=cat-nm>Accessories</span></a></li><li class="prodcat__li-3"><a href="/Assist-Table-Parts/" class="prodcat__a-3" data-parent-href="/Physical-Therapy-Tables/|/ASSIST-hi-lo-tables/|/Assist-Table-Parts/" data-parent-name="Physical Therapy Tables|ASSIST Hi-Low Tables|Replacement Parts" data-key="18025EFEC08840818A78159F4858A864"><span class=cat-nm>Replacement Parts</span></a></li><li class="prodcat__li-3"><a href="/Assist-Therapy-Tables" class="prodcat__a-3" data-parent-href="/Physical-Therapy-Tables/|/ASSIST-hi-lo-tables/|/Assist-Therapy-Tables" data-parent-name="Physical Therapy Tables|ASSIST Hi-Low Tables|Therapy Line" data-key="0222048CCDC143139C8D246ADE1EC64C"><span class=cat-nm>Therapy Line</span></a></li><li class="prodcat__li-3"><a href="/Assist-Changing-Tables" class="prodcat__a-3" data-parent-href="/Physical-Therapy-Tables/|/ASSIST-hi-lo-tables/|/Assist-Changing-Tables" data-parent-name="Physical Therapy Tables|ASSIST Hi-Low Tables|Changing Tables" data-key="3B95FA1D0B7F40ED91FF5FCA61237B49"><span class=cat-nm>Changing Tables</span></a></li></ul></li><li class="prodcat__li-2"><a href="/Treatment-Tables/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Treatment-Tables/" data-parent-name="Physical Therapy Tables|Treatment Tables" data-key="0DEA6ADBC4CE40FE8DA02718FA362DAF"><span class=cat-nm>Treatment Tables</span></a></li><li class="prodcat__li-2"><a href="/Mat-Tables/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Mat-Tables/" data-parent-name="Physical Therapy Tables|Mat Tables" data-key="742EB90DE1A146668B7075462332EA49"><span class=cat-nm>Mat Tables</span></a></li><li class="prodcat__li-2"><a href="/Traction-Table-Units-and-Accessories/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Traction-Table-Units-and-Accessories/" data-parent-name="Physical Therapy Tables|Traction Table, Units and Accessories" data-key="BDF9BBB4A9D044DFB83BABBD9B659742"><span class=cat-nm>Traction Table, Units and Accessories</span></a></li><li class="prodcat__li-2"><a href="/Space-Saver-Tables/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Space-Saver-Tables/" data-parent-name="Physical Therapy Tables|Space Saver Tables" data-key="F2D93D69FA6441718531A1C44C72BB81"><span class=cat-nm>Space Saver Tables</span></a></li><li class="prodcat__li-2"><a href="/Tilt-Tables/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Tilt-Tables/" data-parent-name="Physical Therapy Tables|Tilt Tables" data-key="9EFF21CEE9FA40189C9C093F2BF67F2B"><span class=cat-nm>Tilt Tables</span></a></li><li class="prodcat__li-2"><a href="/Taping-Tables/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Taping-Tables/" data-parent-name="Physical Therapy Tables|Taping Tables" data-key="20D63C5162AD4B3887E5F6EA284299DD"><span class=cat-nm>Taping Tables</span></a></li><li class="prodcat__li-2"><a href="/Bariatric-Equipment/" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Bariatric-Equipment/" data-parent-name="Physical Therapy Tables|Bariatric Equipment" data-key="B7F7801338FD4171BA3FF92CB1F68C24"><span class=cat-nm>Bariatric Equipment</span></a></li><li class="prodcat__li-2"><a href="/Assist-Therapy-Tables" class="prodcat__a-2" data-parent-href="/Physical-Therapy-Tables/|/Assist-Therapy-Tables" data-parent-name="Physical Therapy Tables|Therapy Line" data-key="0222048CCDC143139C8D246ADE1EC64C"><span class=cat-nm>Therapy Line</span></a></li></ul></li></ul>
    </li>
</ul>

    <ul id="header__signin" class="header__signin linkset click-persist">
        <li class="">
            
                <a id="header__signin-open" 
                    class="header__signin-open global-modal" 
                    data-size="small" 
                    data-backdrop="static"
                    title="Sign in to Your Account"
                    href="security_logon.asp?autopage=%2FDefault%2Easp%3F&modal=1">
                    <i class="icon-signin"></i> Sign In
                </a>
            
        </li>
    </ul>
    <ul id="header__cart-preview" class="header__cart-preview linkset click-persist js-click-outside-to-close">
        <li class="link-parent">
            <a class="header__cart-preview__toggle" href="#0">
                <i class="icon-shopping-cart"></i> <span class="hidden-xs hidden-sm">My</span> Cart
                <span id="cart_window_qty" class="cart_window_qty badge">0</span>
            </a>
            <ul>
                <li class="app-minicart" id="cart_window_incl">
                    

	<div id="cart_window" class="cart-preview cart_window">
		

				<script>
					var cartQtyTarg = '#cart_window_qty',
						cartQtyTotal = 0,
						cartWinTarg = '#cart_window_incl';
				</script>

				<div class="cart-empty-text muted">Your shopping cart is empty.</div>

				
					<div class="controls">
						<a href="/showcart.asp?o_key=75C67D9955EF4D619AD72B3087D9C082" class="btn btn-block btn-primary view-cart-button">
							<i class="icon-shopping-cart"></i> View &amp; Edit Cart
						</a>
					</div>
				

		<script type="text/javascript">

			jQuery(function(){
				// Set the template cart qty on initial load
				fncUpdateTemplateQty(cartQtyTarg, cartQtyTotal);
			});

			// Function to update the template qty value
			function fncUpdateTemplateQty(targ, total) {
				jQuery(targ).text(total);
			}

			// Function to remove an item from the cart window
			function fncCartWinRemove(sUnqID, sConfirmText) {
				var bUseRemoveMsg = true;

				if(bUseRemoveMsg){
					var okay = confirm(sConfirmText);
				}
				else{
					okay = true;
				}

				if (okay) {
					jQuery('#li_'+sUnqID).remove();
					try {
						jQuery.ajax({
							url: 'i_i_add_to_cart.asp',
							data: 'type=v200remove&ajax=returnJSON&rkey='+sUnqID,
							type: 'GET',
							dataType: "json",
							success: function(jsonOrder) {
								fncCartRefresh(jsonOrder[1].item_count, jsonOrder[1].o_total);
							}
						});
					} catch (err) {
						//alert(err.message);
						location.reload();
					}
				}
			} //-function fncCartWinRemove(sUnqID)

			// Refreshes the (#) for the cart items count
			function fncCartRefresh(item_count, o_total) {
				if (typeof item_count == "undefined") {
					try {
						jQuery.ajax({
							url: 'shopping_cart_window.asp',
							data: 'cartwindowajax=getcart',
							type: 'GET',
							dataType: 'json',
							error: function (jqXHR, textStatus, errorThrown) {
								alert('Error! ' + errorThrown + ' ' + textStatus);
								},
							success: function (oData) {
								var cart = oData || {};
								if (typeof cart != "undefined") {
									//console.log(cart);
									jQuery(cartQtyTarg).html(cart.items);
									jQuery("#cart_window_subtotal").html(cart.total);
									//return true;
								}
								fncReloadCartWindow();
							}
						});
					} catch(err) {
						alert(err.message);
					}
				} else {
					if (jQuery(cartQtyTarg).length==1) {
						//console.log(cart);
						jQuery(cartQtyTarg).html(item_count);
						jQuery("#cart_window_subtotal").html(o_total);
						//return true;
					}
					fncReloadCartWindow();
				}
			} //- function fncCartRefresh()

			// Reload the spend allowance display
			function fncReloadSpendAllowanceDisplay() {
				try {
					jQuery.ajax({
						url: 'spend_allowance_display.asp',
						data: 'ajax=1&ajaxaction=drawspendallowance',
						type: 'GET',
						success: function(response) {
							jQuery('#cart_total').html(response.cartTotal);
							jQuery('#remaining_allowance').html(response.remainingAllowance);
						},
						error: function(jqXHR, textStatus, errorThrown) {
							alert('Error! ' + errorThrown + ' ' + textStatus);
						}
					});
				} catch(err) {
					alert(err.message);
				}
			} //- function fncReloadSpendAllowanceDisplay()

			// Reload the contents of the cart window
			function fncReloadCartWindow() {
				var bSpendAllowanceEnabled = false;
				try {
					jQuery.ajax({
						url: 'shopping_cart_window.asp',
						data: 'cartwindowajax=ajaxcall',
						type: 'get',
						success: function (oData) {
							jQuery(cartWinTarg).html(oData);
							//fncUpdateTemplateQty(cartQtyTarg, cartQtyTotal);
							$(window).trigger('cartWindowUpdated');
							if (bSpendAllowanceEnabled) {
								fncReloadSpendAllowanceDisplay();
							}
							return true;
						}
					});
				} catch(err) {
					alert(err.message);
				}
			} //-function fncReloadCartWindow()

			function fncConfirmEmptyCart() {
				if(confirm("Are you sure you want to empty your cart?")) {
					fncEmptyCart();
				}
			}

			function fncEmptyCart() {
				jQuery.ajax({
					url: 'shopping_cart_window.asp',
					data: 'pageaction=empty_cart',
					type: 'get',
					success: fncReloadCartWindow
				});
			}

			

		</script>

	</div>
	<!-- /#cart_window -->
	
                </li>
            </ul>
        </li>
    </ul>

        </nav>
    </div>
</div>
    <div class="header__hero-search">
        <div class="header__hero-search__wrap">
            <div class="header__hero-search__container">
                    <h2 class="header__hero-search__header">Search Our Products</h2>

		<form id="frmUnivSearch" class="u-search-form control-group" method="post" action="">
				

				<span class="u-search-group u-search-text">
					<input
						type="text"
						name="u_search_text"
						id="u_search_text"
						class="input-search"
						placeholder="Search..."
						value=""
						autocomplete="off"
						autocorrect="off"
						autocapitalize="off"
						spellcheck="false"
						aria-label="Search Text"
					/>
				</span>

				

				<span class="u-search-group u-search-droplist">
					<select name="u_search_type" id="u_search_type" class=" hide" aria-label="Search Type">
					<option value="pc_combined_results.asp?search_prod=((searchlike~p.sku~<keyword>|Or|searchlike~p.nm~<keyword>|Or|searchlike~p.child_skus~<keyword>|Or|searchlike~p.child_nms~<keyword>|Or|searchlike~p.ds~<keyword>|Or|searchlike~p.search_terms~<keyword>|Or|searchlike~p.searchfield1~<keyword>|Or|searchlike~p.searchfield5~<keyword>)|Or|searchlike~p.child_rollup_search_terms~<keyword>|Or|searchlike~p.search_terms~<keyword>)&search_keyword=<keyword>&ddtloaded=1">Products</option><option value="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>)&s=<keyword>&sfield=searchall&ddtloaded=1">Orders</option><option value="backorders.asp?eosoh.order_date_date_from=&eosoh.order_date_date_to=&group=&s=<keyword>&sfield=searchall&rpp=50&ddtloaded=1&pagesize=50&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>))&page=1&ddt=1&ddtloaded=1">Backorders</option><option value="shipments.asp?ship_date_date_from=&ship_date_date_to=&group=&s=<keyword>&sfield=searchall&rpp=50&ddtloaded=1&pagesize=50&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>))&page=1&ddt=1">Shipments</option><option value="invoices.asp?search2=(searchlike~eoih.ref_id~<keyword>|OR|searchlike~invoice_date~<keyword>|OR|searchlike~eoih.status~<keyword>|OR|searchlike~eoih.po_number~<keyword>|OR|searchlike~eoih.sales_order_number~<keyword>|OR|searchlike~invoice_due~<keyword>)&s=<keyword>&sfield=searchall&ddtloaded=1">Invoices</option><option value="my_addresses.asp?s=<keyword>&sfield=searchall&rpp=50&ddtloaded=1&pagesize=50&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>))&page=1&ddt=1&ddtloaded=1">Addresses</option><option value="payments.asp?sortby=date_received&sortorder=desc&s=<keyword>&sfield=searchall&pagesize=100&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>))&ddtloaded=1">Payments</option><option value="product_stock_ddt.asp?s=<keyword>&sfield=searchall&search2=((searchlike~p.nm~<keyword>%7COR%7Csearchlike~p.sku~<keyword>%7COR%7Csearchlike~p.retail_price~<keyword>))">Price List</option><option value="favorites_lists.asp?s=<keyword>&sfield=searchall&search2=((searchlike~fl.nm~<keyword>))&ddtloaded=1">Favorite Lists</option>				
					</select>
				</span>

				<span class="u-search-group u-search-btn">
					
						<button type="submit" name="u_search_submit" id="u_search_submit" class="btn btn-primary header__search__button" aria-label="Search">
							<i class="icon-search"></i>
						</button>
				</span><input type="hidden" name="search_tip_url" id="search_tip_url" value="" />
		</form>
		
		<script type="application/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 modal=1 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://electro-medical.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';

				/*
				* 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';

				/*
				* Add modalaction to redirect url if populated
				* @author	ejohnston
				* @since	11/18/2022
				* @var		string
				*/
				var sModalAction   				= "";

				/*
				* Website name
				* @author	johns
				* @since	07/26/2012
				* @var		string
				*/
				var sSitename					= 'electromed2';

				var sProductSearchTerm = 'products';
				var bTrimSearchTerm = false;

				var isWorkerDomain = false;

			/**
			* This function handles the form submission.
			*
			* @author		seanm
			* @since		??
			*
			* @author		johns
			* @modified	6/28/2012
			* 
			* @return		void
			*/		
			function fncProcessUniversalSearch(searchTerm, redirect = true) {
				var sPrepopValues  = '';
				var sDelimiter     = '?';
				var sNewSearchPage = '';
				var sSearchType    = '';
				var	sRedirectUrl   = '';
				var sSearchTerm    = jQuery('#u_search_text').val()
				if(searchTerm){ sSearchTerm = searchTerm }

				if (bTrimSearchTerm)
					sSearchTerm = $.trim(sSearchTerm);

				sSearchTerm = encodeURIComponent(sSearchTerm);

				jQuery('#u_search_text').attr('disabled', true);
				jQuery('#u_search_type').attr('disabled', true);
				jQuery('#u_search_submit').attr('disabled', true);

				sSearchType = jQuery('#u_search_type option:selected').text().toLowerCase();

				if ( bUseSplitTermSearching && sSearchType == sProductSearchTerm ) {
					sNewSearchPage = fncBuildSplitTermSearchPage ( sSearchTerm, sSearchType );
				} else {
					querystringTerm = sSearchTerm.replaceAll('(','\\(').replaceAll(')','\\)');
					sNewSearchPage = jQuery('#u_search_type option:selected').val().replace(/<keyword>/ig, querystringTerm);
				} 
				
				/*
				* If there's already a ?, we need to make sure we don't 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 = '/' + 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 += '&modal=1';
				}

				if(sModalAction) {
					sRedirectUrl += '&modalaction=' + sModalAction;
				}

				var config = {
					searchTerm: sSearchTerm,
					url: sRedirectUrl
				};

				runHook('processUniversalSearchUrl',config);
				
				if(!redirect){
					return config.url;
				}else{
					window.location = config.url;
				}
			} //- 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 + '?pageaction=logsearch&SearchFormAjax=1',
					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(',');
				
				sSearchTerms = sSearchTerms.replaceAll('(','\\(').replaceAll(')','\\)')
				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.terms[i];
						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.oSearch[sOriginalTerm] );

							/*
							* 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.oSearch[ui.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~' + aFieldsToCheck[iFieldCounter] + '~' + encodeURIComponent(aSearchTerms[iTermCounter]) + ')';
						
						/*
						* 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([]);
				}
			});

			jQuery(function() {
				if(utils && utils.getParameter('autosearch') == '1'){
					fncProcessUniversalSearch();
				}
			});
		</script>
            </div>
        </div>	
    </div>
</header>
        <div id="home-description" class="home-description">
            <div class="container-fluid">
                <!-- Home Description (Generic) -->
                <p dir="ltr" style="text-align: center;">Elevate your practice with our cutting-edge rehabilitation solutions! With over 40 years of pioneering innovation, we empower clinic owners to deliver faster, more effective patient recoveries. <b data-olk-copy-source="MessageBody">If you are a healthcare professional, register for an account and we will approve you for special discounted pricing.<span> </span></b><span>&nbsp;&nbsp;</span><a href="https://electro-medical.com/content/create-account.asp/"><span style="color: #ffffff;"><strong><u>Get Started</u></strong></span></a></p>
            </div>
        </div> 
            <div id="home-slides" class="container-fluid">

			<div id="slide_show_Main" class="carousel slide">
				<div id="carousel_slide" class="carousel-inner">

							<div class="item active" >
											<a href="https://electro-medical.com/BIOTONE_DPC/"><img src="https://d29eekna00jloo.cloudfront.net/images/biotone%20banner%204.jpg?v=3975201667" alt="BioTone Special" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/TheraTouch/"><img src="https://d29eekna00jloo.cloudfront.net/images/bannercx4-6-24.jpg?v=3975201667" alt="" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/Protonics_G3_Sport/"><img src="https://d29eekna00jloo.cloudfront.net/images/protonics_banner.png?v=3975201667" alt="" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/ASSIST-hi-lo-tables/"><img src="https://d29eekna00jloo.cloudfront.net/images/assist%20banner.png?v=3975201667" alt="" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/Richmar-Products/"><img src="https://d29eekna00jloo.cloudfront.net/images/banner%20rmii%20v2.jpg?v=3975201667" alt="" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/K-Tape-Original-Kinesiology-Tape/"><img src="https://d29eekna00jloo.cloudfront.net/images/k-tape_my_skin_logo_slide.jpg?v=3975201667" alt="" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/Game-Ready-Compression/"><img src="https://d29eekna00jloo.cloudfront.net/images/gr%20banner.jpg?v=3975201667" alt="" class=""></a>

							</div>

							<div class="item " >
											<a href="https://electro-medical.com/SW1/"><img src="https://d29eekna00jloo.cloudfront.net/images/sw1%20banner%20a.jpg?v=3975201667" alt="New Richmar SW1 Shockwave Therapy" class=""></a>

							</div>
					
				</div>

				
					<a href="#slide_show_Main" class="carousel-control left" data-slide="prev">&lsaquo;</a>
					<a href="#slide_show_Main" class="carousel-control right" data-slide="next">&rsaquo;</a>

					<ol class="carousel-indicators">
								<li class="active" data-target="#slide_show_Main" data-slide-to="0">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="1">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="2">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="3">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="4">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="5">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="6">
								</li>
								<li class="" data-target="#slide_show_Main" data-slide-to="7">
								</li>
					</ol>

			</div>

			<script>
				$(function(){
					$('#slide_show_Main').carousel({interval:6000});
				});
			</script>
            </div>
        <div id="home-cat-tiles" class="home-cat-tiles">
            <div class="container-fluid">
                <div class="row-fluid">
                    <!-- Home Categories (Generic) -->
                    <div class="home-cat-tiles__wrap">
<div class="home-cat-tiles__col home-cat-tiles__col1">
<div class="home-cat-tiles__tile tile-1">
<div class="tile-bg tile-bg-1" style="background-image: url('images/092862.jpeg');">&nbsp;</div>
<a href="https://electro-medical.com/Modalities/">
<h3><span style="color: #000000;">Modalities</span></h3>
</a></div>
<div class="home-cat-tiles__2col-wrap">
<div class="home-cat-tiles__tile tile-2">
<div class="tile-bg tile-bg-2" style="background-image: url('images/combo-storage-rack-0271280.jpg');">&nbsp;</div>
<a href="https://electro-medical.com/Clinical-Equipment/">
<h3><span style="color: #ffffff;">Clinical Equipment</span></h3>
</a></div>
<div class="home-cat-tiles__tile tile-3">
<div class="tile-bg tile-bg-3" style="background-image: url('images/karaband.jpg');">&nbsp;</div>
<a href="https://electro-medical.com/Clinical-Supplies/">
<h3><span style="color: #000000;">Clinical Supplies</span></h3>
</a></div>
</div>
</div>
<div class="home-cat-tiles__col home-cat-tiles__col2">
<div class="home-cat-tiles__tile tile-4">
<div class="tile-bg tile-bg-4" style="background-image: url('images/stsx3 n.jpg');">&nbsp;</div>
<a title="Physical Therapy Tables" href="https://electro-medical.com/Physical-Therapy-Tables/">
<h3><span style="color: #000000;">Physical Therapy Tables</span></h3>
</a></div>
<div class="home-cat-tiles__2col-wrap">
<div class="home-cat-tiles__tile tile-5">
<div class="tile-bg tile-bg-5" style="background-image: url('images/DryNeedles.jpg');">&nbsp;</div>
<a href="https://electro-medical.com/Dry-Needling/">
<h3><span style="color: #000000;">Dry Needling</span></h3>
</a></div>
<div class="home-cat-tiles__tile tile-6">
<div class="tile-bg tile-bg-6" style="background-image: url('images/Game.jpg');">&nbsp;</div>
<a href="https://electro-medical.com/Sports-Medicine/">
<h3><span style="color: #ffffff;">Sports Medicine</span></h3>
</a></div>
</div>
</div>
</div>
                </div>
            </div>
        </div>
            <h2 class="trending-products__title">NEW and Trending Products</h2>

<div id="page-main" class="page-main">
    <div class="container-fluid">

<script>
var timerStart = Date.now();  
var lastElapsed = 0; 
var pageHitDate = new Date();
var pageLoad = {
    pageHitKey: '0CE70C02D68543199A331E85E1180AB6',
	sessionId: '022507AF5A994426A3DFC3B29B01E852',
	orderId: '',
	createDate: (pageHitDate.getMonth()+1) + "/"
                + pageHitDate.getDate() + "/" 
                + pageHitDate.getFullYear() + " "  
                + pageHitDate.getHours() + ":"  
                + pageHitDate.getMinutes() + ":" 
                + pageHitDate.getSeconds(),
    priorTimeFrom: '',
    priorTime: '',
    urlRoot: 'electro-medical.com',
    pageName: 'Default.asp',
    uri: window.location.href,
	querystring: '',
	logs: [],
    clientTime: 0,
    serverTime: 0,
	totalTime: 0,
    dbReadCount: 0,
    dbWriteCount: 0
}; 

function addTimer(s) {
	var elapsed = (Date.now()-timerStart); //KEEP milliseconds
	var log = {
        source: 3,
        stepWithinSource: pageLoad.logs.filter( function(obj) { obj.source === 3 }).length,
        nickname: s,
        stepTime: elapsed - lastElapsed,
        cumulativeTime: elapsed
	};
	pageLoad.logs.push(log);
	lastElapsed = elapsed;
}

function logPageLoad() {
    if(pageLoad.logs.length > 0) {
        //sum the server-side, object, & client-side times onto the header.
        var serverTime=0;
        var maxClientSide=0;
        var len = pageLoad.logs.length-1;
        $.each(pageLoad.logs,function(i,o){
            if(o.source==0) { //server-side`
                serverTime=serverTime+o.cumulativeTime;
                pageLoad.dbReadCount += o.dbReadCount;
                pageLoad.dbWriteCount += o.dbWriteCount;
            /*} else if(o.source==2) { //object.. but these times are actually included in the client-side time since it is an ajax call. Don't add it twice. */
            } else if(o.source==3 && o.cumulativeTime > maxClientSide) { // on the last client-side record
                maxClientSide=o.cumulativeTime;
            }
        });
        var pt = pageLoad.priorTime;
        if(pt != "" && !isNaN(pt)){
            pageLoad.priorTime = parseFloat(pt);           
        } else {
            pageLoad.priorTime = 0;
        }
        pageLoad.serverTime = serverTime;
        pageLoad.clientTime = maxClientSide
        pageLoad.totalTime = parseInt(serverTime + maxClientSide + pageLoad.priorTime); //trim decimals
        $.ajax({
            url: '/api/timers/paymentpage/0CE70C02D68543199A331E85E1180AB6',
            data: JSON.stringify(pageLoad),
            type: "POST",
            contentType: "application/json"
        });
        drawPageHitData();
        pageLoad.logs = []; //<-- this is cleared so that the page hit isn't logged more than once.. See containing IF block...
    }
}

function drawPageHitData() {
    
}

function toSecString(ms) {
    var s = (parseInt(ms*10)/10); //only keep 1 decimal
    s = parseInt(s) / 1000;

    return s + "sec(s)";
}

function addPageLoadData(data) {
    /*
    OO data is an object with 3 props: reads, writes, details[]
    */
    if(data.reads) {
        pageLoad.dbReadCount += data.reads;
    }
    if(data.writes) {
        pageLoad.dbWriteCount += data.writes;
    }
    if(data.details) {
        pageLoad.logs = pageLoad.logs.concat(data.details);
    } 
}

addTimer('master top');
</script>

			<div id="wpc_featured_products">
				
			<div class="owl-carousel owl-theme thumbnails">

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="Alpha-Class-4-Laser-Package"><img src="https://d29eekna00jloo.cloudfront.net/images/alpha.png?v=3975201667" title="ALPHA Class IV Laser Therapy Package" alt="ALPHA Class IV Laser Therapy Package" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="Alpha-Class-4-Laser-Package" class="">ALPHA Class IV Laser Therapy Package</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="medsurg-Postop-shoe/"><img src="https://d29eekna00jloo.cloudfront.net/images/medsurg.jpg?v=3975201667" title="Darco MedSurg&reg; -Post-Op Shoe" alt="Darco MedSurg&reg; -Post-Op Shoe" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="medsurg-Postop-shoe/" class="">Darco MedSurg&reg; -Post-Op Shoe</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/inNewin-Kinesio-Classic-2in-X-55Yd-Purple-1-Roll-090293/"><img src="https://d29eekna00jloo.cloudfront.net/images/090293.jpg?v=3975201667" title="KINESIO CLASSIC 2&quot; x 5.5yd    PURPLE  1 ROLL  " alt="KINESIO CLASSIC 2" x 5.5yd    PURPLE  1 ROLL" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/inNewin-Kinesio-Classic-2in-X-55Yd-Purple-1-Roll-090293/" class="">KINESIO CLASSIC 2&quot; x 5.5yd    PURPLE  1 ROLL  </a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="Protonics_MD"><img src="https://d29eekna00jloo.cloudfront.net/images/pgs%20ps-md-pak1%20left.jpg?v=3975201667" title="The Protonics&reg; MD+ System " alt="The Protonics&reg; MD+ System" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="Protonics_MD" class="">The Protonics&reg; MD+ System </a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="Protonics_G3_Sport"><img src="https://d29eekna00jloo.cloudfront.net/images/g3%20sport%20%203.jpg?v=3975201667" title="The Protonics&reg; PRO G3 SYSTEM, OTC Individual System " alt="The Protonics&reg; PRO G3 SYSTEM, OTC Individual System" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="Protonics_G3_Sport" class="">The Protonics&reg; PRO G3 SYSTEM, OTC Individual System </a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="KARATRODE/"><img src="https://d29eekna00jloo.cloudfront.net/images/cloth-backed-electrodes-na203-340ea0.jpg?v=3975201667" title="Karatrode Electrodes  Cloth Backed Electrodes" alt="Karatrode Electrodes  Cloth Backed Electrodes" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="KARATRODE/" class="">Karatrode Electrodes  Cloth Backed Electrodes</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="EMG-PRO"><img src="https://d29eekna00jloo.cloudfront.net/images/dqemg%20.jpg?v=3975201667" title="RICHMAR EMG-PRO Biofeedback Device " alt="RICHMAR EMG-PRO Biofeedback Device" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="EMG-PRO" class="">RICHMAR EMG-PRO Biofeedback Device </a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="KaraBand/"><img src="https://d29eekna00jloo.cloudfront.net/images/karabandthumb.jpg?v=3975201667" title="Kara-Band Latex-Free Exercise Band" alt="Kara-Band Latex-Free Exercise Band" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="KaraBand/" class="">Kara-Band Latex-Free Exercise Band</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="KTape/"><img src="https://d29eekna00jloo.cloudfront.net/images/ktape%204%20new.jpg?v=3975201667" title="K-TAPE&reg; Original Kinesiology Tape" alt="K-TAPE&reg; Original Kinesiology Tape" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="KTape/" class="">K-TAPE&reg; Original Kinesiology Tape</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="PTSTOOLS/"><img src="https://d29eekna00jloo.cloudfront.net/images/pneumatic-lift-stool-0101030.jpg?v=3975201667" title="Pneumatic Lift Stool, Black" alt="Pneumatic Lift Stool, Black" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="PTSTOOLS/" class="">Pneumatic Lift Stool, Black</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/Relief-Pak-Heating-Unit-4-Pack-Unit-RP4/"><img src="https://d29eekna00jloo.cloudfront.net/images/11-1981_thumb.jpg?v=3975201667" title="Relief Pak Heating Unit, 4 Pack Unit" alt="Relief Pak Heating Unit, 4 Pack Unit" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/Relief-Pak-Heating-Unit-4-Pack-Unit-RP4/" class="">Relief Pak Heating Unit, 4 Pack Unit</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="SW1"><img src="https://d29eekna00jloo.cloudfront.net/images/sw1.png?v=3975201667" title="Richmar THERATOUCH&reg; - SW1 Portable RADIAL Shockwave Device" alt="Richmar TheraTouch SW1 Portable Shockwave" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="SW1" class="">Richmar THERATOUCH&reg; - SW1 Portable RADIAL Shockwave Device</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/Richmar-TheratouchandReg-Ux2-Dual-Ultrasound-Unit-DQ2000/"><img src="https://d29eekna00jloo.cloudfront.net/images/dq2000.png?v=3975201667" title="Richmar TheraTouch&reg; UX2 Dual Ultrasound Unit" alt="DQ2000 THERATOUCH DUAL US" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/Richmar-TheratouchandReg-Ux2-Dual-Ultrasound-Unit-DQ2000/" class="">Richmar TheraTouch&reg; UX2 Dual Ultrasound Unit</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="TENS3000/"><img src="https://d29eekna00jloo.cloudfront.net/images/030078%206.jpg?v=3975201667" title="TENS UNIT  2-Channel with Case" alt="TENS UNIT  2-Channel with Case" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="TENS3000/" class="">TENS UNIT  2-Channel with Case</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="TorexColdPacks/"><img src="https://d29eekna00jloo.cloudfront.net/images/thumbtorex-hot-cold-flat-packs-0207110.jpg?v=3975201667" title="Torex&reg;  Professional Cold Flat Packs" alt="Torex&reg;  Professional Cold Flat Packs" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="TorexColdPacks/" class="">Torex&reg;  Professional Cold Flat Packs</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="KinesoSTRONG/"><img src="https://d29eekna00jloo.cloudfront.net/images/090290.jpg?v=3975201667" title="KINESIO TEX CLASSIC STRONG  BLACK  2&quot; x  16.4 YD 1 ROLL " alt="KINESIO TEX CLASSIC STRONG  BLACK  2" x  16.4 YD 1 ROLL" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="KinesoSTRONG/" class="">KINESIO TEX CLASSIC STRONG  BLACK  2&quot; x  16.4 YD 1 ROLL </a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="TorexSleeves/"><img src="https://d29eekna00jloo.cloudfront.net/images/thumbtorex-hot-cold-roll-on-sleeve-medium-0212370.jpg?v=3975201667" title="Torex&reg;  Hot/Cold Roll-On Sleeves" alt="Torex&reg;  Hot/Cold Roll-On Sleeves" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="TorexSleeves/" class="">Torex&reg;  Hot/Cold Roll-On Sleeves</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="CLEARGEL/"><img src="https://d29eekna00jloo.cloudfront.net/images/022563%20c.jpg?v=3975201667" title="CLEAR ULTRASOUND GEL" alt="CLEAR ULTRASOUND GEL" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="CLEARGEL/" class="">CLEAR ULTRASOUND GEL</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="CROSSTAPE/"><img src="https://d29eekna00jloo.cloudfront.net/images/k200-all.jpg?v=3975201667" title="K-TAPE CROSSTAPE<sup>&reg;</sup> for CROSSPUNCTURE<sup>&reg;</sup> Therapy" alt="K-TAPE CROSSTAPE<sup>&reg;</sup> for CROSSPUNCTURE<sup>&reg;</sup> Therapy" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="CROSSTAPE/" class="">K-TAPE CROSSTAPE<sup>&reg;</sup> for CROSSPUNCTURE<sup>&reg;</sup> Therapy</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="CanDoTwist-n-Bend/"><img src="https://d29eekna00jloo.cloudfront.net/images/10-1516.jpg?v=3975201667" title="CanDo Twist-n-Bend Flexible Exercise Bars - 12&quot;  " alt="CanDo Twist-n-Bend Flexible Exercise Bars - 12"  " class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="CanDoTwist-n-Bend/" class="">CanDo Twist-n-Bend Flexible Exercise Bars - 12&quot;  </a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/Rehab-Pro-Pulley-3-In-1-Functional-Trainer-6-1-and-1-1-Ratio-RPP-FT/"><img src="https://d29eekna00jloo.cloudfront.net/images/100903%20new.jpg?v=3975201667" title="REHAB PRO PULLEY 3 in 1 FUNCTIONAL  TRAINER -  6:1 & 1:1 Ratio" alt="REHAB PRO PULLEY 3 in 1 FUNCTIONAL  TRAINER -  6:1 & 1:1 Ratio" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/Rehab-Pro-Pulley-3-In-1-Functional-Trainer-6-1-and-1-1-Ratio-RPP-FT/" class="">REHAB PRO PULLEY 3 in 1 FUNCTIONAL  TRAINER -  6:1 & 1:1 Ratio</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/inNewin-Lumin-Wand-Uv-Sanitizer-LM5000/"><img src="https://d29eekna00jloo.cloudfront.net/images/lw5000.jpeg?v=3975201667" title="LUMIN WAND UV SANITIZER" alt="LUMIN WAND UV SANITIZER" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/inNewin-Lumin-Wand-Uv-Sanitizer-LM5000/" class="">LUMIN WAND UV SANITIZER</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/Scifit-Pro-2-Total-Body-Ergometer-PRO2/"><img src="https://d29eekna00jloo.cloudfront.net/images/thumbscifit-pro-2-total-body-ergometer-fixed-seat-pro232-int0.jpg?v=3975201667" title="SCIFIT PRO 2 Total Body Ergometer" alt="SCIFIT PRO 2 Total Body Ergometer" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/Scifit-Pro-2-Total-Body-Ergometer-PRO2/" class="">SCIFIT PRO 2 Total Body Ergometer</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="Vector/"><img src="https://d29eekna00jloo.cloudfront.net/images/vect%201.jpg?v=3975201667" title="Kayezen VECTOR Resistance Systems Kit and Accessories" alt="Kayezen VECTOR Resistance Systems Kit and Accessories" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="Vector/" class="">Kayezen VECTOR Resistance Systems Kit and Accessories</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="ArcaRays/"><img src="https://d29eekna00jloo.cloudfront.net/images/100150.jpg?v=3975201667" title="ARCARAYS CORE BALANCE PEDALS / STEPS" alt="ARCARAYS CORE BALANCE PEDALS / STEPS" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="ArcaRays/" class="">ARCARAYS CORE BALANCE PEDALS / STEPS</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>

				<div class="specials_item ">
					<div class="specials_item_inner ">

						

						<!-- Product Picture -->
						
							<div class="specials_img">
								<a href="products/inNewin-S3-Balance-Device-S3/"><img src="https://d29eekna00jloo.cloudfront.net/images/100995.jpg?v=3975201667" title="S3 BALANCE DEVICE" alt="S3 BALANCE DEVICE" class="" width="200" height="200" onerror="utils.handleImageError(this)"></a>
							</div>
						

						<div class="specials_info caption">

							<!-- Product Name -->
							
								<div class="specials_nm"><a href="products/inNewin-S3-Balance-Device-S3/" class="">S3 BALANCE DEVICE</a></div>
							

							<!-- Product SKU -->
							

							<!-- Product Rating -->
							

							<!-- Product Description -->
							

							<!-- Product Price -->
							

							<!-- Search Fields -->
							

						</div>
					</div>
				</div>
			</div>
			</div>
    </div>
        <div class="footer-reseller">
            <div class="footer-reseller__col footer-reseller__col-1"></div>
            <div class="footer-reseller__col footer-reseller__col-2">
                <div class="footer-reseller__wrap">
                    <h1>Healthcare Professionals</h1>
<p>If you are a healthcare professional, register for an account and we will approve you for special discounted pricing.&nbsp; &nbsp; <a href="page.asp?p_key=94EE00A182AB40D188DAF26683F87322">Get Started &raquo;</a> &nbsp;</p>
<p>&nbsp;</p>
<h2>New Clinics&nbsp;&nbsp;</h2>
<p>If you are opening a New Clinic or doing an addition to your existing Clinic, we can help. We can assist in the design and mix of equipment needed to achieve your objectives.&nbsp; Contact us to be connected with one of our Specialists.&nbsp; &nbsp; <a href="contact_us.asp">Get Started Today &raquo;</a> &nbsp;</p>
<p>&nbsp;</p>
<h2>National Accounts&nbsp;&nbsp;</h2>
<p>We are equipped to be able to handle all your National Account needs. We are proud to be a member of the NDC, a Nation Medical and Physical Therapy Suppler. This gives us National buying power, and the ability to compete with any National Supply company.&nbsp; Contact us to be connected with one of our National Account Specialists.&nbsp; &nbsp; <a href="contact_us.asp">Get Started Today &raquo;</a>&nbsp;</p>
                </div>
            </div>
        </div>
    

    <!-- Retail Bot WPC Footer Email List -->
    <div class="footer-email-list">
        <p class="footer-email-list__form" style="text-align: center;"><span style="background-color: #ffffff;">&nbsp;<a title="Richmar" href="https://electro-medical.com/Richmar-Products/"><img src="images/richmar.png" alt="" width="151" height="41" /> </a>&nbsp;</span>&nbsp;<a title="Spirit Medical Fitness Eq " href="https://electro-medical.com/Spirit-Medical-Fitness-Equipment/"><img src="images/spirit.png" alt="" width="130" height="41" /></a><span style="background-color: #ffffff;">&nbsp; &nbsp; </span><span style="background-color: #ffffff;">&nbsp;</span><a title="Shuttle" href="https://electro-medical.com/Shuttle-Systems/"><img src="images/shuttle.jpg" alt="" width="173" height="61" /></a> <a href="https://electro-medical.com/ASSIST-hi-lo-tables/"><img src="images/assist2.png" alt="" width="164" height="39" /></a></p>
<p style="text-align: center;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a title="SciFit " href="https://electro-medical.com/SciFit-Medical-Fitness-Equipment/"><img src="images/SCIFIT_.png" alt="" width="145" height="49" /></a>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a title=" Game Ready " href="https://electro-medical.com/Game-Ready-Compression/"><img src="images/gr.jpg" alt="" width="196" height="42" /></a><a href="https://electro-medical.com/Preferred-Products/"><span style="background-color: #ffffff;"><img src="images/empp2.jpg" alt="" width="252" height="68" /></span></a></p>
<p style="text-align: center;"><strong>&nbsp;_______________________________________________________</strong><strong>________________________________________________</strong></p>
<h2 style="text-align: center;"><span style="text-decoration: underline;"><span style="color: #ba372a; text-decoration: underline;">Get 10% off your 1st Order </span></span></h2>
<h3 style="text-align: center;"><span style="color: #ba372a;">when you sign up for the EME newsletter</span><span style="text-decoration: underline;"><span style="color: #ba372a; text-decoration: underline;"></span></span></h3>
<!-- Begin Mailchimp Signup Form -->
<style type="text/css">
	#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif;  width:800px;}
	/* Add your own Mailchimp form style overrides in your site stylesheet or in this style block.
	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
</style>
<center>
<div id="mc_embed_signup"><form id="mc-embedded-subscribe-form" class="validate" action="https://electro-medical.us1.list-manage.com/subscribe/post?u=057959f85432ae9a2a0aa0d4d&amp;id=74e111528a&amp;f_id=00cee9e5f0" method="post" name="mc-embedded-subscribe-form" novalidate="" target="_blank">
<div id="mc_embed_signup_scroll">
<div class="mc-field-group"><label for="mce-EMAIL">Email Address <span class="asterisk">*</span> </label> <input id="mce-EMAIL" class="required email" name="EMAIL" required="" type="email" value="" /> <span class="helper_text" id="mce-EMAIL-HELPERTEXT"></span></div>
<div class="mc-field-group">&nbsp;</div>
<div class="mc-field-group"><label for="mce-FNAME">First Name <span class="asterisk">* &nbsp; &nbsp;&nbsp;</span> </label> <input id="mce-FNAME" class="required" name="FNAME" required="" type="text" value="" /></div>
<div class="mc-field-group">&nbsp;</div>
<div id="mce-responses" class="clear">
<div id="mce-error-response" class="response" style="display: none;">&nbsp;</div>
<div id="mce-success-response" class="response" style="display: none;">&nbsp;</div>
</div>
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input tabindex="-1" name="b_057959f85432ae9a2a0aa0d4d_74e111528a" type="text" value="" /></div>
<div class="clear"><input id="mc-embedded-subscribe" class="button" name="subscribe" type="submit" value="Subscribe" /></div>
</div>
</form></div>
</center><!--End mc_embed_signup-->
<h6 style="text-align: center;"><em>10% off your first order only (max discount is $50.00). One time use only.&nbsp; </em><em>Can not be combined with other coupons, promotions, or sales.</em></h6>
<h6 style="text-align: center;"><em>Applies to published website pricing. </em><em>&nbsp;</em><em>Does not apply to contract or negotiated pricing.</em></h6>
<h6 style="text-align: center;">&nbsp;<em>__________________________________________________________</em><em>__________________________________________</em></h6>
<p style="text-align: center;"><img src="images/visamastercard%203.png.jpg" alt="" width="251" height="39" /></p>
    </div>
</div>
<footer id="retail-footer-1" class="retail-footer-1 print-hide">
    <div class="container-fluid retail-footer__area">
        <div class="retail-footer__col retail-footer__col-1">
            <a class="retail-footer__logo-wrap" href="/">
                <img src="https://d29eekna00jloo.cloudfront.net/images/logo.jpg?v=3975201667" class="retail-footer__logo" alt="Electro-Medical Equipment">
            </a>
        </div>
        <div class="retail-footer__col retail-footer__col-2">
            <div class="nav-header">
                <span class="">Corporate</span>
            </div>
            <address class="retail-footer__address">
                
                <span class="retail-footer__company-name">
                    Electro-Medical Equipment
                </span>
                <br>
                <span class="retail-footer__address-text">
                    PO Box 670893<br>Marietta, GA 30066
                </span>
                
                    <br>
                    <a class="retail-footer__email" href="mailto:info@electro-medical.com?subject=Website Customer Service Request"><i class="icon-envelope icon-fixed-width"></i>Customer Service</a>
                
                    <br>
                    <a class="retail-footer__phone" href="tel:1-800-235-2952"><i class="icon-phone icon-fixed-width"></i>1-800-235-2952</a>
                
            </address>
        </div>

            <div class="retail-footer__col retail-footer__col-3 -hidden-if-empty">
                <ul id="retail-footer-nav__social" class="linkset retail-footer-nav__social retail-footer-nav__social__ul-1">
	<li class="retail-footer-nav__social__li-1" data-key='44FD07733333450CBCFADB166F029A0B'><div class="nav-header"><a href="#" class="">Get Social</a></div></li>
	<li class="retail-footer-nav__social__li-1" data-key='C44ED393EC9042218F3F15DD07B3AAB7'><a href="https://www.facebook.com/pages/category/Physical-Therapist/Electro-Medical-392341067537704/" class="retail-footer-nav__social__a-1" target="_blank"><i class='icon-facebook icon-fixed-width'></i>Facebook</a></li>
	<li class="retail-footer-nav__social__li-1" data-key='3806E2431D444E1A97D85EB4F3DF91E6'><a href="https://twitter.com/Electro_Medical" class="retail-footer-nav__social__a-1" target="_blank"><i class='icon-twitter icon-fixed-width'></i>Twitter</a></li>
	<li class="retail-footer-nav__social__li-1" data-key='822CF34C51A5436781E86BEF2999A7A5'><a href="https://www.youtube.com/channel/UCI0ScQRfd12Bn05GpTVgpSw?app=desktop" class="retail-footer-nav__social__a-1" target="_blank"><i class='icon-youtube icon-fixed-width'></i>YouTube</a></li>
</ul>
            </div>

            <div class="retail-footer__col retail-footer__col-4 -hidden-if-empty">
                <ul class="retail-footer__group linkset click">
                    <li class="retail-footer__link-parent link-parent drop">
                        <span class="nav-header show-mobile">Navigation <i class="icon-plus"></i>
                            <i class="icon-plus"></i>
                        </span>
                        <ul id="retail-footer-nav__menu" class="linkset retail-footer-nav__menu retail-footer-nav__menu__ul-1">
	<li class="retail-footer-nav__menu__li-1" data-key='8EC214EAE5BE4D458B221B61E8981BD3'><a href="content/FAQ.asp" class="retail-footer-nav__menu__a-1">FAQ</a></li>
	<li class="retail-footer-nav__menu__li-1" data-key='F057329EACCC4437AF050452C2D13FFB'><a href="/Cearance/" class="retail-footer-nav__menu__a-1">Special Offers</a></li>
	<li class="retail-footer-nav__menu__li-1" data-key='6DA1CB9340964C75930E040D0598BEC3'><a href="content/AboutUs.asp" class="retail-footer-nav__menu__a-1">About Us</a></li>
	<li class="retail-footer-nav__menu__li-1" data-key='F4178D8A328C4D56AA8E000163F6879C'><a href="/contact_us.asp" class="retail-footer-nav__menu__a-1">Contact Us</a></li>
	<li class="retail-footer-nav__menu__li-1" data-key='199EF689056947B08C6DC87EB69DB5B3'><a href="page.asp?p_key=68DC65AC0FE048038A1FC3F62A741602" class="retail-footer-nav__menu__a-1">Link to Offline Account</a></li>
</ul>
                    </li>
                </ul>
            </div>

            <div class="retail-footer__col retail-footer__col-5 -hidden-if-empty">
                <ul class="retail-footer__col-group linkset click">
                    <li class="retail-footer__link-parent link-parent drop">
                        <span class="nav-header show-mobile">
                            Product Categories <i class="icon-plus"></i>
                        </span>
                        <ul id="retail-footer-nav__categories" class="linkset retail-footer-nav__categories retail-footer-nav__categories__ul-1">
	<li class="retail-footer-nav__categories__li-1" data-key='CA94669A5E8942B3B068E0AC6FD0A62F'><a href="/content/terms.asp" class="retail-footer-nav__categories__a-1">Terms & Conditions</a></li>
	<li class="retail-footer-nav__categories__li-1" data-key='AB49D6ABF3864737938702BD4B840679'><a href="page.asp?p_key=E5EB9FEF0A3F46829C5A065582D91ADC" class="retail-footer-nav__categories__a-1">Financing</a></li>
	<li class="retail-footer-nav__categories__li-1" data-key='5C568441983547E9AD5E719999C03C8B'><a href="content/returns.asp" class="retail-footer-nav__categories__a-1">Returns</a></li>
	<li class="retail-footer-nav__categories__li-1" data-key='1D7BA54AE5AE46B99E629A3E470BC3D6'><a href="content/service.asp" class="retail-footer-nav__categories__a-1">Service & Repair</a></li>
	<li class="retail-footer-nav__categories__li-1" data-key='01603A7AA9D24B2EBC2A7511C79A06E1'><a href="/Privacy" class="retail-footer-nav__categories__a-1">Privacy Policy</a></li>
</ul>
                    </li>
                </ul>
            </div>
    </div>
    <div id="bottom-bar" class="bottom-bar">
        <div class="container-fluid">
            <div class="bottom-bar__copyright">
                <p>&copy;2026. Electro-Medical Equipment. All rights reserved.</p>
            </div>
            <div class="bottom-bar__colophon">
                    <p>Powered by <a href="https://www.cimcloud.com" rel="nofollow" target="_blank">CIMcloud</a></p>
            </div>
        </div>
    </div>
</footer>

<script type="text/javascript">

    // This hides any linksets in the footer that don't have any links
    var footerNavGroups = document.querySelectorAll(".retail-footer__col.-hidden-if-empty");
    Array.prototype.forEach.call(footerNavGroups, function(group) {
        group.querySelector("ul[class*='retail-footer-nav']") ? "" : group.classList.add("hidden");
    });

    /*
        Fixes the mobile nav header since it doesn't pull from the nav link name. 
        Updating the nav link name only renders on desktop.  this will copy that value
        to the mobile header.
        This will work with the core selectors, if the footer markup/classes change, 
        this will likely break.
    */
    var mobileNav = jQuery('.retail-footer__col-4 .nav-header.show-mobile').html();
    var desktopNav = jQuery('#retail-footer-nav__menu .nav-header a').html();
    jQuery('.retail-footer__col-4 .nav-header.show-mobile').html(
        mobileNav.replace('Navigation', desktopNav)
    );
    /*
        Now fix the category menu header the same way.
    */    
    var mobileCats = jQuery('.retail-footer__col-5 .nav-header.show-mobile').html();
    var desktopCats = jQuery('#retail-footer-nav__categories .nav-header a').html();
    jQuery('.retail-footer__col-5 .nav-header.show-mobile').html(
        mobileCats.replace('Product Categories', desktopCats)
    );
</script>
<div class="global-body-append">
    
	<span class="app-logo__validip-info btn btn-mini">
		<img src="https://d29eekna00jloo.cloudfront.net/images/cimcloud-logo-icon.png?v=3975201667" style="height: 12px;">
		<a href="#siteInfo" role="button" data-toggle="modal" class="site-info">	
			<span title="Currently on version 4.14.1" style="color: #00A3E0;">electromed2 (4.14.1)</span>
		</a>&nbsp;&nbsp;
	</span>
	<div id="siteInfo" class="modal hide fade" tabindex="-1"  aria-hidden="true">
		<header class="modal-header">
			<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
			<h3 id="leaveCheckoutLabel"><i class="icon-info-sign"></i> Site Information</h3>
		</header>
		<div class="modal-body app-logo__validip-body">
			
		
		<table border="0" cellpadding="0" cellspacing="0">
            <tr>
				<td class="pageInfoLabel">Core Version:</td>
				<td>
					
						<a style="text-decoration: none;" 
						   href="https://bitbucket.org/websitepipeline/coresite/src/4.14.1/">
						   	4.14.1
						</a>
					
				</td>
			</tr>
				<tr>
					<td class="pageInfoLabel">K8Info Deployments:</td>
					<td>
						<a style="text-decoration: none;" 
						   href="https://electro-medical.com/k8info_deployments.asp">
						   K8Info Deployments Page
						</a>
					</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">ServerName:</td>
					<td>WEBSERVER</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">WS_ID:</td>
					<td>565460A822094FE3AB4EE910A03EB724</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">L_WS_ID:</td>
					<td>565460A822094FE3AB4EE910A03EB724</td>
				</tr>
			<tr>
				<td class="pageInfoLabel">SiteName:</td>
				<td>electromed2</td>
			</tr>
			<tr>
				<td class="pageInfoLabel">Application URL:</td>
				<td></td>
			</tr>
			<tr>
				<td class="pageInfoLabel">Workspace URL:</td>
				<td>https://electromed2.mycimcloud.com</td>
			</tr>
				<tr>
					<td class="pageInfoLabel">OrderFrontURL:</td>
					<td>https://electro-medical.com</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">ALTERNATE_DB_NAME:</td>
					<td>electromed2</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">ALTERNATE_DB_SERVER:</td>
					<td>i2db21\db21</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">FileName:</td>
					<td>c:\inetpub\wwwroot\WebSite\Default.asp</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">Local Commit Hash:</td>
					<td>aec323c1b0473b6ea6a440505731c7fc33b81ae3</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">SCRIPT_NAME:</td>
					<td>/Default.asp</td>
				</tr>
				<tr>
					<td class="pageInfoLabel">HTTP_X_ORIGINAL_URL:</td>
					<td></td>
				</tr>
				<tr>
					<td class="pageInfoLabel">getUrl():</td>
					<td>/Default.asp?</td>
				</tr>
			<tr>
				<td class="pageInfoLabel">cimcloud.helpers.urlPath()</td>
				<td>/Default.asp</td>
			</tr>
			<tr>
				<td class="pageInfoLabel">cimcloud.helpers.pageName</td>
				<td>Default.asp</td>
			</tr>
		</table>
		</div>
		<div class="modal-footer">
			<a class="app-logo__validip-link btn btn-danger" href="https://electro-medical.com/?action=logout"><i class="fas fa-power-off"></i> Sign Out</a>
			<a class="app-logo__validip-link btn" href="https://electro-medical.com/session_info.asp?key=022507AF5A994426A3DFC3B29B01E852"><i class="fas fa-code"></i> Session Info</a>
			<a class="app-logo__validip-link btn" href="https://electro-medical.com/k8info_deployments.asp" target="_blank"><i class="fab fa-docker"></i> K8 Info</a>
			<a id="toggleTimerBtn" class="app-logo__validip-link btn" onclick="toggleTimers()"><i class="fas fa-clock"></i> Toggle Timers</a>
			
				<a class="app-logo__validip-link btn" target="_blank" href="https://bitbucket.org/websitepipeline/electromed2" target="_blank"><i class="fab fa-bitbucket"></i> Bitbucket Repo</a>
			
		</div>
	</div>
	<script>
		$('#demoToolsBtn').click(function() {
			$('.modal').modal('hide');
		});

		function toggleTimers() {
			$.ajax({url: "?toggle=timers&modal=1", 
					success: function(data){
						if(data == "ON") {
							$("#toggleTimerBtn").addClass("btn-danger");
						} else {
							$("#toggleTimerBtn").removeClass("btn-danger");
						}
						utils.popToastr('Success', 'Timers are now ' + data, { 'positionClass' : 'toast-bottom-right' });
					}
				});
		}
	</script><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="hide">
  <symbol id="icon-user-circle-o" viewBox="0 0 28 28">
    <path d="M14 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 id="icon-address-card" viewBox="0 0 32 28">
    <path d="M16 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 id="icon-building" viewBox="0 0 22 28">
    <path d="M21 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 id="icon-currency-dollar" viewBox="0 0 20 20">
    <path d="M10 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 id="icon-check-square" viewBox="0 0 24 28">
    <path d="M10.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 id="icon-life-bouy" viewBox="0 0 28 28">
    <path d="M14 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 id="icon-calendar-plus-o" viewBox="0 0 26 28">
    <path d="M24 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 id="icon-sticky-note" viewBox="0 0 24 28">
    <path d="M16 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 id="icon-document-add" viewBox="0 0 32 32">
    <path d="M21 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 id="icon-document-add1" viewBox="0 0 32 32">
    <path d="M21 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 class="retail-scripts-bot">
	<div class="global-scripts">
    <script>

        var jsConfig = {
            static_pages: {
                content_key: '',
                content_type: ''
            }
        }
        if(processPageTitle){
            //$('.page-header h1').html('&nbsp;').show();
            var originalPageTitle = $('.page-header h1').html();
            var originalSubmitText = $('.form-actions button').html();
            var pageTitleText = "";
            if(pageTitleText.trim() != ''){
                $('.page-header h1').html(pageTitleText);
                $('.form-actions button').html( 'Save ' + pageTitleText);
                if(isWorkerDomain) pageTitleText = sitename.toUpperCase() + ' - ' + pageTitleText;
                document.title = pageTitleText;
            }else if (originalPageTitle){
                pageTitleText = originalPageTitle;
                $('.form-actions button').html( 'Save ' + pageTitleText);
                if(isWorkerDomain) pageTitleText = sitename.toUpperCase() + ' - ' + pageTitleText;
                document.title = pageTitleText;                
            }
            $('.page-header h1').show();
            $('.form-actions button').show();
        }
    </script>

    <script src="../hooks/js_custom_functions.js?aec323c"></script>
    <script src="js/vendor/stretchy.min.js?aec323c" data-filter=".stretchy, .stretchy *"></script>

    <noscript class="noscript">
        WARNING: You will not be able to place an order or use most features of this site with JavaScript disabled
    </noscript>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/js/all.min.js" integrity="sha512-Sr1M6mlMOXTKahO1wcUzFu/kAb3iZVaQWGvxOEePRm7c2NjGRZ7ckRT6218PaSXlz8eEoFpKkDVvl2rTqKrQLA==" crossorigin="anonymous" referrerpolicy="no-referrer" async></script>

<script src="/js/bundles/coreBot.js?aec323c1b0473b6ea6a440505731c7fc33b81ae3" ></script>


<script src="/js/bundles/coreBotPlugins.js?aec323c1b0473b6ea6a440505731c7fc33b81ae3" ></script>
    <script src="../js/retail.js?aec323c"></script>
    
</div>

<div id="appLoadingWidget" class="sk-three-bounce--full-screen app-loading hide">
    <div class="sk-three-bounce">
        <div class="sk-child sk-bounce1"></div>
        <div class="sk-child sk-bounce2"></div>
        <div class="sk-child sk-bounce3"></div>
    </div>
</div>

    <!-- KO Templates -->
    
<script>
	var oConfig = {

		sessionData : {
			sc_id              : "75C67D9955EF4D619AD72B3087D9C082",
			sessionKey         : "022507AF5A994426A3DFC3B29B01E852",
			storefrontUrl      : "https://electro-medical.com",
			orderfrontUrl      : "https://electro-medical.com",
			cdnUrl             : "https://d29eekna00jloo.cloudfront.net",
			isSuperUserSession : false,
			cartPage           : "showcart.asp"
		}
	}; 
	
	const additionalFields = [
		'content1',
		'content2',
		'content3',
		'content4',
		'opt1',
		'opt2',
		'opt3',
		'opt4',
		'opt5',
		'opt6',
		'opt7',
		'opt8',
		'opt9'
	];
</script>
<div class="catalog-templates-scripts">




	<script>
		utils.isMainProduct = function (product) {
			return product && ko.unwrap(viewModel.mainProduct) === product;
		};

		utils.buildQuickAddLink = function(product){
			var link = product.link();
			var orderKey = utils.getParameter('o_key');
			if(orderKey){
				orderKey = '&o_key=' + orderKey;
			}
			if(link.includes('?')){
				link += '&quickadd=true' + orderKey;
			}else{
				link += '?quickadd=true' + orderKey;
			}
			return link;
		};

		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(value[1]) : undefined;
		};

		utils.isActiveQuote = ((utils.getParameter('modalaction') == 'addProduct' || utils.getParameter('modalaction', parent) == 'addProduct') && "".length == 32) && "" != "75C67D9955EF4D619AD72B3087D9C082";

		//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 (uri[uri.length - 1] === '?') {
					separator = '';
				} else {
					separator = '&';
				}
			}
			if (uri.match(re)) {
				return uri.replace(re, '$1' + key + '=' + value + '$2');
			} else {
				return uri + separator + key + '=' + value;
			}
		};

		utils.handleImageError = function (img) {
			handleImageError(img, oConfig.noImagePath);
		};

		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 didn't work
				console.error('failed to save breadcrumbs');
			}
		};

		utils.breadCrumbProperty = function(link) {
			if(link == '' || link === null){
				return '';
			} else {
				return 'itemListElement';
			}
		};

		utils.breadCrumbItemType = function(link) {
			if(link == '' || link === null){
				return '';
			} else {
				return 'ListItem';
			}
		};

		utils.pageUrl = location.pathname + location.search;
		if(utils.pageUrl.charAt(0) == '/') {
			utils.pageUrl = utils.pageUrl.substring(1);
		}
		utils.loginUrl = 'security_logon.asp?autopage=' + encodeURIComponent(utils.pageUrl);

		utils.formatMoney = (function (positiveExample, negativeExample) {
			/*
			This takes an example of a formatted currency and returns a function
			to format numbers in that same format. The first argument is the
			number 1111.2222 formatted with the desired default number of
			decimals. The second argument is the additive inverse of the first.
			For example:
			$1,111.22
			¥ 1,111.22
			€1.111,22
			1 111,22F
			*/
			'use strict';
			function buildFormatter(example) {
				var thousandsSeperator = getGroup(/1([^1]?)1/);
				var decimalSymbol = getGroup(/1([^12]?)2/);
				var decimalPlaces = (example.match(/2/g) || []).length;
				var thousandsRegex = /(\d)(?=(?:\d{3})+$)/g;

				var escapedDecimalSymbol = _.escapeRegExp(decimalSymbol);
				var symbolRegex = new RegExp('^([^1' + escapedDecimalSymbol + ']*).+?([^12' + escapedDecimalSymbol + ']*)$');
				var symbolMatch = symbolRegex.exec(example);
				var prefix = symbolMatch ? symbolMatch[1] || '' : '';
				var suffix = symbolMatch ? symbolMatch[2] || '' : '';
                var infoLost = 0;

				function getGroup(pattern) {
					var match = pattern.exec(example)
					return match ? match[1] : '';
				}

				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(int==Math.pow(10,places)) {
                            // in this case, we have to track a +1 to add to the result because "100" sliced down to 2 places loses info
							/*
							* 2020-07-22 - EJ - More info: This is due to things like utils.formatPrice(1.995, 2) returning 1.00 instead
							* of 2.00 or utils.formatPrice(1.9995, 3) returning 1.000 instead of 2.000
							* This is because the whole number is truncated, then the decimal is rounded and only the decimal portion
							* is added back to the whole number portion.
							* This means the rounded decimal portion is always 1 or less.  If it's less than 1 (ex .89) this works.
							* However, if it's 1.000, it would "lose" 1 since only the decimal portion is added back.
							* PS - Don't ask me about the original design, I didn't design it that way.  I only corrected the "if"
							*      statement above where it was hard-coded to 100 to be Math.pow(10,places) so it would work when
							*      rounded to something other than 2 decimal places.
							*/
                            infoLost = 1;
                        } else {
                            infoLost = 0;
                        }

						return decimalSymbol + result;
					}
				}

				function getZeroString(length) {
					var pow = Math.pow(10, length);
					return pow.toString().slice(1);
				}

				function addThousandsSeperator(integer) {
					return (integer + infoLost).toString().replace(thousandsRegex, '$1' + thousandsSeperator);
				}

				return function (value, places) {
					places = typeof places === 'undefined' ? decimalPlaces : parseInt(places);

					// Truncate the value to get the integer portion.
					var integer = value | 0;
					var decimal = decimalToString( ((value * 1000) % (1 * 1000)) / 1000, 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) {
				var parsedValue = parseFloat(ko.unwrap(value));
				if (isNaN(parsedValue)) return ko.unwrap(value).toString();
				return (parsedValue < 0 ? formatNegative : formatPositive)(Math.abs(parsedValue), places);
			}
		}('$1,111.22', '($1,111.22)'));

		utils.formatPrice = _.partialRight(utils.formatMoney, parseInt(2) || 2);

		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 ' + oConfig.labels.savedCarts;
			} else if (viewModel.mainProduct && viewModel.mainProduct.configuratorEditData && viewModel.mainProduct.configuratorEditData.od_id) {
				return oConfig.labels.updateCartItem || 'Update';
			} else {
				return oConfig.labels.addToCartList || 'Add to Cart';
			}
		};

		utils.atcBelowListButtonText = function() {
			if(utils.isActiveQuote) {
				return 'Add to ' + oConfig.labels.savedCarts + ' Below <i class=\"icon-arrow-down\"></i>';
			} else if (viewModel.mainProduct && viewModel.mainProduct.configuratorEditData && viewModel.mainProduct.configuratorEditData.od_id) {
				if(utils.isActiveQuote) {
					return 'Update ' + oConfig.labels.savedCarts + ' Below <i class=\"icon-arrow-down\"></i>';
				} else {
					return 'Update Cart Below <i class=\"icon-arrow-down\"></i>';
				}
			} else {
				return oConfig.labels.inputQtyATCLabel || 'Add to Cart Below <i class=\"icon-arrow-down\"></i>';
			}
		};

		utils.resetATCForm = function() {
			if(!runHook('catalogTemplatesOverrideResetATCForm', { utils: this })) {
				document.getElementById("atc_form").reset();
				_.forEach(viewModel.results(), function(result) {
					if (setSelectedQty()) {
						result.selectedQty(result.minQty() || 1);
					}else{
						result.selectedQty(undefined);
					}
					result.selectedQty.notifySubscribers();
				});
			}
		}

		utils.addToCart = function (details, cart, parentKey, useInstances) {

			function getQueryStringParameters() {
				var params = {
					type : 'v200add',
					sc_id : oConfig.overrideCartKey || oConfig.sessionData.sc_id,
					s_key : oConfig.sessionData.sessionKey,
					s_url : oConfig.sessionData.storefrontUrl,
					o_url : oConfig.sessionData.orderfrontUrl,
					createsessioncookie : '1',
					noredirect : '1',
					l_ws_key : '',
					mobile : 'no',
					action : 'postlogic',
					modal  : utils.getParameter("modal"),
					modalaction  : utils.getParameter("modalaction"),
					useinstances: useInstances,
					postProcess: true
				};

				// 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 = {};

				var isConfigurator = viewModel.mainProduct && viewModel.mainProduct.useConfigurator();
				var isParentConfigurator = viewModel.mainProduct && viewModel.mainProduct.type == 'parent' && isConfigurator;
				var odChildSkuMatch = '';

				var parentProductInstanceKey = '';
				var childProductConfigs = [];

				if(isConfigurator) {
					useinstances = true;
				}

				if(isParentConfigurator) {
					//' Always use instances if this is a parent-child with configurator on the parent
					useInstances = true;
					var parentProductInstance = utils.createGuid();
					var mainProductIndex = details.findIndex(function (item) { return item.key() == viewModel.mainProduct.key(); });
					if (mainProductIndex == -1) {
						// if it doesn't exist, add the parent to the front
						//details.unshift(viewModel.mainProduct);
						// if it doesn't exist, add the parent to the end
						details.push(viewModel.mainProduct);
					} else {
						var mainProductElement = details.splice(mainProductIndex, 1)[0];
						// if it doex exists, move it to the front
						//details.unshift(mainProductElement);
						//details.splice(mainProductIndex, 1);
						// if it doex exists, move it to the end
						details.push(mainProductElement);
					}
				}

				//' Force use instances on if it's off / undefined and we detect duplicate p_keys
				if(!useInstances && details.length) {
					var distinctProductKeys = details.reduce(function(distinctValues, detail, index) {
						if(distinctValues.indexOf(detail.key()) < 0)
						{
							distinctValues.push(detail.key());
						}
						return distinctValues;
					}, []);

					if(distinctProductKeys && distinctProductKeys.length !== details.length) {
						//' Always use instances if we're adding the same product key to cart in one post
						useInstances = true;
					}
				}

				buildConfiguratorData = function(configQuestions) {

					/* 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'
						}
					*/

					/*
					'	We're setting configType based on the customForm value,
					'	but we should never hit this code if it's 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(oConfig.showProductConfigurator && typeof customForm !== 'undefined' && !!customForm) {
						configType = 'configurator';
					} else {
						configType = 'cartoptions';
					}
					var configJson = {
										choices: [],
										configType: configType
									};
					var cartOptions = '';
					if(configQuestions && configQuestions.length > 0)  {
						configQuestions.forEach(function(question) {
							configJsonQuestion = {
								question: question.q_key(),
								name: question.questionText(),
								questionText: question.questionText(),
								answerText: question.selectedAnswer(),
								question_status: true
							};
							if(question.erpCode()) {
								configJsonQuestion["question_erp_code"] = question.erpCode();
							}
							configJson.choices.push(configJsonQuestion);
							cartOptions += question.questionText() + "~" + question.selectedAnswer() + "|"
						});
					}

					var productConfigData = {
							configJson: configJson,
							cartOptions: cartOptions.slice(0, -1) // trim trailing pipe
					};

					return productConfigData
				}

				handleAddOnProducts = function(item){
					addOnProducts = [];
					if(item.selectedProduct().selectedAddOn && item.selectedProduct().selectedAddOn()){
						addOnProducts.push(item.selectedProduct().selectedAddOn());
					}else if(item.selectedProduct().selectedAddOns && item.selectedProduct().selectedAddOns().length > 0){
						_.forEach(item.selectedProduct().selectedAddOns(), function(item){
							addOnProducts.push(item);
						})
					}
					
					_.forEach(addOnProducts, function(item){
						//handle the add to cart for  addons
						prepareAddToCart(item);
					})
				}

				prepareAddToCart = function(product, childQuestion){
					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 = product.instance || utils.createGuid();

						product.instanceKey = tempInstanceKey;
						product.lineKey = lineKey;

						instanceKeys.push(tempInstanceKey);

						if(!instancesWithKeys[tempInstanceKey]) {
							instancesWithKeys[tempInstanceKey] = [];
						}

						instancesWithKeys[tempInstanceKey].push(lineKey);

						data['instance_' + lineKey] = tempInstanceKey;
						data['p_id_' + lineKey] = productKey;
						data['instance_key_set'] = '1';
						
						if(product.isCarrier) {	
							data["row_display_case_" + lineKey] = "group-parent";
							data['remove_type_' + lineKey] = 'instance';
						}else if(product.carrier && product.carrier.trim() != ''){
							data["remove_type_" + lineKey] = "hide";
							data["qty_display_type_" + lineKey] = "text"; 
							data["row_display_case_" + lineKey] = "group-child";
							if(product.qtyType == 'ratio') {
								data['qty_control_from_' + lineKey] = 'parent';
								data['multiplier_on_parent_qty_' + lineKey] = product.qtyMultiplier;
							}
						}else if(isParentConfigurator && product.type == 'child'){
							data["qty_display_type_" + lineKey] = "text"; 
							data['qty_control_from_' + lineKey] = 'this-line';
							data["row_display_case_" + lineKey] = "group-child";
							data['remove_type_' + lineKey] = 'hide';
							data['unq_' + lineKey] = utils.createGuid();
							data['use_config_questions_' + lineKey] = true;
						}else if(isParentConfigurator && product.type == 'parent') {
							data["row_display_case_" + lineKey] = "group-parent";
							data['remove_type_' + lineKey] = 'instance';
							data['qty_display_type_' + lineKey] = "hide";
							data['unq_' + lineKey] = utils.createGuid();
						}else{
							data['remove_type_' + lineKey] = 'instance';
						}
					}
					
					data['qty_' + lineKey] = product.selectedQty() || minQty;
					if(!!uom){
						data['uom_' + lineKey] = uom.description;
						if(uom.hasOwnProperty("UomId")) data['uom_id_' + lineKey] = uom.UomId;
						data['uom_conversion_' + lineKey] = uom.uom_conversion ?? 1.0;
					}
					data['pw_id_' + lineKey] = ko.unwrap(product.selectedWarehouse().key) || oConfig.defaultWarehouse;

					if(product.type == 'child') {
						if(parentKey && product.key() !== parentKey) {
							data['parent_p_id_' + lineKey] = parentKey;
						} else if(product.parents && product.parents().length > 0){
							data['parent_p_id_' + lineKey] = product.parents()[0].key();
						}
					}

					
					var odUrl = product.link();

					if(odChildSkuMatch != '') {
						var queryStringSeparator = '?';
						if (odUrl.indexOf('?', odUrl.length - 1) !== -1 || odUrl.indexOf('&', odUrl.length - 1) !== -1) {
							// link already ends with a query string separator (? or &)
							queryStringSeparator = '';
						} else if (odUrl.indexOf('?') > -1) {
							// link already has a query string
							queryStringSeparator = '&';
						}
						odUrl = odUrl + queryStringSeparator + 'childskumatch=' + odChildSkuMatch;
					}

					data['url_' + lineKey]           = odUrl;
					data['minqty_' + lineKey]        = product.minOrderQty();
					data['maxqty_' + lineKey]        = product.maxOrderQty();
					data['qty_increment_' + lineKey] = product.stepQty();

					_.assign(data, buildConfiguratorPostData(productKey));
					if(childProductConfigs.length > 0)	data['child_products'] = JSON.stringify(childProductConfigs);

					if (minQty && minQty != oConfig.defaultMinimumQuantity) data['min_order_qty_' + lineKey] = product.minOrderQty();

					if(product.configuratorEditData && product.configuratorEditData.lineNumber) {
						data['line_number_' + lineKey] = product.configuratorEditData.lineNumber;
					}

					if(product.configuratorEditData && product.configuratorEditData.minQty) {
						data['minqty_' + lineKey] = product.configuratorEditData.minQty;
					}

					if(product.configuratorEditData && product.configuratorEditData.maxQty) {
						data['maxqty_' + lineKey] = product.configuratorEditData.maxQty;
					}

					if(product.configuratorEditData && product.configuratorEditData.qtyIncrement) {
						data['qty_increment_' + lineKey] = product.configuratorEditData.qtyIncrement;
					}

					if(product.configuratorEditData && product.configuratorEditData.removeType) {
						data['remove_type_' + lineKey] = product.configuratorEditData.removeType;
					}

					if(product.configuratorEditData && product.configuratorEditData.priceCalcType) {
						data['price_calc_type_' + lineKey] = product.configuratorEditData.priceCalcType;
						if(product.configuratorEditData.priceCalcType == 'fixed') {
							data['price_' + lineKey] = product.configuratorEditData.price;
						}
					}

					var configChild = null;
					if(isParentConfigurator && product.type == 'child') {
						/*
						childQuestion = {
							q_key: ko.observable(product.key()),
							name: 'child-product',
							questionText: ko.observable(product.name()),
							erpCode: ko.observable(product.sku())
						};
						*/

						configChild = {
							p_key: product.key(),
							sku: product.sku(),
							name: product.name(),
							qty: product.selectedQty(),
							uom: uom ? uom.description : '',
							configJson: {}
						};

						childProductConfigs.push(configChild);
					}

					if(product.questions && product.questions().length > 0 && product.hasCartOptions() || isParentConfigurator) {
						var configQuestions = product.questions() ?? [];

						if(isParentConfigurator && product.type == 'parent') {
							configQuestions.concat({
								q_key: ko.observable(product.key()),
								name: ko.observable('child_products'),
								questionText: ko.observable('child_products'),
								selectedAnswer: ko.observable(JSON.stringify(childProductConfigs))
							});
						}

						if(isParentConfigurator && product.type == 'child' && viewModel.mainProduct.questions && viewModel.mainProduct.questions().length > 0) {
							configQuestions.concat(viewModel.mainProduct.questions());
						}

						var configData = buildConfiguratorData(configQuestions);

						if(isParentConfigurator && product.type == 'child' && configData && configData.configJson) {
							configChild.configJson = configData.configJson;
						}

						if(!isParentConfigurator || (isParentConfigurator && product.type == 'child')) {
							data['config_json_' + lineKey] = JSON.stringify(configData.configJson);
							data['cart_option_' + lineKey] = configData.cartOptions;
						}
					}

					if (product.pic) {
						data['pic_t_' + lineKey] = product.pic; 
					}

					additionalFields.forEach(function(field){
						if(product[field] != ''){
							data[field+'_'+lineKey] = product[field];
						}
					});

					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
				}

				_.forEach(details, function (item) {

					if(oConfig.detailConfig.useAddOnProducts && item.showAddOns){
						handleAddOnProducts(item);
					}

					var selectedProduct = item; //.selectedProduct();

					var childQuestion = null;

					if(parentProductInstance) selectedProduct.instance = parentProductInstance;

					if(selectedProduct.isChild() && viewModel.mainProduct && viewModel.mainProduct.useConfigurator()) {
						if(odChildSkuMatch == '') {
							odChildSkuMatch = selectedProduct.sku();
						}
						childQuestion = {
							q_key: ko.observable(selectedProduct.key()),
							questionText: ko.observable(selectedProduct.name()),
							selectedAnswer: ko.observable(selectedProduct.name()),
							erpCode: ko.observable(selectedProduct.sku())
						};
						/////// selectedProduct = viewModel.mainProduct;
						//if (!selectedProduct.questions) { selectedProduct.questions = ko.observableArray(); }
						//selectedProduct.questions.push(childQuestion);
					}
					
					prepareAddToCart(selectedProduct, childQuestion);
					runHook('getPostDataBeforeReturn', { self: self, data: data, product: selectedProduct, productKeys: productKeys });
				});

				data.keys = _.uniq(productKeys).join(',');

				if(instanceKeys.length) {
					data.instances = _.uniq(instanceKeys).join(',');

					for(key in instancesWithKeys) {
						data[key + '_keys'] = instancesWithKeys[key].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('Products added to cart' + cartName + ':\n' + _.map(details, function (product) {
					return '\tQty: ' + (product.selectedQty() || 1) + ' - ' + product.name();
				}).join('\n'));
			}

			function successHandler(responseData, status, request) {
				var cartLines = JSON.parse(responseData)[1].detailLines;
				var newCart = [];
				_.each(cartLines, function(line){
					newCart.push({
						prod_key: line.productID,
						parent_p_id: line.parentProductID,
						qty: line.qty,
						od_key: line.orderDetailKey
					})
				});

				if((oConfig.t_ga4 && oConfig.t_ga4_analytics != '') || (!oConfig.t_ga4_in_gtm && oConfig.t_gtm)) {
					try{
						var gtmProducts = [];
						var line_total = 0;
						_.each(details, function(item){

							var gtmProduct = {
								item_id: item.sku(),
			                    item_name: item.name(),
			                    currency: "USD",
			                    price: Number(item.unitPrice()),
			                    quantity: Number(item.selectedQty())
							}
							gtmProducts.push(gtmProduct);

							line_total = Number(item.selectedQty()) * item.unitPrice();
						});

						if (gtmProducts.length >= 1) {

							window.dataLayer = window.dataLayer || [];
	        				function gtag(){dataLayer.push(arguments);}

							gtag("event", "add_to_cart", {
				                currency: "USD",
				                value: line_total,
				                items: gtmProducts
				            });
						}
					} catch (err){
						console.log(err);
					}
				}else if(oConfig.t_gtm) {
					var gtmProducts = [];
					_.forEach(details, function (item) {

						var gtmProduct = {
							'name': item.name(),
							'id': item.sku(),
							'price': item.unitPrice(),
							'quantity': Number(item.selectedQty())
						}
						gtmProducts.push(gtmProduct);
					});

					if (gtmProducts.length >= 1) {
						window.dataLayer.push({
							'event': oConfig.t_gtm_add_to_cart_event_name,
							'ecommerce': {
								'currencyCode': 'USD',
								'add': {
									'products': gtmProducts
								}
							},
							'customer': {
								'email': cimcloud.session.email,
								'firstname': cimcloud.session.firstName,
								'lastname': cimcloud.session.lastName
							}
						});
					}
				}

				if(oConfig.isModal) {
					parent.modal.done([newCart]);
					try{
						parent.fncReloadCartWindow();
					}catch(err){
					}

					var page = window.parent ? window.parent.location.pathname.split("/").pop() : window.location.pathname.split("/").pop();
					if(!page.includes("payment.asp")) {
						parent.top.utils.toastrATC(details, newCart);
					}
				}else{
					viewModel.activeCart(newCart);

					if(viewModel.mainProduct && viewModel.mainProduct.configuratorEditData) {
						window.location = oConfig.sessionData.cartPage;
						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);

					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 product to cart',
					'There was an error',
					errorToastrConfig
				);

			}
			var bPass = true;

			// TODO: add UoM support (qty_display, etc). Fields aren't 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 && details[0].useConfigurator && details[0].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.toastrATC = function(details, cart) {
			if(utils.isActiveQuote){
				var sPage = oConfig.sessionData.orderfrontUrl + '/' + "payment.asp?o_key=" + oConfig.overrideCartKey;
			}else{
				var sPage = oConfig.sessionData.orderfrontUrl + '/' + oConfig.sessionData.cartPage + "?o_key=" + oConfig.sessionData.sc_id;
			}

			if(utils.isActiveQuote && oConfig.isModal){
				sPage = "javascript:window.history.back();"
			}
			var confirmToastrConfig = {
				'closeButton': true,
				'newestOnTop': true,
				'onclick': function() {
					window.location = sPage;
				},
				'positionClass': 'toast-top-right',
				'preventDuplicates': false,
				'showDuration': 200,
				'hideDuration': 1000,
				'tapToDismiss': false,
				'timeOut': 3000,
				'extendedTimeOut': 1000
			}

			if(cart && utils.isActiveQuote) {
				var confirmTextConfig =  {title: utils.plural(oConfig.labels.savedCartsLabels.itemText, details, true) + ' ' + oConfig.labels.savedCartsLabels.modalConfirmationHeader }
			}else{
				if(utils.isActiveQuote){
					var confirmTextConfig = { title: utils.plural(' product', details, true) + ' added to ' + oConfig.labels.savedCarts }
				}else{
					var confirmTextConfig = { title: utils.plural(' product', details, true) + ' added to Cart'}
				}
			};

			runHook('toastrATCConfiguration', { confirmToastrConfig: confirmToastrConfig, confirmTextConfig: confirmTextConfig });

			utils.popToastr(
				confirmTextConfig.title,
				'Click or tap to view',
				confirmToastrConfig
			);
		}

		utils.modalATC = function(cart, data, details) {
			var modalConfig = cart && utils.isActiveQuote ?
			{
				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(' Product', 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 (c=='x' ? 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 (options[prop]) {
					options[prop] = utils.renderTemplateToContainer(options[prop], 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',
					'showAddOns',
					'addOnLabel',
					'addOnDisplay',
					'showPrice'
				],
				related: productCollectionMapping,
				secondRelated: productCollectionMapping,
				children: productCollectionMapping,
				alsoBought: productCollectionMapping,
				addOns: productCollectionMapping
			}, self);

			self.children.extend({ deferred: true });

			self.atcButtonText = ko.observable('');
			self.atcErrorText = ko.observable('');

			if(self.useCartOptions()) self.useConfigurator(false);

			if(oConfig.isModal && !ko.unwrap(self.link).includes("modal=1")) {
				self.link((function() {
					var processedLink = ko.unwrap(self.link);
					if(processedLink.indexOf('?') > -1) {
						processedLink += "&";
					} else {
						processedLink += "?";
					}
					processedLink += 'modal=1&modalaction=' + utils.getParameter("modalaction");

					return processedLink;
				})());
			}

			if(utils.getParameter('quickadd') == 'true' && self.type === 'parent'){
				self.childDisplayType('droplist');
			}

			self.updateAtcButtonText = function() {
				if(viewModel.mainProduct && viewModel.mainProduct.configuratorEditData && viewModel.mainProduct.configuratorEditData.od_id) {
					self.atcButtonText(oConfig.labels.updateCartItem || 'Update');
				} else if (self.configuratorEditData && self.configuratorEditData.od_id) {
					self.atcButtonText(oConfig.labels.updateCartItem || 'Update');
				} else if (utils.isActiveQuote) {
					self.atcButtonText('Add To ' + oConfig.labels.savedCarts);
				} else {
					self.atcButtonText(oConfig.labels.addToCart || 'Add');
				}
			};

			self.updateAtcButtonText();

			var accordionDisplaySetting = self.tabGroupAccordionDisplay();

			// set defaultTabAccordionState based for first tab
			var defaultTabAccordionState = accordionDisplaySetting === 'open-first' || accordionDisplaySetting === 'open-all';
			self.tabs.forEach(function(tab) {
				tab.open = ko.observable(defaultTabAccordionState);
				// set defaultTabAccordionState for remaining tabs (after first)
				defaultTabAccordionState = accordionDisplaySetting === 'open-all';
			});	

			self.hasCartOptions = ko.computed(function() {
				if(!oConfig.useCartOptions){
					return false;
				}else{
					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() || 
						( oConfig.useCartOptions && self.hasCartOptions() ) ||
						(self.showAddOns && oConfig.detailConfig.useAddOnProducts && oConfig.searchConfig.requireAddOnSelection)
					) && oConfig.pageName == 'pc_combined_results.asp';
			});

			self.priceDisplay = ko.observable(function () {
				var template = 'catalog.details_link';
				if(oConfig.pageName == 'pc_product_detail.asp'){
					template = 'catalog.selected_product_price_display';
				}else 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;
				}

			}());

			self.selectedQty = ko.observable(function() {
				if(viewModel.mainProduct && viewModel.mainProduct.configuratorEditData && viewModel.mainProduct.configuratorEditData.childProducts && self.type == 'child') {
					var child = viewModel.mainProduct.configuratorEditData.childProducts.filter(function(child) {
						if(child.p_key == self.key()) {
							return child.qty;
						}
					});
					if(child.length == 1) {
						return child[0].qty;
					}
				}else if(self.configuratorEditData) {
					return self.configuratorEditData.qty;
				}else if(self.qty){
					return self.qty;
				} else {
					return undefined;
				}
			}());

			self.selectedQty.subscribe(function(newQty) {
				if(self.configuratorEditData) {
					self.configuratorEditData.qty = newQty;
				}
			});

			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 } ) || [] );
			}
				
			_.each(self.uomPrice(),function(uom){
				uom.isDefault( (oConfig.useSalesUomAsDefault && uom.uom() == "uom_sales") || (!oConfig.useSalesUomAsDefault && uom.uom() == "uom_std"))

				var bHasBreaks = false;
				bHasBreaks = uom.breaks && uom.breaks() && uom.breaks().length > 0;
				uom.hasBreaks(bHasBreaks);
			});

			if(oConfig.useSalesUom)
			{
				var salesUomIndex = self.uomPrice().findIndex(function (uom) { return uom.uom() == "uom_sales"});
				if(salesUomIndex > -1) {
					for(i = self.uomPrice().length -1; i > 0; i--) {
						if(i != salesUomIndex) {
							self.uomPrice.splice(i, 1);
						}
					}
				}
			}

			self.selectedUom = ko.observable(
				(function () {
					var uom = undefined;

					// It's 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 can't 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 doesn't match an available uom.
					// There's certainly 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
							}
						});
					}

					if(!uom && self.uomPrice().length > 0) {
						//if still no match then take the first one
						uom = self.uomPrice()[0];
					}

					return uom;
				})());

			// Set the selected quantity back to the default if the UOM changes
			self.selectedUom.subscribe(function(newValue) {
				var defaultQty = newValue.minQty() || newValue.step() || 1;
				self.selectedQty(defaultQty);
			});

			self.processedBreaks = ko.computed(function() {
				if (!( self.selectedUom() && self.selectedUom().hasBreaks() )) {
					return [];
				}

				var processed = [];
				var data = self.selectedUom().breaks();

				//converted from price break popup window to properly display single breaks that actually have multiple break records
				if(data[data.length -1].qty() == '1000000' || data[data.length -1].qty() == '100000000'){
					data.pop();
				}

				//If there's only one break we will skip showing the price break information
				if(data.length == 1) {
					return [];
				}

				processed = data.map(function(lineBreak) {
					var price, startQ, endQ, range, qty, proceed;
					price = lineBreak.price();
					startQ = lineBreak.qty();
					endQ = lineBreak.qtyEnd();
					proceed = true;

					if (endQ != '0') {
						range = startQ + ' - ' + endQ;
					} else {
						range = startQ + '+';
					}

					if(proceed){
						return {
							price: price,
							range: range
						}
					}else{
						return {}
					}
				});
				return processed.filter( function(value){ return JSON.stringify(value) !== '{}'; });
			});

			self.configPrice = buildConfiguratorPriceObservable(self.key());

			self.unitPrice = ko.computed(function () {
				if(oConfig.useListPriceOverride){
					return self.selectedUom().suggestedPrice()
				}

				if(self.configuratorEditData && self.configuratorEditData.priceCalcType == 'fixed') {
					return self.configuratorEditData.price;
				}

				if(self.type == 'child' && viewModel.mainProduct) {
					return self.selectedUom().price() + viewModel.mainProduct.configPrice();
				}

				return self.selectedUom().price() + self.configPrice();
			});

			self.priceTrace = ko.computed(function() {
				var bPriceErrorMessage = 'Price trace is not available';
				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(oConfig.youSaveDecimalPlaces) + '%';
			});

			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 && !oConfig.useListPriceOverride;
			});

			self.childView = function () {
				// return (self.childDisplayType() || 'stand-alone') + '-layout';
				return 'stand-alone-layout';
			}();

			if(!self.mapPriceType() && oConfig.defaultPriceDisplayType) {
				self.mapPriceType(oConfig.defaultPriceDisplayType);
			}

			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.allowQuickAddModal = ko.computed(function() {
				if (oConfig.pageName == 'pc_product_detail.asp') return false;

				/* droplist is really the only child display type that works with quick add */
				if (self.childDisplayType() && !self.childDisplayType().toLowerCase().startsWith('droplist')) return true;

				/* if this is a parent product using configurator, optionally force to detail page */
				if (!oConfig.allowQuickAddParentConfigurator && self.type.toLowerCase() === 'parent' && self.useConfigurator()) return false;

				return true;
			});

			self.isInCart = ko.computed(function(){
				var cartCount = 0;
				if(viewModel.activeCart && viewModel.activeCart().length){
					var product = _.filter(viewModel.activeCart(), function(cart){
						return cart.prod_key == self.key() || cart.parent_p_id == self.key();
					});
					cartCount = product.length;
				}
				return cartCount;
			});

			self.showPrice = function () {
				if (typeof self.showPrice !== 'undefined') return self.showPrice;
				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.showBreaks = ko.observable(function(){
				return oConfig.useBreaks && oConfig.useBreaksTable && oConfig.pageName == 'pc_product_detail.asp';
			}());

			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.pageName == 'pc_combined_results.asp' && oConfig.searchConfig.hideAtcShowInv)) || (oConfig.allowWarehouseSelection && self.showQuickAtc())) {
						return 'warehouse_droplist';
					} else if (oConfig.useWarehousesTable) {
						return 'warehouse_table';
					} else {
						if(self.showQuickAtc()){
							return 'warehouse_info';
						}else{
							return '';
						}
					}
				} else {
					return 'warehouse_off';
				}
			}();

			self.priceBreaksTemplate = function(){
				if(oConfig.useBreaks){
					if(oConfig.useBreaksTable && 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() {
				var template;
				if (self.selectedProduct().uomPrice().length > 1) {
					template = 'catalog.uom_select';
				} else {
					template = 'catalog.uom_input';
				}

				if(document.getElementById(template + '_custom')){
					return template + '_custom';
				}else{
					return template;
				}
			});

			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 === '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.useMinimumQuantity) {
					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.useQuantityIncrement) {
					return self.selectedProduct().selectedUom().step();
				} else {
					return oConfig.defaultQuantityIncrement;
				}
			});

			self.maxQty = ko.computed(function () {
				if (self.configuratorEditData && self.configuratorEditData.maxQty) {
					self.selectedProduct().selectedUom().maxQty(self.configuratorEditData.maxQty);
				}
				if (oConfig.useMaximumQuantity && self.selectedProduct().selectedUom().maxQty() > 0) {
					return self.selectedProduct().selectedUom().maxQty();
				} else {
					return '';
				}
			});
			
			self.recentlyViewedTabExists = ko.computed(function() { 
				if (!Array.isArray(self.tabs) || self.tabs.length === 0) {
					return false;
				}
				return self.tabs.some(function(tab) {
					return tab.dynamicSource == "recently_viewed"; 
				});
			});

			self.customersAlsoBoughtExists = ko.computed(function() { 
				if (!Array.isArray(self.tabs) || self.tabs.length === 0) {
					return false;
				}
				return self.tabs.some(function(tab) { 
					return tab.dynamicSource == "customers_also_bought"; 
				}); 
			});

			self.hasQuantityRestrictions = ko.computed(function () {
				return (oConfig.useMinimumQuantity || oConfig.useMaximumQuantity || oConfig.useQuantityIncrement) && 
						!!(
							(self.minQty() && self.minQty() !== oConfig.defaultMinimumQuantity) || 
							( (!self.selectedUom().uom_conversion() || self.selectedUom().uom_conversion() == 1) && self.stepQty() && self.stepQty() != oConfig.defaultQuantityIncrement) || 
							self.maxQty()
						);
			});

			self.quantityRestrictionsHtml = ko.computed(function () {
				var lines = [];

				if (self.minQty() && self.minQty() !== oConfig.defaultMinimumQuantity)
					lines.push(oConfig.labels.minQtyPopover.replace(/<min_qty>/,self.minQty()));

				if ( (!self.selectedUom().uom_conversion() || self.selectedUom().uom_conversion() == 1) && self.stepQty() && self.stepQty() != oConfig.defaultQuantityIncrement)
					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();

					/*
					var parent = viewModel.mainProduct();
					if (parent.useConfigurator()) {
						self.useConfigurator(true);
					}
					*/
				}

				return utils.addToCart(self, undefined, parentKey);
			};

			self.atcPopupSuccess = function () {

			};

			self.atcPopupFail = function () {

			};

			self.searchfields = function() {
				var includedSearchfields = Object.keys(self).filter(function(key) { return key.startsWith('searchfield'); }).sort();
				var searchfieldsObject = {};
				includedSearchfields.forEach(function(searchfieldName) {
					if(searchfieldName == "searchfields") // The existing searchfields object
					{
						var originalKeys = Object.keys(self[searchfieldName]).filter(function(key) { return key.startsWith('searchfield'); });
						//console.log(JSON.stringify(originalKeys));
						originalKeys.forEach(function(key) {
							if(!searchfieldsObject[key]) {
								searchfieldsObject[key] = ko.unwrap(self[searchfieldName][key])
							}
						});
					} else {
						if(!oConfig.searchFieldsShell[searchfieldName]) {
							// because we can't use "?." until we stop trying to support IE
							// like: oConfig.searchFieldsShell[searchfieldName]?.label || ''
							oConfig.searchFieldsShell[searchfieldName] = {
								label: '',
								show: false
							};
						}
						searchfieldsObject[searchfieldName] = {
							field: ko.observable(searchfieldName),
							value: ko.observable(ko.unwrap(self[searchfieldName])),
							label: ko.observable(oConfig.searchFieldsShell[searchfieldName].label || ''),
							show: ko.observable(!!ko.unwrap(self[searchfieldName]) && (oConfig.searchFieldsShell[searchfieldName].show || false))
						}
					}
				});
				return searchfieldsObject;
			}();

			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.useSkuDisplay && oConfig.detailConfig.useAliases) {
					return 'product_history_detail.asp?search2=(searchexact~p.sku_display~' + parent.sku() + '|OR|searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku()
				}
				else if(oConfig.detailConfig.useAliases){
					return 'product_history_detail.asp?search2=searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku()
				}
				else if(oConfig.detailConfig.useSkuDisplay) {
					return 'product_history_detail.asp?search2=searchexact~p.sku_display~' + parent.sku() + '&s=' + parent.sku()
				}else{
					return 'product_history_detail.asp?search2=searchexact~p.sku~' + parent.sku() + '&s=' + parent.sku()
				}
			};

			self.getSmartListLinkInvoiceStats = function(parent){
				if(!parent){
					return 'products_invoiced_detail.asp'
				}
				if(oConfig.detailConfig.useSkuDisplay && oConfig.detailConfig.useAliases) {
					return 'products_invoiced_detail.asp?search2=(searchexact~p.sku_display~' + parent.sku()+ '|OR|searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku()
				}
				else if(oConfig.detailConfig.useAliases){
					return 'products_invoiced_detail.asp?search2=searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku()
				}
				else if(oConfig.detailConfig.useSkuDisplay) {
					return 'products_invoiced_detail.asp?search2=searchexact~p.sku_display~' + parent.sku() + '&s=' + parent.sku()
				}else{
					return 'products_invoiced_detail.asp?search2=searchexact~p.sku~' + parent.sku() + '&s=' + parent.sku()
				}
			};
			
			self.explodedViewHasQty = function(product){
				hasQty = false;
				_.each(product.children(), function(child){
					if(!hasQty && child.diagramQty() != ''){
						hasQty = true;
					}
				});
				return hasQty;
			};

			self.explodedViewHasNotes = function(product){
				hasNotes = false;
				_.each(product.children(), function(child){
					if(!hasNotes && child.diagramNotes() != ''){
						hasNotes = true;
					}
				});
				return hasNotes;
			};

			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: oConfig.useCartOptions && self.hasCartOptions(),
							label: 'Options',
							field: 'questions',
							template: 'catalog.cart_options'
						},
						{
							if: self.childDisplayType() == 'exploded-view' && self.explodedViewHasQty(self),
							label: oConfig.labels.qtyCol,
							field: 'diagramQty'
						},
						{
							if: self.childDisplayType() == 'exploded-view' && self.explodedViewHasNotes(self),
							label: oConfig.labels.notesCol,
							field: 'diagramNotes'
						}

					],
					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: oConfig.labels.idCol,
						field: 'diagramNumber'
					});
				}

				return _.filter(columns, function (column) {
					return !('if' in column) || ko.unwrap(column.if);
				});
			});

			runHook('productModelReviews', { self: self, product: product, reviews: self.reviews });

			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: answerSet[0],
										value: answerSet[0]
									});
							});
						}
					}
				});
			}

			self.rowCollection = ko.observableArray();

			self.addRows = function(numberOfRows) {
				numberOfRows = numberOfRows || 1;
				for(var i=0;i<numberOfRows;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 it's 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(
								matchedChild[0]
							);
						}
					}
					
					if(viewModel.mainProduct && viewModel.mainProduct.configuratorEditData && viewModel.mainProduct.configuratorEditData.childProducts) {
						var rowCount = 0;
						var rowPopulated = false;
						viewModel.mainProduct.configuratorEditData.childProducts.forEach(function(child) {
							if (child.p_key == viewModel.mainProduct.key()) {
								return;
							}
							if(rowPopulated) {
								self.addRows(1);
								rowCount++;
							}
							var matchedChild = self.rowCollection()[rowCount].children.filter(function(rowChild) {
								return child.p_key == rowChild.key();
							});
							if(matchedChild && matchedChild.length > 0) {
								self.rowCollection()[rowCount].selectedChild(matchedChild[0]);
								self.rowCollection()[rowCount].selectedChild().selectedQty(child.qty);

								var currentChild = self.rowCollection()[rowCount].selectedChild()
								
								if(currentChild.questions && currentChild.questions().length > 0) {
									currentChild.questions().forEach(function(question) {
										var editAnswer = child.configJson.choices.filter(function(item) {
											return item.question === question.q_key();
										});
										if(editAnswer && editAnswer.length > 0) {
											setSelectedCartOptionAnswer(question, editAnswer);
										}
									});
								}

								rowPopulated = true;
							}
						});
					}
				}
			}

			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);
						}
					});
					if(!child.configuratorEditData) {
						var childConfig = self.configuratorEditData?.childProducts?.filter(
							function(childProdConfig) {
								return childProdConfig.p_key == child.key(); 
							}
						);
						if(childConfig && childConfig.length)
						{
							child.configuratorEditData = childConfig[0].configuratorEditData || {};
						}
					}
					child.currentParent(self);
					child.updateAtcButtonText();
					child.setupQuestions();

					if(child.questions && child.questions().length > 0) {
						child.questions().forEach(function(question) {
							var childConfig = child.configuratorEditData?.childProducts?.filter(
								function(childProdConfig) {
									return childProdConfig.p_key == child.key(); 
								}
							);
							if (childConfig && childConfig.length)
							{
								childConfig = childConfig[0];
								if(childConfig.configJson && childConfig.configJson.choices)
								{
									var editAnswer = childConfig.configJson.choices.filter(function(item)
									{
										return item.question === question.q_key();
									});
									if(editAnswer && editAnswer.length > 0)
									{
										setSelectedCartOptionAnswer(question, editAnswer);
									}
								}
							}
						});
					}
				});

				_.forEach(self, function (value, key) {
					var keyString = String(key);
					var matched = keyString.match(/^opt(\d)$/);

					if (matched && value) {
						var selector = {};
						selector.field = matched[0];
						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(child[matched[0] + '_sort']) == 'function' ? child[matched[0] + '_sort']() : child[matched[0] + '_sort']) || 0;
									var optSort = (typeof(child[matched[0]]) == 'function' ? child[matched[0]]() : child[matched[0]]) || 0;

									var thisOpt = {
										option: child[matched[0]],
										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.options[0]);
						}

						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 == oChild[selector.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) {
						filter[option.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 filteredChildren[0];
					} else {
						return self;
					}
				});

				self.setupQuestions();
				self.setupAddRowView();
			}

			if (self.children && self.children().length) {
				self.processChildren();
			} else {
				self.selectedProduct = ko.observable(self);
			}

			self.currentlySelectedChildOptions = [];

			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,
						modal: 1,
						modalaction: utils.getParameter("modalaction")
					},
					dataType: 'json',
					success: function(data) {
						var selector = self.childSelectors().find(function(selector) {
							return selector.field == 'opt' + optNumber;
						});

						if(!selector) {
							selector = {
								field: 'opt' + optNumber,
								label: self['opt' + 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();

							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) {
									if (asyncLoadOptions) asyncLoadOptions.done = false;
									self.loadNextSelector(selector.index + 1, callback, asyncLoadOptions);
								} else {
									//load the child
									if (asyncLoadOptions) asyncLoadOptions.done = true;
									self.loadChildProduct(newValue.pKey, callback);
								}
							}else{
								self.selectedProduct(self);
							}
						});
						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 == asyncLoadOptionsArray[index]) selectedOption = value;
								});
							} else if (oConfig.detailConfig.selectChildProductOnLoad) {
								selectedOption = availableOptions[0];
							}
							option.selectedOption(selectedOption);
						}
					}
				})
			}

			self.loadChildProduct = function(pKey, callback) {
				$.ajax({
					url: oConfig.pageName, //current page.
					data: {
						ajax: 'get-child-product',
						key: pKey,
						parentKey: oConfig.mainProductKey,
						modal: 1,
						modalaction: utils.getParameter("modalaction"),
						action: utils.getParameter("action") == 'showpricetrace' ? 'showpricetrace' : ''
					},
					dataType: 'json',
					success: function(data) {
						var product = ko.mapping.fromJS(data.products[0], productMapping);
						product.type = "child";
						// self.children.push(product);
						if(self.questions && self.questions().length && (oConfig.useCartOptions && 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();
						if(!product.configuratorEditData) {
							var childConfig = self.configuratorEditData?.childProducts?.filter(
								function(childProdConfig) {
									return childProdConfig.p_key == product.key(); 
								}
							);
							if(childConfig && childConfig.length)
							{
								product.configuratorEditData = childConfig[0].configuratorEditData || {};
								self.configuratorEditData.qty = childConfig[0].qty;
								self.configuratorEditData.uom = childConfig[0].uom;
								self.configuratorEditData.maxQty = childConfig[0].maxQty;
								self.configuratorEditData.minQty = childConfig[0].minQty;
								self.configuratorEditData.pw_id = childConfig[0].pw_id;
							} else {
								product.configuratorEditData = self.configuratorEditData;
							}
						}
						product.updateAtcButtonText();
						self.selectedProduct(product);
						self.currentlySelectedChildOptions = self.childSelectors().map(function(childSelector) { return childSelector.selectedOption(); });
						runHook('productDetailLoadChildProductSuccess', { self: self, product: product });
					},
					error: function() {
						utils.popToastrError('Error Loading Product', 'There was an error loading the product');
					},
					complete: callback
				});
			}

			self.quantityRestrictionsHtml.subscribe(function(newValue) {
				var popoverElement = $('#pop-' + $.escapeSelector(self.sku().replace(/([^A-Za-z0-9[\]{}_.:-])\s?/g, '_')));
				if(popoverElement){
					var popoverData = popoverElement.data('popover');
					if (popoverData) {
						popoverData.options.content = newValue;
					}
				}
			});

			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,
						modal: 1,
						modalaction: utils.getParameter("modalaction")
					},
					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);
							}
							if(!product.configuratorEditData) {
								var childConfig = self.configuratorEditData?.childProducts?.filter(
									function(childProdConfig) {
										return childProdConfig.p_key == product.key(); 
									}
								);
								if(childConfig && childConfig.length)
								{
									product.configuratorEditData = childConfig[0].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.children[x] 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') {
					/***** Main method *****/

					// Initial vars
					var rowOpt = '';
					var colOpt = '';
					var swatchOpt = "color_code";

					// Build the matrix
					var rawChildren = self.children();
					var bucketed = bucketChildren(rawChildren, rowOpt, colOpt, swatchOpt);
					bucketed.rowKeys = sortKeys(bucketed.rowKeys);
					bucketed.colKeys = sortKeys(bucketed.colKeys);

					runHook('productDetailMatrixBeforeConstruction', {
						parent: self,
						configs: {
							rowOpt: rowOpt,
							colOpt: colOpt,
							swatchOpt: swatchOpt
						},
						bucketed: bucketed
					});

					var matrix = constructMatrix(bucketed);

					runHook('productDetailMatrixData', {
						parent: self,
						matrix: matrix
					});

					return matrix;
				} else {
					return [];
				}

				/***** Helper functions *****/

				// Find the unique row and column values and their sorts, and index the children.
				function bucketChildren(rawChildren, rowOpt, colOpt, swatchOpt) {
					var initial = {
						products: {},
						rowKeys: {},
						colKeys: {}
					};

					var result = _.reduce(rawChildren, function(acc, cur) {
						var rowLabel = ko.toJS(cur[rowOpt]);
						var rowSort = ko.toJS(cur[rowOpt + '_sort']);
						var rowSwatch = ko.toJS(cur[swatchOpt]);
						var rowThumb = ko.toJS(cur['thumb']);
						var colLabel = ko.toJS(cur[colOpt]);
						var colSort = ko.toJS(cur[colOpt + '_sort']);

						// Index the child
						if (!acc.products[rowLabel]) {
							acc.products[rowLabel] = {};
						}
						acc.products[rowLabel][colLabel] = cur;

						// Keep track of the unique row values
						if (!acc.rowKeys[rowLabel]) {
							acc.rowKeys[rowLabel] = {
								label: rowLabel,
								sort: rowSort,
								swatch: rowSwatch,
								thumb: rowThumb
							};
						}

						// Make sure we have a swatch and thumb
						if (!acc.rowKeys[rowLabel].swatch) {
							acc.rowKeys[rowLabel].swatch = rowSwatch;
						}
						if (!acc.rowKeys[rowLabel].thumb) {
							acc.rowKeys[rowLabel].thumb = rowThumb;
						}

						// Keep track of the unique column values
						acc.colKeys[colLabel] = {
							label: colLabel,
							sort: colSort
						};

						runHook('productDetailMatrixReduce', {
							parent: self,
							configs: {
								rowOpt: rowOpt,
								colOpt: colOpt,
								swatchOpt: swatchOpt
							},
							acc: acc,
							cur: cur
						});

						return acc;
					}, initial);

					runHook('productDetailMatrixBucketed', {
						parent: self,
						configs: {
							rowOpt: rowOpt,
							colOpt: colOpt,
							swatchOpt: swatchOpt
						},
						bucketed: bucketed
					});

					return result;
				}

				// Sort the rowKeys and colKeys
				function sortKeys(obj) {
					var list = _.values(obj);
					var sorted = _.sortBy(list, 'sort');
					return sorted;
				}

				function constructMatrix(bucketed) {
					// Construct the matrix, one row at a time
					var matrix = _.map(bucketed.rowKeys, function(row) {
						// Get values
						var label = row.label || '';
						var swatch = row.swatch || '';
						var thumb = row.thumb || 'images/no-image.png';

						// Generate the columns
						var cols = constructColumns(bucketed, row);

						// Return the results
						var row = {
							label: label,
							swatch: swatch,
							thumb: ko.observable(thumb), // Don't know why this is an observable, so leaving it
							cols: cols
						};

						runHook('productDetailMatrixRow', {
							parent: self,
							bucketed: bucketed,
							row: row
						});

						return row;
					});

					return matrix;
				}

				function constructColumns(bucketed, row) {
					var columns = _.map(bucketed.colKeys, function(col) {
						// Find the product that sits at the intersection of row and col
						var product = bucketed.products[row.label][col.label];

						var col = {
							label: col.label,
							product: product
						};

						runHook('productDetailMatrixCol', {
							parent: self,
							bucketed: bucketed,
							row: row,
							col: col
						});

						return col;
					});

					return columns;
				}
			}).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 product's key
			if (self.key() == oConfig.mainProductKey && self.type === 'parent' && self.childSelectors().length === 0 && getOriginalPageName() === 'pc_product_detail.asp' && self.childDisplayType() == 'droplist') {

				if(!self.opt1 || self.opt1 == ''){
					//force this to stand-alone because it has bad data setup.
					self.type = 'stand-alone';
					console.log('This Parent product is set to "droplist" type but doesn\'t have a value in the opt1 field.  This is required for drop list type products.');
				}else{
					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 = matched[0];
							selector.label = value;
							selector.options = [];
							selector.selectedOption = ko.observable();
							selector.loading = ko.observable(matched[0] === '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.done = false;
						this.getArray = function() {
							if (this.done) return [];
							if(self.currentlySelectedChildOptions && self.currentlySelectedChildOptions.length) {
								return self.currentlySelectedChildOptions.map(function(selectedOption) {return selectedOption.option; } );
							} else {
								return oConfig.childOptionList;
							}
						}
					})());
				}
			}

			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.enableMulitRowAddToCart = ko.computed(function() {
				var items = self.rowCollection().map(
					function(item) {
						return item.selectedChild();
					}
				).filter(
				function(item) {
					return item !== undefined && item.selectedQty() > 0;
				});
				return items.length > 0;
			});

			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',
				'thumbAltText',
				'picAltText',
				'addOnLabel',
				'opt1',
				'opt2',
				'opt3',
				'opt4',
				'opt5',
				'opt6'
			];

			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 = self[propName.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 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{
                    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())
				}

				//Handle Tab Inheritance at the individual tab instead of the array of tabs
				var newTabs = [];
				for(i=1; i <= oConfig.detailConfig.numberOfProductTabs; i++){
					var parentTab = _.filter(self.currentParent().tabs, function(tab){ return tab.index == i})[0];
					var childTab  = _.filter(self.tabs,                 function(tab){ return tab.index == i})[0];
					if(childTab){
						newTabs.push(childTab);
					}else if(!childTab && parentTab){
						//Inherit from the parent
						newTabs.push(parentTab);
					}
				}
				if(newTabs){
					self.tabs = newTabs;
				}

			}

			if (self.showAddOns)  {
				if (self.addOnDisplay == 'checkboxes')
					self.selectedAddOns = ko.observableArray([]);
				else //             ^ note difference in plural
					self.selectedAddOn  = ko.observable();
			}

			self.addOnOptions = function(){
				var options = [];
				
				if(self.addOns){
					options = _.map(self.addOns(), function(product){
						product.selectedQty(product.minQty() || 1);
						return ko.observable(product)
					})
				}
				return options;
			}();

			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.changeRpp = function (value) {
				var sUrl = utils.setParameter('rpp', value);
				sUrl = sUrl + '&page=1';
				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>
	$(function () {
		if(typeof(ko) != 'undefined'){
			ko.applyBindings();
		}
	});
	
</script>
</div>

<div class="cart-templates-scripts">
<script type="text/javascript">

    addTimer("start of ko model");
    $( document ).ready(function() {

        if('default.asp' == 'payment.asp' ){
            $(document).on('hidden', '#global_modal', function () {
                if( $('#handle-modal-exit').val() == 'true'){
                    $('#handle-modal-exit').val(false);
                    viewModel.genericModalComplete();
                }
            });
        }
        addTimer("cart_templates: document.ready");

    });

    function emptyHandler(){}

    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 (window['insightRUM']) {
			insightRUM.rawErrors.push(["Error", sPageName, 1, 1, new Error(message.substring(0,149))]);
		}
	}

    function buildContinueShoppingUrl() {
        var url = ofConfig.continueShopPage;
        if (ofConfig.guestLoggedIn) {
            url = utils.setParameter('action', 'logout', url);
        } else if (ofConfig.superUserOrderFormMode) {
            url = ofConfig.createNewQuoteLink;
        }
        return url;
    }

    function drawContinueShoppingLabel() {
        var label = '<i class="icon-shopping-cart"></i> Continue Shopping';
        var su_workflow = '';
        if (su_workflow === "quote") {
            label = '<i class="icon-plus"></i> Create New ' + su_workflow;
        }
        return label;
    }

    function isValidRequestedDate(date) {
		try {
			isBusinessDay = businessDaySettings[1][""].work_days_of_week == undefined || businessDaySettings[1][""].work_days_of_week.indexOf(date.getDay()+1) > -1;
			isHoliday = businessDaySettings[1][""].holiday_dates != undefined && businessDaySettings[1][""].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 > businessDaySettings[1][""].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.useMultiShipEditUI()) || (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) {
             jQuery.ajax({
                url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=setActiveQuote&quote_id=' + orderKey + '&randomnum=' + new Date().getTime()
                , cache: false
                , success: function(data,status,request){

                }
                , error: function(data) {
                    alert('Failed to set order as active quote.');
                }
                , complete: function(data) {
                }
            });
        }
    }

    utils.removeActiveQuote = function (bStartNewQuote) {
        utils.setActiveQuote('');
        if(bStartNewQuote){
            window.location = 'payment.asp' + (ofConfig.isModal ? '?modal=1' : '');
        }else{
            $('.active-quote-message').hide();
        }
    };

    var orderInfoPostUrl = 'payment.asp'; //'https://' + window.location.hostname + window.location.pathname;
    var orderInfoPostApiUrl = "/ordering/";
    var countries = [];
    var newCustomer = false;
    var viewModel;
    var order;

    function addAddressHandler() {
        viewModel.genericModalComplete();
        //viewModel.allocateShipments(false);
        apiGetShippingAddresses();
    }

    function changeAddressFromFinder(response, object){
        console.log(response);
        var address = new addressInfo({ key: response.sha_key.value, state: '', city: '', zipCode: '', country: '', name: response.sha_key_disp.value, address1: '', global: 0 });
        object.shipTo(address);
    }

    function getAddressOptFields(){
        var addressOptFields = [];
        for(i=1; i <= 5; i++){
            if(ofConfig['showAddressOpt'+i]){
                addressOptFields.push(i);
            }
        }
        return addressOptFields;
    }

    function apiGetShippingAddresses(editedKey) {
        $.ajax({
            url: orderInfoPostUrl + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=apiGetShippingAddresses',
            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.name(newItem.name());
                                oldItem.phone(newItem.phone());
                                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.opt1(newItem.opt1());
                                oldItem.opt2(newItem.opt2());
                                oldItem.opt3(newItem.opt3());
                                oldItem.opt4(newItem.opt4());
                                oldItem.opt5(newItem.opt5());
                                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",
            opt1: "",
            opt2: "",
            opt3: "",
            opt4: "",
            opt5: "",
            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(dd<10) {
            dd='0'+dd
        }

        if(mm<10) {
            mm='0'+mm
        }

        today = yyyy+mm+dd+'-'+rand;
        return today;
    }

    var StateChoice = function(code, name) {
        var self = this;

        var choice = {};
        choice["code"] = code;
        choice["name"] = name;

        ko.mapping.fromJS(choice, {}, self);
    }

    var detailLineInstanceSort = function (a, b) {
            var aInstance = a.instance();
            var bInstance = b.instance();
            var aLineNum = a.orderDetailNum();
            var bLineNum = b.orderDetailNum();
            var aParentId = a.parentProductID().trim();
            var bParentId = b.parentProductID().trim();

            if(aInstance == bInstance) {
                return (aParentId < bParentId) ? -1 : (aParentId > bParentId) ? 1 : 0;
            } else {
                return (aLineNum < bLineNum) ? -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();
        }

        // Order JSON returns isGlobalAddress while the rest of the template loads in data relying on global
        if('isGlobalAddress' in addressData && !('global' in addressData)){
            addressData.global = addressData.isGlobalAddress;
        }
        
        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 self[prop] === 'function') {
                if(self[prop]() === null || self[prop]() === 'null') {
                    self[prop]('');
                }
            }
        }

        self.address1.extend({ required: true });
        self.country.extend({ required: true });
        self.city.extend({ required: false });
        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.isParentConfigurator = options.data.orderDetail.commodity.parentChildType == 'parent' && options.data.orderDetail.configuratorJson.configType == 'configurator' && (options.data.orderDetail.configuratorJson.childProducts?.length ?? 0) > 0;
                    options.data.orderDetail.isChildConfigurator = options.data.orderDetail.commodity.parentChildType == 'child' && options.data.orderDetail.configuratorJson.configType == 'configurator' && options.data.orderDetail.removeType == 'hide' && (options.data.orderDetail.parentProductID?.trim() ?? '') != '';
                    options.data.orderDetail.editing = false;
                    if (!options.data.orderDetail.thumbnail) {
                        options.data.orderDetail.thumbnail = options.data.orderDetail.commodity.pic.thumb;
                    }
                    if (!options.data.orderDetail.configCarrierOrderDetailId || options.data.orderDetail.configCarrierOrderDetailId.trim() == '') {
                        options.data.orderDetail.configCarrierOrderDetailId = '';
                    }

                    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 && item.orderDetail.qtyDisplayType() != 'input';
                                        }).map(function(item) { return item.orderDetail; }) || [];

            var mainProduct = detailLine;

            if(!detailLine.isChildConfigurator()){
                var mainProductArray = self.details().filter(function(item) {
                                                return (!item.orderDetail.isParentConfigurator() && item.orderDetail.instance() == detailLine.instance() && item.orderDetail.removeType() == 'instance')
                                                       || (item.orderDetail.isChildConfigurator() && item.orderDetail.orderDetailKey() == detailLine.parentProductID() && detailLine.rowDisplayCase() != 'group-parent-odkey');
                                            });
                mainProduct = mainProductArray.length > 0 ? mainProductArray[0].orderDetail : detailLine;
            }

            var mainProductQty = mainProduct.qty();

            detailLine.instanceUnitPrice = ko.observable(self.details().reduce(function(current, item) {
                if(!ofConfig.showProductDiscount){
                    item.orderDetail.priceBeforeAdjustment(item.orderDetail.price());
                }
                if(detailLine.rowDisplayCase() == 'group-parent-odkey' && item.orderDetail.orderDetailKey() == detailLine.orderDetailKey() ){
                    return (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price());
                } else if(item.orderDetail.instance() == detailLine.instance() && (item.orderDetail.rowDisplayCase() != 'group-parent-odkey' ) && (detailLine.rowDisplayCase() != 'group-parent-odkey' ) ) {
                    //This IF block is attempting to account for calculating the unit price on "nested" configurator lines.  Any other product type should fall into
                    //  The else block so it just pulls the quantity from the od lines.
                    //TODO:  Account for configurator products AND split by address as this calculation will likely not work in that scenario.
                    //       In this scenario, it should use the extended quantity on the shipment not the one from the OD line.
                    if(item.orderDetail.parentProductID().trim() != '' && item.orderDetail.removeType() != 'instance' && item.orderDetail.removeType() != 'OD_Key' && item.orderDetail.orderDetailKey() != detailLine.orderDetailKey()) {
                        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.instanceUnitPriceDisplay = ko.computed(function(){
                if(detailLine.isParentConfigurator()){
                    return '';
                }
                return utils.formatMoney(detailLine.instanceUnitPrice(), utils.decimalPlacesOnUnitPrices);
            });

            detailLine.instanceExtPrice = ko.observable(self.details().reduce(function(current, item) {
                if(detailLine.isParentConfigurator()){
                    return '';
                }
                if(detailLine.rowDisplayCase() == 'group-parent-odkey' && item.orderDetail.orderDetailKey() == detailLine.orderDetailKey() ){
                    return (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()) * item.qtyToShip();
                } else if(item.orderDetail.instance() == detailLine.instance() && (item.orderDetail.rowDisplayCase() != 'group-parent-odkey' && detailLine.rowDisplayCase() != 'group-parent-odkey' ) ) {
                //if(item.orderDetail.instance() == detailLine.instance() && (item.orderDetail.parentProductID() != detailLine.orderDetailKey() && detailLine.parentProductID() != item.orderDetail.orderDetailKey() ) ) {
                //if(item.orderDetail.instance() == detailLine.instance() && (item.orderDetail.rowDisplayCase() != 'group-parent-odkey' || item.orderDetail.orderDetailKey() == detailLine.orderDetailKey()) ) {
                    return current += (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()) * item.qtyToShip();
                    // return current += item.orderDetail.extTotal();
                } else {
                    return current;
                }
            },0));
        });

        self.details().forEach(function(item) {
            item.orderDetail.configIndependentProducts = self.details().filter(function(configLine) {
                return configLine.orderDetail.parentProductID() == item.orderDetail.orderDetailKey()
                        && configLine.orderDetail.instance() == item.orderDetail.instance() 
                        && configLine.orderDetail.removeType() == 'OD_Key';
            });

            if(typeof item.orderDetail.configIndependentProducts === 'undefined' || !item.orderDetail.configIndependentProducts) {
                item.orderDetail.configIndependentProducts = [];
            }

            item.orderDetail.configParentOrderDetailID = ko.observable(
                self.details().reduce(function(configParentKey, configParent) {
                    if(configParentKey != '') return configParentKey;
                    if(item.orderDetail.isParentConfigurator()) return item.orderDetail.orderDetailKey();
                    if(item.orderDetail.instance() != configParent.orderDetail.instance()) return configParentKey;
                    if(item.orderDetail.parentProductID() == configParent.orderDetail.productID()) return configParent.orderDetail.orderDetailKey();
                    return configParentKey;
                }, '')
            );
        });

        self.details.sort(shipmentDetailsInstanceSort);

        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(self.selectedShipVia.effectiveOrderDate()).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(self.selectedShipVia.effectiveOrderDate()).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('');
            self.selectedShipVia.sv_ref_id = ko.observable('');
        };

        if(self.shipViaChoices && self.shipViaChoices().length > 0){
            self.selectedShipViaChoice = ko.observable(self.shipViaChoices().find(function(choice) {
                return (choice.shipViaChoiceKey() == self.selectedShipVia.shipViaChoiceID() || choice.shipViaRefID() == self.selectedShipVia.sv_ref_id());
            }) || self.shipViaChoices()[0]);
        }else{
            self.selectedShipViaChoice = ko.observable();
        }

        self.shipToValid = ko.computed(function() {
            return ko.validatedObservable(self.shipTo()).isValid();
        });

        self.saveShipToAddress = function(shipment) {

            var shipmentArray = [];

            var details = shipment.details().map(function(map, index, array) {
                return {
                    orderDetailId : map.orderDetailId(),
                    qtyToShip: map.qtyToShip()
                }
            });

            var shipmentInfo = {
                "Key": shipment.key(),
                "ShipmentId": shipment.key(),
                "ShipTo": {
                    key         : shipment.shipTo().key(),
                    name        : shipment.shipTo().name(),
                    company     : shipment.shipTo().company(),
                    attention   : shipment.shipTo().attention(),
                    address1    : shipment.shipTo().address1(),
                    address2    : shipment.shipTo().address2(),
                    address3    : shipment.shipTo().address3(),
                    address4    : shipment.shipTo().address4(),
                    address5    : shipment.shipTo().address5(),
                    city        : shipment.shipTo().city(),
                    state       : shipment.shipTo().state(),
                    zipCode     : shipment.shipTo().zipCode(),
                    county      : shipment.shipTo().county(),
                    country     : shipment.shipTo().country(),
                    email       : shipment.shipTo().email(),
                    firstName   : shipment.shipTo().firstName(),
                    lastName    : shipment.shipTo().lastName(),
                    phone       : shipment.shipTo().phone(),
                    global      : shipment.shipTo().global(),
                    opt1        : shipment.shipTo().opt1(),
                    opt2        : shipment.shipTo().opt2(),
                    opt3        : shipment.shipTo().opt3(),
                    opt4        : shipment.shipTo().opt4(),
                    opt5        : shipment.shipTo().opt5()
                },
                "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_prods[tabindex="-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 + '?ajax=true&pageaction=setShipmentShipVia&o_key=' + viewModel.orderKey()  + '&shipViaChoiceKey=' + shipViaChoiceKey + '&shipmentKey=' + shipmentKey,
                error: function() {
                    alert('error setting Shipping Method');
                }
            }

            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) {

            if (!(newRequestedShipDate instanceof Date) || isNaN(newRequestedShipDate.valueOf())) {
                console.log('requestedShipDate is not a date');
                return;
            }

            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) {
        addTimer("start order mapping");
        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.isParentConfigurator = options.data.commodity.parentChildType == 'parent' && options.data.configuratorJson.configType == 'configurator' && (options.data.configuratorJson.childProducts?.length ?? 0) > 0;
                    options.data.isChildConfigurator = options.data.commodity.parentChildType == 'child' && options.data.configuratorJson.configType == 'configurator' && options.data.removeType == 'hide' && (options.data.parentProductID?.trim() ?? '') != '';
                    options.data.parentProductID  = options.data.parentProductID.trim() || '';
                    options.data.editing = false;
                    options.data.uomConversion = !options.data.uomConversion ? 1 : options.data.uomConversion;
                    options.data.minQty = oConfig.convertMinQtyFromStdToSalesUom(options.data.minQty, options.data.uomConversion);
                    options.data.maxQty = oConfig.convertMaxQtyFromStdToSalesUom(options.data.maxQty, options.data.uomConversion);
                    options.data.qtyIncrement = (options.data.uomConversion == 0 || options.data.uomConversion === 1) ? (options.data.qtyIncrement || oConfig.defaultQuantityIncrement) : 0;
                    if (!options.data.thumbnail) {
                        options.data.thumbnail = options.data.commodity.pic.thumb;
                    }
                    if (!options.data.configCarrierOrderDetailId || options.data.configCarrierOrderDetailId.trim() == '') {
                        options.data.configCarrierOrderDetailId = '';
                    }
                    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({
                            key: "",
                            vaultKey: "",
                            nickName: "",
                            nameOnCard: "",
                            cardType: "",
                            expMonth: 0,
                            expYear: 0,
                            first2: "0",
                            last4: "0",
                            address1: "",
                            address2: "",
                            city: "",
                            state: "",
                            zip: "",
                            country: "",
                            status: true,
                            merchantId: "",
                            customerId: "",
                            accountId: "",
                            gatewayInfoDirty: false,
                            accountLast4: "",
                            achAccountType: "",
                            bankName: "",
                            routingLast4: "",
                            type: "",
                            customerProfileId: ""
                        });
                    } 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' || moment(date).format("MM/DD/YYYY") == '01/01/2001'){
                        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.disablePlaceOrder = ko.observable(false);

        self.detailLines().forEach(function(detailLine) {
            // We can't debounce/trottle an observable
            // so we add a computed to track qty changes.
            // We use this in a subscription to call
            // update cart to update qty change in bulk atc
            // to avoid loading the qty change without posting
            // and updating the entire order model (for perf)
            detailLine.qtyTracker = ko.computed(function() {
                return detailLine.qty();
            }).extend({throttle: 500});
            detailLine.qtyTracker.subscribe(function (newQty) {
                self.postQtyUpdate();
            }, detailLine);
            
            detailLine.workerPriceTracker = ko.computed(function() {
                return detailLine.price();
            }).extend({throttle: 500});
            detailLine.workerPriceTracker.subscribe(function (newQty) {
                self.setWorkerPriceOverride(detailLine);
            }, detailLine);

            detailLine.workerQtyLimitsTracker = ko.computed(function() {
                return {
                    removeType: detailLine.removeType(),
                    minQty: detailLine.minQty(),
                    maxQty: detailLine.maxQty(),
                    qtyIncrement: detailLine.qtyIncrement()
                };
            }).extend({throttle: 500});
            detailLine.workerQtyLimitsTracker.subscribe(function (newValue) {
                self.setWorkerQtyLimits(detailLine);
            });

            detailLine.instanceChildren = self.detailLines().filter(function(item) {
                                            return item.instance() == detailLine.instance() && item != detailLine && item.rowDisplayCase() != 'group-parent-odkey';
                                        }) || [];

            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(!ofConfig.showProductDiscount){
                    item.priceBeforeAdjustment(item.price());
                }
                if(detailLine.rowDisplayCase() == 'group-parent-odkey' && item.orderDetailKey() == detailLine.orderDetailKey() ){
                    return (item.priceBeforeAdjustment() || item.price());
                } else if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' ) && (detailLine.rowDisplayCase() != 'group-parent-odkey' ) ) {
                    //if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' || item.orderDetailKey() == detailLine.orderDetailKey() ) ) {
                    if(item.parentProductID().trim() != '' && item.removeType() != 'instance' && item.removeType() != 'OD_Key' && item.orderDetailKey() != detailLine.orderDetailKey()) {
                        return current += ((item.priceBeforeAdjustment() || item.price()) * item.qty()) / mainProductQty;
                    } else {
                        return current += (item.priceBeforeAdjustment() || item.price());
                    }
                } else {
                    return current;
                }
            },0));

            detailLine.instanceUnitPriceDisplay = ko.computed(function(){
                if(detailLine.isParentConfigurator()){
                    return '';
                }
                return utils.formatMoney(detailLine.instanceUnitPrice(), utils.decimalPlacesOnUnitPrices);
            });

            detailLine.instanceExtPrice = ko.observable(self.detailLines().reduce(function(current, item) {
                if(detailLine.isParentConfigurator()){
                    return '';
                }
                if(detailLine.rowDisplayCase() == 'group-parent-odkey' && item.orderDetailKey() == detailLine.orderDetailKey() ){
                    return item.extTotal();
                } else if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' ) && (detailLine.rowDisplayCase() != 'group-parent-odkey' ) ) {
                //if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' || item.orderDetailKey() == detailLine.orderDetailKey()) ) {
                    return current += item.extTotal();
                } else {
                    return current;
                }
            },0));

            detailLine.hasQuantityRestrictions = ko.computed(function () {
                return !!(
                            (detailLine.minQty() && detailLine.minQty() !== oConfig.defaultMinimumQuantity) || 
                            ((!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() !== oConfig.defaultMinimumQuantity) || 
                            detailLine.maxQty()
                        );
            });

			detailLine.quantityRestrictionsHtml = ko.computed(function () {
				var lines = [];

				if (detailLine.minQty() && detailLine.minQty() != oConfig.defaultMinimumQuantity)
					lines.push(oConfig.labels.minQtyPopover.replace(/<min_qty>/,detailLine.minQty()));

                if ( (!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() != oConfig.defaultQuantityIncrement)
                    lines.push('Qty Increment: ' + detailLine.qtyIncrement());

				if (detailLine.maxQty())
					lines.push('Maximum Qty: ' + detailLine.maxQty());

				return lines.join('<br>');
			});
        });

        self.detailLines().forEach(function(detailLine) {
            detailLine.configIndependentProducts = self.detailLines().filter(function(configLine) {
                return configLine.parentProductID() == detailLine.orderDetailKey()
                        && configLine.instance() == detailLine.instance() 
                        && configLine.removeType() == 'OD_Key';
            });

            if(typeof detailLine.configIndependentProducts === 'undefined' || !detailLine.configIndependentProducts) {
                detailLine.configIndependentProducts = [];
            }

            detailLine.configParentOrderDetailID = ko.observable(
                self.detailLines().reduce(function(configParentKey, configParent) {
                    if(configParentKey != '') return configParentKey;
                    if(detailLine.isParentConfigurator()) return detailLine.orderDetailKey();
                    if(detailLine.instance() != configParent.instance()) return configParentKey;
                    if(detailLine.parentProductID() == configParent.productID()) return configParent.orderDetailKey();
                    return configParentKey;
                }, '')
            );
        });

        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() + '&origin=bill-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 products to shipment');
                },
                complete: function() {
                    self.processing(false);
                }
            }

            postInfo(postOptions, 'updateShipToAddress');

            $('#modal_add_prods[tabindex="-1"]:hidden').remove()
            $('#modal_add_prods').modal('hide');
        };

        self.isOverLineLimit = ko.observable(checkLineLimit(self));

        function checkLineLimit(vm){
            //use the alternate ui (showcart.asp) when over the line limit threshold
            // Don't allow this to happen if using user create shipments since the showcart page doesn't support
            // Split shipping.
            if(oConfig.allowUserCreatedShipments){
                return false;
            }else if (ofConfig.useTooManyLinesRestriction && vm.detailLines().length >= parseInt(ofConfig.tooManyLinesQuantity)){
                return true;
            }else{
                return false;
            }
        }

        self.isMinimumOrderTotalMet = ko.observable(checkOrderTotal(self));
        //moved definition to global scope

        self.shippingComplete = ko.observable(isShippingComplete());

        function isShippingComplete(){
            if ( self.completed() || self.lifecycleStage() == 'cancelled' || self.lifecycleStage() == 'punchout_punched_in') {
                return true;
            }

            // force step 2 if there are no lines on the order.
            if (self.detailLines().length == 0){
                return false;
            }

            // force step 3 if the lines exceed the limit.
            if (self.isOverLineLimit()){
                return true;
            }

            // force step 2 if any shipments are missing an address.
            _.each(self.shipments(),function(shipment){
                if(!shipment.shipTo().key()){
                    return false;
                }
            });

            if(!self.isMinimumOrderTotalMet()){
                utils.setCookie(self.orderKey() + '-step', '2');
            }

            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, detailLine){
            if(detailLine && (detailLine.isParentConfigurator() || detailLine.isChildConfigurator())){
                return detailLine.qty();
            }
            if(detailLine && detailLine.isParentConfigurator()){
                return detailLine.qty();
            }
            var totalQty = 0;
            var mappings = self.itemsOnOrder();
            if(self.useMultiShipEditUI && self.useMultiShipEditUI()){
                mappings = self.itemShipToMap();
            }
            _.each(mappings, 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.setWorkerPriceOverride = function(data){
            var orderDetail = [];

            orderDetail.push({
                orderDetailKey: data.orderDetailKey(),
                PriceCalculationType: 'fixed',
                Price: data.price(),
                PriceBeforeAdjustment: data.price()
            });

            var postOptions = {
                data: "orderDetail=" + encodeURIComponent(JSON.stringify(orderDetail)),
                success: function(data) {
                    $('#cartAdvSettings.collapse').toggleClass('in'); 
                    $('#onOrderAdvBtn').toggleClass('active');
                },
                error: function() {
                    alert('Error saving Unit Price');
                }
            }

            postInfo(postOptions, 'setOrderDetailFields');
        }

        self.setWorkerQtyLimits = function(data) {
            var orderDetail = [];

            orderDetail.push({
                orderDetailKey: data.orderDetailKey(),
                MinQty: data.minQty() * data.uomConversion(),
                MaxQty: data.maxQty() * data.uomConversion(),
                QtyIncrement: data.qtyIncrement(),
                RemoveType: data.removeType()
            });

            var postOptions = {
                data: "orderDetail=" + encodeURIComponent(JSON.stringify(orderDetail)),
                success: function(data) {
                    $('#cartAdvSettings.collapse').toggleClass('in');
                    $('#onOrderAdvBtn').toggleClass('active');
                    toggleLoadingWidget(false);
                },
                error: function() {
                    alert('Error saving qty limits');
                }
            }
            toggleLoadingWidget(true);
            postInfo(postOptions, 'setOrderDetailFields');
        }

        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 resetting Price Override');
                }
            }

            postInfo(postOptions, 'setOrderDetailFields');
        };

        self.resetSuperUserShippingPrice = function(data){
            var postOptions = {
                url: "payment.asp?o_key=" + viewModel.orderKey() + "&svc_key=" + data.shipViaChoiceKey() + '&ajax=true&pageaction=resetShippingPrice&randomnum=' + new Date().getTime() ,
                success: function(data) {
                },
                error: function() {
                    alert('error resetting shipping price');
                }
            }

            postInfo(postOptions, 'resetSuperUserShippingPrice');
        }

        self.returnToPendingOrders = function() {
            window.location = 'quotes.asp?revert=1';
        }

        self.superUserOrderFormMode = ko.observable(ofConfig.superUserOrderFormMode && ofConfig.isSuperUserSession);

        self.getOrderLabel = function(){
            switch(self.recordType()){
                case 'future-order':
                    orderLabel = 'Future Order';
                    break;
                case 'recurring-order':
                    orderLabel = 'Recurring Order';
                    break;
                case 'saved-cart':
                    orderLabel = ofConfig.SavedCartLabel;
                    break;
                default:
                    if(self.superUserOrderFormMode()){
                        orderLabel = ofConfig.SavedCartLabel;
                    }else{
                        orderLabel = 'Order';
                    }
                    break;
            }
            //TODO: once we confirm this logic, return the calculated label instead of the Option.
            //return orderLabel;
            return ofConfig.SavedCartLabel;
        };

        self.superUserSetShipViaPrice = function(data, event){
            var postOptions = {
                url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&svc_key=' + data.shipViaChoiceKey() + '&price=' + event.target.value + '&ajax=true&pageaction=setShippingPrice&randomnum=' + new Date().getTime(),
                success: function(data) {
                },
                error: function() {
                    alert('error resetting shipping price');
                }
            };
            postInfo(postOptions, 'setShippingPrice');
        };

        self.postQtyUpdate = function() {

            var postUrl = 'i_i_add_to_cart.asp' + '?ajax=qtyUpdate&modal=1&o_key=' + viewModel.orderKey();
            var dataString = '';
            var unqString = '';
            var keyCount = 0;

            self.detailLines().forEach(function(detailLine) {
                if(dataString.length) dataString += '&';
                dataString += 'qty_' + detailLine.orderDetailKey() + '=' + detailLine.qty();
                if(unqString.length) unqString +=',';
                unqString += detailLine.orderDetailKey();
            });

            dataString += '&unqs=' + unqString;

            var postOptions = {
                url: postUrl,
                type: "POST",
                data: dataString,
                success: function(data) {
                    //
                },
                error: function() {
                    alert('error updating quantity');
                }
            }

            postInfo(postOptions, '','');
        }

        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: []
                };

                //JB - loop the items on order since we're in single shipment mode.
                viewModel.itemsOnOrder().forEach(function(item){
                    shipmentInfo.Details.push( {
                        OrderDetailId:  item.orderDetailKey(),
                        QtyToShip: item.qty()
                    });
                });
                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() : oConfig.defaultQuantityIncrement);

                    // 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() + '&ajax=true&pageaction=checkPromos&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 ? '&modal=1' : ''));
                                    document.location = 'promo_reward_selection.asp?quickadd=1&next_page=' + nextPage + '&o_key=' + viewModel.orderKey() + (ofConfig.isModal ? '&modal=1' : '');
                                }
                            }
                            , error: function(data) {
                                console.log('Error checking Promos');
                            }
                            , complete: function(data) {
                            }
                        });
                    }
                },
                error: function() {
                    self.addShipment();
                    autoAllocateItems();
                    alert('error saving product list on shipment');
                }
            }

            postInfo(postOptions, 'updateShipToAddress');
            if(moveToNextStep === undefined) {
                moveToNextStep=true;
            }
            if(self.isOverLineLimit()){
                moveToNextStep = true;
            }
            console.log(self);
            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(response[0].Errors).length == 0) {
                        //document.location = 'payment.asp?o_key=' + viewModel.orderKey() + '#checkout_confirmation';
                        scrollToSection('#checkout');
                    }else{
                        scrollToSection('#checkout');
                    }
                },
                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.addShipment = function() {

            var newShipment = getNewShipment();

            var successFunction;

            if(self.shipments().length === 0) {
                /* EJ - 2016-11-15
                   I feel dirty about this, but it's 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 doesn't 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 I'm 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 didn't 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 Shipping Method');
                },
                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_addressbook[tabindex="-1"]:hidden').remove()
            $('#modal_addressbook').modal('hide');
        };

        self.showNewAddressForm = function(shipment) {
            shipment.shipTo(new addressInfo(getNewAddress()));

            $('#modal_addressbook[tabindex="-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", poNumber);
        });

        self.comments.subscribe(function(newComments) {
            postOrderHeaderField("comment", newComments);
        });

        self.nickname.subscribe(function(nickname) {
            postOrderHeaderField("nickname", nickname);
        });

        self.orderCcEmail.subscribe(function(orderCcEmail) {
            postOrderHeaderField("order_cc_email", orderCcEmail);
        });

        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(parts[2], 10);
            var month = parseInt(parts[1], 10);
            var year = parseInt(parts[0], 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))
                monthLength[1] = 29;

            // Check the range of the day
            return day > 0 && day <= monthLength[month - 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", roRunDate);
        });

        self.roRecCase.subscribe(function(roRecCase) {
            postOrderHeaderField("ro_rec_case", roRecCase);
        });

        self.roRecQty.subscribe(function(roRecQty) {
            postOrderHeaderField("ro_rec_qty", 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 = noteBookPayload[0].nb_key;
                noteBook.id    = noteBookPayload[0].id;
                noteBook.refId = noteBookPayload[0].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) {
                orderHeaderFieldsJson[sField] = orderHeaderFields[sField];
            });

            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.refID() != viewModel.paymentMethod.refID()){
                var postOptions = {
                    data: "pm_id=" + paymentMethod.paymentMethodKey(),
                    error: function(data) {
                        alert('error setting pm');
                    },
                    success: function() {
                        $('#ccpm_container').removeClass('hide');
                        if(paymentMethod.paymentType() == 'cc') {
                            oSavedPaymentMethodsCreditCard.updateSelectedCardFromList();
                        } else if(paymentMethod.paymentType() == 'ach-check') {
                            oSavedPaymentMethodsCreditCard.updateSelectedAchFromList();
                        }
                        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'
                                || detailLine.isChildConfigurator());
                    }).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'
                                || detailLine.parentProductID() == outerLine.commodity.productKey()
                                || detailLine.configCarrierOrderDetailId() == outerLine.orderDetailKey());
                    }).length > 0
                }());

                detailLine.instanceChildren = self.detailLines().filter(function(item) {
                    return item.instance() == detailLine.instance() && (item.removeType() != 'instance' || item.isChildConfigurator()) && item.parentProductID().trim() != '' && item != detailLine && item.rowDisplayCase() != 'group-parent-odkey';
                }) || [];

                /*
                var mainProduct = self.detailLines().filter(function(item) {
                                                return item.instance() == detailLine.instance() && item.removeType() == 'instance';
                                            })[0] || detailLine;
                */

                var mainProduct = detailLine;

                if(!detailLine.isChildConfigurator()){
                    var mainProductArray = self.detailLines().filter(function(item) {
                                                    return (!item.isParentConfigurator() && item.instance() == detailLine.instance() && item.removeType() == 'instance')
                                                        || (item.isChildConfigurator() && item.orderDetailKey() == detailLine.parentProductID() && detailLine.rowDisplayCase() != 'group-parent-odkey');
                                                });
                    mainProduct = mainProductArray.length > 0 ? mainProductArray[0] : detailLine;
                }

                var mainProductQty = mainProduct.qty();

                detailLine.superUserMinPrice = ko.observable(detailLine.commodity[ofConfig.superUserMinPriceProperty]() || 0);

                detailLine.instanceUnitPrice = ko.observable(self.detailLines().reduce(function(current, item) {
                    if(!ofConfig.showProductDiscount){
                        item.priceBeforeAdjustment(item.price());
                    }
                    if(detailLine.rowDisplayCase() == 'group-parent-odkey' && item.orderDetailKey() == detailLine.orderDetailKey() ){
                        return (item.priceBeforeAdjustment() || item.price());
                    } else if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' ) && (detailLine.rowDisplayCase() != 'group-parent-odkey' ) ) {
                        //if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' || item.orderDetailKey() == detailLine.orderDetailKey()) ) {
                        if(item.parentProductID().trim() != '' && item.removeType() != 'instance' && item.removeType() != 'OD_Key' && item.orderDetailKey() != detailLine.orderDetailKey()) {
                            return current += ((item.priceBeforeAdjustment() || item.price()) * item.qty()) / mainProductQty;
                        } else {
                            return current += (item.priceBeforeAdjustment() || item.price());
                        }
                    } else {
                        return current;
                    }
                },0));

                detailLine.instanceUnitPriceDisplay = ko.computed(function(){
                    if(detailLine.isParentConfigurator()){
                        return '';
                    }
                    return utils.formatMoney(detailLine.instanceUnitPrice(), utils.decimalPlacesOnUnitPrices);
                });

                detailLine.instanceExtPrice = ko.observable(self.detailLines().reduce(function(current, item) {
                    if(detailLine.isParentConfigurator()){
                        return '';
                    }
                    if(detailLine.rowDisplayCase() == 'group-parent-odkey' && item.orderDetailKey() == detailLine.orderDetailKey() ){
                        return item.extTotal();
                    } else if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' ) && (detailLine.rowDisplayCase() != 'group-parent-odkey' ) ) {
                    //if(item.instance() == detailLine.instance() && (item.rowDisplayCase() != 'group-parent-odkey' || item.orderDetailKey() == detailLine.orderDetailKey()) ) {
                        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 localGrossMarginPercent = parseInt(detailLine.minGrossMarginPercent() || 0);
                        var val = parseInt(newVal);
                        if(val < localGrossMarginPercent) {
                            val = localGrossMarginPercent;
                        }
                        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 localMminGrossMarginAmount = parseInt(detailLine.minGrossMarginAmount() || 0);
                        var val = parseInt(newVal);
                        if(val < localMminGrossMarginAmount) {
                            val = localMminGrossMarginAmount;
                        }
                        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()) * 1000 ) % ( (detailLine.qtyIncrement() || 1) * 1000 ) / 1000;
                                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
                        /* - not a bug, need to notifySubscribers UI was broken
                        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;
                });

                detailLine.hasQuantityRestrictions = ko.computed(function () {
                    return !!(
                                (detailLine.minQty() && detailLine.minQty() !== oConfig.defaultMinimumQuantity) || 
                                ((!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() !== oConfig.defaultMinimumQuantity) || 
                                detailLine.maxQty()
                            );
                });

                detailLine.quantityRestrictionsHtml = ko.computed(function () {
                    var lines = [];

                    if (detailLine.minQty() && detailLine.minQty() != oConfig.defaultMinimumQuantity)
                        lines.push(oConfig.labels.minQtyPopover.replace(/<min_qty>/,detailLine.minQty()));

                    if ( (!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() != oConfig.defaultQuantityIncrement)
                        lines.push('Qty Increment: ' + detailLine.qtyIncrement());

                    if (detailLine.maxQty())
                        lines.push('Maximum Qty: ' + detailLine.maxQty());

                    return lines.join('<br>');
                });
            });

            self.detailLines().forEach(function(detailLine) {
                detailLine.configIndependentProducts = self.detailLines().filter(function(configLine) {
                    return configLine.parentProductID() == detailLine.orderDetailKey()
                            && configLine.instance() == detailLine.instance() 
                            && configLine.removeType() == 'OD_Key';
                });

                if(typeof detailLine.configIndependentProducts === 'undefined' || !detailLine.configIndependentProducts) {
                    detailLine.configIndependentProducts = [];
                }

                detailLine.configParentOrderDetailID = ko.observable(
                    self.detailLines().reduce(function(configParentKey, configParent) {
                        if(configParentKey != '') return configParentKey;
                        if(detailLine.isParentConfigurator()) return detailLine.orderDetailKey();
                        if(detailLine.instance() != configParent.instance()) return configParentKey;
                        if(detailLine.parentProductID() == configParent.productID()) return configParent.orderDetailKey();
                        return configParentKey;
                    }, '')
                );

                items.push(detailLine);
            });

            runHook('ItemsOnOrderArrayBeforeReturn', { detailLines: items });

            return items;
        });
        
        self.detailLines.subscribe(function(){
            self.isMinimumOrderTotalMet(checkOrderTotal(self));
        });
        self.itemsOnOrder.subscribe(function(){
            self.isMinimumOrderTotalMet(checkOrderTotal(self));
        });

        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;
        });
        
        _.each(self.itemShipToMap(), function(item){
            item.qty.subscribe(function () { 
                self.isMinimumOrderTotalMet(checkOrderTotal(self));
            });   
        });

        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.showOrderActionButton = function(data, parent) {
            //override this function for custom logic to show custom buttons
            var sSelectedRefId = self.selectedOrderAction() && self.selectedOrderActionRefId();
            var bShow = data.showButton() && (data.refID() == sSelectedRefId || parent.orderActions().length == 1);

            return bShow;
        };

        self.getAddressFinderId = function(id, data, parent){
            selector = id + '_' + parent.orderDetailKey + '_' + ($.isEmptyObject(data) ? 0 : data.key());
            return selector;
        };

       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.lifecycleStage() == 'punchout_punched_in'){
            self.completed(true);
        }

        self.showConfirmationMessage = ko.observable(function(){
            return (self.completed() || self.lifecycleStage() == 'pending' || self.lifecycleStage() == 'cancelled' || self.selectedLifecycleStage().alwaysShowMessage());
        }())

        self.allowAccountEdits         = ko.observable(self.allowAccountEdits() && ofConfig.AllowAccountEdits);
        self.allowShaEdits             = ko.observable(self.allowShaEdits() && ofConfig.AllowShippingEdits);
        self.allowWarehouseSelection   = ko.observable(ofConfig.allowWarehouseSelection );
        self.superUserRestrictMinPrice = ko.observable(ofConfig.superUserRestrictMinPrice);

        self.postOrderToGoogleAnalytics  = function() {

            if (self.completed() && self.tracked() != '1' ) {

                if(oConfig.t_ga4 && oConfig.t_ga4_analytics != '') {
                    try {

                        var items = [];

                        for(var i = 0; i < self.detailLines().length; i++) {
                            var line = self.detailLines()[i];

                            var item = {
                                item_id: line.sku(),
                                item_name: line.name(),
                                currency: "USD",
                                price: line.price(),
                                quantity: Number(line.qty()),
                                index: i
                            }
                            items.push(item);
                        }

                        if (items.length >= 1) {

                            window.dataLayer = window.dataLayer || [];
                            function gtag(){dataLayer.push(arguments);}

                            gtag("event", "purchase", {
                                transaction_id: self.orderNumber(),
                                affiliation: ofConfig.t_tracking_company,
                                value: self.orderTotal(),
                                tax: self.taxTotal(),
                                shipping: self.shippingTotal(),
                                currency: "USD",
                                coupon: self.couponCode(),
                                items: items
                            });
                        }
                    } catch(err) {
                        console.log(err);
                    } 
                }else if(ofConfig.t_gtm) {
                    try {
                        var productsOrdered = [];
                        var transactionProducts = [];
                        var transactionItems = [];

                        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()
                            });

                            transactionItems.push({
                                'item_id': line.sku(),
                                'item_name': line.name(),
                                'price': line.price(),
                                'quantity': line.qty()
                            });
                        }

                        window.dataLayer.push({ 'pageType' : 'confirmation' });
                        window.dataLayer.push({ 'orderNumber' : self.orderNumber() });
                        window.dataLayer.push({ 'storeName' : ofConfig.t_tracking_company });
                        window.dataLayer.push({ 'productTotal' : self.productTotal() });
                        window.dataLayer.push({ 'shippingTotal' : self.shippingTotal() });
                        window.dataLayer.push({ 'taxTotal' : self.taxTotal() });
                        window.dataLayer.push({ 'orderTotal' : self.orderTotal() });
                        window.dataLayer.push({ 'customerName' : self.customer.firstName() + ' ' + self.customer.lastName() });
                        window.dataLayer.push({ 'customerFirstname' : self.customer.firstName() });
                        window.dataLayer.push({ 'customerLastName' : self.customer.lastName() });
                        window.dataLayer.push({ 'customerCity' : self.account.city() });
                        window.dataLayer.push({ 'customerState' : self.account.state() });
                        window.dataLayer.push({ 'customerCountry' : self.account.country() });
                        window.dataLayer.push({ 'customerEmail' : self.customer.email() });
                        window.dataLayer.push({ 'couponCode' : self.couponCode() });
                        window.dataLayer.push({ 'couponAmount' : self.couponDiscountTotals.totalDiscount() });
                        window.dataLayer.push({ 'paymentMethod' : self.paymentMethod.name() });
                        window.dataLayer.push({ 'sessionIP' : ofConfig.SessionIP });

                        // For Google Analytics (non-EE)
                        window.dataLayer.push({
                            'transactionId': self.orderNumber(),
                            'transactionAffiliation': ofConfig.t_tracking_company,
                            'transactionTotal': self.orderTotal(),
                            'transactionTax': self.taxTotal(),
                            'transactionShipping': self.shippingTotal(),
                            'transactionProducts': transactionProducts,
                            'transactionItems': transactionItems
                        });

                        // For Enhanced Ecommerce
                        window.dataLayer.push({
                            'event': ofConfig.t_gtm_transaction_event_name,
                            'ecommerce': {
                                'purchase': {
                                    'actionField': {
                                        'id': self.orderNumber(),
                                        'affiliation': ofConfig.t_tracking_company,
                                        'revenue': self.orderTotal(),
                                        'tax': self.taxTotal(),
                                        'shipping': self.shippingTotal(),
                                        'coupon': self.couponCode()
                                    },
                                    'products': transactionProducts,
                                    'items': transactionItems
                                }
                            }
                        });

                        window.dataLayer.push({ 'productsOrdered' : productsOrdered });

                    } catch(err) {}

                } 

                if(ofConfig.t_adwords && ofConfig.t_adwords_analytics && ofConfig.t_adwords_conversion){

                    window.dataLayer = window.dataLayer || [];
                    function gtag(){dataLayer.push(arguments);}

                    gtag('event', 'conversion', {
                        'send_to': ofConfig.t_adwords_analytics + '/' + ofConfig.t_adwords_conversion,
                        'value': self.orderTotal(), // Total
                        'currency': 'USD',
                        'transaction_id': self.orderNumber(), // Order ID
                        'shipping' : self.shippingTotal(), // Shipping
                        'tax' : self.taxTotal() // Tax
                    });

                }

                if(ofConfig.t_facebook && ofConfig.t_facebook_analytics && !ofConfig.isSuperUserSession){

                    fbq('track', 'Purchase', {
                        value: self.orderTotal(),
                        currency: 'USD'
                    });

                }

                if(ofConfig.t_bing && ofConfig.t_bing_analytics){

                    var items = [];
                    var item_ids = [];

                    for(var i = 0; i < self.detailLines().length; i++) {
                        var line = self.detailLines()[i];
                        var item_id = line.sku();

                        var item = {
                            id: line.sku(),
                            item_name: line.name(),
                            price: line.price(),
                            quantity: Number(line.qty())
                        }
                        items.push(item);
                        item_ids.push(item_id);
                    }

                    if (items.length >= 1) {
                        window.uetq = window.uetq || [];
                        window.uetq.push('event', 'purchase', { 
                            'transaction_id': self.orderNumber(),
                            'ecomm_prodid': item_ids,
                            'ecomm_pagetype': 'purchase',
                            'revenue_value': self.orderTotal(),  // Value of the conversion
                            'currency': 'USD',
                            'items': items
                        });
                    }

                }
            }
        }

        self.updateOrderAccess = function(){
            if( self.completed() || self.lifecycleStage() == 'cancelled' || self.lifecycleStage() == 'punchout_punched_in'){
                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 );
                self.disablePlaceOrder( true );
            }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(true);
                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 );
                self.disablePlaceOrder( false );
            }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() );
                self.allowQtyControls( false );
                self.disablePlaceOrder( false );
            }

            var inFocusTemplate = true;
            if(self.completed() && inFocusTemplate) {
                $('#focusHeaderExit').removeAttr("data-toggle");
                $('#focusHeaderExit').attr("href" , "https://electro-medical.com");
            }
        };

        self.updateOrderAccess();

        self.continueProcessingForm = 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 doesn't provide any messaging
                // viewModel.paymentMethod.processPaymentUsing() == 1 => 'cc', 2 => 'ach'
                if(viewModel.allowPayMethodEdits() 
                && (viewModel.paymentMethod.processPaymentUsing() === 1 || viewModel.paymentMethod.processPaymentUsing() === 2) 
                && (data.placeOrderActionType() == 'place' || data.placeOrderActionType() == 'validate-only')) {
                    if(viewModel.paymentMethod.processPaymentUsing() === 1) {
                        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;
                        }
                    } else {
                        //validate ACH vault item is selected
                        if($("#ccpm_type").val() !== "ach"){
                            scrollToSection('#payment_methods');
                            bContinueProcessing = 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;
                }
            }

            //hook for adding custom validation checks
            var config = {
                continueProcessing: bContinueProcessing
            };
            runHook('cartTemplatesContinueProcessing', config);
            return config.continueProcessing;
        };

        self.isCCValid = function() {
            var valid = true;
            var currentDate = new Date();
            var currentMonth = currentDate.getMonth() + 1;
            var currentYear = currentDate.getFullYear();

            if(viewModel.paymentMethod.paymentType() != 'cc') {
                return true;
            }

            if(!viewModel.vaultedPayment.status()) {
                valid = false;
            }

            if (viewModel.vaultedPayment.expYear() < currentYear) {
                valid = false;
            }

            if (viewModel.vaultedPayment.expYear() === currentYear && viewModel.vaultedPayment.expMonth() < currentMonth) {
                valid = false;
            }
            
            return valid;
        };

        self.processOrderAction = function(data){
            var bContinueProcessing = self.continueProcessingForm(data);

            if(bContinueProcessing){

                if( data.showComments() && viewModel.customerComment() != '' ){
                    self.saveCustomerComment();
                }

                if( !data.showOrderCcEmail() && viewModel.orderCcEmail() != ''){
                    //if the user entered an email then chose an OA that isn't showing the email input, blank it out.
                    viewModel.orderCcEmail('');
                }

                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';

                runHook('cartTemplateOverridePostOptions', { postOptions: postOptions, data: data, self: self });

                if (bPost){
                    var postOrderAction = function() {
                        if ($.active > 0) {
                            viewModel.processing(true);
                            $( document ).one("ajaxStop", function(){
                                postInfo(postOptions, 'processOrderAction', scrollToId);
                            });
                        }
                        else {
                            postInfo(postOptions, 'processOrderAction', scrollToId);
                        }
                    }

                    if(data.placeOrderActionType() == 'punch-in'){
                        self.postPunchin(postOrderAction, postOptions);
                    } else {
                        postOrderAction();
                    }
                }
            }
        };

        self.postPunchin = function(fncPostOrderAction, orderActionPostOptions){
            toggleLoadingWidget(true);
            var model = viewModel;
            model.activeAjaxRequestCount(model.activeAjaxRequestCount() + 1);
            model.processing(true);

            var bPostPunchIn = false;
            var punchinXmlUrl = orderInfoPostUrl + '?o_key=' + model.orderKey() + '&ajax=true&pageaction=getPunchinXml';
            var getPunchinXmlPostOptions = {
                url: punchinXmlUrl,
                data: { orderKey: viewModel.orderKey() },
                success: function(data) {
                    if (data.trim().startsWith('<?xml')) {
                        $('input#cxml-urlencoded').val(data);
                        orderActionPostOptions.success = function() {
                            bPostPunchIn = true;
                        }
                        orderActionPostOptions.complete = function() {
                            if(bPostPunchIn) {
                                $('form#punch-in').submit();
                            }
                        }
                        fncPostOrderAction();
                    } else {
                        alert('Error Processing Order Action: Unable to retrieve valid punchin data.');
                    }
                },
                error: function() {
                    alert('Error Processing Order Action: Unable to retrieve punchin data.');
                },
                complete: function() {
                    model.activeAjaxRequestCount(model.activeAjaxRequestCount() - 1);
                    if(model.activeAjaxRequestCount() < 1) {
                        model.processing(false);
                    }
                    toggleLoadingWidget(false);
                }
            };
            
            if ($.active > 0) {
                viewModel.processing(true);
                $( document ).one("ajaxStop", function(){
                    $.ajax(getPunchinXmlPostOptions);
                });
            }
            else {
                $.ajax(getPunchinXmlPostOptions);
            }
        };

        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 isn't 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() + '&ajax=true&pageaction=postLogicJSON&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() + '&ajax=true&pageaction=postLogicJSON&randomnum=' + new Date().getTime()
                , data: "postLogicJSON=" + encodeURIComponent(JSON.stringify(postData))
                , cache: false
                , type: 'POST'
                , dataType: 'json'
                , success: function(data,status,request){
                    viewModel.updateNoteBook(note[0]);
                    viewModel.customerComment('');
                    return data.PostedKeys[notebookTableName][0];
                }
                , 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');
            return true;
        };

        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?type=remove&unq=' + orderDetailKey + '&o_id=' + data.orderID() + '&modal=1';

                jQuery.ajax({
                    url: sRemoveUrl
                    , cache: false
                    , type: 'GET'
                    , success: function(data,status,request){
                        //Calling getOrderJSON here to handle removing reward products 
                        // From the UI when the target is removed.
                        viewModel.genericModalComplete();
                    }
                    , 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.addToSavedCart();
                },
                url: orderInfoPostUrl + '?o_key=' + self.orderKey() + '&p_key=' + (productInfo.parentProductId || productInfo.productKey) + '&od_key=' + detailLineId + '&sku=' + productInfo.productSku + '&ajax=true&pageaction=getProductData&modal=1',
                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_product=1&s=' + searchTerm + '&search2=' + search2;
        });

        self.showRemoveLink = function(data){
            if(!ofConfig.allowProductRemoves){
                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 = ko.computed(function(){
            var thisIsCartPage = ofConfig.cartPage === getOriginalPageName();
            var isComplete = self.completed() || (self.lifecycleStage() == 'punchout_punched_in')

            var paymentCrumbLabel = "Payment";
            if(!ofConfig.showPaymentMethodsSection) {
                paymentCrumbLabel = thisIsCartPage ? "Cart" : "Finalize"
            }
            var completeCrumbLabel = ofConfig.isPunchoutSession ? "Sent to Procurement" : "Order Placed";

            var cartCrumb = "<li><a href=\"" + ofConfig.cartPage + "\"><i class=\"icon-shopping-cart\"></i> Cart</a> <span class=\"divider\"><i class=\"icon-chevron-right\"></i></span></li>";
            if(thisIsCartPage) {
                cartCrumb = "";
            }
            var accountCrumb = "<li><a href=\"account.asp\"><i class=\"icon-info-sign\"></i> Billing / Shipping</a> <span class=\"divider\"><i class=\"icon-chevron-right\"></i></span></li>";
            var paymentCrumb = "<li class=\"" + (isComplete ? "" : "active") + "\"><i class=\"icon-lock\"></i> " + paymentCrumbLabel + " <span class=\"divider\"><i class=\"icon-chevron-right\"></i></span></li>";
            var completeCrumb = "<li class=\"" + (isComplete ? "active" : "") + "\"><i class=\"icon-ok\"></i> " + completeCrumbLabel + "</li>";

            var dynamicBreadcrumbMarkup = "<ul class=\"breadcrumb breadcrumb-cart\">" + cartCrumb + accountCrumb + paymentCrumb + completeCrumb + "</ul>";

            if(self.cartType != 'recurring' && (thisIsCartPage || ofConfig.isPunchoutSession || !ofConfig.showPaymentMethodsSection)) {
                return dynamicBreadcrumbMarkup;
            }            

            if(self.recordType() == 'cart') {
                return ofConfig.sPaymentHeaderLabel;
            } else if (self.recordType() == 'recurring') {
                return '<ul class="breadcrumb breadcrumb-cart"><li class="active">Order</li><li><i class="icon-ok"></i> Order Placed</li></ul>';
            } else {
                return '<ul class="breadcrumb breadcrumb-cart"><li class="active">Order</li><li><i class="icon-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
         /*
        Runs when order is completed but payment page doesn't re-fresh
        - Example user pays with a credit card or bill me payment option
        */
        self.orderPlaced.subscribe(function() {
            self.postOrderToGoogleAnalytics();
            postOrderHeaderField('tracked', '1');
            self.tracked('1');
        });
        /*
        Runs when order is completed and the payment page re-freshes
        - Happens when user checks out with paypal and is re-directed back to payment page
        - with a completed order
        */
        if (self.completed() && self.tracked() != '1' ) {
            self.postOrderToGoogleAnalytics();
            postOrderHeaderField('tracked', '1');
            self.tracked('1');
         }

        addTimer("orderModelBottom");
        runHook('orderModelBottom', { self: self, order: self });
        addTimer("end order mapping");
    } // end of var Order = blah blah blah 

    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.firstName(item.s_f_nm);
                address.lastName(item.s_l_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.opt1(item.s_opt1 || '');
                address.opt2(item.s_opt2 || '');
                address.opt3(item.s_opt3 || '');
                address.opt4(item.s_opt4 || '');
                address.opt5(item.s_opt5 || '');
                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) {
        console.log(sOrderField);
        var postData = {};
        var order = [];

        order = [{
            "o_key" : ofConfig.OKey
        }];

        order[0][sOrderField] = viewModelProperty;

        postData =
        {
            "Tables": [
                {
                    "TableName"           : "orders",
                    "TableKeyField"       : "o_key",
                    "UserKeyField"        : "o_key",
                    "UserKeyIsPrimaryKey" : "True",
                    "Data"                : order
                }
            ]
        };

        //Optional additional tables on the order
        if (!!extraTablesJson) {
            postData["Tables"].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++){
            orderLines[0][sDetailFields[i]] = viewModelProperties[i];
        }

        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) {
        toggleLoadingWidget(true);
        callbacks = callbacks || {};

        jQuery.ajax({
            url: 'payment.asp' + '?o_key=' + ofConfig.OKey + '&getorderJSON=' + getOrderJSON + '&ajax=true&pageaction=postLogicJSON&randomnum=' + new Date().getTime(),
            data: "postLogicJSON=" + encodeURIComponent(JSON.stringify(postData)),
            cache: false,
            type: 'POST',
            dataType: 'json',
            success: callbacks.success,
            error: function(jqXHR, textStatus, errorThrown) {
                console.log(jqXHR.status);
                if (typeof callbacks.error == 'function') {
                    callbacks.error(jqXHR, textStatus, errorThrown);
                } else {
                    if(jqXHR.status == 401){
                        location.href = 'showcart.asp?section=ValidateOrderOwnership&err=not-logged-in'
                    }else{
                        alert('Error posting to ' + (postData["Tables"][0]["TableName"] || "postLogicJsonAjax") + '.');
                    }
                }
            },
            complete: function(){
                toggleLoadingWidget(false);
            }
        });
    };


    var apiRoutedPageActions = [
        /*
        // can't be converted yet
        'placeOrder',
        'processOrderAction',
        */
        'setSha',
        'setCCN',
        'setPmId',
        'setCoupon',
        'setGiftCertCode',
        'setOrderHeaderFields',
        'setRequestedShipDate',
        'setShippingPrice',
        'getOrderJSON',
        'resetShippingPrice',
        'setShipmentShipVia'
    ];
    
    apiRoutedPageActions = apiRoutedPageActions.concat([
        'updateShipToAddress',
        'setOrderDetailFields',
        'assignOwnership'
    ]);
    

    var postInfo = function(ajaxOptions, pageAction, scrollToId, model) {
        toggleLoadingWidget(true);
        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;
        
        var querystring;
        var comUrl;
        if(ajaxOptions.url){
            querystring = ajaxOptions.url.substring(ajaxOptions.url.indexOf('?'))
            comUrl = orderInfoPostUrl + querystring;
        }else{
            querystring = '?o_key=' + model.orderKey();
            comUrl = orderInfoPostUrl + '?o_key=' + model.orderKey() + '&ajax=true&pageaction=' + pageAction;
        } 
        var apiUrl = orderInfoPostApiUrl + pageAction + querystring;
                
        if (apiRoutedPageActions.includes(pageAction)) {
            ajaxOptions.url = apiUrl;
        } else if (!ajaxOptions.url) {
            ajaxOptions.url = comUrl;
        }

        if(!ajaxOptions.type) {
            ajaxOptions.type = 'POST';
        }

        ajaxOptions.success = function(data) {
            try{
                var response = JSON.parse(data);
            } catch (error){
                /*
                * if we get invalid json here, it's most likely a redirect due to
                * an expired session or other issue causing an html page to be
                * returned instead of processing the ajax request
                */
                location.href = 'payment.asp?o_key=' + model.orderKey();
            }
            runHook('postInfoAjaxSuccessFunction', {response: response});
            if(Array.isArray(response) && Object.keys(response[0].Errors).length > 0) {
                for (var msg in response[0].Errors) {
                    if(response[0].Errors.hasOwnProperty(msg)) {
                        scrollToId = 'errorList';

                        model.errorMessages.push(
                            {
                                "errorType": msg,
                                "message": response[0].Errors[msg]
                            }
                        );
                    }
                }
            }

            ko.mapping.fromJS(response[1], orderMapping, model);

            model.updateOrderAccess();
            if(model.isOverLineLimit()){
                model.shippingComplete(true);
            }
            if(typeof existingSuccess === 'function') {
                existingSuccess(data);
            }
            
            _.each(model.itemShipToMap(), function(item){
                item.qty.subscribe(function () { 
                    model.isMinimumOrderTotalMet(checkOrderTotal(model));
                });   
            });

            if(scrollToId) {
                model.showConfirmationMessage(true);
                scrollToSection('#' + scrollToId);
            }
            
            model.detailLines().forEach(function(detailLine) {
                // We can't debounce/trottle an observable
                // so we add a computed to track qty changes.
                // We use this in a subscription to call
                // update cart to update qty change in bulk atc
                // to avoid loading the qty change without posting
                // and updating the entire order model (for perf)
                detailLine.qtyTracker = ko.computed(function() {
                    return detailLine.qty();
                }).extend({throttle: 500});
                detailLine.qtyTracker.subscribe(function (newQty) {
                    model.postQtyUpdate();
                }, detailLine);
                detailLine.workerPriceTracker = ko.computed(function() {
                    return detailLine.price();
                }).extend({throttle: 500});
                detailLine.workerPriceTracker.subscribe(function (newQty) {
                    model.setWorkerPriceOverride(detailLine);
                }, detailLine);
                detailLine.workerQtyLimitsTracker = ko.computed(function() {
                    return {
                        removeType: detailLine.removeType(),
                        minQty: detailLine.minQty(),
                        maxQty: detailLine.maxQty(),
                        qtyIncrement: detailLine.qtyIncrement()
                    };
                }).extend({throttle: 500});
                detailLine.workerQtyLimitsTracker.subscribe(function (newValue) {
                    model.setWorkerQtyLimits(detailLine);
                });
            });
        };

        ajaxOptions.error = function(jqXHR, textStatus, errorThrown) {
            if(jqXHR.status == 401){
                location.href = 'showcart.asp?section=ValidateOrderOwnership&err=not-logged-in'
            }
            if (ajaxOptions.url != comUrl) {
                // if API call fails, retry with COM AJAX
                ajaxOptions.url = comUrl;
                $.ajax({
                    url: orderInfoPostUrl + '?o_key=' + model.orderKey() + '&ajax=true&pageaction=logError&url=' + encodeURIComponent(apiUrl) + '&method=' + pageAction + '&message=API error (' + jqXHR.status + ')',
                    success: function() {
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        if(jqXHR.status == 401){
                            location.href = 'showcart.asp?section=ValidateOrderOwnership&err=not-logged-in'
                        }
                    }
                });
                $.ajax(ajaxOptions);
                return;
            }
            if(typeof existingError === 'function') {
                existingError(); //data is not defined
            }
        };

        ajaxOptions.complete = function() {
            runHook('postInfoAjaxCompleteFunction', { model: model, ajaxOptions: ajaxOptions, pageAction: pageAction, scrollToId: scrollToId });
            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());
            }
            toggleLoadingWidget(false);
        };

        $.ajax(ajaxOptions);
    }

    var fixUpNulls = function(account) {
        for(var prop in account) {
            if(account.hasOwnProperty(prop) && typeof account[prop] === 'function') {
                if(account[prop]() === null || account[prop]() === 'null') {
                    account[prop]('');
                }
            }
        }
    }

    var postPayPal = function(orderActionKey) {
        viewModel.processing(true);

        jQuery.ajax({
            url: 'payment.asp' + '?paypal_order_submit=1&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, '');
    }

    var checkOrderTotal = function(model){
        var orderTotalValid = true;
        var subTotal = 0;
        if(ofConfig.useMinimumOrderTotal && !model.completed()){
            if(model.useMultiShipEditUI && model.useMultiShipEditUI()){
                _.each(model.itemShipToMap(), function(item){
                    subTotal += (item.qty() * item.getPrice());
                });
                console.log('itemShipToMap');
            }else if(model.itemsOnOrder){
                _.each(model.itemsOnOrder(), function(item){
                    subTotal += (item.qty() * item.price());
                });
            }else{
                var subTotal = model.productTotal();
            }
            var minimumTotal = ofConfig.minimumOrderTotal;

            if(ofConfig.useAccountMinimumOrderTotal && ofConfig.accountMinimumOrderTotal > 0){
                minimumTotal = ofConfig.accountMinimumOrderTotal;
            }
            if(subTotal < minimumTotal){
                orderTotalValid = false;
            }
        }
        return orderTotalValid;
    }

    $(function() {
        if(getOriginalPageName() !== 'bulk_atc.asp') {
            addGlobalModalCompletionHandler($('#find_product'), addFromProductFinder);
        }

        runHook('cartTemplatesDocumentReady', {self: viewModel});
    });

    addTimer("end of ko model");
</script>
</div>
    <div class="hide browser-alert -bottom">
        <div class="browser-alert__title">
            <strong class="browser-alert__title-text">
            Browser Compatibility Warning
            </strong>
            <button type="button" class="browser-alert__close" onclick="acknowledgeBrowserAlert()">
            <svg width="10" height="9" viewBox="0 0 10 9" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M6.54688 4.5L8.89062 2.15625C9.19531 1.875 9.19531 1.40625 8.89062 1.125L8.375 0.609375C8.09375 0.304688 7.625 0.304688 7.34375 0.609375L5 2.95312L2.63281 0.609375C2.35156 0.304688 1.88281 0.304688 1.60156 0.609375L1.08594 1.125C0.78125 1.40625 0.78125 1.875 1.08594 2.15625L3.42969 4.5L1.08594 6.86719C0.78125 7.14844 0.78125 7.61719 1.08594 7.89844L1.60156 8.41406C1.88281 8.71875 2.35156 8.71875 2.63281 8.41406L5 6.07031L7.34375 8.41406C7.625 8.71875 8.09375 8.71875 8.375 8.41406L8.89062 7.89844C9.19531 7.61719 9.19531 7.14844 8.89062 6.86719L6.54688 4.5Z" fill="white"/>
            </svg>
            </button>
        </div>
        <div class="browser-alert__text">
            The browser you are using is not supported on this site. You may experience issues with some features on the site. It is recommended that you use one of the following browsers - Chrome, Edge, Firefox, or Safari.
        </div>
    </div>
    <script>
        function acknowledgeBrowserAlert(){
            document.querySelector('.browser-alert').style.display = 'none';
            document.cookie = 'browseralert=1';
        }

        if(parseInt(getInternetExplorerVersion()) <= 11){
            jQuery('.browser-alert').show();
        }
    </script>
    </body>

</html>
