1 2<!DOCTYPE html> 3 4<!--[if IE]><![endif]--> 5<!--[if IE 9]> <html class="no-js ie9 lt-ie10" lang="en"> <![endif]--> 6<!--[if gt IE 9]><!--> <html class="no-js" lang="en"> <!--<![endif]--> 7<!-- include files here --> 8 9 10<head> 11 12<link rel="preconnect" href="https://fonts.gstatic.com/" /> 13 14 <link href="https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700&display=swap" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'"/> <base href="https://www.flagandbanner.com/"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 15 <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=2"> 16 17 18 19 <title>Custom Logo Flags | Advertising & Promotional Banners | FlagandBanner.com</title> 20 <meta name="description" content="Design custom flags with your logo or emblem in digital print, applique, or embroidery. Ideal for businesses, schools, and special events."> 21 <meta name="keywords" content=""> 22 <link rel="canonical" href="https://www.flagandbanner.com/custom_showroom/Custom-Flag-Pricing.asp" /> 23<link rel="stylesheet" href="templates/fa/css/custom-font-awesome.min.css"> 24 <link rel="shortcut icon" type="image/x-icon" href="https://d3jy065g9mm97j.cloudfront.net/images/favicon.ico?v=3997506342"> 25 <link rel="icon" type="image/png" href="" sizes="16x16" /> 26 <link rel="icon" type="image/png" href="" sizes="32x32" /> 27 <link rel="icon" type="image/png" href="" sizes="48x48" /> 28 <link rel="preload" href="../css/bootstrap-retail.css?4c33272" as="style" onload="this.onload=null;this.rel='stylesheet'"> 29 <link rel="preload" href="../css/retail.css?4c33272" as="style" onload="this.onload=null;this.rel='stylesheet'"> 30 <link rel="preload" href="../css/focus.css?4c33272" as="style" onload="this.onload=null;this.rel='stylesheet'"> 31 32 33 <style> 34 35 /* 36 ### Skins CSS Overrides 37 */ 38 39 /* Retail Template 40 --------------------------------------------------------------- */ 41 h1, h2, h3, h4, h5, h6, 42 input, button, select, textarea, 43 body, body.retail { 44 font-family: Open Sans 45 } 46 47 html, 48 body, 49 p { 50 color: #333333; 51 } 52 53 a { 54 color: #0a0a0a; 55 } 56 57 .text-warning, 58 a.text-warning { 59 color: #8a6d3b; 60 } 61 62 .text-warning:hover, 63 a.text-warning:hover { 64 color: #66512c; 65 } 66 67 .text-danger, 68 a.text-danger { 69 color: #a94442; 70 } 71 72 .text-danger:hover, 73 a.text-danger:hover { 74 color: #843534; 75 } 76 77 .text-success, 78 a.text-success { 79 color: #3c763d; 80 } 81 82 .text-success:hover, 83 a.text-success:hover { 84 color: #2b542c; 85 } 86 87 .text-info, 88 a.text-info { 89 color: #31708f; 90 } 91 92 .text-info:hover, 93 a.text-info:hover { 94 color: #245269; 95 } 96 97 a:hover, 98 a:focus { 99 color: rgb(36,36,36); 100 } 101 102 h1, h2, h3, h4, h5, h6, 103 .formblock-heading, 104 legend, 105 .checkout-section-heading, 106 .checkout-section.active .checkout-section-heading { 107 color: #444444; 108 } 109 110 .pace .pace-progress { 111 background: #0071c2; 112 } 113 114 /* Retail Topbar 115 --------------------------------------------------------------- */ 116 117 [class*="retail-header"] .topbar { 118 background-color: #0071c2; 119 } 120 121 /* Retail Buttons 122 --------------------------------------------------------------- */ 123 124 .btn-link { 125 color: #0a0a0a; 126 } 127 128 .btn-link:not([disabled]):hover, 129 .btn-link:not([disabled]):focus, 130 .btn-link:not([disabled]):active, 131 .btn-link:not([disabled]).active { 132 color: rgb(36,36,36); 133 } 134 135 /* Primary buttons */ 136 .btn-primary, .btn-primary.button { 137 background-color: #c12535; 138 border-color: #c12535; 139 color: #FFFFFF; 140 } 141 142 .btn-primary:not([disabled]):hover, 143 .btn-primary:not([disabled]):focus, 144 .btn-primary:not([disabled]):active, 145 .btn-primary:not([disabled]).active, 146 .btn-primary:not([disabled]).button:hover, 147 .btn-primary:not([disabled]).button:focus, 148 .btn-primary:not([disabled]).button:active, 149 .btn-primary:not([disabled]).button.active { 150 background-color: rgb(218,62,78); 151 border-color: rgb(218,62,78); 152 color: #FFFFFF; 153 } 154 155 /* Secondary buttons */
156 .btn:not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info), 157 .btn:not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button { 158 background-color: #ffffff; 159 border-color: rgb(204,204,204); 160 color: #222222; 161 } 162 163 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info):hover, 164 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info):focus, 165 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info):active, 166 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).active, 167 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button:hover, 168 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button:focus, 169 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button:active, 170 .btn:not([disabled]):not(.btn-primary):not(.btn-error):not(.btn-danger):not(.btn-warning):not(.btn-success):not(.btn-info).button.active { 171 background-color: rgb(245,245,245); 172 border-color: rgb(204,204,204); 173 color: #222222; 174 } 175 176 .list-group-item.active, 177 .list-group-item.active:hover, 178 .list-group-item.active:focus { 179 color: #FFFFFF !important; 180 border-color: #c12535 !important; 181 background-color: #c12535 !important; 182 } 183 184 /************* 185 ** Unused button settings 186 .btn-secondary, 187 .btn-inverse { 188 color: #222222; 189 border-color: #FDF0D5; 190 background-color: #FDF0D5; 191 } 192 193 .btn-secondary:hover, 194 .btn-secondary:focus, 195 .btn-inverse:hover, 196 .btn-inverse:focus { 197 background-color: rgb(255,255,238); 198 border-color: rgb(255,255,238); 199 } 200 201 .btn-secondary:active, 202 .btn-inverse:active { 203 background-color: rgb(255,255,228); 204 border-color: rgb(255,255,228); 205 } 206 207 .btn-success { 208 color: #468847; 209 border-color: #468847; 210 background-color: #468847; 211 } 212 213 .btn-success:hover, 214 .btn-success:focus { 215 background-color: rgb(96,162,96); 216 border-color: rgb(96,162,96); 217 } 218 219 .btn-success:active { 220 background-color: rgb(85,151,86); 221 border-color: rgb(85,151,86); 222 } 223 224 .btn-danger { 225 color: #FFFFFF; 226 border-color: #B94A48; 227 background-color: #B94A48; 228 } 229 230 .btn-danger:hover, 231 .btn-danger:focus { 232 background-color: rgb(210,100,98); 233 border-color: rgb(210,100,98); 234 } 235 236 .btn-danger:active { 237 background-color: rgb(200,89,87); 238 border-color: rgb(200,89,87); 239 } 240 *************/ 241 242 .toast-success { 243 background-color: #0071c2; 244 } 245 246 247 /* Breadcrumbs 248 --------------------------------------------------------------- */ 249 250 body.retail.focus-mode:not(.account) .breadcrumb.breadcrumb-cart li.active { 251 background: #0071c2; 252 color: #FFFFFF; 253 } 254 255 body.retail.focus-mode:not(.account) .breadcrumb.breadcrumb-cart li.active:after { 256 border-color: transparent; 257 border-left-color: #0071c2;
258 border-width: 20px; 259 } 260 261 262 /* Retail Template 1 263 --------------------------------------------------------------- */ 264 265 /* Topbar */ 266 .topbar #retail-topbar-left-menu>li>a:hover, 267 .topbar #retail-topbar-left-menu>li>a:focus, 268 .topbar #retail-topbar-left-menu>li.open>a { 269 background-color: rgb(26,138,220); 270 color: #FFFFFF; 271 } 272 273 @media (max-width: 980px) { 274 .topbar #retail-topbar-left-menu>li>a:hover, 275 .topbar #retail-topbar-left-menu>li>a:focus, 276 .topbar #retail-topbar-left-menu>li.open>a { 277 background-color: #0071c2; 278 color: #FFFFFF; 279 } 280 } 281 282 .topbar #retail-topbar-left-menu>li ul { 283 background-color: #FFFFFF; 284 } 285 286 .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1 { 287 color: #FFFFFF !important; 288 } 289 290 @media (max-width: 1024px) { 291 .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1 { 292 color: #333333 !important; 293 } 294 } 295 296 .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:hover, 297 .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:focus { 298 color: #FFFFFF !important; 299 } 300 301 @media (max-width: 1024px) { 302 .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:hover, 303 .topbar #retail-topbar-left-menu .retail-topbar-left-menu__a-1:focus { 304 color: #FFFFFF !important; 305 background: #0071c2 !important; 306 } 307 } 308 309 310 .topbar #retail-topbar-left-menu>li ul a:hover, 311 .topbar #retail-topbar-left-menu>li ul a:focus { 312 background-color: rgb(230,230,230); 313 } 314 315 @media (max-width: 980px) { 316 .topbar #retail-topbar-left-menu { 317 background-color: #FFFFFF; 318 } 319 } 320 321 /* Header */ 322 323 .focus-header, 324 [class*="retail-header"] .logo-bar { 325 background-color: #FFFFFF; 326 } 327 328 .focus-header__exit-wrapper { 329 border-color: rgb(230,230,230); 330 } 331 332 .focus-header__exit { 333 color: #222222; 334 } 335 336 .focus-header__exit:focus, 337 .focus-header__exit:active, 338 .focus-header__exit:hover { 339 color: #222222 !important; 340 background-color: rgb(230,230,230); 341 } 342 343 344 [class*="retail-header"] .header__prodcat__toggle, 345 [class*="retail-header"] .header__signin-open { 346 color: #222222 !important; 347 } 348 349 [class*="retail-header"] #header__user-menu>li.link-parent ul, 350 [class*="retail-header"] #header__prodcat>li.link-parent ul { 351 background-color: #FFFFFF; 352 } 353 354 [class*="retail-header"] .topbar__menu-toggle a, 355 [class*="retail-header"] .logo-bar__right .linkset > li > a { 356 color: #222222 !important; 357 } 358 359 [class*="retail-header"] .topbar__menu-toggle a:hover, 360 [class*="retail-header"] .topbar__menu-toggle a:focus { 361 background: rgb(0,88,168) !important; 362 } 363 364 @media (max-width: 980px) { 365 [class*="retail-header"] .logo-bar__right .linkset > li > a { 366 background-color: #0071c2; 367 color: #FFFFFF !important; 368 } 369 } 370 371 [class*="retail-header"] .logo-bar__right .linkset > li > a:hover, 372 [class*="retail-header"] .logo-bar__right .linkset > li > a:active {
373 color: rgb(60,60,60) !important; 374 } 375 @media (max-width: 980px) { 376 [class*="retail-header"] .logo-bar__right .linkset > li > a:hover, 377 [class*="retail-header"] .logo-bar__right .linkset > li > a:focus, 378 [class*="retail-header"] .logo-bar__right .linkset > li > a:active { 379 color: #FFFFFF !important; 380 background: rgb(0,88,168) !important; 381 } 382 } 383 384 [class*="retail-header"] .logo-bar__right .linkset ul>li>a:hover, 385 [class*="retail-header"] .logo-bar__right .linkset ul>li>a:focus { 386 background-color: rgb(230,230,230); 387 } 388 389 [class*="retail-header"] #header__prodcat>li.link-parent li.link-parent.open>a { 390 background-color: #0071c2; 391 color: #FFFFFF; 392 } 393 394 [class*="retail-header"] #header__prodcat>li>ul { 395 border-top: 1px solid #0071c2; 396 } 397 398 [class*="retail-header"] #header__prodcat>li>ul ul { 399 border-left: 5px solid #0071c2; 400 } 401 402 [class*="retail-header"] .header__hero-search { 403 background-image: url('https://d3jy065g9mm97j.cloudfront.net/images/slides/hero-home-gray.jpg?v=3997506342'); 404 } 405 406 /* Introduction */ 407 408 .home-description { 409 background-color: #0071c2; 410 color: #FFFFFF; 411 } 412 413 .home-description:after { 414 border-color: #0071c2 transparent transparent transparent; 415 } 416 417 418 /* Featured */ 419 420 .trending-products__title:after { 421 background-color: #0071c2; 422 } 423 424 /* Reseller */ 425 426 .footer-reseller__col-1 { 427 background-image: url('https://d3jy065g9mm97j.cloudfront.net/images/pc-afb-building-1024x768.jpg?v=3997506342'); 428 } 429 430 .footer-reseller__col-2 { 431 background-color: #0071c2; 432 } 433 434 .footer-reseller__col-2:before { 435 border-color: transparent #0071c2 transparent transparent; 436 } 437 438 .footer-reseller__wrap, 439 .footer-reseller__wrap p { 440 color: #FFFFFF; 441 } 442 443 .footer-reseller h2:after { 444 background-color: #FDF0D5; 445 } 446 447 /* Retail Products 448 --------------------------------------------------------------- */ 449 450 .prod-info { 451 color: #333333; 452 } 453 454 .prod-desc { 455 color: #0a0a0a; 456 } 457 458 .prod-desc p { 459 color: #0a0a0a; 460 } 461 462 .specials_nm { 463 color: #0a0a0a; 464 } 465 466 .specials_nm:hover, 467 .specials_nm:focus { 468 color: rgb(36,36,36); 469 } 470 471 /* Retail Footer 472 --------------------------------------------------------------- */ 473 474 [class*="retail-footer"] { 475 color: #FFFFFF; 476 background-color: #0071c2; 477 } 478 479 [class*="retail-footer"] .bottom-bar { 480 color: rgba(0,0,0,0.5); 481 background-color: #ffffff; 482 } 483 484 [class*="retail-footer"] .bottom-bar__colophon a:hover { 485 color: rgba(0,0,0,0.8); 486 } 487 488 489 490 </style> 491
492<script> 493 // This function is needed for JS hooks. 494 function getOriginalPageName() { 495 return 'page.asp'; 496 } 497 498 function getUrlPath() { 499 return '/custom_showroom/Custom-Flag-Pricing.asp'; 500 } 501 502 function getUrl() { 503 return '/custom_showroom/Custom-Flag-Pricing.asp'; 504 } 505 506 function handleImageError(img, noImagePath){ 507 if(!noImagePath) { 508 noImagePath = 'images/no-image.png'; 509 } 510 if ($(img).attr('src') !== noImagePath) { 511 $(img).attr('src', noImagePath); 512 } 513 } 514 var sitename = "flagb3"; 515 var isWorkerDomain = false; 516 var processPageTitle = isWorkerDomain && !false; 517 var bValidIp = false; 518 var sOfUrl = 'https://www.flagandbanner.com'; 519</script>
519 520 521 <!-- Google Tag Manager --> 522
522<script>
vendor: 363 bytes, lines 522-526
522(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 523 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 524 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 525 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 526 })(window,document,'script','dataLayer','
526GTM-TDD95N
vendor: 3 bytes, line 526
526');
526</script>
526 527 <!-- End Google Tag Manager -->
vendor: 70 bytes, lines 527-528
527 528 <script src="https://www.google.com/recaptcha/api.js?render=
5286LfnksIrAAAAAB0R7wgR2A36kPJ60HpTvHRd5HCR
vendor: 21 bytes, lines 528-529
528"></script> 529
529<style> 530 .grecaptcha-badge { visibility: hidden; } 531 </style> 532
533<script> 534 var utils = {}; 535 536 utils.isCrossOriginFrame = function (parentContext) { 537 try { 538 if(!parentContext) parentContext = window; 539 if (parentContext === window) return false; 540 541 return (document.location.hostname !== parentContext.location.hostname); 542 } catch (e) { 543 return true; 544 } 545 } 546 547 utils.getParameter = function (param, context) { 548 var value; 549 if(!context) context = window; 550 551 // return empty string if cross origin (can't access params) 552 if(utils.isCrossOriginFrame(context)) return ''; 553 554 var parameters = context.location.search.replace('?', ''); 555 556 if (parameters) { 557 var pattern = new RegExp('\\b' + param + '=([^;&]+)', 'gi'); 558 value = parameters.split(pattern)[1]; 559 } 560 561 return value || ''; 562 }; 563 564 utils.buildImagePath = function(image){ 565 if(image && image.indexOf("http") > -1){ 566 imageUrl = image.replace(/http:/i, 'https:'); 567 }else{ 568 image = image.replace(oConfig.storefrontUrl, oConfig.sessionData.cdnUrl).toLowerCase(); 569 if(!image){ 570 imageUrl = oConfig.noImagePath || oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/images/' + oConfig.defaultImage.replace(/^\/+/, ''); 571 } 572 else if(image.indexOf("/") > -1){ 573 imageUrl = oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/' + image.replace(/^\/+/, ''); 574 } 575 else{ 576 imageUrl = oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/images/' + image.replace(/^\/+/, ''); 577 } 578 } 579 580 cacheBustingPrefix = '?'; 581 if(imageUrl.includes('?')) cacheBustingPrefix = '&';
582 return imageUrl + cacheBustingPrefix + 'v=3997506342'; 583 }; 584 585 utils.pageUrl = location.href.replace(/.+\//, ''); 586 utils.loginUrl = 'security_logon.asp?autopage=' + encodeURIComponent(utils.pageUrl); 587 588 utils.pageName = function(){ 589 return "page.asp"; 590 } 591 592 utils.pageType = function(){ 593 var pageType = "webpage"; 594 if(utils.pageUrl == '' && pageType == ''){ 595 pageType = 'home'; 596 }else if(pageType != ''){ 597 switch(pageType){ 598 case 'prodcat': 599 case 'product': 600 pageType = 'catalog'; 601 break; 602 case 'page-section': 603 case 'webpage': 604 pageType = 'content'; 605 break; 606 default: 607 pageType = 'other'; 608 break; 609 } 610 }else{ 611 switch(getOriginalPageName()){ 612 case 'pc_product_detail.asp': 613 case 'pc_combined_results.asp': 614 case 'largest_spend_products.asp': 615 case 'largest_qty_ordered_products.asp': 616 case 'recently_ordered_products.asp': 617 case 'frequently_ordered_products.asp': 618 pageType = 'catalog'; 619 break; 620 case 'showcart.asp': 621 case 'account.asp': 622 pageType = 'checkout'; 623 break; 624 default: 625 pageType = 'other'; 626 break; 627 628 } 629 } 630 return pageType; 631 } 632 633 utils.htmlEncode = function(value){ 634 return $('<textarea/>').text(value).html(); 635 } 636 637 utils.htmlDecode = function(value){ 638 return $("<textarea/>").html(value).text(); 639 } 640 641 utils.pageSubType = function(){ 642 pageSubType = "page"; 643 if("" != ''){ 644 pageSubType = ""; 645 } 646 return pageSubType; 647 } 648 649 utils.scrollTo = function (elementArg) { 650 var element = $(elementArg).first(); 651 if (!element.length) return; 652 653 // If the element is in an inactive tab, make the tab active. 654 utils.activateTab(element); 655 656 $('html, body').animate({ 657 scrollTop: $(element[0]).offset().top - 120 //offset to account for header bar 658 }, 500); 659 660 }; 661 662 utils.activateTab = function (element) { 663 var tab = element.hasClass('.tab-pane') ? element : element.closest('.tab-pane'); 664 if (!tab.length || tab.hasClass('active')) return; 665 var id = tab.attr('id'); 666 tab 667 .closest('.tabbable') 668 .find('.nav-tabs > li > a') 669 .filter('[href="#' + id + '"], [data-target="#' + id + '"]') 670 .tab('show'); 671 } 672 673 utils.popToastr = function(title, subtext, config) { 674 675 var confirmToastrConfig = config ? config : { 676 'closeButton': true, 677 'newestOnTop': true, 678 'positionClass': 'toast-top-right', 679 'preventDuplicates': false, 680 'showDuration': 500, 681 'hideDuration': 1000, 682 'tapToDismiss': false, 683 'timeOut': 5000, 684 'extendedTimeOut': 1000 685 }; 686 687 toastr.success( 688 subtext, 689 title, 690 confirmToastrConfig 691 ); 692 }; 693 694 utils.popToastrError = function(title, subtext, config) { 695 var errorToastrConfig = { 696 'closeButton': true, 697 'newestOnTop': true, 698 'positionClass': 'toast-top-right', 699 'preventDuplicates': false, 700 'showDuration': 500, 701 'hideDuration': 1000, 702 'tapToDismiss': true, 703 'timeOut': 5000, 704 'extendedTimeOut': 1000 705 } 706 707 $.extend(errorToastrConfig, config); 708 709 toggleLoadingWidget(false); 710 711 toastr.error( 712 subtext, 713 title, 714 errorToastrConfig 715 ); 716 } 717 718 utils.decimalPlacesOnUnitPrices = parseInt(2) || 2; 719 utils.decimalPlacesOnTotals = parseInt('2') || 2; 720 utils.decimalPlacesAllowedOnProductQty = 0; 721 utils.defaultQtyIncrement = 1; 722 723 /* 724 * 2024-06-07 - Client-side version (Server-side in Global Functions) 725 * Standard implementation of quantity validation 726 * calculation logic. 727 * This assumes all values passed in already account 728 * for the uom conversion factor if applicable. 729 */ 730 utils.getValidProductQty = function(inputQty, minQty, maxQty, step, allowZeroValue) { 731 732 // init as success result 733 var qtyValidationResult = {
734 inputQty: inputQty, 735 validQty: inputQty, 736 error: '' 737 } 738 739 if(typeof allowZeroValue === 'undefined') allowZeroValue = false; 740 741 //- set defaults 742 if(typeof step === 'undefined') step = utils.defaultQtyIncrement; //- Defined in site_config_overrides.asp 743 if(typeof minQty === 'undefined') minQty = step; 744 if(typeof maxQty === 'undefined') maxQty = 0; 745 746 //- Ensure all values are numeric 747 inputQty = parseFloat(inputQty); 748 minQty = parseFloat(minQty); 749 maxQty = parseFloat(maxQty); 750 step = parseFloat(step); 751 752 //- zero is valid when validating qty inputs elements 753 //- when zero indicates the product is not selected 754 //- for add to cart, like on input-qty view with a single 755 //- add to cart button 756 if(inputQty == 0 && allowZeroValue) { 757 return qtyValidationResult; 758 } 759 760 //- retun min if inputQty is not passed in, is 0 or less than minQty. 761 if( !inputQty || (minQty > 0 && inputQty < minQty)){ 762 qtyValidationResult.validQty = minQty; 763 qtyValidationResult.error = 'min'; 764 return qtyValidationResult; 765 } 766 767 //- DecimalPlacesAllowedOnProductQty defined in site_config_overrides.asp 768 //- and assigned to utils.decimalPlacesAllowedOnProductQty in global_scripts_top.asp 769 //- It can be 0 so we add 1 to it so we have a multiplier of at least 10. 770 //- floatFixMultiplier is used to account for precision issues with floating point 771 //- arithmatic on base-10 decimal numbers. 772 var floatFixMultiplier = Math.pow(10, (parseFloat(utils.decimalPlacesAllowedOnProductQty) + 1)); 773 774 var PadDifferenceFromMin = ( (inputQty * floatFixMultiplier) - (minQty * floatFixMultiplier) ); 775 var padStep = step * floatFixMultiplier; 776 var padMinQty = minQty * floatFixMultiplier; 777 var padMaxQty = maxQty * floatFixMultiplier; 778 779 //- Force max to valid value 780 if(maxQty < minQty) maxQty = 0; 781 if(maxQty > 0) { 782 var maxStepMod = (padMaxQty - padMinQty) % padStep; 783 if(maxStepMod != 0) { 784 var maxAdjust = Math.floor( (padMaxQty - padMinQty) / padStep ) * padStep; 785 786 maxQty = (padMinQty + maxAdjust) / floatFixMultiplier; 787 } 788 } 789 790 //- return max if inputQty is greater than max 791 if(maxQty > 0 && inputQty > maxQty){ 792 qtyValidationResult.validQty = maxQty; 793 qtyValidationResult.error = 'max'; 794 return qtyValidationResult; 795 } 796 797 // 1 isn't a valid default for qty when using 798 // fractional quantities without a defined increment 799 // or if it's off when it's simple sales uom, so 800 // we set increment/step to 0 801 var stepMod = step ? ( parseFloat( PadDifferenceFromMin % padStep ) / floatFixMultiplier ) : 0; 802 803 if(stepMod != 0){ 804 805 padValidQty = (Math.ceil( PadDifferenceFromMin / padStep ) * padStep) + padMinQty 806 807 var validQty = Math.round(padValidQty) / floatFixMultiplier; 808 809 qtyValidationResult.validQty = validQty; 810 if(maxQty > 0 && validQty > maxQty) qtyValidationResult.validQty = maxQty; 811 if(validQty < minQty) qtyValidationResult.validQty = minQty; 812 qtyValidationResult.error = 'inc'; 813 return qtyValidationResult; 814 } 815 816 return qtyValidationResult; 817 } 818 819</script>
vendor: 2 bytes, line 819
819
820<script> 821 var cimcloud = { 822 helpers: { 823 url: getUrl, 824 urlPath: getUrlPath, 825 loginUrl: utils.loginUrl, 826 pageType: utils.pageType, 827 pageSubType: utils.pageSubType, 828 pageName: utils.pageName, 829 pageKey: 'B5C8B43721D042E3BE244C0AC84508EA', 830 urlParameter: utils.getParameter, 831 buildImagePath: utils.buildImagePath, 832 environment: "production" 833 }, 834 session: { 835 accountNumber: "", 836 accountName: "", 837 username: "", 838 email: "", 839 firstName: "", 840 lastName: "", 841 sitename: "flagb3", 842 isLoggedIn: false, 843 isImpersonation: false, 844 parentSession: { 845 username: "", 846 email: "", 847 firstName: "", 848 lastName: "" 849 }, 850 appliedRights: "APPLICATION-DEFAULTS-BASE_INVOICES-SETTINGS,FLAGB3-CUSTOM-SETTINGS,SEARCH-FIELDS,APPLICATION-DEFAULTS-CATALOG-ALLOW-ATC-SETTINGS,APPLICATION-DEFAULTS-CUSTOM-PRODUCT-CATEGORIES-SETTINGS,APPLICATION-DEFAULTS-SHOW-CREATE-USER-SETTINGS,COUPON-TO-ERP-USE-FIXED-ITEM,APPLICATION-DEFAULTS-MODIFICATIONS-SETTINGS,SHOW_BO_ON_ORDER_CONFIRMATION_EMAIL,PRODUCT-IMAGES,CUSTOM - DISABLE INVOICE NUMBER REQUIREMENT,SHIPPING-SETTINGS,SET-ACCOUNT-NUMBER-PREFIX,S100-CIMCLOUD-B2B-A,PC-INV-IDP,COUPON2,APPLICATION-DEFAULTS-CART-CHECKOUT-SETTINGS-SETTINGS,APPLICATION-DEFAULTS-ENABLE ANONYMOUS SESSION CACHING-SETTINGS,ADV-PRICE-DISPLAY-SETTINGS,20231206-182066,FLAGB3-DEFAULTS-SHOW-CREATE-ACCOUNT-SETTINGS,BASE_INVOICES,COUPON3,ENABLE-SHIPPING-EDITS,ENABLE ANONYMOUS SESSION CACHING,APPLICATION-DEFAULTS-MODIFICATIONS-WORKER-SETTINGS,SHOW-PRICE-BREAKS,EMAIL-A-FRIEND,MODIFICATIONS,ENABLE-SHIPPING-ADDS,PRODUCT-CATEGORIES,QUOTES-SAVED-CARTS,INV-ERP-100,APPLICATION-DEFAULTS-BASE_INVOICES-WORKERS-SETTINGS,APPLICATION-DEFAULTS-PRODUCT-GALLERY-SETTINGS,LOCATOR-AUTO-POP,APPLICATION-DEFAULTS-S100-CIMCLOUD-B2B-A-SETTINGS,APPLICATION-DEFAULTS-SHIPPING-SETTINGS-SETTINGS,TOGGLE-RETAIL-TEMPLATE,ABAN-CART-EMAIL,PRODUCT-DETAIL-CONFIGURATOR,PRODUCT-DESC,APPLICATION-CUSTOM-SETTINGS,CATALOG-CUSTOMIZATIONS,UPLOAD-ATC,APPLICATION-DEFAULTS-CUSTOM - DISABLE INVOICE NUMBER REQUIREMENT-SETTINGS,RECENTLY-VIEWED-PRODUCTS,SHOW-CREATE-ACCOUNT,COUPON,TOGGLE-CUSTOM-PRODUCT-CATEGORIES,PRODUCT-PRICE-LIST,APPLICATION-DEFAULTS-BASE-SHOW_SHIPPING_ADDRESSES-SETTINGS,PRODUCT-DOCS,APPLICATION-DEFAULTS-CATALOG-ENABLE-PRODUCT-DISPLAY-FIELDS-SETTINGS,APPLICATION-DEFAULTS-PRODUCT-CATEGORIES-SETTINGS,APPLICATION-DEFAULTS-SITE-CONFIGURATION-CHANGES-SETTINGS,LOCATOR-GEO-DATA,APPLICATION-DEFAULTS-GOOGLEFEED-SETTINGS,BASE-SHIPPING_ADDRESSES,BASE_PAYMENTS-AND-CREDITS,SHOW-CREATE-USER,BASE_ORDERS-AND-SHIPMENTS,APPLICATION-DEFAULTS-CUSTOM-RETAIL-TEMPLATE-SETTINGS-SETTINGS,APPLICATION-DEFAULTS-BASE_ORDERS-AND-SHIPMENTS-SETTINGS,PC-CHILD-SEARCH-ROLLUP,RELATED-PRODUCTS,20200226-783995,PC-REVIEWS,APPLICATION-DEFAULTS-BASE-ADVANCED_CUSTOMER_PRICE_SETTINGS-SETTINGS,SITEMAPGEN,APPLICATION-DEFAULTS-CUSTOM-BILL TO ACCOUNT FIELD SETTINGS-SETTINGS,APPLICATION-DEFAULTS-PC-INV-IDP-SETTINGS,APPLICATION-DEFAULTS-CUSTOM-DUPLICATE-EMAIL-ADDRESS-MESSAGE-SETTINGS,BULK-ADD-TO-CART,ENABLE-BILLING-EDITS,TAXEXEMPT-C1,CUSTOM-BILL TO ACCOUNT FIELD SETTINGS,CART-CHECKOUT-SETTINGS,LOCATOR,GOOGLEFEED,PRODUCT-GALLERY,CATALOG-ALLOW-ATC,APPLICATION-DEFAULTS-SET-ACCOUNT-NUMBER-PREFIX-SETTINGS,PC-BOUGHT,CUSTOM-DUPLICATE-EMAIL-ADDRESS-MESSAGE-TOGGLE".split(',') 851 }, 852 catalog: {} 853 } 854 855 var viewModels = viewModels || {}; 856</script>
856 857 858 859
860<script src="/js/bundles/coreTop.js?4c332722dd6231439a1b8843ea4e6344b958c87f" ></script>
860 861 862
863<script src="/js/bundles/corePlugins.js?4c332722dd6231439a1b8843ea4e6344b958c87f" ></script>
863 864 865
866<script src="/js/bundles/coreVendors.js?4c332722dd6231439a1b8843ea4e6344b958c87f" ></script>
866<style> 867 .retail-header-0 .navigation-bar { 868 background-color: #0071c2; 869 color: #FFFFFF; 870 } 871 872 .retail-header-0 .navigation__account-cart .linkset a.header__user-menu__toggle, 873 .retail-header-0 .navigation__account-cart .linkset a.header__cart-preview__toggle, 874 .retail-header-0 .navigation__shop .shop__toggle, 875 .retail-header-0 .navigation__menu .header-nav__a-1, 876 .retail-header-0 .navigation__menu .header-nav__a-2 { 877 color: #FFFFFF; 878 } 879 880 .retail-header-0 .navigation__account-cart .linkset a.header__signin-open { 881 color: #FFFFFF !important; 882 } 883 884 .retail-header-0 .navigation__account-cart .linkset .link-parent.open a.header__signin-open, 885 .retail-header-0 .navigation__account-cart .linkset a.header__signin-open:hover, 886 .retail-header-0 .navigation__account-cart .linkset a.header__signin-open:focus, 887 .retail-header-0 .navigation__account-cart .linkset .link-parent.open a.header__user-menu__toggle, 888 .retail-header-0 .navigation__account-cart .linkset a.header__user-menu__toggle:hover, 889 .retail-header-0 .navigation__account-cart .linkset a.header__user-menu__toggle:focus, 890 .retail-header-0 .navigation__account-cart .linkset .link-parent.open a.header__cart-preview__toggle, 891 .retail-header-0 .navigation__account-cart .linkset a.header__cart-preview__toggle:hover, 892 .retail-header-0 .navigation__account-cart .linkset a.header__cart-preview__toggle:focus, 893 .retail-header-0 .navigation__shop .link-parent.open .shop__toggle, 894 .retail-header-0 .navigation__shop .shop__toggle:hover, 895 .retail-header-0 .navigation__shop .shop__toggle:focus, 896 .retail-header-0 .navigation__menu .link-parent.open .header-nav__a-1, 897 .retail-header-0 .navigation__menu .header-nav__a-1:hover, 898 .retail-header-0 .navigation__menu .header-nav__a-1:focus { 899 background-color: #FFFFFF !important; 900 color: #0071c2 !important; 901 } 902 903 .retail-header-0 .navigation-bar .header__cart-preview .cart_window_qty { 904 background-color: #FFFFFF; 905 color: #0071c2; 906 } 907 908 .retail-header-0 .navigation__account-cart .linkset .link-parent.open a.header__cart-preview__toggle .cart_window_qty, 909 .retail-header-0 .navigation__account-cart .linkset a.header__cart-preview__toggle:hover .cart_window_qty, 910 .retail-header-0 .navigation__account-cart .linkset a.header__cart-preview__toggle:focus .cart_window_qty { 911 background-color: #0071c2; 912 color: #FFFFFF; 913 } 914 #home-slides .item .carousel-caption a, 915 #home-slides .carousel-indicators li.active { 916 background-color: #c12535; 917 color: #FFFFFF; 918 } 919 #home-slides .item .carousel-caption a:hover, 920 #home-slides .item .carousel-caption a:focus { 921 background-color: rgb(218,62,78); 922 color: #FFFFFF; 923 } 924 #home-content {
925 border-top: 4px solid #0071c2; 926 } 927 .layout__sidebar h1, 928 .layout__sidebar #sidebar-nav>li li:hover>a { 929 background: #0071c2; 930 color: #FFFFFF; 931 } 932 #home-slides .item .carousel-caption h4 { 933 color: #444444; 934 } 935 #home-slides .item .carousel-caption p { 936 color: #333333; 937 } 938</style> 939 940
941<script async src="/js/jquery.swiftype.autocomplete.min.js"></script>
vendor: 2 bytes, line 941
941
942<script async src="/js/jquery.swiftype.search.js"></script>
942 943 944<!-- BEGIN swiftype Script -->
945<script type="text/javascript"> 946(function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){ 947(w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t); 948e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e); 949})(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_fab_st'); 950 951_fab_st('install','neNec_aapWjJvxxmaRSx','2.0.0'); 952</script>
952 953<!-- END swiftype Script --><!-- Google Tag Manager -->
954<script>!function(){"use strict";function l(e){for(var t=e,r=0,n=document.cookie.split(";");r<n.length;r++){var o=n[r].split("=");if(o[0].trim()===t)return o[1]}}function s(e){return localStorage.getItem(e)}function u(e){return window[e]}function A(e,t){e=document.querySelector(e);return t?null==e?void 0:e.getAttribute(t):null==e?void 0:e.textContent}var e=window,t=document,r="script",n="dataLayer",o="https://sgtm.flagandbanner.com",a="",i="5wifbrvvhs",c="dms7pvv=GgxLMSYvSz03LE9DPEQQVEFGR1AWDFsPHwkRFxwGBAgdBhMEXAEJBA%3D%3D",g="cookie",v="stape_uid",E="",d=!1;try{var d=!!g&&(m=navigator.userAgent,!!(m=new RegExp("Version/([0-9._]+)(.*Mobile)?.*Safari.*").exec(m)))&&16.4<=parseFloat(m[1]),f="stapeUserId"===g,I=d&&!f?function(e,t,r){void 0===t&&(t="");var n={cookie:l,localStorage:s,jsVariable:u,cssSelector:A},t=Array.isArray(t)?t:[t];if(e&&n[e])for(var o=n[e],a=0,i=t;a<i.length;a++){var c=i[a],c=r?o(c,r):o(c);if(c)return c}else console.warn("invalid uid source",e)}(g,v,E):void 0;d=d&&(!!I||f)}catch(e){console.error(e)}var m=e,g=(m[n]=m[n]||[],m[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"}),t.getElementsByTagName(r)[0]),v=I?"&bi="+encodeURIComponent(I):"",E=t.createElement(r),f=(d&&(i=8<i.length?i.replace(/([a-z]{8}$)/,"kp$1"):"kp"+i),!d&&a?a:o);E.async=!0,E.src=f+"/"+i+".js?"+c+v,null!=(e=g.parentNode)&&e.insertBefore(E,g)}();</script>
954 955<!-- End Google Tag Manager --> 956 957<style> 958 #category-layout #catalog-sidebar { 959 display:none; 960 } 961 #category-layout #catalog-main { 962 width: 100%; 963 } 964 965 @media (max-width: 768px) { 966 .prod-ds { 967 display: block; 968 } 969} 970 .btn-primary, .btn-primary.button { 971 background-color: #c12525; 972 border-color: #ffffff; 973 color: #FFFFFF; 974} 975 .page-main .category-window__btn-wrapper{ 976 display:none; 977 } 978 .retail-footer-0 #template-social .twitter { 979 background-position: -187px 0px; 980 } 981 982.retail-footer-0 #template-social .facebook { 983 background-position: -63px 0px; 984} 985 .retail-footer-0 #template-social .youtube { 986 background-position: 0px 0px; 987} 988 .retail-footer-0 #template-social .instagram { 989 background-position: -126px 0px; 990} 991 .retail-footer-0 #template-social .pinterest { 992 background-position: -375px 0px; 993} 994 995</style> 996</head> 997 998<body class="webpage static interior retail t-ui-phase-4 site-type-4 loggedout t-ui-phase-4 interior sp-webpage loggedout site-type-4 production flagb3"> 999 1000 1001 <!-- Google Tag Manager (noscript) -->
vendor: 77 bytes, lines 1001-1002
1001 1002 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
1002GTM-TDD95N
vendor: 92 bytes, lines 1002-1003
1002" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 1003
1003<!-- End Google Tag Manager (noscript) --> 1004 1005 1006 <noscript class="noscript-padding"></noscript> 1007 1008 1009 1010<header id="retail-header-0" class="retail-header-0 print-hide"> 1011 1012 <div id="topbar" class="topbar print-hide"> 1013 </div> 1014 1015 <div id="logo-bar" class="logo-bar"> 1016 <div class="container-fluid"> 1017 <div class="logo-bar__logo"> 1018 1019 <a href="https://www.flagandbanner.com" class="logo hidden-xs"> 1020 <img src="https://d3jy065g9mm97j.cloudfront.net/images/flagbannerlogo50-2.jpg?v=3997506342&v=3997506342" alt="FlagandBanner.com Logo"> 1021 </a> 1022 1023 <a href="https://www.flagandbanner.com" class="logo visible-xs"> 1024 <img src="https://d3jy065g9mm97j.cloudfront.net/images/flagbannerlogo50-2.jpg?v=3997506342&v=3997506342" alt="FlagandBanner.com Logo"> 1025 </a> 1026 1027 <a class="logo-bar__phone mobile" href="tel:5013757633"><i class="icon-phone icon-fixed-width"></i>501-375-7633</a> 1028 </div> 1029 <nav class="logo-bar__right"> 1030 <a class="logo-bar__phone desktop" href="tel:5013757633"><i class="icon-phone icon-fixed-width"></i>501-375-7633</a> 1031 1032 1033 <form id="frmUnivSearch" class="u-search-form control-group" method="post" action=""> 1034 1035 1036 <span class="u-search-group u-search-text"> 1037 <input 1038 type="text" 1039 name="u_search_text" 1040 id="u_search_text" 1041 class="input-search st-default-search-input" 1042 placeholder="Search..." 1043 value="" 1044 autocomplete="off" 1045 autocorrect="off" 1046 autocapitalize="off" 1047 spellcheck="false" 1048 aria-label="Search Text" 1049 /> 1050 </span> 1051 1052 1053 1054 <span class="u-search-group u-search-droplist"> 1055 <select name="u_search_type" id="u_search_type" class=" hide" aria-label="Search Type"> 1056 <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> 1057 </select> 1058 </span> 1059
1060 <span class="u-search-group u-search-btn"> 1061 1062 <button type="submit" name="u_search_submit" id="u_search_submit" class="btn btn-primary header__search__button" aria-label="Search"> 1063 <i class="icon-search"></i> 1064 </button> 1065 </span><input type="hidden" name="search_tip_url" id="search_tip_url" value="" /> 1066 </form> 1067 1068
1068<script type="application/javascript"> 1069 1070 // Execute when DOM ready 1071 $(function(){ 1072 1073 // Form post 1074 $('#frmUnivSearch').on('submit', function(e){ 1075 e.preventDefault(); 1076 fncProcessUniversalSearch(); 1077 }); 1078 1079 }); 1080 /* Boolean Vars */ 1081 /* 1082 * Add the STOREFRONTURL to the page being redirected to 1083 * @author johns 1084 * @since 6/28/2012 1085 * @var bool 1086 */ 1087 var bAddStoreFrontUrlToPost = true; 1088 1089 /* 1090 * Log the keyword search 1091 * @author johns 1092 * @since 6/28/2012 1093 * @var bool 1094 */ 1095 var bUseKeywordSearchLogging = true; 1096 1097 /* 1098 * Create searchstring by the splitting the terms on spaces 1099 * @author johns 1100 * @since 6/28/2012 1101 * @var bool 1102 */ 1103 var bUseSplitTermSearching = true; 1104 1105 /* 1106 * Use Auto Suggestions when searching 1107 * @author johns 1108 * @since 07/26/2012 1109 * @var bool 1110 */ 1111 var bUseAutoSuggestions = true; 1112 1113 /* 1114 * Add Categories to the Searchstring 1115 * @author johns 1116 * @since 07/26/2012 1117 * @var bool 1118 */ 1119 var bUseCategories = false; 1120 1121 /* 1122 * Add modal=1 to redirect url 1123 * @author ejohnston 1124 * @since 10/02/2017 1125 * @var bool 1126 */ 1127 var bUseModal = false; 1128 1129 /* String Vars */ 1130 /* 1131 * VBScript variable for STOREFRONTURL 1132 * @author johns 1133 * @since 6/28/2012 1134 * @var string 1135 * Updated 2017-10-03 EJ - Used order front url to avoid SSL mixed content errors 1136 */ 1137 var sStoreFrontUrl = 'https://www.flagandbanner.com'; 1138 1139 /* 1140 * Name of the current page loaded 1141 * @author johns 1142 * @since 6/28/2012 1143 * @var string 1144 * Updated 201-11-15 EJ - Changed var name to avoid conflict 1145 */ 1146 var searchPageName = 'i_i_u_search.asp'; 1147 1148 /* 1149 * List of product fields to check for a product search 1150 * @author johns 1151 * @since 6/28/2012 1152 * @var string 1153 */ 1154 var sProductFieldsToCheck = 'p.sku, p.nm, p.ds, p.search_terms, p.child_rollup_search_terms, p.child_skus'; 1155 1156 /* 1157 * List of fields to check for a website search 1158 * @author johns 1159 * @since 6/28/2012 1160 * @var string 1161 */ 1162 var sWebsiteFieldsToCheck = 'p.nm,p.ds,staticpages.se_pagetitle,staticpages.se_ds,staticpages.se_keywords'; 1163 1164 /* 1165 * Name of the page to redirect to for product searches 1166 * @author johns 1167 * @since 6/28/2012 1168 * @var string 1169 */ 1170 var sProductSearchPage = 'pc_combined_results.asp'; 1171 1172 /* 1173 * Name of the page to redirect to for website searches 1174 * @author johns 1175 * @since 6/28/2012 1176 * @var string 1177 */ 1178 var sWebsiteSearchPage = 'search_results.asp'; 1179 1180 /* 1181 * List of category fields to check for a product search 1182 * @author johns 1183 * @since 07/26/2012 1184 * @var string 1185 */ 1186 var sCategoryFieldsToCheck = 'pc.nm,pc.ds'; 1187 1188 //- these are for the search tips ajax call redirect 1189 /* 1190 * Page the search is being performed on 1191 * @author johns 1192 * @since 07/26/2012 1193 * @var string 1194 */ 1195 var sInitPage = '/page.asp'; 1196 1197 /* 1198 * Add modalaction to redirect url if populated 1199 * @author ejohnston 1200 * @since 11/18/2022 1201 * @var string 1202 */ 1203 var sModalAction = ""; 1204 1205 /* 1206 * Website name 1207 * @author johns 1208 * @since 07/26/2012 1209 * @var string 1210 */ 1211 var sSitename = 'flagb3'; 1212 1213 var sProductSearchTerm = 'products'; 1214 var bTrimSearchTerm = false; 1215 1216 var isWorkerDomain = false; 1217 1218 /** 1219 * This function handles the form submission. 1220 * 1221 * @author seanm 1222 * @since ?? 1223 * 1224 * @author johns 1225 * @modified 6/28/2012 1226 * 1227 * @return void 1228 */ 1229 function fncProcessUniversalSearch(searchTerm, redirect = true) { 1230 var sPrepopValues = ''; 1231 var sDelimiter = '?'; 1232 var sNewSearchPage = ''; 1233 var sSearchType = ''; 1234 var sRedirectUrl = ''; 1235 var sSearchTerm = jQuery('#u_search_text').val() 1236 if(searchTerm){ sSearchTerm = searchTerm } 1237 1238 if (bTrimSearchTerm) 1239 sSearchTerm = $.trim(sSearchTerm); 1240 1241 sSearchTerm = encodeURIComponent(sSearchTerm); 1242 1243 jQuery('#u_search_text').attr('disabled', true); 1244 jQuery('#u_search_type').attr('disabled', true); 1245 jQuery('#u_search_submit').attr('disabled', true); 1246 1247 sSearchType = jQuery('#u_search_type option:selected').text().toLowerCase(); 1248 1249 if ( bUseSplitTermSearching && sSearchType == sProductSearchTerm ) { 1250 sNewSearchPage = fncBuildSplitTermSearchPage ( sSearchTerm, sSearchType ); 1251 } else { 1252 querystringTerm = sSearchTerm.replaceAll('(','\\(').replaceAll(')','\\)'); 1253 sNewSearchPage = jQuery('#u_search_type option:selected').val().replace(/<keyword>/ig, querystringTerm); 1254 } 1255 1256 /* 1257 * If there's already a ?, we need to make sure we don't add another. 1258 */ 1259 if ( sNewSearchPage.indexOf('?') >= 0 ) { 1260 sDelimiter = '&'; 1261 } 1262 1263 /* 1264 * PMH #134437 1265 * Added search_keyword to query string regardless of whether splitting is in use. That allows 1266 * the search textbox to always populate. 1267 */ 1268 if (bUseSplitTermSearching && sSearchType == sProductSearchTerm ) { 1269 sPrepopValues = sDelimiter + 'search_keyword=' + sSearchTerm; 1270 } else { 1271 if (sNewSearchPage.indexOf('search_keyword') == -1) 1272 sPrepopValues = sDelimiter + 'search_keyword=' + sSearchTerm + sDelimiter + 'u_search_type=' + jQuery('#u_search_type option:selected').text(); 1273 else 1274 sPrepopValues = sDelimiter + 'u_search_type=' + jQuery('#u_search_type option:selected').text(); 1275 } 1276 1277 if ( sNewSearchPage.indexOf('u_search_type') >= 0 ) { 1278 sPrepopValues = ''; 1279 } 1280 1281 if ( bAddStoreFrontUrlToPost ) { 1282 sNewSearchPage = '/' + sNewSearchPage; 1283 } 1284 1285 if ( bUseAutoSuggestions ) { 1286 fncCheckSearchSuggestions(); 1287 sRedirectUrl = jQuery('#search_tip_url').val(); 1288 } //- if ( bUseAutoSuggestions ) 1289 1290 if ( sRedirectUrl === '' ) { 1291 sRedirectUrl = sNewSearchPage + sPrepopValues; 1292 } 1293 1294 if ( bUseKeywordSearchLogging ) { 1295 fncLogKeywordSearch(sSearchType, sSearchTerm, sRedirectUrl) 1296 } 1297 1298 if(bUseModal) { 1299 sRedirectUrl += '&modal=1'; 1300 } 1301 1302 if(sModalAction) { 1303 sRedirectUrl += '&modalaction=' + sModalAction; 1304 } 1305 1306 var config = { 1307 searchTerm: sSearchTerm, 1308 url: sRedirectUrl 1309 }; 1310 1311 runHook('processUniversalSearchUrl',config); 1312 1313 if(!redirect){ 1314 return config.url; 1315 }else{ 1316 window.location = config.url; 1317 } 1318 } //- function fncProcessUniversalSearch() 1319 1320 /** 1321 * This function fires an ajax call to log the keyword search. 1322 * 1323 * @author johns 1324 * @since 6/28/2012 1325 * 1326 * @param sType (string): type of search submitted 1327 * @param sKeyword (string): keyword(s) searching for 1328 * @param sUrl (string): url redirected to see the results 1329 * of the search 1330 * 1331 * @return void 1332 */ 1333 function fncLogKeywordSearch ( sType, sKeyword, sUrl ) { 1334 1335 jQuery.ajax({ 1336 url: searchPageName + '?pageaction=logsearch&SearchFormAjax=1', 1337 data: 'search_type=' + sType + '&search_term=' + sKeyword + '&search_url=' + sUrl + '&r_id=' + new Date().getTime(), 1338 type: 'POST', 1339 dataType: 'text', 1340 beforeSend: '', 1341 success: function () { return; } 1342 }); 1343 1344 } //- function fncLogKeywordSearch ( sType, sKeyword, sUrl ) 1345 1346 /**
1347 * This function builds a searchstring from phrases (denoted 1348 * by single or double quotes) and other search terms. 1349 * 1350 * @author johns 1351 * @since 6/28/2012 1352 * 1353 * @param sSearchType (string): type of search submitted 1354 * @param sSearchTerms (string): phrases or words searching for 1355 * 1356 * @return string (page used to redirect to with the appropriate searchstring) 1357 */ 1358 function fncBuildSplitTermSearchPage ( sSearchTerms, sSearchType ) { 1359 1360 /* 1361 * array variables 1362 */ 1363 var aNewSearchTerms; 1364 var aFieldsToCheck; 1365 var aTerms; 1366 1367 /* 1368 * string variables 1369 */ 1370 var sTerms = ''; 1371 var aNewSearchTerms = []; 1372 var sResult = ''; 1373 var sSearchStringQSVar = ''; 1374 1375 /* 1376 * determine which list of fields to use and which 1377 * page we need to redirect to based on search 1378 * type 1379 */ 1380 switch (sSearchType) { 1381 case 'website': 1382 sSearchPage = sWebsiteSearchPage; 1383 sFieldsToCheck = sWebsiteFieldsToCheck; 1384 sSearchStringQSVar = 'search_website'; 1385 break; 1386 1387 case sProductSearchTerm: 1388 sSearchPage = sProductSearchPage; 1389 sFieldsToCheck = sProductFieldsToCheck; 1390 1391 if ( bUseCategories ) aCategoryFieldsToCheck = sCategoryFieldsToCheck.split(','); 1392 1393 sSearchStringQSVar = 'search_prod'; 1394 sCategorySearchStringQSVar = 'search_cat'; 1395 break; 1396 } 1397 1398 /* 1399 * build an array from a list of fields to check in the extended search 1400 * by splitting the list on ',' 1401 */ 1402 aFieldsToCheck = sFieldsToCheck.split(','); 1403 1404 sSearchTerms = sSearchTerms.replaceAll('(','\\(').replaceAll(')','\\)') 1405 aNewSearchTerms = decodeURIComponent(sSearchTerms).split(/\s+/); 1406 1407 sSearchTerms = encodeURIComponent(sSearchTerms); 1408 1409 1410 if ('1' == '1') { 1411 sSearchPage = sSearchPage + '?' + sSearchStringQSVar + '=' + fncBuildSearchString(aNewSearchTerms, aFieldsToCheck); 1412 1413 if (bUseCategories && sSearchType === sProductSearchTerm) { 1414 sSearchPage = sSearchPage + '&' + sCategorySearchStringQSVar + '=' + fncBuildSearchString(aNewSearchTerms, aCategoryFieldsToCheck); 1415 } 1416 } 1417 1418 return sSearchPage; 1419 } // fncBuildSplitTermSearchPage 1420 1421 function fncCheckSearchSuggestions () { 1422 var sSearchTerm = ''; 1423 1424 try { 1425 1426 /* 1427 * if it is blank, ge the value of term being searched 1428 * for 1429 */ 1430 sSearchTerm = jQuery('#u_search_text').val(); 1431 sSearchTerm = sSearchTerm.toLowerCase(); 1432 1433 /* 1434 * loop through the json object build by the ajax call 1435 * to build the search tips list 1436 */ 1437 for ( var i = 0, goTo = window.oSearch.terms.length; i < goTo; i++ ) { 1438 1439 /* 1440 * get the term value of json object 1441 */ 1442 sTerm = window.oSearch.terms[i]; 1443 sOriginalTerm = sTerm; 1444 sTerm = sTerm.toLowerCase(); 1445 1446 /* 1447 * see if the term matches the word being searched for 1448 */ 1449 if ( sTerm == sSearchTerm ) { 1450 1451 /* 1452 * check the term that matched an suggested term 1453 * has an specific url to redirect to 1454 */ 1455 fncGetSearchTermRedirectUrl ( window.oSearch[sOriginalTerm] ); 1456 1457 /* 1458 * if a specific redirect url has been found then exit the "terms" for loop 1459 */ 1460 if ( jQuery('#search_tip_url').val() !== '' ) break; 1461 1462 } //- if ( sTerm == sSearchTerm ) 1463 1464 } //- for ( var i = 0, goTo = window.oSearch.terms.length; i < goTo; i++ ) 1465 1466 } catch ( oError ) { 1467 //alert(oError.message); 1468 } //- try 1469 1470 return 1471 1472 } //- function fncGetSearchSuggestionUrl () 1473 1474 /** 1475 * AJAX Call to get search term suggestions 1476 * 1477 * @author johns 1478 * @since 4/15/2010 1479 * 1480 * @return void 1481 */ 1482 function fncGetSuggestions ( text ) { 1483 1484 try { 1485 1486 //- check to see if the ajax call should be fired again 1487 //- run it again, if length of the search term = 0 1488 if ( text.length < 1 ) { 1489 window.bGetSuggestions = false; 1490 } //- if ( text.length < 1 ) 1491 1492 if ( ! window.bGetSuggestions ) { 1493 1494 if ( text.length >= 1 ) { 1495 1496 //- set it to true once inside the ajax call so it does not fire again 1497 window.bGetSuggestions = true; 1498 1499 text = text.substr(0,1); 1500 1501 jQuery.ajax({ 1502 url: 'i_i_pc_search_form.asp' 1503 , data: ({ searchformaction : 'ajaxcall' 1504 , searchformactiontype : 'getsearchtips' 1505 , firstchar : text 1506 , ajax: new Date().getTime() 1507 }) 1508 , cache: false 1509 , dataType: 'json' 1510 , error: function(jqXHR, textStatus, errorThrown) { console.log('error - ' + errorThrown); } 1511 , success: fncLoadSuggestions 1512 });
1513 1514 } //- if ( text.length >= 1 ) 1515 1516 } //- if ( ! window.bGetSuggestions ) 1517 1518 } catch ( oError ) { 1519 //alert(oError.message); 1520 } //- try 1521 1522 }// function fncGetSuggestions() 1523 1524 /** 1525 * AJAX callback function to load search 1526 * term suggestions 1527 * 1528 * @author johns 1529 * @since 4/15/2010 1530 * 1531 * @return void 1532 */ 1533 function fncLoadSuggestions ( oData ) { 1534 1535 window.oSearch = oData; 1536 1537 jQuery('#u_search_text') 1538 .autocomplete(oData.terms,{ 1539 select: function ( event, ui ) { 1540 1541 /* 1542 * get the search term selected from the auto complete list (json object) 1543 */ 1544 oResult = window.oSearch[ui.item.label]; 1545 1546 /* 1547 * check the term that matched an suggested term 1548 * has an specific url to redirect to 1549 */ 1550 fncGetSearchTermRedirectUrl ( oResult ); 1551 1552 } 1553 }); 1554 1555 } //- function fncLoadSuggestions ( oData ) 1556 1557 /** 1558 * This function determines if the term that matched an 1559 * suggested term has an specific url to redirect to. 1560 * 1561 * @author johns 1562 * @since 7/30/2012 1563 * 1564 * @param oResult (json object): term in the json object 1565 * that matched the term entered by the user 1566 * 1567 * @return void 1568 */ 1569 function fncGetSearchTermRedirectUrl ( oResult ) { 1570 1571 /* 1572 * if the term matching the word being searched for 1573 * has action = 'link' and the url is not blank then 1574 * set the hidden input field for the search tip url 1575 * to the url of the current term index 1576 */ 1577 if ( oResult.action == 'link' && oResult.url != '' ) { 1578 1579 /* 1580 * get the length of the name of the site currently on(needed 1581 * to see if the sitename/virtualweb needs to be 1582 * stripped off) 1583 */ 1584 iLenSitename = sSitename.length; 1585 1586 /* 1587 * if on an admin server strip off the '/sitename/virtualweb/' off the 1588 * current page name (pulled from the Request.ServerVariables("SCRIPT_NAME") 1589 */ 1590 if ( sInitPage.substr(0,iLenSitename + 13) === '/' + sSitename + '/virtualweb/' ) { 1591 sInitPage = sInitPage.substr(iLenSitename + 13); 1592 } //- if ( sInitPage.substr(0,iLenSitename + 13) === '/' + sSitename + '/virtualweb/' ) 1593 1594 /* 1595 * check to see if the static page is located in 1596 * a directory (only assuming one directory deep off the root 1597 * since static pages are only one directory deep 1598 * off the root) 1599 */ 1600 if ( sInitPage.indexOf('/') >= 0 ) { 1601 sResultUrl = '../' + oResult.url; 1602 } else { 1603 sResultUrl = oResult.url; 1604 } //- if ( sInitPage.indexOf('/') >= 0 ) 1605 1606 /* 1607 * set the hidden input field to the url of the matched term 1608 */ 1609 jQuery('#search_tip_url').val(sResultUrl); 1610 1611 } //- if ( oResult.action == 'link' && oResult.url != '' ) 1612 1613 } //- function fncGetSearchTermRedirectUrl ( oResult ) 1614 1615 /**
1616 * This function builds a searchstring based on the list of 1617 * split search terms and the list of fields to check. 1618 * 1619 * @author johns 1620 * @since 7/30/2012 1621 * 1622 * @param aSearchTerms (array): list of search terms 1623 * @param aFieldsToCheck (array): list of fields to check 1624 * 1625 * @return string (WSP formatted searchstring) 1626 */ 1627 function fncBuildSearchString ( aSearchTerms, aFieldsToCheck ) { 1628 /* 1629 * string variables 1630 */ 1631 /* 1632 * New Search String Built 1633 * @author johns 1634 * @since 08/15/2012 1635 * @var string 1636 */ 1637 var sNewSearchString = ''; 1638 1639 /* 1640 * boolean variables 1641 */ 1642 /* 1643 * Is this the First Field in the list of fields 1644 * to check in split term searching? 1645 * @author johns 1646 * @since 08/14/2012 1647 * @var bool 1648 */ 1649 var bFirstField = true; 1650 1651 /* 1652 * loop through the search terms split on whitespace 1653 */ 1654 for ( var iTermCounter = 0, iTermGoTo = aSearchTerms.length - 1; iTermCounter <= iTermGoTo; iTermCounter++ ) { 1655 1656 /* 1657 * loop through the fields to search list with the current search term 1658 */ 1659 for ( var iFieldCounter = 0, iFieldGoTo = aFieldsToCheck.length - 1; iFieldCounter <= iFieldGoTo; iFieldCounter++ ) { 1660 1661 /* 1662 * check to see if we are at the first field 1663 * if so, add the opening parantheses 1664 */ 1665 if ( bFirstField ) { 1666 sNewSearchString += '('; 1667 } //- if ( bFirstField ) 1668 1669 /* 1670 * check to see if the searchstring var has assigned to anything yet 1671 * if so, concatentate '|Or|' to the end of the string 1672 */ 1673 if ( sNewSearchString != '' && ! bFirstField ) { 1674 sNewSearchString += '|Or|'; 1675 } //- if ( sNewSearchString != '' && ! bFirstField ) 1676 1677 /* 1678 * build the searchstring with the current search term and field based 1679 * on the search type 1680 */ 1681 sNewSearchString += '(searchlike~' + aFieldsToCheck[iFieldCounter] + '~' + encodeURIComponent(aSearchTerms[iTermCounter]) + ')'; 1682 1683 /* 1684 * set the var to false that signals we are on the first field the next time 1685 * through the loop 1686 */ 1687 bFirstField = false; 1688 1689 } //- for ( var iFieldCounter = 0, iFieldGoTo = aFieldsToCheck.length - 1; iFieldCounter <= iFieldGoTo; iFieldCounter++ ) 1690 1691 /* 1692 * after looping through the fields to search with the current search term, 1693 * reset the var that signals we are on the first field the next time we 1694 * loop through them 1695 */ 1696 bFirstField = true; 1697 1698 /* 1699 * after looping through the fields to search with the current search term, 1700 * check to see if we just looped through the last search term 1701 */ 1702 if ( iTermCounter >= iTermGoTo ) { 1703 1704 /* 1705 * if we are at the last search term, add the closing parantheses to 1706 * the current search term 1707 */ 1708 sNewSearchString += ')'; 1709 1710 } else { 1711 1712 /* 1713 * if we are not at the last search term, add the closing parantheses 1714 * to the current search term and concatenate '|And|' to the end of 1715 * the searchstring 1716 */ 1717 sNewSearchString += ')|And|'; 1718 1719 } //- if ( iTermCounter >= iTermGoTo ) 1720 1721 } //- for ( var iTermCounter = 0, iTermGoTo = aSearchTerms.length - 1; iTermCounter <= iTermGoTo; iTermCounter++ ) 1722 1723 return sNewSearchString 1724 1725 } //- function fncBuildSearchString ( aSearchTerms, aFieldsToCheck ) 1726 1727 jQuery(function() { 1728 jQuery('#u_search_text').keyup(function() { 1729 1730 if ( bUseAutoSuggestions ) { 1731 fncGetSuggestions(this.value); 1732 } //- if ( bUseAutoSuggestions ) 1733 1734 }); 1735 1736 if (bUseAutoSuggestions) { 1737 jQuery('#search_keyword').autocomplete([]); 1738 } 1739 }); 1740 1741 jQuery(function() { 1742 if(utils && utils.getParameter('autosearch') == '1'){ 1743 fncProcessUniversalSearch(); 1744 } 1745 }); 1746 </script>
1746 1747 </nav> 1748 </div> 1749 </div> 1750 <div class="navigation-bar"> 1751 <div class="container-fluid"> 1752 <div class="navigation__shop-menu"> 1753 <ul class="navigation__shop linkset click js-click-outside-to-close"> 1754 <li class="link-parent"> 1755 <a class="shop__toggle"><i class="icon-tags"></i> Shop <i class="icon-caret-down"></i></a> 1756 <ul id="shop-nav" class="shop-nav linkset plus shop-nav__ul-1"> 1757 <li class="flags shop-nav__li-1" data-key='E7CFCDD1BA744C94AF1FDFE80E3E949C'><a href="flags/flags.asp" class="shop-nav__a-1">Flags and Banners</a> 1758 <ul class="shop-nav__ul-2"> 1759 <li class="shop-nav__li-2" data-key='5452D457ACA746F8A1C2BFD927F4BB0A'><a href="flags/american-flags.asp" class="shop-nav__a-2">American</a> 1760 <ul class="shop-nav__ul-3"> 1761 <li class="shop-nav__li-3" data-key='41B2B687C3FE4E54A6DE7CE883562711'><a href="flags/flags-american-outdoor.asp" class="shop-nav__a-3">Outdoor American Flags</a></li> 1762 <li class="shop-nav__li-3" data-key='88CEA3687E09479F88658ED40A897C91'><a href="flags/indoor-american-flags.asp" class="shop-nav__a-3">Indoor American Flags</a></li> 1763 <li class="shop-nav__li-3" data-key='9AD308008BE64F7E93217DB4FA0297AE'><a href="banners/american_banners.asp" class="shop-nav__a-3">American Banners</a></li> 1764 <li class="shop-nav__li-3" data-key='3818795F0E19424F9D4C4B9B55194D3D'><a href="flags/american-mini-stick.asp" class="shop-nav__a-3">Miniature American Stick Flags</a></li> 1765 <li class="shop-nav__li-3" data-key='21AF6419A9D349A6B3B73477E53F56EC'><a href="flags/american-car-flags.asp" class="shop-nav__a-3">American Car Flags</a></li> 1766 <li class="shop-nav__li-3" data-key='267C4CF93A6D4E2C83748BC896621A09'><a href="flags/outdoor-american-flag-kits.asp" class="shop-nav__a-3">Outdoor American Flag Kits</a></li> 1767 <li class="shop-nav__li-3" data-key='6E8C1307681F4F32998FBEE1682EDC28'><a href="flags/indoor-american-flag-kits.asp" class="shop-nav__a-3">Indoor American Flag Kits</a></li> 1768 <li class="shop-nav__li-3" data-key='49EF5B8F68B64D32AFB43176080895E7'><a href="products/american-star-flags.asp" class="shop-nav__a-3">Historical American Star Flags</a></li> 1769 <li class="shop-nav__li-3" data-key='5C69ED8DF3A5462E94900ABFF1BE5778'><a href="flags/desk-american-flag-sets.asp" class="shop-nav__a-3">American Flag Desk Sets</a></li> 1770 <li class="shop-nav__li-3" data-key='39A2341ABC6D4333B01DD685A841D1FE'><a href="products/us-flags-school.asp" class="shop-nav__a-3">Classroom American Flag Kits</a></li> 1771 </ul></li> 1772 <li class="shop-nav__li-2" data-key='BFF38958CE0844CE84FF80480E9CA34A'><a href="flags/military-flags.asp" class="shop-nav__a-2">Military and Civilian Service</a> 1773 <ul class="shop-nav__ul-3"> 1774 <li class="shop-nav__li-3" data-key='F858301C57E04146A70067BC5B016C3B'><a href="flags/navy-flags.asp" class="shop-nav__a-3">Navy Flags & Banners</a></li> 1775 <li class="shop-nav__li-3" data-key='D8CFBD8ACB91417D9803C6530A221F79'><a href="flags/army-flags.asp" class="shop-nav__a-3">Army Flags & Banners</a></li> 1776 <li class="shop-nav__li-3" data-key='252AE0CD08CB419E930069BFBCAF27C6'><a href="flags/air-force-flags.asp" class="shop-nav__a-3">Air Force Flags & Banners</a></li> 1777 <li class="shop-nav__li-3" data-key='0DE4BC8D6D2E4097AF0DE80AC30DF439'><a href="flags/marine-corps-flags.asp" class="shop-nav__a-3">Marine Corps Flags & Banners</a></li> 1778 <li class="shop-nav__li-3" data-key='5FF31588F5A7491EA412C1239345EAEF'><a href="flags/coast-guard-flags.asp" class="shop-nav__a-3">Coast Guard Flags & Banners</a></li> 1779 <li class="shop-nav__li-3" data-key='BC0213A293614774BC3614D7D383960C'><a href="flags/space-command.asp" class="shop-nav__a-3">Space Force Flags & Banners</a></li> 1780 <li class="shop-nav__li-3" data-key='5B7518B225C64093B53DC14993C8D3D1'><a href="flags/flags-military-service-outdoor.asp" class="shop-nav__a-3">Outdoor Military Flags & Banners</a></li> 1781 <li class="shop-nav__li-3" data-key='88CE6B6E9E814F69AABA555E6D97798C'><a href="flags/flags-military-service-indoor-parade.asp" class="shop-nav__a-3">Indoor Military Flags & Banners</a></li> 1782 <li class="shop-nav__li-3" data-key='6897C32E4E984EB1AB98595359674835'><a href="flags/general-admiral-star-flags-kits.asp" class="shop-nav__a-3">General & Admiral Star Flags & Kits</a></li> 1783 <li class="shop-nav__li-3" data-key='52026AEDF2E74AC2AFB69D0DDB017DEE'><a href="flags/retired-military-flags.asp" class="shop-nav__a-3">Retired Military Flags & Kits</a></li> 1784 <li class="shop-nav__li-3" data-key='F1CA046214EA4933B97E7C4F5FD6A510'><a href="flags/flags-military-service-miniature.asp" class="shop-nav__a-3">Miniature Military & Service Flags</a></li> 1785 <li class="shop-nav__li-3" data-key='BB2C8D77F07F40C3A9A80EDA1273A3D8'><a href="pennants/military_pennants.asp" class="shop-nav__a-3">Military & Service Pennants</a></li> 1786 <li class="shop-nav__li-3" data-key='D643379A0578403FBC8BC8737600A265'><a href="flags/service-persons-flags.asp" class="shop-nav__a-3">Public Service Flags & Banners</a></li> 1787 <li class="shop-nav__li-3" data-key='BEFC88F41D624FA39C78A80E41CDF292'><a href="holidays/pow_mia_flags_and_banners.asp" class="shop-nav__a-3">POW-MIA & KIA Flags</a></li> 1788 <li class="shop-nav__li-3" data-key='2FF785CFDA4644EB86943C14E98EB08A'><a href="flags/thin-line-flags.asp" class="shop-nav__a-3">
1788Thin Line Flags</a></li> 1789 <li class="shop-nav__li-3" data-key='1E06FFF501DC4778B003BDCBED137FF5'><a href="flags/special-military-government-flags.asp" class="shop-nav__a-3">Specialty Military & Government Flags</a></li> 1790 <li class="shop-nav__li-3" data-key='8C62562CD77D4DC3B474A37C24A03245'><a href="holidays/support_our_troops.asp" class="shop-nav__a-3">Support Our Troops Flags</a></li> 1791 <li class="shop-nav__li-3" data-key='ECDCF68CF5FD41CC92CB28A58AB47560'><a href="flags/service-star-flags-banners.asp" class="shop-nav__a-3">Service Star Flags & Banners</a></li> 1792 </ul></li> 1793 <li class="shop-nav__li-2" data-key='A5BEFB42E2F6493BBF75EEE232152621'><a href="flags/historical-flags.asp" class="shop-nav__a-2">Historical</a> 1794 <ul class="shop-nav__ul-3"> 1795 <li class="shop-nav__li-3" data-key='E6F16EDDD9E64982851AE21EECD4BDF2'><a href="products/betsy-ross.asp" class="shop-nav__a-3">Betsy Ross Flags</a></li> 1796 <li class="shop-nav__li-3" data-key='9635CF4ED8204B4080949859525FE9BB'><a href="products/american-star-flags.asp" class="shop-nav__a-3">Historical American Star Flags</a></li> 1797 <li class="shop-nav__li-3" data-key='8B63D6F473BA4DD68FFB89822F8EA081'><a href="holidays/dont_tread_on_me_flags_and_gifts.asp" class="shop-nav__a-3">Gadsden Flags</a></li> 1798 <li class="shop-nav__li-3" data-key='241DBA6274B0470FA6F55770DDC7DDE9'><a href="products/revolutionary-war.asp" class="shop-nav__a-3">American Revolutionary War Flags</a></li> 1799 <li class="shop-nav__li-3" data-key='B02C504C97974B3D85BEA03A987CE75A'><a href="products/historical-pirate-flags.asp" class="shop-nav__a-3">Historical Pirate Flags</a></li> 1800 <li class="shop-nav__li-3" data-key='A6209722F9454C0E850C164341C9197C'><a href="flags/flags-historical-miniature.asp" class="shop-nav__a-3">Miniature Historical Flags</a></li> 1801 </ul></li> 1802 <li class="shop-nav__li-2" data-key='FFCBA6D17B314FA29523142FAD845ED0'><a href="flags/nautical-flags.asp" class="shop-nav__a-2">Nautical</a> 1803 <ul class="shop-nav__ul-3"> 1804 <li class="shop-nav__li-3" data-key='2B95E4D18FEF4922B9CE50A6F02B0B1A'><a href="nautical/international-code-signal-flags-pennants.asp" class="shop-nav__a-3">International Code Signal Flags & Pennants</a></li> 1805 <li class="shop-nav__li-3" data-key='905AEDF60A0F498D820E4AEB34E8B511'><a href="flags/beach-warning-flags.asp" class="shop-nav__a-3">Beach Warning Flags</a></li> 1806 <li class="shop-nav__li-3" data-key='67E047FAECA74595801DAA5C1F4F8C34'><a href="flags/flags-nautical-outdoor.asp" class="shop-nav__a-3">Boating and Nautical Fun Flags</a></li> 1807 <li class="shop-nav__li-3" data-key='46663D9E428646F19ABB964EB4BE29BB'><a href="flags/flags-nautical-miniature.asp" class="shop-nav__a-3">Miniature Nautical Flags</a></li> 1808 <li class="shop-nav__li-3" data-key='111F7EA29B704013B9C5DD571C5200AC'><a href="pennants/nautical_pennants.asp" class="shop-nav__a-3">Nautical Pennants</a></li> 1809 </ul></li> 1810 <li class="shop-nav__li-2" data-key='644153A578EA4A61AAE9B0E87CCDEEE0'><a href="flags/world-flags.asp" class="shop-nav__a-2">World</a> 1811 <ul class="shop-nav__ul-3"> 1812 <li class="shop-nav__li-3" data-key='7C420DAB366741B28413AFB8A52EAB5B'><a href="flags/world-flags.asp" class="shop-nav__a-3">A through Z</a></li> 1813 <li class="shop-nav__li-3" data-key='5FB006D9DD224C8CBFCA20068673D33D'><a href="flags/mexico-world-flags.asp" class="shop-nav__a-3">Mexican Flags</a></li> 1814 <li class="shop-nav__li-3" data-key='AAA43971FDD34B919F62DD218CFCADAD'><a href="flags/france-world-flags.asp" class="shop-nav__a-3">French Flags</a></li> 1815 <li class="shop-nav__li-3" data-key='EE74745866CB4F638CD57FB261005A13'><a href="flags/italy-world-flags.asp" class="shop-nav__a-3">Italian Flags</a></li> 1816 <li class="shop-nav__li-3" data-key='DCF7206B97294F66ADACAD7816E50ADB'><a href="flags/germany-world-flags.asp" class="shop-nav__a-3">German Flags</a></li> 1817 <li class="shop-nav__li-3" data-key='82E4840E4CBC462CB39BC3D6F1123525'><a href="flags/canada-world-flags.asp" class="shop-nav__a-3">Canadian Flags</a></li> 1818 <li class="shop-nav__li-3" data-key='0818F6FD8C32434AAF788D659A8C01AC'><a href="flags/provincial-flags.asp" class="shop-nav__a-3">British Territory & Canadian Province Flags</a></li> 1819 <li class="shop-nav__li-3" data-key='1C4276E0FF0445CCBEE376E5E83D2186'><a href="holidays/united_nations_day.asp" class="shop-nav__a-3">United Nations Flags</a></li> 1820 <li class="shop-nav__li-3" data-key='4B399B8A320940C08D6CB6346D177A0E'><a href="flags/flags-world-indoor-parade.asp" class="shop-nav__a-3">Indoor World Flags & Kits</a></li> 1821 <li class="shop-nav__li-3" data-key='93A3C64A91E04B55BA40C73EC1349D9C'>
1821<a href="flags/flags-world-miniature.asp" class="shop-nav__a-3">Miniature World Flags</a></li> 1822 </ul></li> 1823 <li class="shop-nav__li-2" data-key='064284EE5D6248E8ACC603660767FCB5'><a href="flags/state-territory-flags.asp" class="shop-nav__a-2">State and Territory</a> 1824 <ul class="shop-nav__ul-3"> 1825 <li class="shop-nav__li-3" data-key='187571E89E7F4E35AAC04D056BA57B8C'><a href="flags/state-territory-flags.asp" class="shop-nav__a-3">A through W</a></li> 1826 <li class="shop-nav__li-3" data-key='13D63BE2C3124CA1A9BE976F8E76C882'><a href="flags/ar-state-flags.asp" class="shop-nav__a-3">Arkansas Flag</a></li> 1827 <li class="shop-nav__li-3" data-key='D646621EF15545C99325EB17CF741A53'><a href="flags/tx-state-flags.asp" class="shop-nav__a-3">Texas Flag</a></li> 1828 <li class="shop-nav__li-3" data-key='F49403D7D71F4E5C86B7BD76DAA0D455'><a href="flags/hi-state-flags.asp" class="shop-nav__a-3">Hawaii Flag</a></li> 1829 <li class="shop-nav__li-3" data-key='3EA0E6F063C54B5B907FE12AB661CC3C'><a href="flags/ca-state-flags.asp" class="shop-nav__a-3">California Flag</a></li> 1830 <li class="shop-nav__li-3" data-key='984F14FEDD4E4666B8E59B06C7D5A68A'><a href="flags/50-state-complete-flag-kits.asp" class="shop-nav__a-3">50 State Complete Flag Sets</a></li> 1831 <li class="shop-nav__li-3" data-key='1E893F5F86EB4914BC581131F7D650C8'><a href="flags/flags-state-territory-indoor-parade.asp" class="shop-nav__a-3">Indoor State & Territory Flags & Kits</a></li> 1832 <li class="shop-nav__li-3" data-key='46FC59C2C86944729458D20C8542B282'><a href="flags/native-american-flags.asp" class="shop-nav__a-3">Native American Flags</a></li> 1833 <li class="shop-nav__li-3" data-key='3685B91DE55F404D9BA7AA170FC0003F'><a href="banners/state-territory-banners.asp" class="shop-nav__a-3">State & Territory Banners</a></li> 1834 <li class="shop-nav__li-3" data-key='F7B8C405EF244B4BB458A3B130A99077'><a href="flags/flags-state-territory-miniature.asp" class="shop-nav__a-3">Miniature State & Territory Banners</a></li> 1835 <li class="shop-nav__li-3" data-key='3DE8BA9A7CD34C9C86BCD839C8125B84'><a href="flags/us-state-flagpole.asp" class="shop-nav__a-3">State & Territory Tangle Free Spinning Flagpole Kits</a></li> 1836 <li class="shop-nav__li-3" data-key='5B7296A00F914D6E9591797BCB572F0B'><a href="flags/city-district-flags.asp" class="shop-nav__a-3">City and District Flags</a></li> 1837 </ul></li> 1838 <li class="shop-nav__li-2" data-key='7E396EC1F2E143F7B5AA7F359A610EBA'><a href="flags/sports-flags.asp" class="shop-nav__a-2">Sports</a> 1839 <ul class="shop-nav__ul-3"> 1840 <li class="shop-nav__li-3" data-key='9D3AB9BA91B64C679658EB464902E154'><a href="flags/college-flags.asp" class="shop-nav__a-3">College & University Flags & Banners</a></li> 1841 <li class="shop-nav__li-3" data-key='6198BD9334E043F5B24343DE29DE8ED2'><a href="flags/golf-flags.asp" class="shop-nav__a-3">Golf Flags</a></li> 1842 <li class="shop-nav__li-3" data-key='E9585E3161064DDD99A2A8E5080E217F'><a href="flags/nascar-flags.asp" class="shop-nav__a-3">Racing Flags & Banners</a></li> 1843 </ul></li> 1844 <li class="shop-nav__li-2" data-key='5A5703FAA77445B5B5CD4BF96697C251'><a href="flags/organizational-flags.asp" class="shop-nav__a-2">Organizations</a> 1845 <ul class="shop-nav__ul-3"> 1846 <li class="shop-nav__li-3" data-key='339D97C04F814A2294FF586E57D887D6'><a href="flags/political.asp" class="shop-nav__a-3">Political Flags & Banners</a></li> 1847 <li class="shop-nav__li-3" data-key='B7F057E0D1B34F81B61134015F9B0BCE'><a href="flags/religious-flags.asp" class="shop-nav__a-3">Religious Flags & Banners</a></li> 1848 <li class="shop-nav__li-3" data-key='9BC7140B63834B2C980BD07BE111186F'><a href="products/iso-flags-banners.asp" class="shop-nav__a-3">BSI & ISO Flags & Banners</a></li> 1849 <li class="shop-nav__li-3" data-key='9198C5C605C94FC1A5C36E7ADD3B6619'><a href="flags/cultural-awareness-flags.asp" class="shop-nav__a-3">Cultural Awareness Flags</a></li> 1850 <li class="shop-nav__li-3" data-key='D81FA39869C149BEAA76471EAF0A83F9'><a href="flags/flags-organizations-outdoor.asp" class="shop-nav__a-3">Outdoor Organizations Flags</a></li> 1851 <li class="shop-nav__li-3" data-key='E295F5863EA44EC3B8E36DE9315A5EF0'><a href="flags/organization-indoor-flags-kits.asp" class="shop-nav__a-3">Indoor Organizations Flags</a></li> 1852 <li class="shop-nav__li-3" data-key='CF3ABB04709646E6A736F851192B7B89'><a href="flags/flags-organizations-miniature.asp" class="shop-nav__a-3">Miniature Organizations Flags</a></li> 1853 </ul></li> 1854 <li class="shop-nav__li-2" data-key='91D0A60E64AA4DF392A1C09CA4CC432C'><a href="flags/streamers.asp" class="shop-nav__a-2">Streamers</a></li> 1855 <li class="shop-nav__li-2" data-key='B27622B1AABC4FCC8B9D7390338C85A7'><a href="banners/home-garden-banners.asp" class="shop-nav__a-2">Decorative</a> 1856 <ul class="shop-nav__ul-3"> 1857 <li class="shop-nav__li-3" data-key='7B9C0687C3CE40FB83C85B7FCDA8A9EC'><a href="banners/winter.asp" class="shop-nav__a-3">Winter Season Flags & Banners</a></li> 1858 <li class="shop-nav__li-3" data-key='046C5851DF2E401BA78CEE4D9C5627CC'><a href="banners/spring.asp" class="shop-nav__a-3">Spring Season Flags & Banners</a></li> 1859 <li class="shop-nav__li-3" data-key='0134673C1AB04BB3B5F9E41D6CA85B1A'><a href="banners/summer.asp" class="shop-nav__a-3">Summer Season Flags & Banners</a></li> 1860 <li class="shop-nav__li-3" data-key='01FE451FE2D24E5B92E4FFF411B5BE0C'><a href="banners/fall-harvest.asp" class="shop-nav__a-3">Fall Season Flags & Banners</a></li> 1861 <li class="shop-nav__li-3" data-key='1FEFC4A931284D5EA1CDB6D358EC1F35'><a href="banners/celebrations-life-events.asp" class="shop-nav__a-3">Celebrations & Event Flags & Banners</a></li> 1862 <li class="shop-nav__li-3" data-key='52FA59D71627491F8BB0E0847893FB06'><a href="flags/holiday-flags-banners.asp" class="shop-nav__a-3">Holiday Flags & Banners</a></li> 1863 <li class="shop-nav__li-3" data-key='C264B59DBDA34A00B3F5D398F90C0235'><a href="banners/door-hangers.asp" class="shop-nav__a-3">Door Hanger Banners</a></li> 1864 <li class="shop-nav__li-3" data-key='D34D39627A344E96AC8EB273FD4AA621'><a href="flags/fun-novelty-flags.asp" class="shop-nav__a-3">Fun & Novelty Flags</a></li> 1865 <li class="shop-nav__li-3" data-key='54C4C19605214F919393F8619DF57466'><a href="banners/patriotic-americana-political.asp" class="shop-nav__a-3">Patriotic Flags & Banners</a></li> 1866 <li class="shop-nav__li-3" data-key='7AEF820BFB2F431C8C2A1BAA467A770A'><a href="flags/military-home-garden.asp" class="shop-nav__a-3">Military & Service Banners</a></li> 1867 <li class="shop-nav__li-3" data-key='638BF301A272466DA8A04F4577CBA536'><a href="banners/religious-cemetery-peace.asp" class="shop-nav__a-3">Religious Flags & Banners</a></li> 1868 <li class="shop-nav__li-3" data-key='5ED18887EC234D22AD61E13AB08A47B4'><a href="products/historical-pirate-flags.asp" class="shop-nav__a-3">Pirate Flags</a></li> 1869 <li class="shop-nav__li-3" data-key='691DB017601C43739F87420D0E6B79F7'><a href="banners/pets-animals.asp" class="shop-nav__a-3">Pet & Animal Flags & Banners</a></li> 1870 <li class="shop-nav__li-3" data-key='C78015E9EAD94E968CF7950DFAAE309C'><a href="flags/flags-windsocks.asp" class="shop-nav__a-3">Windsocks & Wind Spinners</a></li> 1871 <li class="shop-nav__li-3" data-key='BC3735DCFB4C471995082EF3FA21BA0F'><a href="holidays/back_to_school_ideas_for_teachers_and_parents.asp" class="shop-nav__a-3">Back to School Flags & Banners</a></li> 1872 </ul></li> 1873 <li class="shop-nav__li-2" data-key='7BE4B991A23A49CBB20525C870A9C300'><a href="flags/commercial.asp" class="shop-nav__a-2">Commercial</a> 1874 <ul class="shop-nav__ul-3"> 1875 <li class="shop-nav__li-3" data-key='9CE6BA01AEEB452EB089088BBBAD03AB'><a href="flags/safety-flags.asp" class="shop-nav__a-3">Safety Flags & Banners</a></li> 1876 <li class="shop-nav__li-3" data-key='5FF6FE60B8C642D7A95722545D672173'><a href="flags/drape-flags.asp" class="shop-nav__a-3">Drape Flags</a></li> 1877 <li class="shop-nav__li-3" data-key='249BF421295F47C7BCD3F82B6DE060E9'><a href="flags/feather-flag.asp" class="shop-nav__a-3">Feather Flags</a></li> 1878 <li class="shop-nav__li-3" data-key='16CAF67FEB54497B836A23B2EED23CA1'><a href="banners/banners-advertising-message.asp" class="shop-nav__a-3">Message Advertising Banners</a></li> 1879 <li class="shop-nav__li-3" data-key='37BA79E8F01843A29FFBF6E35A7BDF9F'><a href="flags/flags-advertising-message.asp" class="shop-nav__a-3">Message Advertising Flags</a></li> 1880 <li class="shop-nav__li-3" data-key='6B6AF0928E664827B6B74E205106EA4E'><a href="banners/banners-advertising-automotive.asp" class="shop-nav__a-3">Automotive Advertising Banners</a></li> 1881 <li class="shop-nav__li-3" data-key='930CC609A7CE408FA41E0ECD0DEF9B6E'><a href="flags/flags-advertising-automotive.asp" class="shop-nav__a-3">Automotive Advertising Flags</a></li> 1882 <li class="shop-nav__li-3" data-key='F34430874AEF448E8E7FBF800DE2EE1C'><a href="banners/banners-advertising-spanish.asp" class="shop-nav__a-3">Spanish Advertising Banners</a></li> 1883 <li class="shop-nav__li-3" data-key='FCCBDB6C31FC4B65B5E5B126ED3CCB9B'><a href="flags/flags-advertising-spanish.asp" class="shop-nav__a-3">Spanish Advertising Flags</a></li> 1884 <li class="shop-nav__li-3" data-key='4217FA1075C543038048941B1C8C598C'><a href="signs/advertising-signs.asp" class="shop-nav__a-3">Advertising Signs</a></li> 1885 </ul></li> 1886 <li class="shop-nav__li-2" data-key='016BB708F87D4C069707E5EA2FAA9301'><a href="/flags/flags-advertising-color-flags-outdoor.asp" class="shop-nav__a-2">Solid Color and Striped Color</a> 1887 <ul class="shop-nav__ul-3"> 1888 <li class="shop-nav__li-3" data-key='3C44863F85864316BF1D9D9BE494C666'><a href="flags/drape-flags.asp" class="shop-nav__a-3">Drape Flags</a></li> 1889 <li class="shop-nav__li-3" data-key='A7D0042D517140BB835957B7A67C65C8'><a href="flags/feather-flag.asp" class="shop-nav__a-3">Feather Flags</a></li> 1890 <li class="shop-nav__li-3" data-key='9B9CF188C9B94AA88246147DB741F2A5'><a href="pennants/air-quality-flags.asp" class="shop-nav__a-3">Air Quality Flags</a></li> 1891 <li class="shop-nav__li-3" data-key='9720D42D3AFE4E4596B8D870B1302F51'><a href="flags/beach-warning-flags.asp" class="shop-nav__a-3">Beach Warning Flags</a></li>
1892 <li class="shop-nav__li-3" data-key='5907EC6899B24B329711681B37D36EE2'><a href="pennants/colorful_single_pennants.asp" class="shop-nav__a-3">Colorful Single Pennant Flags</a></li> 1893 <li class="shop-nav__li-3" data-key='409341414ADE49389AED474A1254EA28'><a href="flags/red-color-flags.asp" class="shop-nav__a-3">Red Flags</a></li> 1894 <li class="shop-nav__li-3" data-key='1F7DE164971B4545927927CB84AF0465'><a href="flags/orange-color-flags.asp" class="shop-nav__a-3">Orange Flags</a></li> 1895 <li class="shop-nav__li-3" data-key='FB636BE8A8E84587A2DF876CFBA5B422'><a href="flags/yellow-gold-color-flags.asp" class="shop-nav__a-3">Yellow & Gold Flags</a></li> 1896 <li class="shop-nav__li-3" data-key='D82A23CFC0BE4ADEB2897DF1BD5E0738'><a href="flags/green-color-flags.asp" class="shop-nav__a-3">Green Flags</a></li> 1897 <li class="shop-nav__li-3" data-key='F50002EA648149A9B06E2E03AA869AB2'><a href="flags/blue-color-flags.asp" class="shop-nav__a-3">Blue Flags</a></li> 1898 <li class="shop-nav__li-3" data-key='A34FAAF8DD6348F6A955CFC864E319FE'><a href="flags/purple-pink-color-flags.asp" class="shop-nav__a-3">Purple & Pink Flags</a></li> 1899 <li class="shop-nav__li-3" data-key='6C4E32818616403D99B3013756CFAC7B'><a href="flags/black-white-gray-color-flags.asp" class="shop-nav__a-3">Black, White, & Gray Flags</a></li> 1900 <li class="shop-nav__li-3" data-key='7F5FB61089424E83BF0D50ADD5B30291'><a href="flags/brown-cream-color-flags.asp" class="shop-nav__a-3">Brown & Cream Flags</a></li> 1901 </ul></li> 1902 <li class="shop-nav__li-2" data-key='8CCFCE36B57842FAB11C06053D3D97B8'><a href="banners/street-pole-banners.asp" class="shop-nav__a-2">Street Pole</a> 1903 <ul class="shop-nav__ul-3"> 1904 <li class="shop-nav__li-3" data-key='09BC2F10CD1C4929AA8A58462916A23E'><a href="banners/advertising-street-pole-banners.asp" class="shop-nav__a-3">Advertising Street Pole Banners</a></li> 1905 <li class="shop-nav__li-3" data-key='179897B7FDFD44AD9734CA9341F34B12'><a href="banners/american-patriotic-street-pole-banners.asp" class="shop-nav__a-3">American Patriotic Street Pole Banners</a></li> 1906 <li class="shop-nav__li-3" data-key='A9C01E7A156D429FA7831E52BC81936C'><a href="banners/municipal-beautification-street-pole-banners.asp" class="shop-nav__a-3">Municipal Beautification Street Pole Banners</a></li> 1907 <li class="shop-nav__li-3" data-key='7E4AED1C22B04F588033BB350BA30ED4'><a href="banners/holiday-street-pole-banners.asp" class="shop-nav__a-3">Holiday Street Pole Banners</a></li> 1908 <li class="shop-nav__li-3" data-key='AA8A3E975B4E4569838BF0A08B326F49'><a href="banners/winter-street-pole-banners.asp" class="shop-nav__a-3">Winter Season Street Pole Banners</a></li> 1909 <li class="shop-nav__li-3" data-key='DAACF5C66E7447E78C18EE989C763AFA'><a href="banners/spring-street-pole-banners.asp" class="shop-nav__a-3">Spring Season Street Pole Banners</a></li> 1910 <li class="shop-nav__li-3" data-key='C289E3A92BBC450D8AA0979819A6163C'><a href="banners/summer-street-pole-banners.asp" class="shop-nav__a-3">Summer Season Street Pole Banners</a></li> 1911 <li class="shop-nav__li-3" data-key='E68F86A9B2054B3CB45F2E7663AE7EFB'><a href="banners/fall-street-pole-banners.asp" class="shop-nav__a-3">Fall Season Street Pole Banners</a></li> 1912 </ul></li> 1913 <li class="shop-nav__li-2" data-key='83E70A52825641C7B1E0D3A092EA160D'><a href="flags/car-flags.asp" class="shop-nav__a-2">Car Flags</a></li> 1914 </ul></li> 1915 <li class="custom shop-nav__li-1" data-key='8EBF9820CA75403E90ECA34376279AF3'><a href="custom_showroom/custom_flags_banners.asp" class="shop-nav__a-1">Custom</a> 1916 <ul class="shop-nav__ul-2"> 1917 <li class="shop-nav__li-2" data-key='73CB7AAB8A7D40EE83CC3321FC401AF0'><a href="products/custom-printed-single-reverse-flag.asp" class="shop-nav__a-2">Order Custom Flag Online</a></li> 1918 <li class="shop-nav__li-2" data-key='0C60612C75D8473A926B1E1C97C99827'><a href="customer_service/Custom-Order-Request.asp" class="shop-nav__a-2">Get a FREE Quote</a></li> 1919 <li class="shop-nav__li-2" data-key='FDB8D7C0EFF144C0B1C02D80772C6C7C'><a href="custom_showroom/Custom-Flag-Pricing.asp" class="shop-nav__a-2">Flags</a> 1920 <ul class="shop-nav__ul-3"> 1921 <li class="shop-nav__li-3" data-key='F61FBEBCCFE4460EB99E4C0F4D6652FB'><a href="custom_showroom/digital-flags.asp" class="shop-nav__a-3">Digitally Printed Flags</a></li> 1922 <li class="shop-nav__li-3" data-key='9C47A93FF3E440C48AC3D24B30586049'><a href="custom_showroom/embroidered-flags.asp" class="shop-nav__a-3">Embroidered Flags</a></li> 1923 <li class="shop-nav__li-3" data-key='8EBADA08E07342CBA511E7E45B8F73CE'><a href="custom_showroom/applique-flags.asp" class="shop-nav__a-3">Appliqued Flags</a></li> 1924 <li class="shop-nav__li-3" data-key='FBA8C8BACEC145D9B6ABFB66985F1DBE'><a href="custom_showroom/digital-flags.asp" class="shop-nav__a-3">Standard Shaped Flags</a></li> 1925 <li class="shop-nav__li-3" data-key='54DDD50B1BEF416AB960AA9266CE0FA0'><a href="custom_showroom/burgee-flags.asp" class="shop-nav__a-3">Burgee Shaped Flags</a></li> 1926 <li class="shop-nav__li-3" data-key='3062C3EF9F0249DD8549E3F28764A90F'><a href="custom_showroom/pennant-flags.asp" class="shop-nav__a-3">Pennant Shaped Flags</a></li> 1927 <li class="shop-nav__li-3" data-key='75403FFB354F465F91C77D8C0F204EF8'><a href="custom_showroom/team-spirit-flags.asp" class="shop-nav__a-3">Team Spirit Flags</a></li> 1928 <li class="shop-nav__li-3" data-key='070E021C10E14CBFA0BF104953B1E629'><a href="custom_showroom/miniature-flags.asp" class="shop-nav__a-3">Miniature Flags</a></li> 1929 <li class="shop-nav__li-3" data-key='C2D87D08D7CC47B59E0B39AC2E34FB84'><a href="custom_showroom/feather-flag.asp" class="shop-nav__a-3">Feather Flags</a></li> 1930 <li class="shop-nav__li-3" data-key='F0A5EC9D52C2475BB4929858699FB6D7'><a href="custom_showroom/teardrop-flag.asp" class="shop-nav__a-3">Teardrop Flags</a></li> 1931 <li class="shop-nav__li-3" data-key='D4D479AF195B49E2916F8E26FE6613CE'><a href="custom_showroom/blade-flag.asp" class="shop-nav__a-3">Blade Flags</a></li> 1932 <li class="shop-nav__li-3" data-key='D7B92460F2A54198A179361362CF9D68'><a href="custom_showroom/car-flags.asp" class="shop-nav__a-3">Car Flags</a></li> 1933 </ul></li> 1934 <li class="shop-nav__li-2" data-key='2635B40A9F7B483E92243DDD3BDE4779'><a href="custom_showroom/Custom-Banners.asp" class="shop-nav__a-2">Banners</a> 1935 <ul class="shop-nav__ul-3"> 1936 <li class="shop-nav__li-3" data-key='2C07C83767514C96B9E2EAA2EAAACB69'><a href="custom_showroom/simple-applique-banners.asp" class="shop-nav__a-3">Simple Applique Banners</a></li> 1937 <li class="shop-nav__li-3" data-key='2765FAE6A70942B09C0A1C7720F6C08C'><a href="custom_showroom/commercial-grade-vinyl-banners.asp" class="shop-nav__a-3">Custom Commercial Grade Vinyl Banners</a></li> 1938 <li class="shop-nav__li-3" data-key='72A7DAD4542545FABBFDEEFE9E347B50'><a href="custom_showroom/mesh-vinyl-banners.asp" class="shop-nav__a-3">Mesh Banners</a></li> 1939 <li class="shop-nav__li-3" data-key='94A0B11D33744FB4887611EFAD4C600B'><a href="custom_showroom/window-scrim-banners.asp" class="shop-nav__a-3">Self-Adhesive Window Scrim Banners</a></li> 1940 <li class="shop-nav__li-3" data-key='8DD93483B5AA4E338B5B82302A8D9708'><a href="custom_showroom/fast-and-affordable.asp" class="shop-nav__a-3">Fast & Affordable Banners</a></li> 1941 <li class="shop-nav__li-3" data-key='256B5403B3EF4B0FAFA6E6A27B5180C4'><a href="custom_showroom/gonfalons.asp" class="shop-nav__a-3">Gonfalons</a></li> 1942 <li class="shop-nav__li-3" data-key='0EA3E44AE4AB4A82BC77B5E0EDE1D488'><a href="products/retractable-banner-stand.asp" class="shop-nav__a-3">Retractable Banners</a></li> 1943 <li class="shop-nav__li-3" data-key='0C99106935264D30B905AE8896E52092'><a href="custom_showroom/parade-banners.asp" class="shop-nav__a-3">Parade Banners</a></li> 1944 <li class="shop-nav__li-3" data-key='387E0625957B40CCBC875B02532DC71D'><a href="products/pillowcase-banner-stand.asp" class="shop-nav__a-3">Pillowcase Banners</a></li> 1945 <li class="shop-nav__li-3" data-key='01BABD590B884D0B8BC582AEB16E9D13'><a href="products/pillowcase-banner-wall.asp" class="shop-nav__a-3">Pillowcase Banner Walls</a></li> 1946 <li class="shop-nav__li-3" data-key='F9CEB7C5C316432492CE0F8EB87287B8'><a href="products/pop-up-banner-wall.asp" class="shop-nav__a-3">Pop Up Banner Walls</a></li> 1947 <li class="shop-nav__li-3" data-key='F3F5BF9470DC42D5967673166DA6627D'><a href="products/aframe-display-kit.asp" class="shop-nav__a-3">A-Frame Banners</a></li> 1948 <li class="shop-nav__li-3" data-key='C761D713555A4E8C95B82C8E8C4614E1'><a href="custom_showroom/barricade-banners.asp" class="shop-nav__a-3">Barricade Banners</a></li> 1949 </ul></li> 1950 <li class="shop-nav__li-2" data-key='43FE9D79E7C6495A98735C8CF04A411D'><a href="custom_showroom/guidons.asp" class="shop-nav__a-2">Guidons</a> 1951 <ul class="shop-nav__ul-3"> 1952 <li class="shop-nav__li-3" data-key='24AD86FBE3444E4D8590BFDB738A847D'><a href="custom_showroom/guidons.asp#appliq" class="shop-nav__a-3">Appliqued Regulation Guidons</a></li> 1953 <li class="shop-nav__li-3" data-key='5E52C0B8F1DA4DC6A19308BFCE505FAB'><a href="custom_showroom/guidons.asp#print" class="shop-nav__a-3">Printed Guidons</a></li> 1954 <li class="shop-nav__li-3" data-key='F87E4C8DD5C34F1FAC0610E5F8860457'><a href="custom_showroom/guidons.asp#streamer" class="shop-nav__a-3">Embroidered Service Streamers</a></li> 1955 </ul></li> 1956 <li class="shop-nav__li-2" data-key='4F2263B8212E4F1593296B8E1471E139'><a href="custom_showroom/custom-pennants.asp" class="shop-nav__a-2">Pennants</a> 1957 <ul class="shop-nav__ul-3"> 1958 <li class="shop-nav__li-3" data-key='45C34850E279445DA8D5870DF93B8726'><a href="https://www.flagandbanner.com/custom_showroom/custom-pennants.asp#digitalshort" class="shop-nav__a-3">Digital Print String Pennants</a></li> 1959 <li class="shop-nav__li-3" data-key='4FD0F96FA4B74492BC30DCAF1D9CA274'><a href="custom_showroom/custom-pennants.asp#prempenn" class="shop-nav__a-3">Premium Felt Single Pennants</a></li> 1960 <li class="shop-nav__li-3" data-key='2C3B46D3964246B1BDD345CB9339B998'>
1960<a href="custom_showroom/custom-pennants.asp#pennflag" class="shop-nav__a-3">Single Pennant Flags</a></li> 1961 </ul></li> 1962 <li class="shop-nav__li-2" data-key='4268CF35E7664BC78A1FE7C34A0C5AC0'><a href="custom_showroom/Custom-Street-Poles.asp" class="shop-nav__a-2">Street Pole Banners</a> 1963 <ul class="shop-nav__ul-3"> 1964 <li class="shop-nav__li-3" data-key='FE926C02513849D0BA66D5222CD1B910'><a href="custom_showroom/Custom-Street-Poles.asp#custstreet" class="shop-nav__a-3">Custom Street Pole Banners</a></li> 1965 <li class="shop-nav__li-3" data-key='BC159139231643758456DC115CE9D6D9'><a href="custom_showroom/Custom-Street-Poles.asp#sunstreet" class="shop-nav__a-3">Sunbrella Street Pole Banners</a></li> 1966 <li class="shop-nav__li-3" data-key='090870D32F1F48B28702C8318B45B4FB'><a href="custom_showroom/Custom-Street-Poles.asp#copoly" class="shop-nav__a-3">Combined Poly Street Pole Banners</a></li> 1967 <li class="shop-nav__li-3" data-key='B1552FE0648B4B40A66E2C83A0297CBB'><a href="custom_showroom/Custom-Street-Poles.asp#stockstreet" class="shop-nav__a-3">Stock Street Pole Banners</a></li> 1968 </ul></li> 1969 <li class="shop-nav__li-2" data-key='844E3C3912A0413FB550CC2EBF484605'><a href="custom_showroom/trade-show-display.asp" class="shop-nav__a-2">Trade Show Displays</a> 1970 <ul class="shop-nav__ul-3"> 1971 <li class="shop-nav__li-3" data-key='749DED9C9C544E5D8D6AD485A0593FF4'><a href="products/pop-up-banner-wall.asp" class="shop-nav__a-3">Pop Up Banner Walls</a></li> 1972 <li class="shop-nav__li-3" data-key='8CE29D84E8BB4D63ABDE518B6C90F5F4'><a href="products/pillowcase-banner-wall.asp" class="shop-nav__a-3">Pillowcase Banner Walls</a></li> 1973 <li class="shop-nav__li-3" data-key='37EB47EC7CD748DD88452FDAD033C7CF'><a href="products/retractable-banner-stand.asp" class="shop-nav__a-3">Retractable Banner Stands</a></li> 1974 <li class="shop-nav__li-3" data-key='9D32A043E2FC40A0907E9DA26168363E'><a href="products/pillowcase-banner-stand.asp" class="shop-nav__a-3">Pillowcase Banner Stands</a></li> 1975 <li class="shop-nav__li-3" data-key='E65985CB737F41DEA7C6FB57347EF17D'><a href="products/x-display-banner-stands.asp" class="shop-nav__a-3">Light Weight Banner Stands & Table Top Stands</a></li> 1976 <li class="shop-nav__li-3" data-key='24E0EC4345494BD6A1829BE467436268'><a href="products/aframe-display-kit.asp" class="shop-nav__a-3">A-Frame Banners</a></li> 1977 </ul></li> 1978 <li class="shop-nav__li-2" data-key='7AE149EFB7234CDBBDE85DB77E4F12F5'><a href="custom_showroom/custom-event-tents.asp" class="shop-nav__a-2">Event Tents</a></li> 1979 <li class="shop-nav__li-2" data-key='ABC50A3BEC734DFEAE08A5E6A2043068'><a href="custom_showroom/custom-logo-mats.asp" class="shop-nav__a-2">Logo Mats</a></li> 1980 <li class="shop-nav__li-2" data-key='49EE64C31E6543919DE57E558315E029'><a href="custom_showroom/Custom-Table-Throws.asp" class="shop-nav__a-2">Table Throws</a> 1981 <ul class="shop-nav__ul-3"> 1982 <li class="shop-nav__li-3" data-key='835930C5E8BF40F99DEAA48419009B09'><a href="custom_showroom/Custom-Table-Throws.asp#throw" class="shop-nav__a-3">Table Throws</a></li> 1983 <li class="shop-nav__li-3" data-key='2F474BED2CC14AB88BF97024FFD082AF'><a href="custom_showroom/Custom-Table-Throws.asp#stretch" class="shop-nav__a-3">Stretch Table Covers</a></li> 1984 <li class="shop-nav__li-3" data-key='1BBEC46DACEA4F3598DF44F92539DB41'><a href="custom_showroom/Custom-Table-Throws.asp#runner" class="shop-nav__a-3">Table Runners</a></li> 1985 <li class="shop-nav__li-3" data-key='90139892B9614EF0A3FA2AB322CC1F81'><a href="custom_showroom/Custom-Table-Throws.asp#solid" class="shop-nav__a-3">Solid Color Table Throws</a></li> 1986 </ul></li> 1987 <li class="shop-nav__li-2" data-key='B8A62814E77E4415A4572E7F3AAD4D18'><a href="custom_showroom/custom-ordering-information.asp" class="shop-nav__a-2">Custom Info & Gallery</a> 1988 <ul class="shop-nav__ul-3"> 1989 <li class="shop-nav__li-3" data-key='E10BC40FEFDE4868B483B0300D69F7AF'><a href="customer_service/graphic-art-requirements.asp" class="shop-nav__a-3">Graphic Art Requirements</a></li> 1990 <li class="shop-nav__li-3" data-key='DCFE7A8756AE4E17AC8E35C561C25E65'><a href="customer_service/installation-services.asp" class="shop-nav__a-3">Installation Services</a></li> 1991 <li class="shop-nav__li-3" data-key='9BC14731FA05474EA8D4E8996E4082BE'><a href="customer_service/nylon-fabric-color-chart.asp" class="shop-nav__a-3">
1991Nylon Fabric Color Chart</a></li> 1992 <li class="shop-nav__li-3" data-key='702107464DBC492EA1709DAFEDB4CD93'><a href="customer_service/pantone-color-chart.asp" class="shop-nav__a-3">Pantone Color Chart</a></li> 1993 <li class="shop-nav__li-3" data-key='52816C415ACA4F07B404E3C270CD727F'><a href="custom_showroom/custom-artwork-template.asp" class="shop-nav__a-3">Custom Artwork Templates</a></li> 1994 </ul></li> 1995 </ul></li> 1996 <li class="poles shop-nav__li-1" data-key='EAEED4CD090B4EBEA09EA968E9153701'><a href="flag_banner_poles/flag_poles.asp" class="shop-nav__a-1">Poles</a> 1997 <ul class="shop-nav__ul-2"> 1998 <li class="shop-nav__li-2" data-key='10ED41C3367A495782622E5CDF3ABF27'><a href="flag_banner_poles/residential-flag-poles.asp" class="shop-nav__a-2">Residential</a> 1999 <ul class="shop-nav__ul-3"> 2000 <li class="shop-nav__li-3" data-key='C8D01BE09C7048658BFACB5C64D6EEE8'><a href="flag_banner_poles/residential-in-ground.asp" class="shop-nav__a-3">Residential In-Ground Flagpoles</a></li> 2001 <li class="shop-nav__li-3" data-key='B5A721A17E74436D9C05B515C9B14CF9'><a href="flag_banner_poles/residential-house-mount.asp" class="shop-nav__a-3">Residential House Mount Flagpoles</a></li> 2002 <li class="shop-nav__li-3" data-key='4431D594BB7748C89903B27B10C97554'><a href="flag_banner_poles/vehicle-boat-flagpoles.asp" class="shop-nav__a-3">Vehicle & Boat Flagpoles</a></li> 2003 <li class="shop-nav__li-3" data-key='5695772A9D2243FB9E0FB8DF78C1C116'><a href="flag_banner_poles/tailgating-portable.asp" class="shop-nav__a-3">RV, Tailgating, & Portable Flagpoles & Accessories</a></li> 2004 </ul></li> 2005 <li class="shop-nav__li-2" data-key='2BDFB7525FCF4CCBB6DB953222427FEC'><a href="flag_banner_poles/commercial-flag-poles.asp" class="shop-nav__a-2">Commercial</a> 2006 <ul class="shop-nav__ul-3"> 2007 <li class="shop-nav__li-3" data-key='2114666314924A44B72AC3221438E817'><a href="flag_banner_poles/commercial-in-ground.asp" class="shop-nav__a-3">Commercial In-Ground Flagpoles</a></li> 2008 <li class="shop-nav__li-3" data-key='179CE33016444C9288A2080767AB3B53'><a href="flag_banner_poles/wall-mount-flagpoles.asp" class="shop-nav__a-3">Commercial Wall Mount Flagpoles</a></li> 2009 <li class="shop-nav__li-3" data-key='A4890CF74A7E41BC964B62E5CCAB1060'><a href="flag_banner_poles/tilt-down-flagpoles.asp" class="shop-nav__a-3">Tilt Down Flagpoles</a></li> 2010 <li class="shop-nav__li-3" data-key='F35E507007E647CA929567ED2BBE0189'><a href="flag_banner_poles/nautical-flag-poles.asp" class="shop-nav__a-3">Nautical Flagpoles</a></li> 2011 <li class="shop-nav__li-3" data-key='F2371308E9C84A25845C81924985CB57'><a href="flag_banner_poles/advertising_poles.asp" class="shop-nav__a-3">Advertising Flagpoles</a></li> 2012 </ul></li> 2013 <li class="shop-nav__li-2" data-key='3B617C99E3EB448BB900CAAE82BBC611'><a href="flag_banner_poles/ceremonial-flag-poles.asp" class="shop-nav__a-2">Ceremonial (Indoor and Parade)</a> 2014 <ul class="shop-nav__ul-3"> 2015 <li class="shop-nav__li-3" data-key='461D66A1EB3140ECA282AD9A974D60D3'><a href="flag_banner_poles/indoor-flagpoles.asp" class="shop-nav__a-3">Indoor Flagpoles & Kits (No Flags)</a></li> 2016 <li class="shop-nav__li-3" data-key='4F2C05A6E4CA4C019B8113C09D282856'><a href="flags/indoor-american-flag-kits.asp" class="shop-nav__a-3">Indoor American Flag Kits</a></li> 2017 <li class="shop-nav__li-3" data-key='20C334905D204524A8443F8F4422FFD3'><a href="flags/flags-state-territory-indoor-parade.asp" class="shop-nav__a-3">Indoor State & Territory Flags & Kits</a></li> 2018 <li class="shop-nav__li-3" data-key='A13EDA7684CB49FB89465C7C1E6D8246'><a href="flags/flags-world-indoor-parade.asp" class="shop-nav__a-3">World Flags & Kits</a></li> 2019 <li class="shop-nav__li-3" data-key='9D4124F0C718414BA0F15F24085DB919'><a href="flags/flags-city-district-indoor-parade.asp" class="shop-nav__a-3">City & District Flags & Kits</a></li> 2020 <li class="shop-nav__li-3" data-key='B6E31E2FB61B488B8A70529FAE4D4677'><a href="flag_banner_poles/gonfalon-ceremonial-banner-pole-kits.asp" class="shop-nav__a-3">Gonfalon Ceremonial Banner Pole Kits</a></li> 2021 <li class="shop-nav__li-3" data-key='C1FBA81A6705497E973C89AC82844036'><a href="flags/flags-military-service-indoor-parade.asp" class="shop-nav__a-3">Military & Service Flags & Kits</a></li> 2022 <li class="shop-nav__li-3" data-key='35FD8F41D8424A21B8A81C241E2BCB51'><a href="flags/general-admiral-star-flags-kits.asp" class="shop-nav__a-3">General & Admiral Star Flags & Kits</a></li> 2023 <li class="shop-nav__li-3" data-key='15A9D53DE9EB496DB4EB2B4DC20E5170'><a href="flags/flags-cultural-awareness-indoor-parade.asp" class="shop-nav__a-3">Cultural Awareness Flags & Kits</a></li> 2024 <li class="shop-nav__li-3" data-key='2F6669440854497BA45CB63FF35CA723'><a href="flags/flags-religious-indoor-parade.asp" class="shop-nav__a-3">Religious Flags & Kits</a></li> 2025 <li class="shop-nav__li-3" data-key='8BB59EA719D246F6919FC62452942800'><a href="flags/organization-indoor-flags-kits.asp" class="shop-nav__a-3">Organizations Flags & Kits</a></li> 2026 <li class="shop-nav__li-3" data-key='DD56C28D16B348DDA732B2A531E58DB7'><a href="flags/flags-provinces-indoor-parade.asp" class="shop-nav__a-3">British Territory & Canadian Province Flags & Kits</a></li> 2027 <li class="shop-nav__li-3" data-key='4077FEDD752E47DE8D3A07605337AA26'><a href="hardware/crossbars-lead-poles.asp" class="shop-nav__a-3">Crossbars & Lead Poles</a></li> 2028 <li class="shop-nav__li-3" data-key='115203277A924B48851616ED95E492E2'><a href="flag_banner_poles/miniature-flag-sticks.asp" class="shop-nav__a-3">Miniature Poles</a></li> 2029 </ul></li> 2030 <li class="shop-nav__li-2" data-key='066B1EF9E47E4CCA9577D58B75854464'><a href="flag_banner_poles/garden-flag-stands.asp" class="shop-nav__a-2">Garden Flag Stands</a></li> 2031 <li class="shop-nav__li-2" data-key='8F93CF0B2C8F4DAE8653CDD188E366CF'><a href="flag_banner_poles/street-pole-systems.asp" class="shop-nav__a-2">Street Pole</a></li> 2032 <li class="shop-nav__li-2" data-key='763E1C2CE6EE4EDBB22C305642E00841'><a href="hardware/grave-markers.asp" class="shop-nav__a-2">Grave Markers</a></li> 2033 <li class="shop-nav__li-2" data-key='B04D3340FF3649F69AFE921BF2F245C7'><a href="flag_banner_poles/telescoping-flagpoles.asp" class="shop-nav__a-2">Telescoping</a></li> 2034 <li class="shop-nav__li-2" data-key='49A0986C147B4A31B75A6B7840D0F62A'><a href="flag_banner_poles/banner-stands-poles.asp" class="shop-nav__a-2">Trade Show Acessories</a></li> 2035 </ul></li> 2036 <li class="bunting shop-nav__li-1" data-key='8D302EBB4154471B8B90A0D19643585F'><a href="bunting/bunting.asp" class="shop-nav__a-1">Bunting</a> 2037 <ul class="shop-nav__ul-2"> 2038 <li class="shop-nav__li-2" data-key='B318AF7E82D84AA2960CE5FA255882C4'><a href="bunting/pleated_flag_bunting_fans.asp" class="shop-nav__a-2">Patriotic</a> 2039 <ul class="shop-nav__ul-3"> 2040 <li class="shop-nav__li-3" data-key='BB90CB1CE8CF47C88FA140316538FB2C'><a href="patriotic_gifts/decorating-kits.asp" class="shop-nav__a-3">Decorating Kits</a></li> 2041 <li class="shop-nav__li-3" data-key='939623AE082042C58812FA3D5079A1CE'><a href="bunting/patriotic-fans-and-flats.asp" class="shop-nav__a-3">Patriotic Fans & Flats</a></li> 2042 <li class="shop-nav__li-3" data-key='589696B493C74EA88C18F2C92A52CD97'><a href="pennants/american_pennants.asp" class="shop-nav__a-3">American String Pennants</a></li> 2043 <li class="shop-nav__li-3" data-key='6D95E514CFA9419396D3000746D1F837'><a href="bunting/patriotic-fabrics.asp" class="shop-nav__a-3">Patriotic Fabrics</a></li> 2044 </ul></li> 2045 <li class="shop-nav__li-2" data-key='A7D4B40FBDEB4F68AFDDD02424408D7C'><a href="bunting/world.asp" class="shop-nav__a-2">World</a></li> 2046 <li class="shop-nav__li-2" data-key='DE318874C3E94664827D63845A36B094'><a href="bunting/mourning.asp" class="shop-nav__a-2">Mourning</a></li> 2047 <li class="shop-nav__li-2" data-key='C2C0437853CB47C5AFF2550D708E86E9'><a href="bunting/sports.asp" class="shop-nav__a-2">Sports</a></li> 2048 <li class="shop-nav__li-2" data-key='BD271FC001A44EBF8AFBDAD2018ACB55'><a href="bunting/solid-color-nylon-fabric.asp" class="shop-nav__a-2">Solid Color</a> 2049 <ul class="shop-nav__ul-3"> 2050 <li class="shop-nav__li-3" data-key='F8FDB3549E4843F38C5BC00DA57D5A28'><a href="bunting/solid-color-fabrics-red.asp" class="shop-nav__a-3">Solid Color Fabrics with Reds</a></li> 2051 <li class="shop-nav__li-3" data-key='9DD118A165294D74AC4A538F1AF5CC0E'><a href="bunting/solid-color-fabrics-oranges.asp" class="shop-nav__a-3">Solid Color Fabrics with Oranges</a></li> 2052 <li class="shop-nav__li-3" data-key='41FC30C8EB534D8687924088E988FBE4'><a href="bunting/solid-color-fabrics-yellow-gold.asp" class="shop-nav__a-3">Solid Color Fabrics with Yellows & Golds</a></li> 2053 <li class="shop-nav__li-3" data-key='46DCF45B61A740B3ACAFFDABA39370C9'><a href="bunting/solid-color-fabrics-greens.asp" class="shop-nav__a-3">Solid Color Fabrics with Greens</a></li> 2054 <li class="shop-nav__li-3" data-key='2128130163174A84848615E6CA968AC5'><a href="bunting/solid-color-fabrics-blue.asp" class="shop-nav__a-3">Solid Color Fabrics with Blues</a></li> 2055 <li class="shop-nav__li-3" data-key='9F5B84819AFB4468905CE09B9DDB1074'><a href="bunting/solid-color-fabrics-purple-pink.asp" class="shop-nav__a-3">Solid Color Fabrics with Pinks & Purples</a></li> 2056 <li class="shop-nav__li-3" data-key='CC9AF23C2E3548619D8EC34A38DE28BD'><a href="bunting/solid-color-fabrics-black-white-gray.asp" class="shop-nav__a-3">Solid Color Fabrics with Blacks, Whites & Grays</a></li> 2057 <li class="shop-nav__li-3" data-key='6941467AD14243EE8B94AF5849D1345C'><a href="bunting/solid-color-fabrics-brown-cream.asp" class="shop-nav__a-3">Solid Color Fabrics with Browns & Creams</a></li> 2058 </ul></li> 2059 </ul></li> 2060 <li class="pennants shop-nav__li-1" data-key='7786E1FBE6544E139956434B4C41960D'><a href="pennants/pennants.asp" class="shop-nav__a-1">String Pennants</a> 2061 <ul class="shop-nav__ul-2"> 2062 <li class="shop-nav__li-2" data-key='96F9F1F5877A4E1D99006D745BBBB0E3'><a href="pennants/colorful_string_pennants.asp" class="shop-nav__a-2">Colorful</a> 2063 <ul class="shop-nav__ul-3"> 2064 <li class="shop-nav__li-3" data-key='B2E99D4A3D34425C94446D7B7038C6B8'><a href="pennants/solid-color-string-pennants.asp" class="shop-nav__a-3">Solid Color String Pennants</a></li> 2065 <li class="shop-nav__li-3" data-key='DF04D47741F443AC911E207EFDB7ACA2'><a href="pennants/rainbow-string-pennants.asp" class="shop-nav__a-3">String Pennants in Rainbow Assortments</a></li> 2066 <li class="shop-nav__li-3" data-key='F3823456E14A4E5DB7C20C18E5CED8FD'><a href="pennants/plasticloth.asp" class="shop-nav__a-3">Heavy Duty Plasticloth String Pennants</a></li> 2067 <li class="shop-nav__li-3" data-key='BF3E90854F3F4B848465960F4AD8FDB7'><a href="pennants/metallic-string-pennants.asp" class="shop-nav__a-3">Metallic String Pennants</a></li> 2068 <li class="shop-nav__li-3" data-key='321D1DD8167F40288DBA19421ED6F0F7'><a href="pennants/red-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Reds</a></li> 2069 <li class="shop-nav__li-3" data-key='735187639D0248D486CA6A36C35903DB'><a href="pennants/orange-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Oranges</a></li> 2070 <li class="shop-nav__li-3" data-key='3FF7054D5FF545B3A2F9C90B91A34C92'><a href="pennants/yellow-gold-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Yellows & Golds</a></li> 2071 <li class="shop-nav__li-3" data-key='3C439B1AD03546418F13A40B95F212C0'><a href="pennants/green-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Greens</a></li> 2072 <li class="shop-nav__li-3" data-key='EBC0251F798B4C33A71DB72E3D36E306'><a href="pennants/blue-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Blues & Turquoise</a></li> 2073 <li class="shop-nav__li-3" data-key='F14962EDF8034299A2FE5AA12DCA9F33'><a href="pennants/purple-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Purples</a></li> 2074 <li class="shop-nav__li-3" data-key='CDB3184DFD1142D29737F714977BB442'><a href="pennants/white-black-string-pennants.asp" class="shop-nav__a-3">String Pennant Flags with Blacks & Whites</a></li> 2075 <li class="shop-nav__li-3" data-key='BDC8B9E2D90642839970E2384156BCD2'><a href="pennants/gray-silver-string-pennants.asp" class="shop-nav__a-3">
2075String Pennant Flags with Grays & Silvers</a></li> 2076 </ul></li> 2077 <li class="shop-nav__li-2" data-key='B18F1A3B70D24F2895524218B1B0B1E2'><a href="pennants/american_pennants.asp" class="shop-nav__a-2">American</a></li> 2078 <li class="shop-nav__li-2" data-key='7A9ADC75C35846A6B01165620E53ADFC'><a href="pennants/world_pennants.asp" class="shop-nav__a-2">World</a></li> 2079 <li class="shop-nav__li-2" data-key='4C593E024611435EBE5921095DAA2F3D'><a href="pennants/racing.asp" class="shop-nav__a-2">Racing</a></li> 2080 <li class="shop-nav__li-2" data-key='CA2FC3FF269B425986DE25833F6064CA'><a href="pennants/commercial.asp" class="shop-nav__a-2">Commercial</a> 2081 <ul class="shop-nav__ul-3"> 2082 <li class="shop-nav__li-3" data-key='E14B3BA8E9C74382B62E93F38FF059A5'><a href="pennants/advertising-pennants.asp" class="shop-nav__a-3">Advertising Pennants</a></li> 2083 <li class="shop-nav__li-3" data-key='7BB1DCECEDD4402BB96DD26340907C8C'><a href="pennants/safety_pennants.asp" class="shop-nav__a-3">Safety Pennants</a></li> 2084 </ul></li> 2085 </ul></li> 2086 <li class="hardware shop-nav__li-1" data-key='D68C02F8E5DB463F8B82B742CB1571C3'><a href="hardware/hardware.asp" class="shop-nav__a-1">Parts and Accessories</a> 2087 <ul class="shop-nav__ul-2"> 2088 <li class="shop-nav__li-2" data-key='6421A69E27E44CBABEE3EB46CCF2B897'><a href="/hardware/outdoor.asp" class="shop-nav__a-2">Outdoor</a> 2089 <ul class="shop-nav__ul-3"> 2090 <li class="shop-nav__li-3" data-key='6DD95BDC404C43BAA95A0B9C184B1841'><a href="hardware/rope-and-snap-hooks.asp" class="shop-nav__a-3">Rope & Snap Hooks</a></li> 2091 <li class="shop-nav__li-3" data-key='361260BA55D64C45843941A52D38EEF7'><a href="hardware/flag-pole-pulleys.asp" class="shop-nav__a-3">Flagpole Pulleys & Cleats</a></li> 2092 <li class="shop-nav__li-3" data-key='330A1D6C1A994D64849C9F99E7674934'><a href="hardware/hardware-brackets-holders-outdoor.asp" class="shop-nav__a-3">Outdoor Brackets & Holders</a></li> 2093 <li class="shop-nav__li-3" data-key='91DBE410609145F0A6BBAD7320F7B6CA'><a href="hardware/hardware-lighting-outdoor.asp" class="shop-nav__a-3">Outdoor Flag Lighting</a></li> 2094 <li class="shop-nav__li-3" data-key='ABDF3FD0B8C34025B95261C9AA225D93'><a href="hardware/hardware-bases-outdoor.asp" class="shop-nav__a-3">Outdoor Flagpole Bases</a></li> 2095 <li class="shop-nav__li-3" data-key='B355AC2A53FD4E48B2A00C25D622330D'><a href="hardware/hardware-hanging-hardware-outdoor.asp" class="shop-nav__a-3">Outdoor Hanging Hardware</a></li> 2096 <li class="shop-nav__li-3" data-key='66C1F6F2794C485CBB0048E29B8FFF21'><a href="hardware/hardware-ornaments-finials-outdoor.asp" class="shop-nav__a-3">Outdoor Ornaments & Finials</a></li> 2097 <li class="shop-nav__li-3" data-key='40D882F28755469083A32E9A21D9260F'><a href="hardware/nautical-flagpole-sockets.asp" class="shop-nav__a-3">Nautical Sockets & Holders</a></li> 2098 </ul></li> 2099 <li class="shop-nav__li-2" data-key='6FD5AB7699DF45BCAF53FAF9390328A2'><a href="/hardware/indoor.asp" class="shop-nav__a-2">Indoor & Parade</a> 2100 <ul class="shop-nav__ul-3"> 2101 <li class="shop-nav__li-3" data-key='4FE70AB882464F24BC924204EE5BEAAF'><a href="hardware/hardware-brackets-holders-indoor-parade.asp" class="shop-nav__a-3">Indoor & Parade Brackets & Holders</a></li> 2102 <li class="shop-nav__li-3" data-key='81A2BA932F2647268B4813A5373470D3'><a href="hardware/hardware-bases-indoor-parade.asp" class="shop-nav__a-3">Indoor & Parade Flagpole Bases</a></li> 2103 <li class="shop-nav__li-3" data-key='05C47309B0A0476EB1C62E55AD956C07'><a href="hardware/hardware-hanging-hardware-indoor-parade.asp" class="shop-nav__a-3">Indoor & Parade Hanging Hardware</a></li> 2104 <li class="shop-nav__li-3" data-key='8CB443CF60164EC0B9D7012816CF4DCA'><a href="hardware/hardware-ornaments-finials-indoor-parade.asp" class="shop-nav__a-3">Indoor Ornaments & Finials</a></li> 2105 <li class="shop-nav__li-3" data-key='DECD6EDC7442476C8E78CAC955852B87'><a href="hardware/cord-tassels.asp" class="shop-nav__a-3">Cords and Tassels & Fringe</a></li> 2106 <li class="shop-nav__li-3" data-key='52CBB5C7C071498E96962D72F348078B'><a href="hardware/ferrules-joints.asp" class="shop-nav__a-3">Ferrules & Joints</a></li> 2107 <li class="shop-nav__li-3" data-key='EF4DBE688D3F45EEB4E6BCC60F7D81FA'><a href="hardware/hardware-lighting-indoor-parade.asp" class="shop-nav__a-3">Indoor Flag Lighting</a></li> 2108 <li class="shop-nav__li-3" data-key='215DB31B919D4639BC5AE27993BF5C32'><a href="hardware/hardware-brackets-holders-miniature.asp" class="shop-nav__a-3">Miniature Brackets & Holders</a></li> 2109 <li class="shop-nav__li-3" data-key='113496451C43400F88B1CF0F66DE3E3E'><a href="hardware/hardware-bases-miniature.asp" class="shop-nav__a-3">Miniature Flag Bases</a></li> 2110 <li class="shop-nav__li-3" data-key='A9F334C1E2CF45478EE2AED161DD804E'><a href="hardware/hardware-ornaments-finials-miniature.asp" class="shop-nav__a-3">Miniature Ornaments & Finials</a></li> 2111 <li class="shop-nav__li-3" data-key='F71B1EFE908B4CEC98937247F5D35206'><a href="hardware/crossbars-lead-poles.asp" class="shop-nav__a-3">Crossbars & Lead Poles</a></li> 2112 <li class="shop-nav__li-3" data-key='F765E54133D84FFA8BEF269BE22B002D'><a href="hardware/parade-accessories.asp" class="shop-nav__a-3">Parade Accessories</a></li> 2113 </ul></li> 2114 <li class="shop-nav__li-2" data-key='C66270EDF18C4DE9BA2F82B6437AEEA5'><a href="hardware/covers-cases.asp" class="shop-nav__a-2">Display Cases</a></li> 2115 <li class="shop-nav__li-2" data-key='7D5C7B6CD73D48449582A35F737250E7'>
2115<a href="hardware/streetpole-hardware.asp" class="shop-nav__a-2">Street Pole</a></li> 2116 <li class="shop-nav__li-2" data-key='8189A89AF95C4AEFA0E69A321D751D7C'><a href="hardware/trade-show-accessories.asp" class="shop-nav__a-2">Trade Show</a></li> 2117 </ul></li> 2118 <li class="shop-nav__li-1" data-key='0D5DA8932FB6476EB10E15050F8EBA3F'><a href="custom_showroom/trade-show-display.asp" class="shop-nav__a-1">Trade Show</a></li> 2119 <li class="shop-nav__li-1" data-key='A38C23FF076C469C9B55EF40585709DF'><a href="patriotic_gifts/shop.asp" class="shop-nav__a-1">Gift Shop</a> 2120 <ul class="shop-nav__ul-2"> 2121 <li class="shop-nav__li-2" data-key='7488EC2879E14129AF6A33266BA57CB2'><a href="patriotic_gifts/apparel-accessories.asp" class="shop-nav__a-2">Apparel and Accessories</a> 2122 <ul class="shop-nav__ul-3"> 2123 <li class="shop-nav__li-3" data-key='6671FE47199E43E2AA3ED8E035F52B5E'><a href="patriotic_gifts/boutique_apparel.asp" class="shop-nav__a-3">Patriotic Clothing</a></li> 2124 <li class="shop-nav__li-3" data-key='B28ACE453CAE4477A0158A2B4EBF1922'><a href="patriotic_gifts/clothing-accessories.asp" class="shop-nav__a-3">Patriotic American Flag Accessories</a></li> 2125 <li class="shop-nav__li-3" data-key='2556326D12FA40CB856B495BBB413019'><a href="patriotic_gifts/boutique_jewelry.asp" class="shop-nav__a-3">Patriotic Jewelry</a></li> 2126 </ul></li> 2127 <li class="shop-nav__li-2" data-key='65246F9D1E0047F4A46AA7AACD1C00C6'><a href="patriotic_gifts/boutique_home_garden.asp" class="shop-nav__a-2">Home & Garden</a> 2128 <ul class="shop-nav__ul-3"> 2129 <li class="shop-nav__li-3" data-key='79D3F4DCD79B4337B295AF7F92D64083'><a href="patriotic_gifts/photo_albums_frames.asp" class="shop-nav__a-3">Photo Albums & Frames</a></li> 2130 <li class="shop-nav__li-3" data-key='7EAA5499B49A470DBF5ED8768DAF6E2F'><a href="signs/signs.asp" class="shop-nav__a-3">Signs & Decals</a></li> 2131 <li class="shop-nav__li-3" data-key='896ABBAC08FE4C439CFEE4A661BCE1E3'><a href="patriotic_crafts/boutique_crafts.asp" class="shop-nav__a-3">Patriotic Craft Material</a></li> 2132 <li class="shop-nav__li-3" data-key='AE092D1F7C6B47AF8244C5F750AFFBBC'><a href="patriotic_gifts/boutique_dining_kitchen.asp" class="shop-nav__a-3">Dining & Kitchen</a></li> 2133 <li class="shop-nav__li-3" data-key='C7541350A56D445BBE88BA91C54EC94D'><a href="patriotic_gifts/artificial_garden_rocks.asp" class="shop-nav__a-3">Artificial Rocks</a></li> 2134 <li class="shop-nav__li-3" data-key='8D84C19ADBF54B3CB1B7A9BD0E85E0AD'><a href="patriotic_gifts/bird_feeders_houses.asp" class="shop-nav__a-3">Bird Feeders & Houses</a></li> 2135 <li class="shop-nav__li-3" data-key='328B4028478244A3870C0DC659A7E3C9'><a href="patriotic_gifts/blankets-pillows.asp" class="shop-nav__a-3">Blankets & Pillows</a></li> 2136 <li class="shop-nav__li-3" data-key='0BBFDCD21F7A4C20BD0847AAAC9D4D5C'><a href="patriotic_gifts/candles_holders.asp" class="shop-nav__a-3">Candles & Candle Holders</a></li> 2137 <li class="shop-nav__li-3" data-key='C933BDA2C9EE4E2C8D2052A201663520'><a href="patriotic_gifts/car_accessories.asp" class="shop-nav__a-3">Car Accessories</a></li> 2138 <li class="shop-nav__li-3" data-key='D057FD5CB9974921B636C7F954D970EF'><a href="patriotic_gifts/decorative_boxes.asp" class="shop-nav__a-3">Decorative Boxes</a></li> 2139 <li class="shop-nav__li-3" data-key='636B60A54F72422CBE8CA015C4189115'><a href="patriotic_gifts/decorative_hardware.asp" class="shop-nav__a-3">Decorative Hardware</a></li> 2140 <li class="shop-nav__li-3" data-key='5D5A7FA6F1B0467F9E90585960E20500'><a href="patriotic_gifts/figurines_sculptures.asp" class="shop-nav__a-3">Figurines & Sculptures</a></li> 2141 <li class="shop-nav__li-3" data-key='1E7433EE7A554E2C9F866D9F3A996BF2'><a href="patriotic_gifts/hanging_decor.asp" class="shop-nav__a-3">Hanging Decor</a></li> 2142 <li class="shop-nav__li-3" data-key='3E723FEADA73495E8D00832DE1BA9242'><a href="patriotic_gifts/indoor_lighting.asp" class="shop-nav__a-3">Indoor Lighting</a></li> 2143 <li class="shop-nav__li-3" data-key='6A3047B745194C6ABE33E12DB9EE5D44'><a href="banners/mailbox-covers.asp" class="shop-nav__a-3">Mailbox Covers</a></li> 2144 <li class="shop-nav__li-3" data-key='E8A4CF11E1464BF089F5AB48E73E404E'><a href="patriotic_gifts/rugs.asp" class="shop-nav__a-3">Rugs</a></li> 2145 <li class="shop-nav__li-3" data-key='0909A93F86D0451892DA4F4844B9F375'><a href="patriotic_gifts/thermometers-and-rain-gauges.asp" class="shop-nav__a-3">Thermometers & Rain Gauges</a></li> 2146 <li class="shop-nav__li-3" data-key='04ECA0E31FC44E0B925E2D6C029082E8'><a href="patriotic_gifts/wall_art.asp" class="shop-nav__a-3">Wall Art</a></li> 2147 <li class="shop-nav__li-3" data-key='4B28F86B7E504CD4BF9CF7EB0CA78536'><a href="patriotic_gifts/wreaths.asp" class="shop-nav__a-3">Wreaths</a></li> 2148 <li class="shop-nav__li-3" data-key='F4504209573740A7AB76BA989FEFC556'><a href="patriotic_gifts/pet-accessories.asp" class="shop-nav__a-3">
2148Pet Accessories</a></li> 2149 </ul></li> 2150 <li class="shop-nav__li-2" data-key='02D109B31CA84137B6F0C740FC1B359C'><a href="patriotic_gifts/boutique_office.asp" class="shop-nav__a-2">Office</a> 2151 <ul class="shop-nav__ul-3"> 2152 <li class="shop-nav__li-3" data-key='195F2E9D91B5421197637AD868D324DD'><a href="flags/indoor-american-flag-kits.asp" class="shop-nav__a-3">Indoor American Flag Kits</a></li> 2153 <li class="shop-nav__li-3" data-key='404D966743344831A145DE9C7D05102A'><a href="flags/flags-state-territory-indoor-parade.asp" class="shop-nav__a-3">Indoor State & Territory Flags & Kits</a></li> 2154 <li class="shop-nav__li-3" data-key='0CF682029BC8403D878A581FAAABE80E'><a href="flags/desk-flag-sets.asp" class="shop-nav__a-3">Desk Flag Sets</a></li> 2155 <li class="shop-nav__li-3" data-key='8E8CB6568A2E4C44864FBB1307FA8466'><a href="flags/miniature-flags.asp" class="shop-nav__a-3">Miniature Flags</a></li> 2156 <li class="shop-nav__li-3" data-key='5358F5E8A8EF4E698A1F767B8157700E'><a href="patriotic_gifts/book_bookends.asp" class="shop-nav__a-3">Books</a></li> 2157 <li class="shop-nav__li-3" data-key='B88064A4184F47F29DD0648E3C1E2170'><a href="patriotic_gifts/paperweights.asp" class="shop-nav__a-3">Paperweights</a></li> 2158 <li class="shop-nav__li-3" data-key='3E3D6AD08E274B588EDDED85C00BC4FF'><a href="signs/advertising-signs.asp" class="shop-nav__a-3">Advertising Signs</a></li> 2159 <li class="shop-nav__li-3" data-key='4135F69817C44CC8A785AC1DA6E4473E'><a href="signs/road-traffic-signs.asp" class="shop-nav__a-3">Road & Traffic Signs</a></li> 2160 </ul></li> 2161 <li class="shop-nav__li-2" data-key='10153CEA589246D69387C0E104F905D0'><a href="patriotic_gifts/themed-gifts.asp" class="shop-nav__a-2">Themed Gifts</a> 2162 <ul class="shop-nav__ul-3"> 2163 <li class="shop-nav__li-3" data-key='AE1537ADB5814BFBB6634196D398FDF0'><a href="holidays/spring_flags_and_decorations.asp" class="shop-nav__a-3">Spring Flags & Decorations</a></li> 2164 <li class="shop-nav__li-3" data-key='BB5964DD43C74F91B081C0D1CF2A3DF1'><a href="holidays/summer_flags_and_decorations.asp" class="shop-nav__a-3">Summer Flags & Decorations</a></li> 2165 <li class="shop-nav__li-3" data-key='D764AE99F0804B409E41E1F50D35B260'><a href="holidays/autumn_flags_and_decorations.asp" class="shop-nav__a-3">Autumn Flags & Decorations</a></li> 2166 <li class="shop-nav__li-3" data-key='6C419B5535624182962F7670BB1BBBFC'><a href="holidays/winter_flags_and_decorations.asp" class="shop-nav__a-3">Winter Flags & Decorations</a></li> 2167 <li class="shop-nav__li-3" data-key='7AC4343722AD4D35B4818B7E22EA094A'><a href="holidays/farm-fresh-decor.asp" class="shop-nav__a-3">Farm Fresh Decor</a></li> 2168 <li class="shop-nav__li-3" data-key='5BBD5973F22647DFB5599AF161C477BF'><a href="products/citizenship-gifts.asp" class="shop-nav__a-3">Citizenship Gifts</a></li> 2169 <li class="shop-nav__li-3" data-key='F8E645F88BC14ABBA3F9BE083F6D14D6'><a href="holidays/graduations.asp" class="shop-nav__a-3">Graduation</a></li> 2170 <li class="shop-nav__li-3" data-key='2A347A92EA7D4F748E657A098EFF41C5'><a href="patriotic_gifts/military-gifts.asp" class="shop-nav__a-3">Military Gifts</a></li> 2171 <li class="shop-nav__li-3" data-key='12619696E07A4BD18922CDC554798DBD'><a href="holidays/international-firefighters-day.asp" class="shop-nav__a-3">International Firefighters Day</a></li> 2172 <li class="shop-nav__li-3" data-key='24A19B63D92B4D5282DEAB404EFDCD0A'><a href="patriotic_gifts/dreamland-ballroom-gifts.asp" class="shop-nav__a-3">Dreamland Ballroom Gifts</a></li> 2173 <li class="shop-nav__li-3" data-key='856B47C334F44A3BB27C74051ED33C67'><a href="nautical/nautical-decor.asp" class="shop-nav__a-3">Nautical Themed Home & Garden Decorations</a></li> 2174 <li class="shop-nav__li-3" data-key='7F530E2B4F104472AF5FBB620267AE5C'><a href="holidays/arkansas_razorback_flags_gifts_and_apparel.asp" class="shop-nav__a-3">Razorbacks Flags & Gifts</a></li> 2175 </ul></li> 2176 <li class="shop-nav__li-2" data-key='25E86F7A06314710AF0A657CE500B34C'><a href="holidays/party_supplies.asp" class="shop-nav__a-2">Patriotic Party Supplies</a> 2177 <ul class="shop-nav__ul-3"> 2178 <li class="shop-nav__li-3" data-key='812BD60922AE4A0B9275E9F5FA7AADB2'><a href="flags/american-flags.asp" class="shop-nav__a-3">American Flags</a></li> 2179 <li class="shop-nav__li-3" data-key='77B8B3173B09442EBBEB12885066D3B1'><a href="bunting/bunting.asp" class="shop-nav__a-3">Patriotic Bunting</a></li> 2180 <li class="shop-nav__li-3" data-key='AD31DE1E6CFA4C3F8C6991D2CEB993B8'><a href="pennants/american_pennants.asp" class="shop-nav__a-3">American String Pennants</a></li> 2181 <li class="shop-nav__li-3" data-key='CA9485E0F25E414EB24445EFE1051A61'><a href="patriotic_gifts/boutique_dining_kitchen.asp" class="shop-nav__a-3">Dining & Kitchen</a></li> 2182 <li class="shop-nav__li-3" data-key='FBA055A4C2374F8A975721ECF114060C'><a href="patriotic_crafts/boutique_crafts.asp" class="shop-nav__a-3">Patriotic Craft Material</a></li> 2183 <li class="shop-nav__li-3" data-key='9E379365F754433995F7D35FEC5897CF'><a href="patriotic_gifts/boutique_apparel.asp" class="shop-nav__a-3">Apparel</a></li> 2184 <li class="shop-nav__li-3" data-key='B89497D8452F4EAB85963D41CF2A4029'><a href="patriotic_gifts/boutique_jewelry.asp" class="shop-nav__a-3">Jewelry</a></li> 2185 </ul></li>
2186 <li class="shop-nav__li-2" data-key='300A20376C034E9AB445C59E57DD7B9B'><a href="patriotic_gifts/boutique_toys.asp" class="shop-nav__a-2">Toys & Games</a> 2187 <ul class="shop-nav__ul-3"> 2188 <li class="shop-nav__li-3" data-key='6AD49856D3BE4AF6B9D3535E41002E89'><a href="patriotic_toys/balls_novelty_toys.asp" class="shop-nav__a-3">Kites & Novelty</a></li> 2189 <li class="shop-nav__li-3" data-key='3D014C159DAD4476A7BB363B8561F46B'><a href="patriotic_toys/games.asp" class="shop-nav__a-3">Games</a></li> 2190 <li class="shop-nav__li-3" data-key='9FD3874986374568903594803E3FCD9D'><a href="patriotic_toys/stickers.asp" class="shop-nav__a-3">Stickers & Stationary</a></li> 2191 </ul></li> 2192 <li class="shop-nav__li-2" data-key='563C846CA8104008B7AD7FD4C5D83E1E'><a href="products/made_in_usa.asp" class="shop-nav__a-2">Made in USA Gifts</a> 2193 <ul class="shop-nav__ul-3"> 2194 <li class="shop-nav__li-3" data-key='FF850BC6CD804312ADEE79ED35185325'><a href="products/usa-made-flags-and-poles.asp" class="shop-nav__a-3">American Made Flags & Flagpoles</a></li> 2195 <li class="shop-nav__li-3" data-key='7CE57AB9812E4303903FD3D8ECCCDDC2'><a href="products/usa-made-games.asp" class="shop-nav__a-3">American Made Games & Puzzles</a></li> 2196 <li class="shop-nav__li-3" data-key='0DA2244FB6E44744A08850FAD58A6613'><a href="products/usa-made-gifts.asp" class="shop-nav__a-3">American Made Gifts & Mementos</a></li> 2197 <li class="shop-nav__li-3" data-key='14CC4EED6D8D4F27B11AFB1D5AD0FE47'><a href="products/usa-made-banners.asp" class="shop-nav__a-3">American Made Home & Garden Banners</a></li> 2198 <li class="shop-nav__li-3" data-key='3616C2A203A04B8087514359E1378F2E'><a href="products/usa-made-patriotic-decoration.asp" class="shop-nav__a-3">American Made Patriotic Decorations</a></li> 2199 <li class="shop-nav__li-3" data-key='28E030FC974340259E4CF1963E4ACB68'><a href="pennants/colorful_string_pennants.asp" class="shop-nav__a-3">American Made String Pennants</a></li> 2200 <li class="shop-nav__li-3" data-key='88EA22C466A9432B88C48FC998917166'><a href="pennants/colorful_single_pennants.asp" class="shop-nav__a-3">American Made Colorful Single Pennant Flags</a></li> 2201 </ul></li> 2202 </ul></li> 2203 <li class="shop-nav__li-1" data-key='0D3B38D6DAEB4182ACBAEE64279C9203'><a href="holidays/usa-250-anniversary.asp" class="shop-nav__a-1">USA 250th Anniversary</a></li> 2204 <li class="shop-nav__li-1" data-key='D95F93A7C79D433DBBCF79852B279A20'><a href="patriotic_gifts/memorial-decorations.asp" class="shop-nav__a-1">Memorials</a></li> 2205 <li class="holidays shop-nav__li-1" data-key='ACE656679F4743BDBE49B43F17EB1890'><a href="customer_service/calendar-of-events-holidays.asp" class="shop-nav__a-1">Flag Events & Holidays</a> 2206 <ul class="shop-nav__ul-2"> 2207 <li class="shop-nav__li-2" data-key='1A6E4459B9A54F189125D897AD69DFCB'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#jan" class="shop-nav__a-2">January</a> 2208 <ul class="shop-nav__ul-3"> 2209 <li class="shop-nav__li-3" data-key='4731E844791F4FCEA6C950980AA12525'><a href="holidays/new_years_flags_and_decorations.asp" class="shop-nav__a-3">New Year's Day</a></li> 2210 <li class="shop-nav__li-3" data-key='F89841273E4E4ECD804BCDCEF872A557'><a href="holidays/georgia_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Georgia State Birthday</a></li> 2211 <li class="shop-nav__li-3" data-key='2693867D8EDA412982513A3DED2A8BB2'><a href="holidays/alaska_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Alaska State Birthday</a></li> 2212 <li class="shop-nav__li-3" data-key='FD60C098A50F44DCBE411FC128E2B859'><a href="holidays/utah_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Utah State Birthday</a></li> 2213 <li class="shop-nav__li-3" data-key='F00517D919F7467F948B2E7B7664A5EF'><a href="holidays/new_mexico_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">New Mexico State Birthday</a></li> 2214 <li class="shop-nav__li-3" data-key='C2FA4FE61C0C449B83921C1D9A844982'><a href="holidays/connecticut_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Connecticut State Birthday</a></li> 2215 <li class="shop-nav__li-3" data-key='D549AB90F9A243FEA607D257B4C44077'><a href="holidays/religious_freedom_day.asp" class="shop-nav__a-3">Religious Freedom Day</a></li> 2216 <li class="shop-nav__li-3" data-key='240A2F84EB0E4A18B4053310BE00E63E'><a href="holidays/presidential_inauguration_day.asp" class="shop-nav__a-3">Inauguration Day</a></li> 2217 <li class="shop-nav__li-3" data-key='399BD548DCFC4C0CA39802965C4A1B9D'><a href="holidays/martin_luther_king_jr_day.asp" class="shop-nav__a-3">Martin Luther King Jr. Day</a></li> 2218 <li class="shop-nav__li-3" data-key='71F7A86F30E644F9B155776898F32EF4'><a href="holidays/michigan_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Michigan State Birthday</a></li> 2219 <li class="shop-nav__li-3" data-key='54077A6B7D3B4F02850807D68BBF948C'><a href="holidays/kansas_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Kansas State Birthday</a></li> 2220 </ul></li> 2221 <li class="shop-nav__li-2" data-key='C18829F06FF84309B2541CC1747510E4'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#feb" class="shop-nav__a-2">February</a> 2222 <ul class="shop-nav__ul-3"> 2223 <li class="shop-nav__li-3" data-key='F5F3C5BE88F84790A0C222B944D0E8C5'><a href="holidays/black_history_month.asp" class="shop-nav__a-3">Black History Month</a></li> 2224 <li class="shop-nav__li-3" data-key='BBAFCB66009247E79F0B313D8456162F'><a href="holidays/spring_flags_and_decorations.asp" class="shop-nav__a-3">Spring Season</a></li> 2225 <li class="shop-nav__li-3" data-key='45C14DDA4B1E4205B103730D7F9FBABE'><a href="holidays/massachusetts_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Massachusetts State Birthday</a></li> 2226 <li class="shop-nav__li-3" data-key='C48F4C0277F443729351727642E5577C'><a href="holidays/chinese_new_year.asp" class="shop-nav__a-3">Chinese New Year</a></li> 2227 <li class="shop-nav__li-3" data-key='D783B7C10A6D4476BA7E280F28DB293C'><a href="holidays/valentines_day_banner_and_gift_ideas.asp" class="shop-nav__a-3">Valentine's Day</a></li> 2228 <li class="shop-nav__li-3" data-key='4AB291DF43944FFDBEDDE33A59C0D143'><a href="holidays/oregon_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Oregon State Birthday</a></li> 2229 <li class="shop-nav__li-3" data-key='3FF66375F5474BCF89CA66058D629BD3'><a href="holidays/arizona_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Arizona State Birthday</a></li> 2230 <li class="shop-nav__li-3" data-key='1B452D48C6FC4F458F2F392D08BDCD53'><a href="holidays/presidents_day_decorations.asp" class="shop-nav__a-3">President's Day</a></li> 2231 </ul></li> 2232 <li class="shop-nav__li-2" data-key='1418E6C2D97E4E15A9F47982A12F328A'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#mar" class="shop-nav__a-2">March</a> 2233 <ul class="shop-nav__ul-3"> 2234 <li class="shop-nav__li-3" data-key='1C6EF57B25664168A9980242F8D6E163'><a href="holidays/mardi_gras_flags_decorations_and_gifts.asp" class="shop-nav__a-3">Mardi Gras</a></li> 2235 <li class="shop-nav__li-3" data-key='5D4A5978A89E4B14BE491574C01335E7'><a href="holidays/irish_american_heritage_month.asp" class="shop-nav__a-3">Irish American Heritage Month</a></li> 2236 <li class="shop-nav__li-3" data-key='6AB09F297F4A4B7DBBEE4AE0E4FEA152'><a href="holidays/national_womens_history_month.asp" class="shop-nav__a-3">Women's History Month</a></li> 2237 <li class="shop-nav__li-3" data-key='481A3FD6844248D9A368EE31E822D7DD'><a href="banners/college_sports_banners.asp" class="shop-nav__a-3">March Madness</a></li> 2238 <li class="shop-nav__li-3" data-key='165635D99C064F85953BAA3CF04260C7'><a href="holidays/ohio_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Ohio State Birthday</a></li> 2239 <li class="shop-nav__li-3" data-key='C759519445924B65977CF16ABD4E7023'><a href="holidays/nebraska_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Nebraska State Birthday</a></li> 2240 <li class="shop-nav__li-3" data-key='CA12DD1161374978A400F60B0F4F48E6'>
2240<a href="holidays/florida_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Florida State Birthday</a></li> 2241 <li class="shop-nav__li-3" data-key='E9B47B7C4542465CA5CAB05ED666CA32'><a href="holidays/vermont_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Vermont State Birthday</a></li> 2242 <li class="shop-nav__li-3" data-key='8ECF481DC2A741B69C087E403195EEDF'><a href="holidays/remember_the_alamo_day.asp" class="shop-nav__a-3">Remember The Alamo Day</a></li> 2243 <li class="shop-nav__li-3" data-key='98CE6CFBB4BA450690D00AEB912E9013'><a href="holidays/st_patricks_day.asp" class="shop-nav__a-3">St. Patrick's Day</a></li> 2244 <li class="shop-nav__li-3" data-key='43C4DE8D61C94940B0A588658A383D39'><a href="holidays/maine_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Maine State Birthday</a></li> 2245 </ul></li> 2246 <li class="shop-nav__li-2" data-key='60D65D20FBB04F94B6EF83D11A9849FF'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#apr" class="shop-nav__a-2">April</a> 2247 <ul class="shop-nav__ul-3"> 2248 <li class="shop-nav__li-3" data-key='E337C3059EEE49738AC01740057B5CEC'><a href="holidays/easter_flags_banners_and_decorations.asp" class="shop-nav__a-3">Easter</a></li> 2249 <li class="shop-nav__li-3" data-key='C1CCB4AA3558426498092AEBC4722DA1'><a href="holidays/prevention_of_cruelty_to_animals_month.asp" class="shop-nav__a-3">Prevention of Cruelty to Animals Month</a></li> 2250 <li class="shop-nav__li-3" data-key='C228E574D57643A5BDBD40A3256BB7FD'><a href="holidays/earth_day.asp" class="shop-nav__a-3">Earth Day</a></li> 2251 <li class="shop-nav__li-3" data-key='A88B295C179341C7A35DC8BFFC16D6A9'><a href="holidays/maryland_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Maryland State Birthday</a></li> 2252 <li class="shop-nav__li-3" data-key='A549B6391BE8489EAE55A0AD9777A423'><a href="holidays/louisiana_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Louisiana State Birthday</a></li> 2253 </ul></li> 2254 <li class="shop-nav__li-2" data-key='92DDBBCBF3104C3E968DE771FB5EA2C1'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#may" class="shop-nav__a-2">May</a> 2255 <ul class="shop-nav__ul-3"> 2256 <li class="shop-nav__li-3" data-key='636043C839824FBBA2CE40BFC9FCF1F6'><a href="holidays/jewish_american_heritage_month.asp" class="shop-nav__a-3">Jewish American Heritage Month</a></li> 2257 <li class="shop-nav__li-3" data-key='758D712CB666468E858ADF8578E64959'><a href="holidays/asian_pacific_american_heritage_month.asp" class="shop-nav__a-3">Asian Pacific American Month</a></li> 2258 <li class="shop-nav__li-3" data-key='7C89EA4D7E49450997F7C98AF16CF3E6'><a href="holidays/arkansas_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Arkansas Heritage Month</a></li> 2259 <li class="shop-nav__li-3" data-key='5198FC59E4584FBABA0A65C52449B295'><a href="holidays/firefighter_flags_and_gifts.asp" class="shop-nav__a-3">International Firefighter's Day</a></li> 2260 <li class="shop-nav__li-3" data-key='5B08CA47ECC34825ADD0C1F4B1B94175'><a href="holidays/cinco_de_mayo.asp" class="shop-nav__a-3">Cinco De Mayo</a></li> 2261 <li class="shop-nav__li-3" data-key='7024C28074F54E5094ADFA0744B44F75'><a href="holidays/national_teacher_day.asp" class="shop-nav__a-3">National Teacher's Day</a></li> 2262 <li class="shop-nav__li-3" data-key='088F399CF52B48F9A5CCDFCAF99C5FBB'><a href="holidays/minnesota_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Minnesota State Birthday</a></li> 2263 <li class="shop-nav__li-3" data-key='BCBF548F5A96423E903209B4F6B1AF71'><a href="holidays/mothers_day.asp" class="shop-nav__a-3">Mother's Day</a></li> 2264 <li class="shop-nav__li-3" data-key='996E5A40D510427C84B7EF75AD25F0FA'><a href="flags/service-persons-flags.asp" class="shop-nav__a-3">National Fallen Firefighters Memorial Service</a></li> 2265 <li class="shop-nav__li-3" data-key='A614E757A650424CACB2958DE95B47BE'><a href="holidays/peace_officers_memorial_day.asp" class="shop-nav__a-3">Peace Officer's Memorial Day</a></li> 2266 <li class="shop-nav__li-3" data-key='E152245ABD14463E8993D0D729EB108C'><a href="holidays/armed_forces_flags_and_gifts.asp" class="shop-nav__a-3">Armed Forces Day</a></li> 2267 <li class="shop-nav__li-3" data-key='D7E180401EEA4CFEA693CD41CF25D488'><a href="holidays/south_carolina_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">South Carolina State Birthday</a></li> 2268 <li class="shop-nav__li-3" data-key='C61F31D843964256B802D79ED92CF964'><a href="holidays/memorial_day.asp" class="shop-nav__a-3">Memorial Day</a></li> 2269 <li class="shop-nav__li-3" data-key='D4D32FF9906A4FE4A1983E75ECA08EB3'><a href="holidays/rhode_island_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">
2269Rhode Island State Birthday</a></li> 2270 <li class="shop-nav__li-3" data-key='A619F3D8354D4931B9D6694ADD88A867'><a href="holidays/wisconsin_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Wisconsin State Birthday</a></li> 2271 <li class="shop-nav__li-3" data-key='17D14B63652D4C46BA3D6E8ECC31A613'><a href="holidays/graduations.asp" class="shop-nav__a-3">Graduation</a></li> 2272 </ul></li> 2273 <li class="shop-nav__li-2" data-key='F87138435C7445CCB106E0DB29A78D54'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#jun" class="shop-nav__a-2">June</a> 2274 <ul class="shop-nav__ul-3"> 2275 <li class="shop-nav__li-3" data-key='04096D76569C41FFA0966E29C7C9D2A1'><a href="holidays/summer_flags_and_decorations.asp" class="shop-nav__a-3">Summer Season</a></li> 2276 <li class="shop-nav__li-3" data-key='6E53E81707194497969ADCBA5E143B24'><a href="holidays/adopt-a-cat_month.asp" class="shop-nav__a-3">Adopt A Cat Month</a></li> 2277 <li class="shop-nav__li-3" data-key='7AE80E1DE44243B9BBE9F7B24C289AF7'><a href="holidays/lgbt-pride-month.asp" class="shop-nav__a-3">Gay and Lesbian Heritage Month</a></li> 2278 <li class="shop-nav__li-3" data-key='D32FD4CCA6F94BEBBB4C60EE4E673703'><a href="holidays/cancer_survivor_day.asp" class="shop-nav__a-3">Cancer Survivor Day</a></li> 2279 <li class="shop-nav__li-3" data-key='C349863B756647D9867ECFEA1CE06C93'><a href="flags/nba-flags.asp" class="shop-nav__a-3">NBA Finals</a></li> 2280 <li class="shop-nav__li-3" data-key='E5E9FC398C264E65999EBF330D227E3B'><a href="holidays/kentucky_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Kentucky State Birthday</a></li> 2281 <li class="shop-nav__li-3" data-key='02D93D9AC4814338BADDBD8C4598026A'><a href="holidays/tennessee_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Tennessee State Birthday</a></li> 2282 <li class="shop-nav__li-3" data-key='303D141FAD7849EBBE73B428EC398E76'><a href="holidays/remember_d-day.asp" class="shop-nav__a-3">D-Day Remembrance Day</a></li> 2283 <li class="shop-nav__li-3" data-key='BCABD3E95A7C4C9897F6831996011370'><a href="holidays/king_kamehameha_day.asp" class="shop-nav__a-3">King Kamehameha Day</a></li> 2284 <li class="shop-nav__li-3" data-key='F867C179DF1C4FA9AB9BB5F9D098D67D'><a href="holidays/iowa_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Iowa State Birthday</a></li> 2285 <li class="shop-nav__li-3" data-key='1003A945629A480480467BC543A63DE2'><a href="flags/soccer-flags.asp" class="shop-nav__a-3">FIFA World Cup</a></li> 2286 <li class="shop-nav__li-3" data-key='95CAD4E4E62F4D7C8717B55BD89944F2'><a href="holidays/arkansas_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Arkansas State Birthday</a></li> 2287 <li class="shop-nav__li-3" data-key='592853446F42495DA35E7B51094408B6'><a href="holidays/army_flags_and_gifts.asp" class="shop-nav__a-3">Army Birthday</a></li> 2288 <li class="shop-nav__li-3" data-key='7A0EE41DF0704B2999CD9B05B888D24D'><a href="holidays/american_flag_day.asp" class="shop-nav__a-3">American Flag Day</a></li> 2289 <li class="shop-nav__li-3" data-key='24658D8450B549A1AC6DD739AD888371'><a href="holidays/fathers_day.asp" class="shop-nav__a-3">Father's Day</a></li> 2290 <li class="shop-nav__li-3" data-key='3822863E9C904FD0B6D0D73728161C9A'><a href="flags/nhl-flags.asp" class="shop-nav__a-3">Stanley Cup</a></li> 2291 <li class="shop-nav__li-3" data-key='1531D990BE9446488F7EB703E1D53593'><a href="holidays/west_virginia_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">West Virginia State Birthday</a></li> 2292 <li class="shop-nav__li-3" data-key='D3BF23C2E56B46F3910B41DDA3BBB8BC'><a href="holidays/new_hampshire_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">New Hampshire State Birthday</a></li> 2293 <li class="shop-nav__li-3" data-key='24AD0DBD7A9548F3B2C64DEC9755BDF5'><a href="holidays/virginia_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Virginia State Birthday</a></li> 2294 <li class="shop-nav__li-3" data-key='364E9818F42D46159400635C861CDAC0'><a href="holidays/world_war_1_anniversary.asp" class="shop-nav__a-3">World War 1 Day</a></li> 2295 </ul></li> 2296 <li class="shop-nav__li-2" data-key='5837BA3D65CA4B119292B5962F4CD6F5'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#jul" class="shop-nav__a-2">July</a> 2297 <ul class="shop-nav__ul-3"> 2298 <li class="shop-nav__li-3" data-key='4BD00A715CB64220A5804689E5168E61'><a href="holidays/canada_day.asp" class="shop-nav__a-3">Canada Day</a></li> 2299 <li class="shop-nav__li-3" data-key='6C71FF9806DF4CF1AD7E3422A235B90D'><a href="holidays/idaho_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Idaho State Birthday</a></li> 2300 <li class="shop-nav__li-3" data-key='D1E8EDBFFAD34955B1B6269F90F5694C'><a href="holidays/4th-of-july.asp" class="shop-nav__a-3">USA Independence Day</a></li> 2301 <li class="shop-nav__li-3" data-key='1AFCC6F08D3145C59D4DADF2B4CFBABC'><a href="holidays/wyoming_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Wyoming State Birthday</a></li> 2302 <li class="shop-nav__li-3" data-key='D8F7855C7CE84C23A9C172A06913CACF'><a href="holidays/bastille_day.asp" class="shop-nav__a-3">Bastille Day</a></li> 2303 <li class="shop-nav__li-3" data-key='975C7C6FD4D84CE49D71B83BF37B8A7C'><a href="holidays/new_york_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">New York State Birthday</a></li> 2304 <li class="shop-nav__li-3" data-key='AFB69FB05E6545819CD97114EF8AA369'><a href="holidays/korean_war_veterans_day.asp" class="shop-nav__a-3">Korean War Veterans Day</a></li> 2305 </ul></li> 2306 <li class="shop-nav__li-2" data-key='FABC577BC7B34A77B331EAFC7C12AEC6'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#aug" class="shop-nav__a-2">August</a> 2307 <ul class="shop-nav__ul-3"> 2308 <li class="shop-nav__li-3" data-key='BBF7F36125D24F1E8A92B84013A31634'><a href="holidays/arkansas_razorback_flags_gifts_and_apparel.asp" class="shop-nav__a-3">Razorback Football Season</a></li> 2309 <li class="shop-nav__li-3" data-key='6C9D567C2B6341228B46D3105FFB60B5'><a href="holidays/back_to_school_ideas_for_teachers_and_parents.asp" class="shop-nav__a-3">Back to School</a></li> 2310 <li class="shop-nav__li-3" data-key='981DC0CBC4204140B7A1AC80D99E3CD2'><a href="holidays/colorado_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Colorado State Birthday</a></li> 2311 <li class="shop-nav__li-3" data-key='B232AB2ED2E24D169CEFB9576D6A643D'><a href="holidays/coast_guard_flags_and_gifts.asp" class="shop-nav__a-3">Coast Guard Birthday</a></li> 2312 <li class="shop-nav__li-3" data-key='6CA6A3D8722540F6A1D2FCB9BE05E2B7'><a href="holidays/missouri_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Missouri State Birthday</a></li> 2313 <li class="shop-nav__li-3" data-key='0E9EE350EDE0413188E9C4696F9578AD'><a href="holidays/hawaii_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Hawaii State Birthday</a></li> 2314 <li class="shop-nav__li-3" data-key='453849654A3344BDBFDF4450A7451ECE'><a href="holidays/womens_equality_day.asp" class="shop-nav__a-3">Women's Equality Day</a></li> 2315 </ul></li> 2316 <li class="shop-nav__li-2" data-key='3C49B89CD0724AB991723E592BEA14CC'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#sep" class="shop-nav__a-2">September</a> 2317 <ul class="shop-nav__ul-3"> 2318 <li class="shop-nav__li-3" data-key='9DB9AFCC70FA439B91A89E88C88E12CD'><a href="holidays/autumn_flags_and_decorations.asp" class="shop-nav__a-3">Fall Season</a></li> 2319 <li class="shop-nav__li-3" data-key='EC4F88FB714C4C4384F0E5B4343FF10E'><a href="holidays/latino_and_hispanic_heritage_month.asp" class="shop-nav__a-3">Latino and Hispanic Month</a></li> 2320 <li class="shop-nav__li-3" data-key='AD284C8A78CF40D4AAE8920E6E726088'><a href="holidays/labor_day_decorations.asp" class="shop-nav__a-3">Labor Day</a></li> 2321 <li class="shop-nav__li-3" data-key='389F4B49103E45CEA47315DDC15E7022'><a href="holidays/california_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">California State Birthday</a></li> 2322 <li class="shop-nav__li-3" data-key='0804F1CACB9646AD90345B3832A6A571'><a href="holidays/patriot_day_and_9-11-01_remembrance_day_flags.asp" class="shop-nav__a-3">Patriot Day</a></li> 2323 <li class="shop-nav__li-3" data-key='B5D7196696A34114847CE0F8FA7D9D4C'><a href="holidays/constitution_and_citizenship_day_gifts_and_decorations.asp" class="shop-nav__a-3">
2323Constitution & Citizenship Day</a></li> 2324 <li class="shop-nav__li-3" data-key='FFD0868A32D047F09B7A54CE73B2DBA8'><a href="holidays/pirate_day_flags_banners_and_decorations.asp" class="shop-nav__a-3">Talk Like A Pirate Day</a></li> 2325 <li class="shop-nav__li-3" data-key='2B1D8E55455E4B319CA88843FF1C2CA6'><a href="holidays/air_force_flags_and_gifts.asp" class="shop-nav__a-3">Air Force Birthday</a></li> 2326 <li class="shop-nav__li-3" data-key='2CDF65AF00A04AE89235621FA733D596'><a href="holidays/gold_star_mothers_day_flags_and_gifts.asp" class="shop-nav__a-3">Gold Star Mother's Day</a></li> 2327 </ul></li> 2328 <li class="shop-nav__li-2" data-key='8FAC320548314EF89B66F2783DE3FF6C'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#oct" class="shop-nav__a-2">October</a> 2329 <ul class="shop-nav__ul-3"> 2330 <li class="shop-nav__li-3" data-key='DB53EE3547EF4D99B74DF60C3C9418C6'><a href="holidays/adopt-a-dog_month.asp" class="shop-nav__a-3">Adopt a Dog Month</a></li> 2331 <li class="shop-nav__li-3" data-key='0932810F468548418C7D31DB4E7E29EC'><a href="holidays/diversity_month.asp" class="shop-nav__a-3">Diversity Month</a></li> 2332 <li class="shop-nav__li-3" data-key='617EF1596D1A4B588E8D61E2D812093A'><a href="holidays/national_day.asp" class="shop-nav__a-3">National Day</a></li> 2333 <li class="shop-nav__li-3" data-key='9D6C3E33CE7846809C890BB876D86915'><a href="holidays/german-american_day.asp" class="shop-nav__a-3">German-American Day</a></li> 2334 <li class="shop-nav__li-3" data-key='A4663DA6A1B348228F373A8B58ABC33A'><a href="holidays/leif_erikson_day.asp" class="shop-nav__a-3">Leif Erikson Day</a></li> 2335 <li class="shop-nav__li-3" data-key='0770355C86604885BDDBCB37B17D79A5'><a href="holidays/navy_flags_and_gifts.asp" class="shop-nav__a-3">Navy Birthday</a></li> 2336 <li class="shop-nav__li-3" data-key='271F5F663E0B4D8D9780D5A1AFC5DCBC'><a href="holidays/pink_ribbon_and_breast_cancer_awareness.asp" class="shop-nav__a-3">Breast Cancer Awareness & Race for the Cure</a></li> 2337 <li class="shop-nav__li-3" data-key='29BF06E0719249FCA7C8FD53AE418A81'><a href="holidays/united_nations_day.asp" class="shop-nav__a-3">United Nations Day</a></li> 2338 <li class="shop-nav__li-3" data-key='5D5CE7CC50E247199FE582C0A5EA635C'><a href="holidays/nevada_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Nevada State Birthday</a></li> 2339 <li class="shop-nav__li-3" data-key='758F1582FBA64FD8BCB00C0C4CD81A50'><a href="holidays/halloween_decorations.asp" class="shop-nav__a-3">Halloween</a></li> 2340 </ul></li> 2341 <li class="shop-nav__li-2" data-key='206F748E52F54F1EBFB0342831C4936D'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#nov" class="shop-nav__a-2">November</a> 2342 <ul class="shop-nav__ul-3"> 2343 <li class="shop-nav__li-3" data-key='8958AC3F254140D6A497FF3B41DE3001'><a href="holidays/national_alaska_native_and_american_indian_heritage_month.asp" class="shop-nav__a-3">Alaska Native & American Indian Month</a></li> 2344 <li class="shop-nav__li-3" data-key='D9C398FCAD4F4859B7B4C2F3CD3CDD77'><a href="holidays/north_dakota_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">North Dakota State Birthday</a></li> 2345 <li class="shop-nav__li-3" data-key='A1C9241ABDB04575B8A442A5B00C5679'><a href="holidays/south_dakota_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">South Dakota State Birthday</a></li> 2346 <li class="shop-nav__li-3" data-key='E4844CE01E8A43FA93609F52BCC2BAA3'><a href="holidays/political_party_election.asp" class="shop-nav__a-3">Presidential Election</a></li> 2347 <li class="shop-nav__li-3" data-key='F7A0B47D6C1A4F34A4B49CD2F7E4DD1E'><a href="holidays/montana_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Montana State Birthday</a></li> 2348 <li class="shop-nav__li-3" data-key='B98C787F204A4B2FA3DB15A5D6AC1717'><a href="holidays/marine_corps_flags_and_gifts.asp" class="shop-nav__a-3">Marine Corps Birthday</a></li> 2349 <li class="shop-nav__li-3" data-key='F9BDF238E4BF4CE098CE1FF9ADBEE462'><a href="holidays/veterans_day.asp" class="shop-nav__a-3">Veterans Day</a></li> 2350 <li class="shop-nav__li-3" data-key='1DB133BBA82C4A4FBD89FFC515FB2A21'><a href="holidays/washington_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Washington State Birthday</a></li> 2351 <li class="shop-nav__li-3" data-key='2F65FE2F3EDE4AFDBC82FA2BD7B2335A'><a href="holidays/oklahoma_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Oklahoma State Birthday</a></li> 2352 <li class="shop-nav__li-3" data-key='357C38894C6E432886A90667AC07664B'><a href="holidays/north_carolina_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">North Carolina State Birthday</a></li> 2353 <li class="shop-nav__li-3" data-key='2C1106290BDC4B5E82D24BEE399AD58C'><a href="holidays/thanksgiving_and_harvest.asp" class="shop-nav__a-3">Thanksgiving</a></li> 2354 </ul></li> 2355 <li class="shop-nav__li-2" data-key='E0AC2701ABC84C0CB58139B15926793B'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#dec" class="shop-nav__a-2">December</a> 2356 <ul class="shop-nav__ul-3"> 2357 <li class="shop-nav__li-3" data-key='0534F178B49B48EAA0AF463D2AEC3019'><a href="holidays/winter_flags_and_decorations.asp" class="shop-nav__a-3">Winter Season</a></li> 2358 <li class="shop-nav__li-3" data-key='726182A5767449DABB52C770F3F826B6'><a href="holidays/world_aids_awareness_day.asp" class="shop-nav__a-3">World AIDS Awareness Day</a></li> 2359 <li class="shop-nav__li-3" data-key='003FEDD536D848CFB8F85E2F8DA1357B'><a href="holidays/illinois_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Illinois State Birthday</a></li> 2360 <li class="shop-nav__li-3" data-key='A0A0C8664B954066ACD815230B9E2EDB'><a href="holidays/delaware_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Delaware State Birthday</a></li> 2361 <li class="shop-nav__li-3" data-key='9C0979EA81054331BD656B0DF42A7CDB'><a href="holidays/mississippi_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Mississippi State Birthday</a></li> 2362 <li class="shop-nav__li-3" data-key='98DB9146BC2742FFB179F4711DC9A326'><a href="holidays/indiana_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Indiana State Birthday</a></li> 2363 <li class="shop-nav__li-3" data-key='BD12DCAA1B6C4BF1B1CA87383D428060'><a href="holidays/national_poinsettia_day.asp" class="shop-nav__a-3">National Poinsettia Day</a></li> 2364 <li class="shop-nav__li-3" data-key='9BA578C1E38A459E860314A676ADC72D'><a href="holidays/pennsylvania_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Pennsylvania State Birthday</a></li> 2365 <li class="shop-nav__li-3" data-key='FCDA37C658C546418DDE8F4E8B0C5191'><a href="holidays/alabama_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Alabama State Birthday</a></li> 2366 <li class="shop-nav__li-3" data-key='67C04B5C1B3946518502BD5F0BA8200D'><a href="holidays/new_jersey_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">New Jersey State Birthday</a></li> 2367 <li class="shop-nav__li-3" data-key='6FA497953EAB4109B685B3600EC55D6B'><a href="holidays/pearl_harbor_remembrance_day.asp" class="shop-nav__a-3">Pearl Harbor Remembrance Day</a></li> 2368 <li class="shop-nav__li-3" data-key='7B036C8FFDA94548B61141A1AE8B7B33'><a href="holidays/chanukah-flags-and-banners.asp" class="shop-nav__a-3">Chanukah</a></li> 2369 <li class="shop-nav__li-3" data-key='038F32AA24AB4B758CDA5851AC416C68'><a href="patriotic_gifts/boutique_christmas.asp" class="shop-nav__a-3">Christmas</a></li> 2370 <li class="shop-nav__li-3" data-key='17E0CE9191BE42AA94D018B197193217'><a href="holidays/texas_state_birthday_flags_and_gifts.asp" class="shop-nav__a-3">Texas State Birthday</a></li> 2371 <li class="shop-nav__li-3" data-key='A3353A9AA3CE4E5E8E9FDE1950C4B526'><a href="holidays/new_years_flags_and_decorations.asp" class="shop-nav__a-3">New Year's Eve</a></li> 2372 </ul></li> 2373 </ul></li> 2374 <li class="shop-nav__li-1" data-key='522C2211B0764D9D9C5C8BE3A818A3A8'><a href="holidays/whats_new.asp" class="shop-nav__a-1">What's New</a></li> 2375 <li class="best-sellers shop-nav__li-1" data-key='80C4BF7D38A146BD901CCE4375B2DB4E'><a href="products/best-sellers.asp" class="shop-nav__a-1">Best Sellers</a></li> 2376 <li class="shop-nav__li-1" data-key='BA5E78DF24B24390A8F0EEB26902C060'><a href="patriotic_gifts/clearance.asp" class="shop-nav__a-1">Clearance</a></li> 2377 <li class="shop-nav__li-1" data-key='931530C891434A3DB122FB578DB350E9'><a href="flags/flag_alerts.asp" class="shop-nav__a-1">Join Our Mail List</a></li> 2378 <li class="shop-nav__li-1" data-key='635CD37A5493419FBC1520CE7796D7F7'><a href="flags/half-staff.asp" class="shop-nav__a-1">American Flag Status</a></li> 2379</ul> 2380 </li> 2381 </ul> 2382 <ul id="header-nav" class="navigation__menu linkset click-persist js-click-outside-to-close header-nav__ul-1"> 2383 <li class="header-nav__li-1" data-key='0515755A77AA45A9B08E0F7D526174BB'><a href="javascript:void(0);" class="header-nav__a-1"><i class=icon-reorder></i> Menu <i class=icon-caret-down></i></a> 2384 <ul class="header-nav__ul-2">
2385 <li class="header-nav__li-2" data-key='5BFB16597F034A859B4C1701EA2C3BCA'><a href="customer_service/Custom-Order-Request.asp" class="header-nav__a-2"><i class=icon-file></i> Get A Quote</a></li> 2386 <li class="header-nav__li-2" data-key='8F57262AFB234F7197DC625BD6261938'><a href="customer_service/helpful_documents.asp" class="header-nav__a-2"><i class=icon-question-sign></i> FAQ</a></li> 2387 <li class="header-nav__li-2" data-key='A9DC4A972D564F148AA3FD0895D6C1BF'><a href="content/about-us.asp" class="header-nav__a-2"><i class=icon-group></i> Our Story</a></li> 2388 <li class="header-nav__li-2" data-key='1353D0FFDA4F43BAA88076738378ED34'><a href="up-in-your-business-radio-show/main.asp" class="header-nav__a-2"><i class=icon-microphone></i> Our Podcast</a></li> 2389 <li class="header-nav__li-2" data-key='7654CB4C3B644CE08C4F85B64890F8AB'><a href="brave-magazine/index.asp" class="header-nav__a-2"><i class=icon-book></i> Our Magazine</a></li> 2390 <li class="header-nav__li-2" data-key='83612F76F75D47A0A4713E8E5E8ECEBE'><a href="https://www.ourcornermarket.com" class="header-nav__a-2"><i class=icon-desktop></i> OurCornerMarket.com</a></li> 2391 <li class="header-nav__li-2" data-key='5C34557B871440E2A1C0699D5931A925'><a href="https://bannerisms.com" class="header-nav__a-2" target=blank><i class=icon-star></i> Kerry's Blog</a></li> 2392 <li class="header-nav__li-2" data-key='2FE53D8F66974FC0BC72F5958F46026D'><a href="https://www.dreamlandballroom.org/" class="header-nav__a-2" target=blank><i class=icon-music></i> Dreamland</a></li> 2393 <li class="header-nav__li-2" data-key='C938CB12B6F44DD5BBEAD7F0E2961937'><a href="customer_service/contact_us.asp" class="header-nav__a-2"><i class=icon-phone></i> Contact Us</a></li> 2394 </ul></li> 2395</ul> 2396 </div> 2397 2398 <div class="navigation__account-cart"> 2399 2400 <ul id="header__signin" class="header__signin linkset click-persist"> 2401 <li class=""> 2402 2403 <a id="header__signin-open" 2404 class="header__signin-open global-modal" 2405 data-size="small" 2406 data-backdrop="static" 2407 title="Sign in to Your Account" 2408 href="security_logon.asp?autopage=%2Fcustom%5Fshowroom%2FCustom%2DFlag%2DPricing%2Easp&modal=1"> 2409 <i class="icon-signin"></i> Sign In 2410 </a> 2411 2412 </li> 2413 </ul> 2414 <ul id="header__cart-preview" class="header__cart-preview linkset click-persist js-click-outside-to-close"> 2415 <li class="link-parent"> 2416 <a class="header__cart-preview__toggle" href="#0"> 2417 <i class="icon-shopping-cart"></i> <span class="hidden-xs hidden-sm">My</span> Cart 2418 <span id="cart_window_qty" class="cart_window_qty badge">0</span> 2419 </a> 2420 <ul> 2421 <li class="app-minicart" id="cart_window_incl"> 2422 2423 2424 <div id="cart_window" class="cart-preview cart_window"> 2425 2426 2427
2427<script> 2428 var cartQtyTarg = '#cart_window_qty', 2429 cartQtyTotal = 0, 2430 cartWinTarg = '#cart_window_incl'; 2431 </script>
2431 2432 2433 <div class="cart-empty-text muted">Your shopping cart is empty.</div> 2434 2435 2436 <div class="controls"> 2437 <a href="/showcart.asp?o_key=89D17E098FCD447A874C26E29C88E23B" class="btn btn-block btn-primary view-cart-button"> 2438 <i class="icon-shopping-cart"></i> View & Edit Cart 2439 </a> 2440 </div> 2441 2442 2443
2443<script type="text/javascript"> 2444 2445 jQuery(function(){ 2446 // Set the template cart qty on initial load 2447 fncUpdateTemplateQty(cartQtyTarg, cartQtyTotal); 2448 }); 2449 2450 // Function to update the template qty value 2451 function fncUpdateTemplateQty(targ, total) { 2452 jQuery(targ).text(total); 2453 } 2454 2455 // Function to remove an item from the cart window 2456 function fncCartWinRemove(sUnqID, sConfirmText) { 2457 var bUseRemoveMsg = true; 2458 2459 if(bUseRemoveMsg){ 2460 var okay = confirm(sConfirmText); 2461 } 2462 else{ 2463 okay = true; 2464 } 2465 2466 if (okay) { 2467 jQuery('#li_'+sUnqID).remove(); 2468 try { 2469 jQuery.ajax({ 2470 url: 'i_i_add_to_cart.asp', 2471 data: 'type=v200remove&ajax=returnJSON&rkey='+sUnqID, 2472 type: 'GET', 2473 dataType: "json", 2474 success: function(jsonOrder) { 2475 fncCartRefresh(jsonOrder[1].item_count, jsonOrder[1].o_total); 2476 } 2477 }); 2478 } catch (err) { 2479 //alert(err.message); 2480 location.reload(); 2481 } 2482 } 2483 } //-function fncCartWinRemove(sUnqID) 2484 2485 // Refreshes the (#) for the cart items count 2486 function fncCartRefresh(item_count, o_total) { 2487 if (typeof item_count == "undefined") { 2488 try { 2489 jQuery.ajax({ 2490 url: 'shopping_cart_window.asp', 2491 data: 'cartwindowajax=getcart', 2492 type: 'GET', 2493 dataType: 'json', 2494 error: function (jqXHR, textStatus, errorThrown) { 2495 alert('Error! ' + errorThrown + ' ' + textStatus); 2496 }, 2497 success: function (oData) { 2498 var cart = oData || {}; 2499 if (typeof cart != "undefined") { 2500 //console.log(cart); 2501 jQuery(cartQtyTarg).html(cart.items); 2502 jQuery("#cart_window_subtotal").html(cart.total); 2503 //return true; 2504 } 2505 fncReloadCartWindow(); 2506 } 2507 }); 2508 } catch(err) { 2509 alert(err.message); 2510 } 2511 } else { 2512 if (jQuery(cartQtyTarg).length==1) { 2513 //console.log(cart); 2514 jQuery(cartQtyTarg).html(item_count); 2515 jQuery("#cart_window_subtotal").html(o_total); 2516 //return true; 2517 } 2518 fncReloadCartWindow(); 2519 } 2520 } //- function fncCartRefresh() 2521 2522 // Reload the contents of the cart window 2523 function fncReloadCartWindow() { 2524 try { 2525 jQuery.ajax({ 2526 url: 'shopping_cart_window.asp', 2527 data: 'cartwindowajax=ajaxcall', 2528 type: 'get', 2529 success: function (oData) { 2530 jQuery(cartWinTarg).html(oData); 2531 //fncUpdateTemplateQty(cartQtyTarg, cartQtyTotal); 2532 $(window).trigger('cartWindowUpdated'); 2533 return true; 2534 } 2535 }); 2536 } catch(err) { 2537 alert(err.message); 2538 } 2539 } //-function fncReloadCartWindow() 2540 2541 function fncConfirmEmptyCart() { 2542 if(confirm("Are you sure you want to empty your cart?")) { 2543 fncEmptyCart(); 2544 } 2545 } 2546 2547 function fncEmptyCart() { 2548 jQuery.ajax({ 2549 url: 'shopping_cart_window.asp', 2550 data: 'pageaction=empty_cart', 2551 type: 'get', 2552 success: fncReloadCartWindow 2553 }); 2554 } 2555 2556 2557 2558 </script>
2558 2559 2560 </div> 2561 <!-- /#cart_window --> 2562 2563 </li> 2564 </ul> 2565 </li> 2566 </ul> 2567 2568 </div> 2569 </div> 2570 </div> 2571 2572</header> 2573<div class="layout__container container-fluid"> 2574 <div class="layout__sidebar"> 2575 <h1>Shop FlagandBanner.com</h1> 2576 <ul id="sidebar-nav" class="sidebar-nav linkset plus js-click-outside-to-close print-hide sidebar-nav__ul-1"> 2577 <li class="flags sidebar-nav__li-1" data-key='E7CFCDD1BA744C94AF1FDFE80E3E949C'><a href="flags/flags.asp" class="sidebar-nav__a-1">Flags and Banners</a> 2578 <ul class="sidebar-nav__ul-2"> 2579 <li class="sidebar-nav__li-2" data-key='5452D457ACA746F8A1C2BFD927F4BB0A'><a href="flags/american-flags.asp" class="sidebar-nav__a-2">American</a> 2580 <ul class="sidebar-nav__ul-3"> 2581 <li class="sidebar-nav__li-3" data-key='41B2B687C3FE4E54A6DE7CE883562711'><a href="flags/flags-american-outdoor.asp" class="sidebar-nav__a-3">Outdoor American Flags</a></li> 2582 <li class="sidebar-nav__li-3" data-key='88CEA3687E09479F88658ED40A897C91'><a href="flags/indoor-american-flags.asp" class="sidebar-nav__a-3">Indoor American Flags</a></li> 2583 <li class="sidebar-nav__li-3" data-key='9AD308008BE64F7E93217DB4FA0297AE'><a href="banners/american_banners.asp" class="sidebar-nav__a-3">American Banners</a></li> 2584 <li class="sidebar-nav__li-3" data-key='3818795F0E19424F9D4C4B9B55194D3D'><a href="flags/american-mini-stick.asp" class="sidebar-nav__a-3">Miniature American Stick Flags</a></li> 2585 <li class="sidebar-nav__li-3" data-key='21AF6419A9D349A6B3B73477E53F56EC'><a href="flags/american-car-flags.asp" class="sidebar-nav__a-3">American Car Flags</a></li> 2586 <li class="sidebar-nav__li-3" data-key='267C4CF93A6D4E2C83748BC896621A09'><a href="flags/outdoor-american-flag-kits.asp" class="sidebar-nav__a-3">Outdoor American Flag Kits</a></li> 2587 <li class="sidebar-nav__li-3" data-key='6E8C1307681F4F32998FBEE1682EDC28'><a href="flags/indoor-american-flag-kits.asp" class="sidebar-nav__a-3">Indoor American Flag Kits</a></li> 2588 <li class="sidebar-nav__li-3" data-key='49EF5B8F68B64D32AFB43176080895E7'><a href="products/american-star-flags.asp" class="sidebar-nav__a-3">Historical American Star Flags</a></li> 2589 <li class="sidebar-nav__li-3" data-key='5C69ED8DF3A5462E94900ABFF1BE5778'><a href="flags/desk-american-flag-sets.asp" class="sidebar-nav__a-3">American Flag Desk Sets</a></li> 2590 <li class="sidebar-nav__li-3" data-key='39A2341ABC6D4333B01DD685A841D1FE'><a href="products/us-flags-school.asp" class="sidebar-nav__a-3">Classroom American Flag Kits</a></li> 2591 </ul></li> 2592 <li class="sidebar-nav__li-2" data-key='BFF38958CE0844CE84FF80480E9CA34A'><a href="flags/military-flags.asp" class="sidebar-nav__a-2">Military and Civilian Service</a> 2593 <ul class="sidebar-nav__ul-3"> 2594 <li class="sidebar-nav__li-3" data-key='F858301C57E04146A70067BC5B016C3B'><a href="flags/navy-flags.asp" class="sidebar-nav__a-3">Navy Flags & Banners</a></li> 2595 <li class="sidebar-nav__li-3" data-key='D8CFBD8ACB91417D9803C6530A221F79'><a href="flags/army-flags.asp" class="sidebar-nav__a-3">Army Flags & Banners</a></li> 2596 <li class="sidebar-nav__li-3" data-key='252AE0CD08CB419E930069BFBCAF27C6'><a href="flags/air-force-flags.asp" class="sidebar-nav__a-3">Air Force Flags & Banners</a></li> 2597 <li class="sidebar-nav__li-3" data-key='0DE4BC8D6D2E4097AF0DE80AC30DF439'><a href="flags/marine-corps-flags.asp" class="sidebar-nav__a-3">Marine Corps Flags & Banners</a></li> 2598 <li class="sidebar-nav__li-3" data-key='5FF31588F5A7491EA412C1239345EAEF'><a href="flags/coast-guard-flags.asp" class="sidebar-nav__a-3">Coast Guard Flags & Banners</a></li> 2599 <li class="sidebar-nav__li-3" data-key='BC0213A293614774BC3614D7D383960C'><a href="flags/space-command.asp" class="sidebar-nav__a-3">Space Force Flags & Banners</a></li> 2600 <li class="sidebar-nav__li-3" data-key='5B7518B225C64093B53DC14993C8D3D1'><a href="flags/flags-military-service-outdoor.asp" class="sidebar-nav__a-3">Outdoor Military Flags & Banners</a></li> 2601 <li class="sidebar-nav__li-3" data-key='88CE6B6E9E814F69AABA555E6D97798C'><a href="flags/flags-military-service-indoor-parade.asp" class="sidebar-nav__a-3">Indoor Military Flags & Banners</a></li> 2602 <li class="sidebar-nav__li-3" data-key='6897C32E4E984EB1AB98595359674835'><a href="flags/general-admiral-star-flags-kits.asp" class="sidebar-nav__a-3">General & Admiral Star Flags & Kits</a></li> 2603 <li class="sidebar-nav__li-3" data-key='52026AEDF2E74AC2AFB69D0DDB017DEE'><a href="flags/retired-military-flags.asp" class="sidebar-nav__a-3">Retired Military Flags & Kits</a></li> 2604 <li class="sidebar-nav__li-3" data-key='F1CA046214EA4933B97E7C4F5FD6A510'><a href="flags/flags-military-service-miniature.asp" class="sidebar-nav__a-3">Miniature Military & Service Flags</a></li> 2605 <li class="sidebar-nav__li-3" data-key='BB2C8D77F07F40C3A9A80EDA1273A3D8'><a href="pennants/military_pennants.asp" class="sidebar-nav__a-3">Military & Service Pennants</a></li> 2606 <li class="sidebar-nav__li-3" data-key='D643379A0578403FBC8BC8737600A265'><a href="flags/service-persons-flags.asp" class="sidebar-nav__a-3">Public Service Flags & Banners</a></li> 2607 <li class="sidebar-nav__li-3" data-key='BEFC88F41D624FA39C78A80E41CDF292'><a href="holidays/pow_mia_flags_and_banners.asp" class="sidebar-nav__a-3">POW-MIA & KIA Flags</a></li> 2608 <li class="sidebar-nav__li-3" data-key='2FF785CFDA4644EB86943C14E98EB08A'><a href="flags/thin-line-flags.asp" class="sidebar-nav__a-3">
2608Thin Line Flags</a></li> 2609 <li class="sidebar-nav__li-3" data-key='1E06FFF501DC4778B003BDCBED137FF5'><a href="flags/special-military-government-flags.asp" class="sidebar-nav__a-3">Specialty Military & Government Flags</a></li> 2610 <li class="sidebar-nav__li-3" data-key='8C62562CD77D4DC3B474A37C24A03245'><a href="holidays/support_our_troops.asp" class="sidebar-nav__a-3">Support Our Troops Flags</a></li> 2611 <li class="sidebar-nav__li-3" data-key='ECDCF68CF5FD41CC92CB28A58AB47560'><a href="flags/service-star-flags-banners.asp" class="sidebar-nav__a-3">Service Star Flags & Banners</a></li> 2612 </ul></li> 2613 <li class="sidebar-nav__li-2" data-key='A5BEFB42E2F6493BBF75EEE232152621'><a href="flags/historical-flags.asp" class="sidebar-nav__a-2">Historical</a> 2614 <ul class="sidebar-nav__ul-3"> 2615 <li class="sidebar-nav__li-3" data-key='E6F16EDDD9E64982851AE21EECD4BDF2'><a href="products/betsy-ross.asp" class="sidebar-nav__a-3">Betsy Ross Flags</a></li> 2616 <li class="sidebar-nav__li-3" data-key='9635CF4ED8204B4080949859525FE9BB'><a href="products/american-star-flags.asp" class="sidebar-nav__a-3">Historical American Star Flags</a></li> 2617 <li class="sidebar-nav__li-3" data-key='8B63D6F473BA4DD68FFB89822F8EA081'><a href="holidays/dont_tread_on_me_flags_and_gifts.asp" class="sidebar-nav__a-3">Gadsden Flags</a></li> 2618 <li class="sidebar-nav__li-3" data-key='241DBA6274B0470FA6F55770DDC7DDE9'><a href="products/revolutionary-war.asp" class="sidebar-nav__a-3">American Revolutionary War Flags</a></li> 2619 <li class="sidebar-nav__li-3" data-key='B02C504C97974B3D85BEA03A987CE75A'><a href="products/historical-pirate-flags.asp" class="sidebar-nav__a-3">Historical Pirate Flags</a></li> 2620 <li class="sidebar-nav__li-3" data-key='A6209722F9454C0E850C164341C9197C'><a href="flags/flags-historical-miniature.asp" class="sidebar-nav__a-3">Miniature Historical Flags</a></li> 2621 </ul></li> 2622 <li class="sidebar-nav__li-2" data-key='FFCBA6D17B314FA29523142FAD845ED0'><a href="flags/nautical-flags.asp" class="sidebar-nav__a-2">Nautical</a> 2623 <ul class="sidebar-nav__ul-3"> 2624 <li class="sidebar-nav__li-3" data-key='2B95E4D18FEF4922B9CE50A6F02B0B1A'><a href="nautical/international-code-signal-flags-pennants.asp" class="sidebar-nav__a-3">International Code Signal Flags & Pennants</a></li> 2625 <li class="sidebar-nav__li-3" data-key='905AEDF60A0F498D820E4AEB34E8B511'><a href="flags/beach-warning-flags.asp" class="sidebar-nav__a-3">Beach Warning Flags</a></li> 2626 <li class="sidebar-nav__li-3" data-key='67E047FAECA74595801DAA5C1F4F8C34'><a href="flags/flags-nautical-outdoor.asp" class="sidebar-nav__a-3">Boating and Nautical Fun Flags</a></li> 2627 <li class="sidebar-nav__li-3" data-key='46663D9E428646F19ABB964EB4BE29BB'><a href="flags/flags-nautical-miniature.asp" class="sidebar-nav__a-3">Miniature Nautical Flags</a></li> 2628 <li class="sidebar-nav__li-3" data-key='111F7EA29B704013B9C5DD571C5200AC'><a href="pennants/nautical_pennants.asp" class="sidebar-nav__a-3">Nautical Pennants</a></li> 2629 </ul></li> 2630 <li class="sidebar-nav__li-2" data-key='644153A578EA4A61AAE9B0E87CCDEEE0'><a href="flags/world-flags.asp" class="sidebar-nav__a-2">World</a> 2631 <ul class="sidebar-nav__ul-3"> 2632 <li class="sidebar-nav__li-3" data-key='7C420DAB366741B28413AFB8A52EAB5B'><a href="flags/world-flags.asp" class="sidebar-nav__a-3">A through Z</a></li> 2633 <li class="sidebar-nav__li-3" data-key='5FB006D9DD224C8CBFCA20068673D33D'><a href="flags/mexico-world-flags.asp" class="sidebar-nav__a-3">Mexican Flags</a></li> 2634 <li class="sidebar-nav__li-3" data-key='AAA43971FDD34B919F62DD218CFCADAD'><a href="flags/france-world-flags.asp" class="sidebar-nav__a-3">French Flags</a></li> 2635 <li class="sidebar-nav__li-3" data-key='EE74745866CB4F638CD57FB261005A13'><a href="flags/italy-world-flags.asp" class="sidebar-nav__a-3">Italian Flags</a></li> 2636 <li class="sidebar-nav__li-3" data-key='DCF7206B97294F66ADACAD7816E50ADB'><a href="flags/germany-world-flags.asp" class="sidebar-nav__a-3">German Flags</a></li> 2637 <li class="sidebar-nav__li-3" data-key='82E4840E4CBC462CB39BC3D6F1123525'>
2637<a href="flags/canada-world-flags.asp" class="sidebar-nav__a-3">Canadian Flags</a></li> 2638 <li class="sidebar-nav__li-3" data-key='0818F6FD8C32434AAF788D659A8C01AC'><a href="flags/provincial-flags.asp" class="sidebar-nav__a-3">British Territory & Canadian Province Flags</a></li> 2639 <li class="sidebar-nav__li-3" data-key='1C4276E0FF0445CCBEE376E5E83D2186'><a href="holidays/united_nations_day.asp" class="sidebar-nav__a-3">United Nations Flags</a></li> 2640 <li class="sidebar-nav__li-3" data-key='4B399B8A320940C08D6CB6346D177A0E'><a href="flags/flags-world-indoor-parade.asp" class="sidebar-nav__a-3">Indoor World Flags & Kits</a></li> 2641 <li class="sidebar-nav__li-3" data-key='93A3C64A91E04B55BA40C73EC1349D9C'><a href="flags/flags-world-miniature.asp" class="sidebar-nav__a-3">Miniature World Flags</a></li> 2642 </ul></li> 2643 <li class="sidebar-nav__li-2" data-key='064284EE5D6248E8ACC603660767FCB5'><a href="flags/state-territory-flags.asp" class="sidebar-nav__a-2">State and Territory</a> 2644 <ul class="sidebar-nav__ul-3"> 2645 <li class="sidebar-nav__li-3" data-key='187571E89E7F4E35AAC04D056BA57B8C'><a href="flags/state-territory-flags.asp" class="sidebar-nav__a-3">A through W</a></li> 2646 <li class="sidebar-nav__li-3" data-key='13D63BE2C3124CA1A9BE976F8E76C882'><a href="flags/ar-state-flags.asp" class="sidebar-nav__a-3">Arkansas Flag</a></li> 2647 <li class="sidebar-nav__li-3" data-key='D646621EF15545C99325EB17CF741A53'><a href="flags/tx-state-flags.asp" class="sidebar-nav__a-3">Texas Flag</a></li> 2648 <li class="sidebar-nav__li-3" data-key='F49403D7D71F4E5C86B7BD76DAA0D455'><a href="flags/hi-state-flags.asp" class="sidebar-nav__a-3">Hawaii Flag</a></li> 2649 <li class="sidebar-nav__li-3" data-key='3EA0E6F063C54B5B907FE12AB661CC3C'><a href="flags/ca-state-flags.asp" class="sidebar-nav__a-3">California Flag</a></li> 2650 <li class="sidebar-nav__li-3" data-key='984F14FEDD4E4666B8E59B06C7D5A68A'><a href="flags/50-state-complete-flag-kits.asp" class="sidebar-nav__a-3">50 State Complete Flag Sets</a></li> 2651 <li class="sidebar-nav__li-3" data-key='1E893F5F86EB4914BC581131F7D650C8'><a href="flags/flags-state-territory-indoor-parade.asp" class="sidebar-nav__a-3">Indoor State & Territory Flags & Kits</a></li> 2652 <li class="sidebar-nav__li-3" data-key='46FC59C2C86944729458D20C8542B282'><a href="flags/native-american-flags.asp" class="sidebar-nav__a-3">Native American Flags</a></li> 2653 <li class="sidebar-nav__li-3" data-key='3685B91DE55F404D9BA7AA170FC0003F'><a href="banners/state-territory-banners.asp" class="sidebar-nav__a-3">State & Territory Banners</a></li> 2654 <li class="sidebar-nav__li-3" data-key='F7B8C405EF244B4BB458A3B130A99077'><a href="flags/flags-state-territory-miniature.asp" class="sidebar-nav__a-3">Miniature State & Territory Banners</a></li> 2655 <li class="sidebar-nav__li-3" data-key='3DE8BA9A7CD34C9C86BCD839C8125B84'><a href="flags/us-state-flagpole.asp" class="sidebar-nav__a-3">State & Territory Tangle Free Spinning Flagpole Kits</a></li> 2656 <li class="sidebar-nav__li-3" data-key='5B7296A00F914D6E9591797BCB572F0B'><a href="flags/city-district-flags.asp" class="sidebar-nav__a-3">City and District Flags</a></li> 2657 </ul></li> 2658 <li class="sidebar-nav__li-2" data-key='7E396EC1F2E143F7B5AA7F359A610EBA'><a href="flags/sports-flags.asp" class="sidebar-nav__a-2">Sports</a> 2659 <ul class="sidebar-nav__ul-3"> 2660 <li class="sidebar-nav__li-3" data-key='9D3AB9BA91B64C679658EB464902E154'><a href="flags/college-flags.asp" class="sidebar-nav__a-3">College & University Flags & Banners</a></li> 2661 <li class="sidebar-nav__li-3" data-key='6198BD9334E043F5B24343DE29DE8ED2'><a href="flags/golf-flags.asp" class="sidebar-nav__a-3">Golf Flags</a></li> 2662 <li class="sidebar-nav__li-3" data-key='E9585E3161064DDD99A2A8E5080E217F'><a href="flags/nascar-flags.asp" class="sidebar-nav__a-3">Racing Flags & Banners</a></li> 2663 </ul></li> 2664 <li class="sidebar-nav__li-2" data-key='5A5703FAA77445B5B5CD4BF96697C251'><a href="flags/organizational-flags.asp" class="sidebar-nav__a-2">Organizations</a> 2665 <ul class="sidebar-nav__ul-3"> 2666 <li class="sidebar-nav__li-3" data-key='339D97C04F814A2294FF586E
266657D887D6'><a href="flags/political.asp" class="sidebar-nav__a-3">Political Flags & Banners</a></li> 2667 <li class="sidebar-nav__li-3" data-key='B7F057E0D1B34F81B61134015F9B0BCE'><a href="flags/religious-flags.asp" class="sidebar-nav__a-3">Religious Flags & Banners</a></li> 2668 <li class="sidebar-nav__li-3" data-key='9BC7140B63834B2C980BD07BE111186F'><a href="products/iso-flags-banners.asp" class="sidebar-nav__a-3">BSI & ISO Flags & Banners</a></li> 2669 <li class="sidebar-nav__li-3" data-key='9198C5C605C94FC1A5C36E7ADD3B6619'><a href="flags/cultural-awareness-flags.asp" class="sidebar-nav__a-3">Cultural Awareness Flags</a></li> 2670 <li class="sidebar-nav__li-3" data-key='D81FA39869C149BEAA76471EAF0A83F9'><a href="flags/flags-organizations-outdoor.asp" class="sidebar-nav__a-3">Outdoor Organizations Flags</a></li> 2671 <li class="sidebar-nav__li-3" data-key='E295F5863EA44EC3B8E36DE9315A5EF0'><a href="flags/organization-indoor-flags-kits.asp" class="sidebar-nav__a-3">Indoor Organizations Flags</a></li> 2672 <li class="sidebar-nav__li-3" data-key='CF3ABB04709646E6A736F851192B7B89'><a href="flags/flags-organizations-miniature.asp" class="sidebar-nav__a-3">Miniature Organizations Flags</a></li> 2673 </ul></li> 2674 <li class="sidebar-nav__li-2" data-key='91D0A60E64AA4DF392A1C09CA4CC432C'><a href="flags/streamers.asp" class="sidebar-nav__a-2">Streamers</a></li> 2675 <li class="sidebar-nav__li-2" data-key='B27622B1AABC4FCC8B9D7390338C85A7'><a href="banners/home-garden-banners.asp" class="sidebar-nav__a-2">Decorative</a> 2676 <ul class="sidebar-nav__ul-3"> 2677 <li class="sidebar-nav__li-3" data-key='7B9C0687C3CE40FB83C85B7FCDA8A9EC'><a href="banners/winter.asp" class="sidebar-nav__a-3">Winter Season Flags & Banners</a></li> 2678 <li class="sidebar-nav__li-3" data-key='046C5851DF2E401BA78CEE4D9C5627CC'><a href="banners/spring.asp" class="sidebar-nav__a-3">Spring Season Flags & Banners</a></li> 2679 <li class="sidebar-nav__li-3" data-key='0134673C1AB04BB3B5F9E41D6CA85B1A'><a href="banners/summer.asp" class="sidebar-nav__a-3">Summer Season Flags & Banners</a></li> 2680 <li class="sidebar-nav__li-3" data-key='01FE451FE2D24E5B92E4FFF411B5BE0C'><a href="banners/fall-harvest.asp" class="sidebar-nav__a-3">Fall Season Flags & Banners</a></li> 2681 <li class="sidebar-nav__li-3" data-key='1FEFC4A931284D5EA1CDB6D358EC1F35'><a href="banners/celebrations-life-events.asp" class="sidebar-nav__a-3">Celebrations & Event Flags & Banners</a></li> 2682 <li class="sidebar-nav__li-3" data-key='52FA59D71627491F8BB0E0847893FB06'><a href="flags/holiday-flags-banners.asp" class="sidebar-nav__a-3">Holiday Flags & Banners</a></li> 2683 <li class="sidebar-nav__li-3" data-key='C264B59DBDA34A00B3F5D398F90C0235'><a href="banners/door-hangers.asp" class="sidebar-nav__a-3">Door Hanger Banners</a></li> 2684 <li class="sidebar-nav__li-3" data-key='D34D39627A344E96AC8EB273FD4AA621'><a href="flags/fun-novelty-flags.asp" class="sidebar-nav__a-3">Fun & Novelty Flags</a></li> 2685 <li class="sidebar-nav__li-3" data-key='54C4C19605214F919393F8619DF57466'><a href="banners/patriotic-americana-political.asp" class="sidebar-nav__a-3">Patriotic Flags & Banners</a></li> 2686 <li class="sidebar-nav__li-3" data-key='7AEF820BFB2F431C8C2A1BAA467A770A'><a href="flags/military-home-garden.asp" class="sidebar-nav__a-3">Military & Service Banners</a></li> 2687 <li class="sidebar-nav__li-3" data-key='638BF301A272466DA8A04F4577CBA536'><a href="banners/religious-cemetery-peace.asp" class="sidebar-nav__a-3">Religious Flags & Banners</a></li> 2688 <li class="sidebar-nav__li-3" data-key='5ED18887EC234D22AD61E13AB08A47B4'><a href="products/historical-pirate-flags.asp" class="sidebar-nav__a-3">Pirate Flags</a></li> 2689 <li class="sidebar-nav__li-3" data-key='691DB017601C43739F87420D0E6B79F7'><a href="banners/pets-animals.asp" class="sidebar-nav__a-3">Pet & Animal Flags & Banners</a></li> 2690 <li class="sidebar-nav__li-3" data-key='C78015E9EAD94E968CF7950DFAAE309C'><a href="flags/flags-windsocks.asp" class="sidebar-nav__a-3">Windsocks & Wind Spinners</a></li> 2691 <li class="sidebar-nav__li-3" data-key='BC3735DCFB4C471995082EF3FA21BA0F'><a href="holidays/back_to_school_ideas_for_teachers_and_parents.asp" class="sidebar-nav__a-3">Back to School Flags & Banners</a></li> 2692 </ul></li> 2693 <li class="sidebar-nav__li-2" data-key='7BE4B991A23A49CBB20525C870A9C300'><a href="flags/commercial.asp" class="sidebar-nav__a-2">Commercial</a> 2694 <ul class="sidebar-nav__ul-3"> 2695 <li class="sidebar-nav__li-3" data-key='9CE6BA01AEEB452EB089088BBBAD03AB'><a href="flags/safety-flags.asp" class="sidebar-nav__a-3">Safety Flags & Banners</a></li> 2696 <li class="sidebar-nav__li-3" data-key='5FF6FE60B8C642D7A95722545D672173'><a href="flags/drape-flags.asp" class="sidebar-nav__a-3">Drape Flags</a></li> 2697 <li class="sidebar-nav__li-3" data-key='249BF421295F47C7BCD3F82B6DE060E9'><a href="flags/feather-flag.asp" class="sidebar-nav__a-3">Feather Flags</a></li> 2698 <li class="sidebar-nav__li-3" data-key='16CAF67FEB54497B836A23B2EED23CA1'><a href="banners/banners-advertising-message.asp" class="sidebar-nav__a-3">Message Advertising Banners</a></li> 2699 <li class="sidebar-nav__li-3" data-key='37BA79E8F01843A29FFBF6E35A7BDF9F'><a href="flags/flags-advertising-message.asp" class="sidebar-nav__a-3">Message Advertising Flags</a></li> 2700 <li class="sidebar-nav__li-3" data-key='6B6AF0928E664827B6B74E205106EA4E'><a href="banners/banners-advertising-automotive.asp" class="sidebar-nav__a-3">Automotive Advertising Banners</a></li> 2701 <li class="sidebar-nav__li-3" data-key='930CC609A7CE408FA41E0ECD0DEF9B6E'><a href="flags/flags-advertising-automotive.asp" class="sidebar-nav__a-3">Automotive Advertising Flags</a></li> 2702 <li class="sidebar-nav__li-3" data-key='F34430874AEF448E8E7FBF800DE2EE1C'><a href="banners/banners-advertising-spanish.asp" class="sidebar-nav__a-3">Spanish Advertising Banners</a></li> 2703 <li class="sidebar-nav__li-3" data-key='FCCBDB6C31FC4B65B5E5B126ED3CCB9B'><a href="flags/flags-advertising-spanish.asp" class="sidebar-nav__a-3">Spanish Advertising Flags</a></li> 2704 <li class="sidebar-nav__li-3" data-key='4217FA1075C543038048941B1C8C598C'><a href="signs/advertising-signs.asp" class="sidebar-nav__a-3">Advertising Signs</a></li> 2705 </ul></li> 2706 <li class="sidebar-nav__li-2" data-key='016BB708F87D4C069707E5EA2FAA9301'><a href="/flags/flags-advertising-color-flags-outdoor.asp" class="sidebar-nav__a-2">Solid Color and Striped Color</a> 2707 <ul class="sidebar-nav__ul-3"> 2708 <li class="sidebar-nav__li-3" data-key='3C44863F85864316BF1D9D9BE494C666'><a href="flags/drape-flags.asp" class="sidebar-nav__a-3">Drape Flags</a></li> 2709 <li class="sidebar-nav__li-3" data-key='A7D0042D517140BB835957B7A67C65C8'><a href="flags/feather-flag.asp" class="sidebar-nav__a-3">Feather Flags</a></li> 2710 <li class="sidebar-nav__li-3" data-key='9B9CF188C9B94AA88246147DB741F2A5'><a href="pennants/air-quality-flags.asp" class="sidebar-nav__a-3">Air Quality Flags</a></li> 2711 <li class="sidebar-nav__li-3" data-key='9720D42D3AFE4E4596B8D870B1302F51'><a href="flags/beach-warning-flags.asp" class="sidebar-nav__a-3">Beach Warning Flags</a></li> 2712 <li class="sidebar-nav__li-3" data-key='5907EC6899B24B329711681
2712B37D36EE2'><a href="pennants/colorful_single_pennants.asp" class="sidebar-nav__a-3">Colorful Single Pennant Flags</a></li> 2713 <li class="sidebar-nav__li-3" data-key='409341414ADE49389AED474A1254EA28'><a href="flags/red-color-flags.asp" class="sidebar-nav__a-3">Red Flags</a></li> 2714 <li class="sidebar-nav__li-3" data-key='1F7DE164971B4545927927CB84AF0465'><a href="flags/orange-color-flags.asp" class="sidebar-nav__a-3">Orange Flags</a></li> 2715 <li class="sidebar-nav__li-3" data-key='FB636BE8A8E84587A2DF876CFBA5B422'><a href="flags/yellow-gold-color-flags.asp" class="sidebar-nav__a-3">Yellow & Gold Flags</a></li> 2716 <li class="sidebar-nav__li-3" data-key='D82A23CFC0BE4ADEB2897DF1BD5E0738'><a href="flags/green-color-flags.asp" class="sidebar-nav__a-3">Green Flags</a></li> 2717 <li class="sidebar-nav__li-3" data-key='F50002EA648149A9B06E2E03AA869AB2'><a href="flags/blue-color-flags.asp" class="sidebar-nav__a-3">Blue Flags</a></li> 2718 <li class="sidebar-nav__li-3" data-key='A34FAAF8DD6348F6A955CFC864E319FE'><a href="flags/purple-pink-color-flags.asp" class="sidebar-nav__a-3">Purple & Pink Flags</a></li> 2719 <li class="sidebar-nav__li-3" data-key='6C4E32818616403D99B3013756CFAC7B'><a href="flags/black-white-gray-color-flags.asp" class="sidebar-nav__a-3">Black, White, & Gray Flags</a></li> 2720 <li class="sidebar-nav__li-3" data-key='7F5FB61089424E83BF0D50ADD5B30291'><a href="flags/brown-cream-color-flags.asp" class="sidebar-nav__a-3">Brown & Cream Flags</a></li> 2721 </ul></li> 2722 <li class="sidebar-nav__li-2" data-key='8CCFCE36B57842FAB11C06053D3D97B8'><a href="banners/street-pole-banners.asp" class="sidebar-nav__a-2">Street Pole</a> 2723 <ul class="sidebar-nav__ul-3"> 2724 <li class="sidebar-nav__li-3" data-key='09BC2F10CD1C4929AA8A58462916A23E'><a href="banners/advertising-street-pole-banners.asp" class="sidebar-nav__a-3">Advertising Street Pole Banners</a></li> 2725 <li class="sidebar-nav__li-3" data-key='179897B7FDFD44AD9734CA9341F34B12'><a href="banners/american-patriotic-street-pole-banners.asp" class="sidebar-nav__a-3">American Patriotic Street Pole Banners</a></li> 2726 <li class="sidebar-nav__li-3" data-key='A9C01E7A156D429FA7831E52BC81936C'><a href="banners/municipal-beautification-street-pole-banners.asp" class="sidebar-nav__a-3">Municipal Beautification Street Pole Banners</a></li> 2727 <li class="sidebar-nav__li-3" data-key='7E4AED1C22B04F588033BB350BA30ED4'><a href="banners/holiday-street-pole-banners.asp" class="sidebar-nav__a-3">Holiday Street Pole Banners</a></li> 2728 <li class="sidebar-nav__li-3" data-key='AA8A3E975B4E4569838BF0A08B326F49'><a href="banners/winter-street-pole-banners.asp" class="sidebar-nav__a-3">Winter Season Street Pole Banners</a></li> 2729 <li class="sidebar-nav__li-3" data-key='DAACF5C66E7447E78C18EE989C763AFA'><a href="banners/spring-street-pole-banners.asp" class="sidebar-nav__a-3">Spring Season Street Pole Banners</a></li> 2730 <li class="sidebar-nav__li-3" data-key='C289E3A92BBC450D8AA0979819A6163C'><a href="banners/summer-street-pole-banners.asp" class="sidebar-nav__a-3">Summer Season Street Pole Banners</a></li> 2731 <li class="sidebar-nav__li-3" data-key='E68F86A9B2054B3CB45F2E7663AE7EFB'><a href="banners/fall-street-pole-banners.asp" class="sidebar-nav__a-3">Fall Season Street Pole Banners</a></li> 2732 </ul></li> 2733 <li class="sidebar-nav__li-2" data-key='83E70A52825641C7B1E0D3A092EA160D'><a href="flags/car-flags.asp" class="sidebar-nav__a-2">Car Flags</a></li> 2734 </ul></li> 2735 <li class="custom sidebar-nav__li-1" data-key='8EBF9820CA75403E90ECA34376279AF3'><a href="custom_showroom/custom_flags_banners.asp" class="sidebar-nav__a-1">Custom</a> 2736 <ul class="sidebar-nav__ul-2"> 2737 <li class="sidebar-nav__li-2" data-key='73CB7AAB8A7D40EE83CC3321FC401AF0'><a href="products/custom-printed-single-reverse-flag.asp" class="sidebar-nav__a-2">Order Custom Flag Online</a></li> 2738 <li class="sidebar-nav__li-2" data-key='0C60612C75D8473A926B1E1C97C99827'><a href="customer_service/Custom-Order-Request.asp" class="sidebar-nav__a-2">Get a FREE Quote</a></li> 2739 <li class="sidebar-nav__li-2" data-key='FDB8D7C0EFF144C0B1C02D80772C6C7C'><a href="custom_showroom/Custom-Flag-Pricing.asp" class="sidebar-nav__a-2">Flags</a> 2740 <ul class="sidebar-nav__ul-3"> 2741 <li class="sidebar-nav__li-3" data-key='F61FBEBCCFE4460EB99E4C0F4D6652FB'><a href="custom_showroom/digital-flags.asp" class="sidebar-nav__a-3">Digitally Printed Flags</a></li> 2742 <li class="sidebar-nav__li-3" data-key='9C47A93FF3E440C48AC3D24B30586049'><a href="custom_showroom/embroidered-flags.asp" class="sidebar-nav__a-3">Embroidered Flags</a></li> 2743 <li class="sidebar-nav__li-3" data-key='8EBADA08E07342CBA511E7E45B8F73CE'><a href="custom_showroom/applique-flags.asp" class="sidebar-nav__a-3">Appliqued Flags</a></li> 2744 <li class="sidebar-nav__li-3" data-key='FBA8C8BACEC145D9B6ABFB66985F1DBE'><a href="custom_showroom/digital-flags.asp" class="sidebar-nav__a-3">Standard Shaped Flags</a></li> 2745 <li class="sidebar-nav__li-3" data-key='54DDD50B1BEF416AB960AA9266CE0FA0'><a href="custom_showroom/burgee-flags.asp" class="sidebar-nav__a-3">Burgee Shaped Flags</a></li> 2746 <li class="sidebar-nav__li-3" data-key='3062C3EF9F0249DD8549E3F28764A90F'><a href="custom_showroom/pennant-flags.asp" class="sidebar-nav__a-3">Pennant Shaped Flags</a></li> 2747 <li class="sidebar-nav__li-3" data-key='75403FFB354F465F91C77D8C0F204EF8'><a href="custom_showroom/team-spirit-flags.asp" class="sidebar-nav__a-3">Team Spirit Flags</a></li> 2748 <li class="sidebar-nav__li-3" data-key='070E021C10E14CBFA0BF104953B1E629'><a href="custom_showroom/miniature-flags.asp" class="sidebar-nav__a-3">Miniature Flags</a></li> 2749 <li class="sidebar-nav__li-3" data-key='C2D87D08D7CC47B59E0B39AC2E34FB84'><a href="custom_showroom/feather-flag.asp" class="sidebar-nav__a-3">Feather Flags</a></li> 2750 <li class="sidebar-nav__li-3" data-key='F0A5EC9D52C2475BB4929858699FB6D7'><a href="custom_showroom/teardrop-flag.asp" class="sidebar-nav__a-3">Teardrop Flags</a></li> 2751 <li class="sidebar-nav__li-3" data-key='D4D479AF195B49E2916F8E26FE6613CE'><a href="custom_showroom/blade-flag.asp" class="sidebar-nav__a-3">Blade Flags</a></li> 2752 <li class="sidebar-nav__li-3" data-key='D7B92460F2A54198A179361362CF9D68'><a href="custom_showroom/car-flags.asp" class="sidebar-nav__a-3">Car Flags</a></li> 2753 </ul></li> 2754 <li class="sidebar-nav__li-2" data-key='2635B40A9F7B483E92243DDD3BDE4779'><a href="custom_showroom/Custom-Banners.asp" class="sidebar-nav__a-2">Banners</a> 2755 <ul class="sidebar-nav__ul-3"> 2756 <li class="sidebar-nav__li-3" data-key='2C07C83767514C96B9E2EAA2EAAACB69'><a href="custom_showroom/simple-applique-banners.asp" class="sidebar-nav__a-3">Simple Applique Banners</a></li> 2757 <li class="sidebar-nav__li-3" data-key='2765FAE6A70942B09C0A1C7720F6C08C'><a href="custom_showroom/commercial-grade-vinyl-banners.asp" class="sidebar-nav__a-3">Custom Commercial Grade Vinyl Banners</a></li> 2758 <li class="sidebar-nav__li-3" data-key='72A7DAD4542545FABBFDEEFE9E347B50'><a href="custom_showroom/mesh-vinyl-banners.asp" class="sidebar-nav__a-3">Mesh Banners</a></li> 2759 <li class="sidebar-nav__li-3" data-key='94A0B11D33744FB4887611EFAD4C600B'><a href="custom_showroom/window-scrim-banners.asp" class="sidebar-nav__a-3">Self-Adhesive Window Scrim Banners</a></li> 2760 <li class="sidebar-nav__li-3" data-key='8DD93483B5AA4E338B5B82302A8D9708'><a href="custom_showroom/fast-and-affordable.asp" class="sidebar-nav__a-3">Fast & Affordable Banners</a></li> 2761 <li class="sidebar-nav__li-3" data-key='256B5403B3EF4B0FAFA6E6A27B5180C4'><a href="custom_showroom/gonfalons.asp" class="sidebar-nav__a-3">Gonfalons</a></li> 2762 <li class="sidebar-nav__li-3" data-key='0EA3E44AE4AB4A82BC77B5E0EDE1D488'><a href="products/retractable-banner-stand.asp" class="sidebar-nav__a-3">Retractable Banners</a></li> 2763 <li class="sidebar-nav__li-3" data-key='0C99106935264D30B905AE8896E52092'><a href="custom_showroom/parade-banners.asp" class="sidebar-nav__a-3">Parade Banners</a></li> 2764 <li class="sidebar-nav__li-3" data-key='387E0625957B40CCBC875B02532DC71D'><a href="products/pillowcase-banner-stand.asp" class="sidebar-nav__a-3">Pillowcase Banners</a></li> 2765 <li class="sidebar-nav__li-3" data-key='01BABD590B884D0B8BC582AEB16E9D13'><a href="products/pillowcase-banner-wall.asp" class="sidebar-nav__a-3">Pillowcase Banner Walls</a></li> 2766 <li class="sidebar-nav__li-3" data-key='F9CEB7C5C316432492CE0F8EB87287B8'><a href="products/pop-up-banner-wall.asp" class="sidebar-nav__a-3">Pop Up Banner Walls</a></li> 2767 <li class="sidebar-nav__li-3" data-key='F3F5BF9470DC42D5967673166DA6627D'><a href="products/aframe-display-kit.asp" class="sidebar-nav__a-3">A-Frame Banners</a></li> 2768 <li class="sidebar-nav__li-3" data-key='C761D713555A4E8C95B82C8E8C4614E1'><a href="custom_showroom/barricade-banners.asp" class="sidebar-nav__a-3">Barricade Banners</a></li> 2769 </ul></li> 2770 <li class="sidebar-nav__li-2" data-key='43FE9D79E7C6495A98735C8CF04A411D'><a href="custom_showroom/guidons.asp" class="sidebar-nav__a-2">Guidons</a> 2771 <ul class="sidebar-nav__ul-3"> 2772 <li class="sidebar-nav__li-3" data-key='24AD86FBE3444E4D8590BFDB738A847D'><a href="custom_showroom/guidons.asp#appliq" class="sidebar-nav__a-3">Appliqued Regulation Guidons</a></li> 2773 <li class="sidebar-nav__li-3" data-key='5E52C0B8F1DA4DC6A19308BFCE505FAB'><a href="custom_showroom/guidons.asp#print" class="sidebar-nav__a-3">Printed Guidons</a></li> 2774 <li class="sidebar-nav__li-3" data-key='F87E4C8DD5C34F1FAC0610E5F8860457'><a href="custom_showroom/guidons.asp#streamer" class="sidebar-nav__a-3">Embroidered Service Streamers</a></li> 2775 </ul></li> 2776 <li class="sidebar-nav__li-2" data-key='4F2263B8212E4F1593296B8E1471E139'><a href="custom_showroom/custom-pennants.asp" class="sidebar-nav__a-2">Pennants</a> 2777 <ul class="sidebar-nav__ul-3"> 2778 <li class="sidebar-nav__li-3" data-key='45C34850E279445DA8D5870DF93B8726'><a href="https://www.flagandbanner.com/custom_showroom/custom-pennants.asp#digitalshort" class="sidebar-nav__a-3">Digital Print String Pennants</a></li> 2779 <li class="sidebar-nav__li-3" data-key='4FD0F96FA4B74492BC30DCAF1D9CA274'><a href="custom_showroom/custom-pennants.asp#prempenn" class="sidebar-nav__a-3">Premium Felt Single Pennants</a></li> 2780 <li class="sidebar-nav__li-3" data-key='2C3B46D3964246B1BDD345CB9339B998'>
2780<a href="custom_showroom/custom-pennants.asp#pennflag" class="sidebar-nav__a-3">Single Pennant Flags</a></li> 2781 </ul></li> 2782 <li class="sidebar-nav__li-2" data-key='4268CF35E7664BC78A1FE7C34A0C5AC0'><a href="custom_showroom/Custom-Street-Poles.asp" class="sidebar-nav__a-2">Street Pole Banners</a> 2783 <ul class="sidebar-nav__ul-3"> 2784 <li class="sidebar-nav__li-3" data-key='FE926C02513849D0BA66D5222CD1B910'><a href="custom_showroom/Custom-Street-Poles.asp#custstreet" class="sidebar-nav__a-3">Custom Street Pole Banners</a></li> 2785 <li class="sidebar-nav__li-3" data-key='BC159139231643758456DC115CE9D6D9'><a href="custom_showroom/Custom-Street-Poles.asp#sunstreet" class="sidebar-nav__a-3">Sunbrella Street Pole Banners</a></li> 2786 <li class="sidebar-nav__li-3" data-key='090870D32F1F48B28702C8318B45B4FB'><a href="custom_showroom/Custom-Street-Poles.asp#copoly" class="sidebar-nav__a-3">Combined Poly Street Pole Banners</a></li> 2787 <li class="sidebar-nav__li-3" data-key='B1552FE0648B4B40A66E2C83A0297CBB'><a href="custom_showroom/Custom-Street-Poles.asp#stockstreet" class="sidebar-nav__a-3">Stock Street Pole Banners</a></li> 2788 </ul></li> 2789 <li class="sidebar-nav__li-2" data-key='844E3C3912A0413FB550CC2EBF484605'><a href="custom_showroom/trade-show-display.asp" class="sidebar-nav__a-2">Trade Show Displays</a> 2790 <ul class="sidebar-nav__ul-3"> 2791 <li class="sidebar-nav__li-3" data-key='749DED9C9C544E5D8D6AD485A0593FF4'><a href="products/pop-up-banner-wall.asp" class="sidebar-nav__a-3">Pop Up Banner Walls</a></li> 2792 <li class="sidebar-nav__li-3" data-key='8CE29D84E8BB4D63ABDE518B6C90F5F4'><a href="products/pillowcase-banner-wall.asp" class="sidebar-nav__a-3">Pillowcase Banner Walls</a></li> 2793 <li class="sidebar-nav__li-3" data-key='37EB47EC7CD748DD88452FDAD033C7CF'><a href="products/retractable-banner-stand.asp" class="sidebar-nav__a-3">Retractable Banner Stands</a></li> 2794 <li class="sidebar-nav__li-3" data-key='9D32A043E2FC40A0907E9DA26168363E'><a href="products/pillowcase-banner-stand.asp" class="sidebar-nav__a-3">Pillowcase Banner Stands</a></li> 2795 <li class="sidebar-nav__li-3" data-key='E65985CB737F41DEA7C6FB57347EF17D'><a href="products/x-display-banner-stands.asp" class="sidebar-nav__a-3">Light Weight Banner Stands & Table Top Stands</a></li> 2796 <li class="sidebar-nav__li-3" data-key='24E0EC4345494BD6A1829BE467436268'><a href="products/aframe-display-kit.asp" class="sidebar-nav__a-3">A-Frame Banners</a></li> 2797 </ul></li> 2798 <li class="sidebar-nav__li-2" data-key='7AE149EFB7234CDBBDE85DB77E4F12F5'><a href="custom_showroom/custom-event-tents.asp" class="sidebar-nav__a-2">Event Tents</a></li> 2799 <li class="sidebar-nav__li-2" data-key='ABC50A3BEC734DFEAE08A5E6A2043068'><a href="custom_showroom/custom-logo-mats.asp" class="sidebar-nav__a-2">Logo Mats</a></li> 2800 <li class="sidebar-nav__li-2" data-key='49EE64C31E6543919DE57E558315E029'><a href="custom_showroom/Custom-Table-Throws.asp" class="sidebar-nav__a-2">Table Throws</a> 2801 <ul class="sidebar-nav__ul-3"> 2802 <li class="sidebar-nav__li-3" data-key='835930C5E8BF40F99DEAA48419009B09'><a href="custom_showroom/Custom-Table-Throws.asp#throw" class="sidebar-nav__a-3">Table Throws</a></li> 2803 <li class="sidebar-nav__li-3" data-key='2F474BED2CC14AB88BF97024FFD082AF'><a href="custom_showroom/Custom-Table-Throws.asp#stretch" class="sidebar-nav__a-3">Stretch Table Covers</a></li> 2804 <li class="sidebar-nav__li-3" data-key='1BBEC46DACEA4F3598DF44F92539DB41'><a href="custom_showroom/Custom-Table-Throws.asp#runner" class="sidebar-nav__a-3">Table Runners</a></li> 2805 <li class="sidebar-nav__li-3" data-key='90139892B9614EF0A3FA2AB322CC1F81'><a href="custom_showroom/Custom-Table-Throws.asp#solid" class="sidebar-nav__a-3">Solid Color Table Throws</a></li> 2806 </ul></li> 2807 <li class="sidebar-nav__li-2" data-key='B8A62814E77E4415A4572E7F3AAD4D18'><a href="custom_showroom/custom-ordering-information.asp" class="sidebar-nav__a-2">Custom Info & Gallery</a> 2808 <ul class="sidebar-nav__ul-3"> 2809 <li class="sidebar-nav__li-3" data-key='E10BC40FEFDE4868B483B0300D69F7AF'><a href="customer_service/graphic-art-requirements.asp" class="sidebar-nav__a-3">Graphic Art Requirements</a></li> 2810 <li class="sidebar-nav__li-3" data-key='DCFE7A8756AE4E17AC8E35C561C25E65'><a href="customer_service/installation-services.asp" class="sidebar-nav__a-3">Installation Services</a></li> 2811 <li class="sidebar-nav__li-3" data-key='9BC14731FA05474EA8D4E8996E4082BE'><a href="customer_service/nylon-fabric-color-chart.asp" class="sidebar-nav__a-3">
2811Nylon Fabric Color Chart</a></li> 2812 <li class="sidebar-nav__li-3" data-key='702107464DBC492EA1709DAFEDB4CD93'><a href="customer_service/pantone-color-chart.asp" class="sidebar-nav__a-3">Pantone Color Chart</a></li> 2813 <li class="sidebar-nav__li-3" data-key='52816C415ACA4F07B404E3C270CD727F'><a href="custom_showroom/custom-artwork-template.asp" class="sidebar-nav__a-3">Custom Artwork Templates</a></li> 2814 </ul></li> 2815 </ul></li> 2816 <li class="poles sidebar-nav__li-1" data-key='EAEED4CD090B4EBEA09EA968E9153701'><a href="flag_banner_poles/flag_poles.asp" class="sidebar-nav__a-1">Poles</a> 2817 <ul class="sidebar-nav__ul-2"> 2818 <li class="sidebar-nav__li-2" data-key='10ED41C3367A495782622E5CDF3ABF27'><a href="flag_banner_poles/residential-flag-poles.asp" class="sidebar-nav__a-2">Residential</a> 2819 <ul class="sidebar-nav__ul-3"> 2820 <li class="sidebar-nav__li-3" data-key='C8D01BE09C7048658BFACB5C64D6EEE8'><a href="flag_banner_poles/residential-in-ground.asp" class="sidebar-nav__a-3">Residential In-Ground Flagpoles</a></li> 2821 <li class="sidebar-nav__li-3" data-key='B5A721A17E74436D9C05B515C9B14CF9'><a href="flag_banner_poles/residential-house-mount.asp" class="sidebar-nav__a-3">Residential House Mount Flagpoles</a></li> 2822 <li class="sidebar-nav__li-3" data-key='4431D594BB7748C89903B27B10C97554'><a href="flag_banner_poles/vehicle-boat-flagpoles.asp" class="sidebar-nav__a-3">Vehicle & Boat Flagpoles</a></li> 2823 <li class="sidebar-nav__li-3" data-key='5695772A9D2243FB9E0FB8DF78C1C116'><a href="flag_banner_poles/tailgating-portable.asp" class="sidebar-nav__a-3">RV, Tailgating, & Portable Flagpoles & Accessories</a></li> 2824 </ul></li> 2825 <li class="sidebar-nav__li-2" data-key='2BDFB7525FCF4CCBB6DB953222427FEC'><a href="flag_banner_poles/commercial-flag-poles.asp" class="sidebar-nav__a-2">Commercial</a> 2826 <ul class="sidebar-nav__ul-3"> 2827 <li class="sidebar-nav__li-3" data-key='2114666314924A44B72AC3221438E817'><a href="flag_banner_poles/commercial-in-ground.asp" class="sidebar-nav__a-3">Commercial In-Ground Flagpoles</a></li> 2828 <li class="sidebar-nav__li-3" data-key='179CE33016444C9288A2080767AB3B53'><a href="flag_banner_poles/wall-mount-flagpoles.asp" class="sidebar-nav__a-3">Commercial Wall Mount Flagpoles</a></li> 2829 <li class="sidebar-nav__li-3" data-key='A4890CF74A7E41BC964B62E5CCAB1060'><a href="flag_banner_poles/tilt-down-flagpoles.asp" class="sidebar-nav__a-3">Tilt Down Flagpoles</a></li> 2830 <li class="sidebar-nav__li-3" data-key='F35E507007E647CA929567ED2BBE0189'><a href="flag_banner_poles/nautical-flag-poles.asp" class="sidebar-nav__a-3">Nautical Flagpoles</a></li> 2831 <li class="sidebar-nav__li-3" data-key='F2371308E9C84A25845C81924985CB57'><a href="flag_banner_poles/advertising_poles.asp" class="sidebar-nav__a-3">Advertising Flagpoles</a></li> 2832 </ul></li> 2833 <li class="sidebar-nav__li-2" data-key='3B617C99E3EB448BB900CAAE82BBC611'><a href="flag_banner_poles/ceremonial-flag-poles.asp" class="sidebar-nav__a-2">Ceremonial (Indoor and Parade)</a> 2834 <ul class="sidebar-nav__ul-3"> 2835 <li class="sidebar-nav__li-3" data-key='461D66A1EB3140ECA282AD9A974D60D3'><a href="flag_banner_poles/indoor-flagpoles.asp" class="sidebar-nav__a-3">Indoor Flagpoles & Kits (No Flags)</a></li> 2836 <li class="sidebar-nav__li-3" data-key='4F2C05A6E4CA4C019B8113C09D282856'><a href="flags/indoor-american-flag-kits.asp" class="sidebar-nav__a-3">Indoor American Flag Kits</a></li> 2837 <li class="sidebar-nav__li-3" data-key='20C334905D204524A8443F8F4422FFD3'><a href="flags/flags-state-territory-indoor-parade.asp" class="sidebar-nav__a-3">Indoor State & Territory Flags & Kits</a></li> 2838 <li class="sidebar-nav__li-3" data-key='A13EDA7684CB49FB89465C7C1E6D8246'><a href="flags/flags-world-indoor-parade.asp" class="sidebar-nav__a-3">World Flags & Kits</a></li> 2839 <li class="sidebar-nav__li-3" data-key='9D4124F0C718414BA0F15F24085DB919'><a href="flags/flags-city-district-indoor-parade.asp" class="sidebar-nav__a-3">City & District Flags & Kits</a></li> 2840 <li class="sidebar-nav__li-3" data-key='B6E31E2FB61B488B8A70529FAE4D4677'><a href="flag_banner_poles/gonfalon-ceremonial-banner-pole-kits.asp" class="sidebar-nav__a-3">Gonfalon Ceremonial Banner Pole Kits</a></li> 2841 <li class="sidebar-nav__li-3" data-key='C1FBA81A6705497E973C89AC82844036'><a href="flags/flags-military-service-indoor-parade.asp" class="sidebar-nav__a-3">Military & Service Flags & Kits</a></li> 2842 <li class="sidebar-nav__li-3" data-key='35FD8F41D8424A21B8A81C241E2BCB51'><a href="flags/general-admiral-star-flags-kits.asp" class="sidebar-nav__a-3">General & Admiral Star Flags & Kits</a></li> 2843 <li class="sidebar-nav__li-3" data-key='15A9D53DE9EB496DB4EB2B4DC20E5170'><a href="flags/flags-cultural-awareness-indoor-parade.asp" class="sidebar-nav__a-3">Cultural Awareness Flags & Kits</a></li> 2844 <li class="sidebar-nav__li-3" data-key='2F6669440854497BA45CB63FF35CA723'><a href="flags/flags-religious-indoor-parade.asp" class="sidebar-nav__a-3">Religious Flags & Kits</a></li> 2845 <li class="sidebar-nav__li-3" data-key='8BB59EA719D246F6919FC62452942800'><a href="flags/organization-indoor-flags-kits.asp" class="sidebar-nav__a-3">Organizations Flags & Kits</a></li> 2846 <li class="sidebar-nav__li-3" data-key='DD56C28D16B348DDA732B2A531E58DB7'><a href="flags/flags-provinces-indoor-parade.asp" class="sidebar-nav__a-3">British Territory & Canadian Province Flags & Kits</a></li> 2847 <li class="sidebar-nav__li-3" data-key='4077FEDD752E47DE8D3A07605337AA26'><a href="hardware/crossbars-lead-poles.asp" class="sidebar-nav__a-3">Crossbars & Lead Poles</a></li> 2848 <li class="sidebar-nav__li-3" data-key='115203277A924B48851616ED95E492E2'><a href="flag_banner_poles/miniature-flag-sticks.asp" class="sidebar-nav__a-3">Miniature Poles</a></li> 2849 </ul></li> 2850 <li class="sidebar-nav__li-2" data-key='066B1EF9E47E4CCA9577D58B75854464'><a href="flag_banner_poles/garden-flag-stands.asp" class="sidebar-nav__a-2">Garden Flag Stands</a></li> 2851 <li class="sidebar-nav__li-2" data-key='8F93CF0B2C8F4DAE8653CDD188E366CF'><a href="flag_banner_poles/street-pole-systems.asp" class="sidebar-nav__a-2">Street Pole</a></li> 2852 <li class="sidebar-nav__li-2" data-key='763E1C2CE6EE4EDBB22C305642E00841'><a href="hardware/grave-markers.asp" class="sidebar-nav__a-2">Grave Markers</a></li> 2853 <li class="sidebar-nav__li-2" data-key='B04D3340FF3649F69AFE921BF2F245C7'><a href="flag_banner_poles/telescoping-flagpoles.asp" class="sidebar-nav__a-2">Telescoping</a></li> 2854 <li class="sidebar-nav__li-2" data-key='49A0986C147B4A31B75A6B7840D0F62A'><a href="flag_banner_poles/banner-stands-poles.asp" class="sidebar-nav__a-2">Trade Show Acessories</a></li> 2855 </ul></li> 2856 <li class="bunting sidebar-nav__li-1" data-key='8D302EBB4154471B8B90A0D19643585F'><a href="bunting/bunting.asp" class="sidebar-nav__a-1">Bunting</a> 2857 <ul class="sidebar-nav__ul-2"> 2858 <li class="sidebar-nav__li-2" data-key='B318AF7E82D84AA2960CE5FA255882C4'><a href="bunting/pleated_flag_bunting_fans.asp" class="sidebar-nav__a-2">Patriotic</a> 2859 <ul class="sidebar-nav__ul-3"> 2860 <li class="sidebar-nav__li-3" data-key='BB90CB1CE8CF47C88FA140316538FB2C'><a href="patriotic_gifts/decorating-kits.asp" class="sidebar-nav__a-3">Decorating Kits</a></li> 2861 <li class="sidebar-nav__li-3" data-key='939623AE082042C58812FA3D5079A1CE'><a href="bunting/patriotic-fans-and-flats.asp" class="sidebar-nav__a-3">Patriotic Fans & Flats</a></li> 2862 <li class="sidebar-nav__li-3" data-key='589696B493C74EA88C18F2C92A52CD97'><a href="pennants/american_pennants.asp" class="sidebar-nav__a-3">American String Pennants</a></li> 2863 <li class="sidebar-nav__li-3" data-key='6D95E514CFA9419396D3000746D1F837'><a href="bunting/patriotic-fabrics.asp" class="sidebar-nav__a-3">Patriotic Fabrics</a></li> 2864 </ul></li> 2865 <li class="sidebar-nav__li-2" data-key='A7D4B40FBDEB4F68AFDDD02424408D7C'><a href="bunting/world.asp" class="sidebar-nav__a-2">World</a></li> 2866 <li class="sidebar-nav__li-2" data-key='DE318874C3E94664827D63845A36B094'><a href="bunting/mourning.asp" class="sidebar-nav__a-2">Mourning</a></li> 2867 <li class="sidebar-nav__li-2" data-key='C2C0437853CB47C5AFF2550D708E86E9'><a href="bunting/sports.asp" class="sidebar-nav__a-2">Sports</a></li> 2868 <li class="sidebar-nav__li-2" data-key='BD271FC001A44EBF8AFBDAD2018ACB55'><a href="bunting/solid-color-nylon-fabric.asp" class="sidebar-nav__a-2">Solid Color</a> 2869 <ul class="sidebar-nav__ul-3"> 2870 <li class="sidebar-nav__li-3" data-key='F8FDB3549E4843F38C5BC00DA57D5A28'><a href="bunting/solid-color-fabrics-red.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Reds</a></li> 2871 <li class="sidebar-nav__li-3" data-key='9DD118A165294D74AC4A538F1AF5CC0E'><a href="bunting/solid-color-fabrics-oranges.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Oranges</a></li> 2872 <li class="sidebar-nav__li-3" data-key='41FC30C8EB534D8687924088E988FBE4'><a href="bunting/solid-color-fabrics-yellow-gold.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Yellows & Golds</a></li> 2873 <li class="sidebar-nav__li-3" data-key='46DCF45B61A740B3ACAFFDABA39370C9'><a href="bunting/solid-color-fabrics-greens.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Greens</a></li> 2874 <li class="sidebar-nav__li-3" data-key='2128130163174A84848615E6CA968AC5'><a href="bunting/solid-color-fabrics-blue.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Blues</a></li> 2875 <li class="sidebar-nav__li-3" data-key='9F5B84819AFB4468905CE09B9DDB1074'><a href="bunting/solid-color-fabrics-purple-pink.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Pinks & Purples</a></li> 2876 <li class="sidebar-nav__li-3" data-key='CC9AF23C2E3548619D8EC34A38DE28BD'><a href="bunting/solid-color-fabrics-black-white-gray.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Blacks, Whites & Grays</a></li> 2877 <li class="sidebar-nav__li-3" data-key='6941467AD14243EE8B94AF5849D1345C'><a href="bunting/solid-color-fabrics-brown-cream.asp" class="sidebar-nav__a-3">Solid Color Fabrics with Browns & Creams</a></li> 2878 </ul></li> 2879 </ul></li> 2880 <li class="pennants sidebar-nav__li-1" data-key='7786E1FBE6544E139956434B4C41960D'><a href="pennants/pennants.asp" class="sidebar-nav__a-1">String Pennants</a> 2881 <ul class="sidebar-nav__ul-2"> 2882 <li class="sidebar-nav__li-2" data-key='96F9F1F5877A4E1D99006D745BBBB0E3'><a href="pennants/colorful_string_pennants.asp" class="sidebar-nav__a-2">Colorful</a> 2883 <ul class="sidebar-nav__ul-3"> 2884 <li class="sidebar-nav__li-3" data-key='B2E99D4A3D34425C94446D7B7038C6B8'><a href="pennants/solid-color-string-pennants.asp" class="sidebar-nav__a-3">Solid Color String Pennants</a></li> 2885 <li class="sidebar-nav__li-3" data-key='DF04D47741F443AC911E207EFDB7ACA2'><a href="pennants/rainbow-string-pennants.asp" class="sidebar-nav__a-3">String Pennants in Rainbow Assortments</a></li> 2886 <li class="sidebar-nav__li-3" data-key='F3823456E14A4E5DB7C20C18E5CED8FD'><a href="pennants/plasticloth.asp" class="sidebar-nav__a-3">Heavy Duty Plasticloth String Pennants</a></li> 2887 <li class="sidebar-nav__li-3" data-key='BF3E90854F3F4B848465960F4AD8FDB7'><a href="pennants/metallic-string-pennants.asp" class="sidebar-nav__a-3">Metallic String Pennants</a></li> 2888 <li class="sidebar-nav__li-3" data-key='321D1DD8167F40288DBA19421ED6F0F7'><a href="pennants/red-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Reds</a></li> 2889 <li class="sidebar-nav__li-3" data-key='735187639D0248D486CA6A36C35903DB'><a href="pennants/orange-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Oranges</a></li> 2890 <li class="sidebar-nav__li-3" data-key='3FF7054D5FF545B3A2F9C90B91A34C92'><a href="pennants/yellow-gold-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Yellows & Golds</a></li> 2891 <li class="sidebar-nav__li-3" data-key='3C439B1AD03546418F13A40B95F212C0'><a href="pennants/green-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Greens</a></li> 2892 <li class="sidebar-nav__li-3" data-key='EBC0251F798B4C33A71DB72E3D36E306'><a href="pennants/blue-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Blues & Turquoise</a></li> 2893 <li class="sidebar-nav__li-3" data-key='F14962EDF8034299A2FE5AA12DCA9F33'><a href="pennants/purple-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Purples</a></li> 2894 <li class="sidebar-nav__li-3" data-key='CDB3184DFD1142D29737F714977BB442'><a href="pennants/white-black-string-pennants.asp" class="sidebar-nav__a-3">String Pennant Flags with Blacks & Whites</a></li> 2895 <li class="sidebar-nav__li-3" data-key='BDC8B9E2D90642839970E2384156BCD2'><a href="pennants/gray-silver-string-pennants.asp" class="sidebar-nav__a-3">
2895String Pennant Flags with Grays & Silvers</a></li> 2896 </ul></li> 2897 <li class="sidebar-nav__li-2" data-key='B18F1A3B70D24F2895524218B1B0B1E2'><a href="pennants/american_pennants.asp" class="sidebar-nav__a-2">American</a></li> 2898 <li class="sidebar-nav__li-2" data-key='7A9ADC75C35846A6B01165620E53ADFC'><a href="pennants/world_pennants.asp" class="sidebar-nav__a-2">World</a></li> 2899 <li class="sidebar-nav__li-2" data-key='4C593E024611435EBE5921095DAA2F3D'><a href="pennants/racing.asp" class="sidebar-nav__a-2">Racing</a></li> 2900 <li class="sidebar-nav__li-2" data-key='CA2FC3FF269B425986DE25833F6064CA'><a href="pennants/commercial.asp" class="sidebar-nav__a-2">Commercial</a> 2901 <ul class="sidebar-nav__ul-3"> 2902 <li class="sidebar-nav__li-3" data-key='E14B3BA8E9C74382B62E93F38FF059A5'><a href="pennants/advertising-pennants.asp" class="sidebar-nav__a-3">Advertising Pennants</a></li> 2903 <li class="sidebar-nav__li-3" data-key='7BB1DCECEDD4402BB96DD26340907C8C'><a href="pennants/safety_pennants.asp" class="sidebar-nav__a-3">Safety Pennants</a></li> 2904 </ul></li> 2905 </ul></li> 2906 <li class="hardware sidebar-nav__li-1" data-key='D68C02F8E5DB463F8B82B742CB1571C3'><a href="hardware/hardware.asp" class="sidebar-nav__a-1">Parts and Accessories</a> 2907 <ul class="sidebar-nav__ul-2"> 2908 <li class="sidebar-nav__li-2" data-key='6421A69E27E44CBABEE3EB46CCF2B897'><a href="/hardware/outdoor.asp" class="sidebar-nav__a-2">Outdoor</a> 2909 <ul class="sidebar-nav__ul-3"> 2910 <li class="sidebar-nav__li-3" data-key='6DD95BDC404C43BAA95A0B9C184B1841'><a href="hardware/rope-and-snap-hooks.asp" class="sidebar-nav__a-3">Rope & Snap Hooks</a></li> 2911 <li class="sidebar-nav__li-3" data-key='361260BA55D64C45843941A52D38EEF7'><a href="hardware/flag-pole-pulleys.asp" class="sidebar-nav__a-3">Flagpole Pulleys & Cleats</a></li> 2912 <li class="sidebar-nav__li-3" data-key='330A1D6C1A994D64849C9F99E7674934'><a href="hardware/hardware-brackets-holders-outdoor.asp" class="sidebar-nav__a-3">Outdoor Brackets & Holders</a></li> 2913 <li class="sidebar-nav__li-3" data-key='91DBE410609145F0A6BBAD7320F7B6CA'><a href="hardware/hardware-lighting-outdoor.asp" class="sidebar-nav__a-3">Outdoor Flag Lighting</a></li> 2914 <li class="sidebar-nav__li-3" data-key='ABDF3FD0B8C34025B95261C9AA225D93'><a href="hardware/hardware-bases-outdoor.asp" class="sidebar-nav__a-3">Outdoor Flagpole Bases</a></li> 2915 <li class="sidebar-nav__li-3" data-key='B355AC2A53FD4E48B2A00C25D622330D'><a href="hardware/hardware-hanging-hardware-outdoor.asp" class="sidebar-nav__a-3">Outdoor Hanging Hardware</a></li> 2916 <li class="sidebar-nav__li-3" data-key='66C1F6F2794C485CBB0048E29B8FFF21'><a href="hardware/hardware-ornaments-finials-outdoor.asp" class="sidebar-nav__a-3">Outdoor Ornaments & Finials</a></li> 2917 <li class="sidebar-nav__li-3" data-key='40D882F28755469083A32E9A21D9260F'><a href="hardware/nautical-flagpole-sockets.asp" class="sidebar-nav__a-3">Nautical Sockets & Holders</a></li> 2918 </ul></li> 2919 <li class="sidebar-nav__li-2" data-key='6FD5AB7699DF45BCAF53FAF9390328A2'><a href="/hardware/indoor.asp" class="sidebar-nav__a-2">Indoor & Parade</a> 2920 <ul class="sidebar-nav__ul-3"> 2921 <li class="sidebar-nav__li-3" data-key='4FE70AB882464F24BC924204EE5BEAAF'><a href="hardware/hardware-brackets-holders-indoor-parade.asp" class="sidebar-nav__a-3">Indoor & Parade Brackets & Holders</a></li> 2922 <li class="sidebar-nav__li-3" data-key='81A2BA932F2647268B4813A5373470D3'><a href="hardware/hardware-bases-indoor-parade.asp" class="sidebar-nav__a-3">Indoor & Parade Flagpole Bases</a></li> 2923 <li class="sidebar-nav__li-3" data-key='05C47309B0A0476EB1C62E55AD956C07'><a href="hardware/hardware-hanging-hardware-indoor-parade.asp" class="sidebar-nav__a-3">Indoor & Parade Hanging Hardware</a></li> 2924 <li class="sidebar-nav__li-3" data-key='8CB443CF60164EC0B9D7012816CF4DCA'><a href="hardware/hardware-ornaments-finials-indoor-parade.asp" class="sidebar-nav__a-3">Indoor Ornaments & Finials</a></li> 2925 <li class="sidebar-nav__li-3" data-key='DECD6EDC7442476C8E78CAC955852B87'><a href="hardware/cord-tassels.asp" class="sidebar-nav__a-3">Cords and Tassels & Fringe</a></li> 2926 <li class="sidebar-nav__li-3" data-key='52CBB5C7C071498E96962D72F348078B'><a href="hardware/ferrules-joints.asp" class="sidebar-nav__a-3">Ferrules & Joints</a></li> 2927 <li class="sidebar-nav__li-3" data-key='EF4DBE688D3F45EEB4E6BCC60F7D81FA'><a href="hardware/hardware-lighting-indoor-parade.asp" class="sidebar-nav__a-3">Indoor Flag Lighting</a></li> 2928 <li class="sidebar-nav__li-3" data-key='215DB31B919D4639BC5AE27993BF5C32'><a href="hardware/hardware-brackets-holders-miniature.asp" class="sidebar-nav__a-3">Miniature Brackets & Holders</a></li> 2929 <li class="sidebar-nav__li-3" data-key='113496451C43400F88B1CF0F66DE3E3E'><a href="hardware/hardware-bases-miniature.asp" class="sidebar-nav__a-3">Miniature Flag Bases</a></li> 2930 <li class="sidebar-nav__li-3" data-key='A9F334C1E2CF45478EE2AED161DD804E'><a href="hardware/hardware-ornaments-finials-miniature.asp" class="sidebar-nav__a-3">Miniature Ornaments & Finials</a></li> 2931 <li class="sidebar-nav__li-3" data-key='F71B1EFE908B4CEC98937247F5D35206'><a href="hardware/crossbars-lead-poles.asp" class="sidebar-nav__a-3">Crossbars & Lead Poles</a></li> 2932 <li class="sidebar-nav__li-3" data-key='F765E54133D84FFA8BEF269BE22B002D'><a href="hardware/parade-accessories.asp" class="sidebar-nav__a-3">Parade Accessories</a></li> 2933 </ul></li> 2934 <li class="sidebar-nav__li-2" data-key='C66270EDF18C4DE9BA2F82B6437AEEA5'><a href="hardware/covers-cases.asp" class="sidebar-nav__a-2">Display Cases</a></li> 2935 <li class="sidebar-nav__li-2" data-key='7D5C7B6CD73D48449582A35F737250E7'>
2935<a href="hardware/streetpole-hardware.asp" class="sidebar-nav__a-2">Street Pole</a></li> 2936 <li class="sidebar-nav__li-2" data-key='8189A89AF95C4AEFA0E69A321D751D7C'><a href="hardware/trade-show-accessories.asp" class="sidebar-nav__a-2">Trade Show</a></li> 2937 </ul></li> 2938 <li class="sidebar-nav__li-1" data-key='0D5DA8932FB6476EB10E15050F8EBA3F'><a href="custom_showroom/trade-show-display.asp" class="sidebar-nav__a-1">Trade Show</a></li> 2939 <li class="sidebar-nav__li-1" data-key='A38C23FF076C469C9B55EF40585709DF'><a href="patriotic_gifts/shop.asp" class="sidebar-nav__a-1">Gift Shop</a> 2940 <ul class="sidebar-nav__ul-2"> 2941 <li class="sidebar-nav__li-2" data-key='7488EC2879E14129AF6A33266BA57CB2'><a href="patriotic_gifts/apparel-accessories.asp" class="sidebar-nav__a-2">Apparel and Accessories</a> 2942 <ul class="sidebar-nav__ul-3"> 2943 <li class="sidebar-nav__li-3" data-key='6671FE47199E43E2AA3ED8E035F52B5E'><a href="patriotic_gifts/boutique_apparel.asp" class="sidebar-nav__a-3">Patriotic Clothing</a></li> 2944 <li class="sidebar-nav__li-3" data-key='B28ACE453CAE4477A0158A2B4EBF1922'><a href="patriotic_gifts/clothing-accessories.asp" class="sidebar-nav__a-3">Patriotic American Flag Accessories</a></li> 2945 <li class="sidebar-nav__li-3" data-key='2556326D12FA40CB856B495BBB413019'><a href="patriotic_gifts/boutique_jewelry.asp" class="sidebar-nav__a-3">Patriotic Jewelry</a></li> 2946 </ul></li> 2947 <li class="sidebar-nav__li-2" data-key='65246F9D1E0047F4A46AA7AACD1C00C6'><a href="patriotic_gifts/boutique_home_garden.asp" class="sidebar-nav__a-2">Home & Garden</a> 2948 <ul class="sidebar-nav__ul-3"> 2949 <li class="sidebar-nav__li-3" data-key='79D3F4DCD79B4337B295AF7F92D64083'><a href="patriotic_gifts/photo_albums_frames.asp" class="sidebar-nav__a-3">Photo Albums & Frames</a></li> 2950 <li class="sidebar-nav__li-3" data-key='7EAA5499B49A470DBF5ED8768DAF6E2F'><a href="signs/signs.asp" class="sidebar-nav__a-3">Signs & Decals</a></li> 2951 <li class="sidebar-nav__li-3" data-key='896ABBAC08FE4C439CFEE4A661BCE1E3'><a href="patriotic_crafts/boutique_crafts.asp" class="sidebar-nav__a-3">Patriotic Craft Material</a></li> 2952 <li class="sidebar-nav__li-3" data-key='AE092D1F7C6B47AF8244C5F750AFFBBC'><a href="patriotic_gifts/boutique_dining_kitchen.asp" class="sidebar-nav__a-3">Dining & Kitchen</a></li> 2953 <li class="sidebar-nav__li-3" data-key='C7541350A56D445BBE88BA91C54EC94D'><a href="patriotic_gifts/artificial_garden_rocks.asp" class="sidebar-nav__a-3">Artificial Rocks</a></li> 2954 <li class="sidebar-nav__li-3" data-key='8D84C19ADBF54B3CB1B7A9BD0E85E0AD'><a href="patriotic_gifts/bird_feeders_houses.asp" class="sidebar-nav__a-3">Bird Feeders & Houses</a></li> 2955 <li class="sidebar-nav__li-3" data-key='328B4028478244A3870C0DC659A7E3C9'><a href="patriotic_gifts/blankets-pillows.asp" class="sidebar-nav__a-3">Blankets & Pillows</a></li> 2956 <li class="sidebar-nav__li-3" data-key='0BBFDCD21F7A4C20BD0847AAAC9D4D5C'><a href="patriotic_gifts/candles_holders.asp" class="sidebar-nav__a-3">Candles & Candle Holders</a></li> 2957 <li class="sidebar-nav__li-3" data-key='C933BDA2C9EE4E2C8D2052A201663520'><a href="patriotic_gifts/car_accessories.asp" class="sidebar-nav__a-3">Car Accessories</a></li> 2958 <li class="sidebar-nav__li-3" data-key='D057FD5CB9974921B636C7F954D970EF'><a href="patriotic_gifts/decorative_boxes.asp" class="sidebar-nav__a-3">Decorative Boxes</a></li> 2959 <li class="sidebar-nav__li-3" data-key='636B60A54F72422CBE8CA015C4189115'><a href="patriotic_gifts/decorative_hardware.asp" class="sidebar-nav__a-3">Decorative Hardware</a></li> 2960 <li class="sidebar-nav__li-3" data-key='5D5A7FA6F1B0467F9E90585960E20500'><a href="patriotic_gifts/figurines_sculptures.asp" class="sidebar-nav__a-3">Figurines & Sculptures</a></li> 2961 <li class="sidebar-nav__li-3" data-key='1E7433EE7A554E2C9F866D9F3A996BF2'><a href="patriotic_gifts/hanging_decor.asp" class="sidebar-nav__a-3">Hanging Decor</a></li> 2962 <li class="sidebar-nav__li-3" data-key='3E723FEADA73495E8D00832DE1BA9242'><a href="patriotic_gifts/indoor_lighting.asp" class="sidebar-nav__a-3">Indoor Lighting</a></li> 2963 <li class="sidebar-nav__li-3" data-key='6A3047B745194C6ABE33E12DB9EE5D44'><a href="banners/mailbox-covers.asp" class="sidebar-nav__a-3">Mailbox Covers</a></li> 2964 <li class="sidebar-nav__li-3" data-key='E8A4CF11E1464BF089F5AB48E73E404E'><a href="patriotic_gifts/rugs.asp" class="sidebar-nav__a-3">Rugs</a></li> 2965 <li class="sidebar-nav__li-3" data-key='0909A93F86D0451892DA4F4844B9F375'><a href="patriotic_gifts/thermometers-and-rain-gauges.asp" class="sidebar-nav__a-3">Thermometers & Rain Gauges</a></li> 2966 <li class="sidebar-nav__li-3" data-key='04ECA0E31FC44E0B925E2D6C029082E8'><a href="patriotic_gifts/wall_art.asp" class="sidebar-nav__a-3">Wall Art</a></li> 2967 <li class="sidebar-nav__li-3" data-key='4B28F86B7E504CD4BF9CF7EB0CA78536'><a href="patriotic_gifts/wreaths.asp" class="sidebar-nav__a-3">Wreaths</a></li> 2968 <li class="sidebar-nav__li-3" data-key='F4504209573740A7AB76BA989FEFC556'><a href="patriotic_gifts/pet-accessories.asp" class="sidebar-nav__a-3">
2968Pet Accessories</a></li> 2969 </ul></li> 2970 <li class="sidebar-nav__li-2" data-key='02D109B31CA84137B6F0C740FC1B359C'><a href="patriotic_gifts/boutique_office.asp" class="sidebar-nav__a-2">Office</a> 2971 <ul class="sidebar-nav__ul-3"> 2972 <li class="sidebar-nav__li-3" data-key='195F2E9D91B5421197637AD868D324DD'><a href="flags/indoor-american-flag-kits.asp" class="sidebar-nav__a-3">Indoor American Flag Kits</a></li> 2973 <li class="sidebar-nav__li-3" data-key='404D966743344831A145DE9C7D05102A'><a href="flags/flags-state-territory-indoor-parade.asp" class="sidebar-nav__a-3">Indoor State & Territory Flags & Kits</a></li> 2974 <li class="sidebar-nav__li-3" data-key='0CF682029BC8403D878A581FAAABE80E'><a href="flags/desk-flag-sets.asp" class="sidebar-nav__a-3">Desk Flag Sets</a></li> 2975 <li class="sidebar-nav__li-3" data-key='8E8CB6568A2E4C44864FBB1307FA8466'><a href="flags/miniature-flags.asp" class="sidebar-nav__a-3">Miniature Flags</a></li> 2976 <li class="sidebar-nav__li-3" data-key='5358F5E8A8EF4E698A1F767B8157700E'><a href="patriotic_gifts/book_bookends.asp" class="sidebar-nav__a-3">Books</a></li> 2977 <li class="sidebar-nav__li-3" data-key='B88064A4184F47F29DD0648E3C1E2170'><a href="patriotic_gifts/paperweights.asp" class="sidebar-nav__a-3">Paperweights</a></li> 2978 <li class="sidebar-nav__li-3" data-key='3E3D6AD08E274B588EDDED85C00BC4FF'><a href="signs/advertising-signs.asp" class="sidebar-nav__a-3">Advertising Signs</a></li> 2979 <li class="sidebar-nav__li-3" data-key='4135F69817C44CC8A785AC1DA6E4473E'><a href="signs/road-traffic-signs.asp" class="sidebar-nav__a-3">Road & Traffic Signs</a></li> 2980 </ul></li> 2981 <li class="sidebar-nav__li-2" data-key='10153CEA589246D69387C0E104F905D0'><a href="patriotic_gifts/themed-gifts.asp" class="sidebar-nav__a-2">Themed Gifts</a> 2982 <ul class="sidebar-nav__ul-3"> 2983 <li class="sidebar-nav__li-3" data-key='AE1537ADB5814BFBB6634196D398FDF0'><a href="holidays/spring_flags_and_decorations.asp" class="sidebar-nav__a-3">Spring Flags & Decorations</a></li> 2984 <li class="sidebar-nav__li-3" data-key='BB5964DD43C74F91B081C0D1CF2A3DF1'><a href="holidays/summer_flags_and_decorations.asp" class="sidebar-nav__a-3">Summer Flags & Decorations</a></li> 2985 <li class="sidebar-nav__li-3" data-key='D764AE99F0804B409E41E1F50D35B260'><a href="holidays/autumn_flags_and_decorations.asp" class="sidebar-nav__a-3">Autumn Flags & Decorations</a></li> 2986 <li class="sidebar-nav__li-3" data-key='6C419B5535624182962F7670BB1BBBFC'><a href="holidays/winter_flags_and_decorations.asp" class="sidebar-nav__a-3">Winter Flags & Decorations</a></li> 2987 <li class="sidebar-nav__li-3" data-key='7AC4343722AD4D35B4818B7E22EA094A'><a href="holidays/farm-fresh-decor.asp" class="sidebar-nav__a-3">Farm Fresh Decor</a></li> 2988 <li class="sidebar-nav__li-3" data-key='5BBD5973F22647DFB5599AF161C477BF'><a href="products/citizenship-gifts.asp" class="sidebar-nav__a-3">Citizenship Gifts</a></li> 2989 <li class="sidebar-nav__li-3" data-key='F8E645F88BC14ABBA3F9BE083F6D14D6'><a href="holidays/graduations.asp" class="sidebar-nav__a-3">Graduation</a></li> 2990 <li class="sidebar-nav__li-3" data-key='2A347A92EA7D4F748E657A098EFF41C5'><a href="patriotic_gifts/military-gifts.asp" class="sidebar-nav__a-3">Military Gifts</a></li> 2991 <li class="sidebar-nav__li-3" data-key='12619696E07A4BD18922CDC554798DBD'><a href="holidays/international-firefighters-day.asp" class="sidebar-nav__a-3">International Firefighters Day</a></li> 2992 <li class="sidebar-nav__li-3" data-key='24A19B63D92B4D5282DEAB404EFDCD0A'><a href="patriotic_gifts/dreamland-ballroom-gifts.asp" class="sidebar-nav__a-3">Dreamland Ballroom Gifts</a></li> 2993 <li class="sidebar-nav__li-3" data-key='856B47C334F44A3BB27C74051ED33C67'><a href="nautical/nautical-decor.asp" class="sidebar-nav__a-3">Nautical Themed Home & Garden Decorations</a></li> 2994 <li class="sidebar-nav__li-3" data-key='7F530E2B4F104472AF5FBB620267AE5C'><a href="holidays/arkansas_razorback_flags_gifts_and_apparel.asp" class="sidebar-nav__a-3">Razorbacks Flags & Gifts</a></li> 2995 </ul></li> 2996 <li class="sidebar-nav__li-2" data-key='25E86F7A06314710AF0A657CE500B34C'><a href="holidays/party_supplies.asp" class="sidebar-nav__a-2">Patriotic Party Supplies</a> 2997 <ul class="sidebar-nav__ul-3"> 2998 <li class="sidebar-nav__li-3" data-key='812BD60922AE4A0B9275E9F5FA7AADB2'><a href="flags/american-flags.asp" class="sidebar-nav__a-3">American Flags</a></li> 2999 <li class="sidebar-nav__li-3" data-key='77B8B3173B09442EBBEB12885066D3B1'><a href="bunting/bunting.asp" class="sidebar-nav__a-3">Patriotic Bunting</a></li> 3000 <li class="sidebar-nav__li-3" data-key='AD31DE1E6CFA4C3F8C6991D2CEB993B8'><a href="pennants/american_pennants.asp" class="sidebar-nav__a-3">American String Pennants</a></li> 3001 <li class="sidebar-nav__li-3" data-key='CA9485E0F25E414EB24445EFE1051A61'><a href="patriotic_gifts/boutique_dining_kitchen.asp" class="sidebar-nav__a-3">Dining & Kitchen</a></li> 3002 <li class="sidebar-nav__li-3" data-key='FBA055A4C2374F8A975721ECF114060C'><a href="patriotic_crafts/boutique_crafts.asp" class="sidebar-nav__a-3">Patriotic Craft Material</a></li> 3003 <li class="sidebar-nav__li-3" data-key='9E379365F754433995F7D35FEC5897CF'><a href="patriotic_gifts/boutique_apparel.asp" class="sidebar-nav__a-3">Apparel</a></li> 3004 <li class="sidebar-nav__li-3" data-key='B89497D8452F4EAB85963D41CF2A4029'><a href="patriotic_gifts/boutique_jewelry.asp" class="sidebar-nav__a-3">Jewelry</a></li> 3005 </ul></li> 3006 <li class="sidebar-nav__li-2" data-key='300A20376C034E9AB445C59
3006E57DD7B9B'><a href="patriotic_gifts/boutique_toys.asp" class="sidebar-nav__a-2">Toys & Games</a> 3007 <ul class="sidebar-nav__ul-3"> 3008 <li class="sidebar-nav__li-3" data-key='6AD49856D3BE4AF6B9D3535E41002E89'><a href="patriotic_toys/balls_novelty_toys.asp" class="sidebar-nav__a-3">Kites & Novelty</a></li> 3009 <li class="sidebar-nav__li-3" data-key='3D014C159DAD4476A7BB363B8561F46B'><a href="patriotic_toys/games.asp" class="sidebar-nav__a-3">Games</a></li> 3010 <li class="sidebar-nav__li-3" data-key='9FD3874986374568903594803E3FCD9D'><a href="patriotic_toys/stickers.asp" class="sidebar-nav__a-3">Stickers & Stationary</a></li> 3011 </ul></li> 3012 <li class="sidebar-nav__li-2" data-key='563C846CA8104008B7AD7FD4C5D83E1E'><a href="products/made_in_usa.asp" class="sidebar-nav__a-2">Made in USA Gifts</a> 3013 <ul class="sidebar-nav__ul-3"> 3014 <li class="sidebar-nav__li-3" data-key='FF850BC6CD804312ADEE79ED35185325'><a href="products/usa-made-flags-and-poles.asp" class="sidebar-nav__a-3">American Made Flags & Flagpoles</a></li> 3015 <li class="sidebar-nav__li-3" data-key='7CE57AB9812E4303903FD3D8ECCCDDC2'><a href="products/usa-made-games.asp" class="sidebar-nav__a-3">American Made Games & Puzzles</a></li> 3016 <li class="sidebar-nav__li-3" data-key='0DA2244FB6E44744A08850FAD58A6613'><a href="products/usa-made-gifts.asp" class="sidebar-nav__a-3">American Made Gifts & Mementos</a></li> 3017 <li class="sidebar-nav__li-3" data-key='14CC4EED6D8D4F27B11AFB1D5AD0FE47'><a href="products/usa-made-banners.asp" class="sidebar-nav__a-3">American Made Home & Garden Banners</a></li> 3018 <li class="sidebar-nav__li-3" data-key='3616C2A203A04B8087514359E1378F2E'><a href="products/usa-made-patriotic-decoration.asp" class="sidebar-nav__a-3">American Made Patriotic Decorations</a></li> 3019 <li class="sidebar-nav__li-3" data-key='28E030FC974340259E4CF1963E4ACB68'><a href="pennants/colorful_string_pennants.asp" class="sidebar-nav__a-3">American Made String Pennants</a></li> 3020 <li class="sidebar-nav__li-3" data-key='88EA22C466A9432B88C48FC998917166'><a href="pennants/colorful_single_pennants.asp" class="sidebar-nav__a-3">American Made Colorful Single Pennant Flags</a></li> 3021 </ul></li> 3022 </ul></li> 3023 <li class="sidebar-nav__li-1" data-key='0D3B38D6DAEB4182ACBAEE64279C9203'><a href="holidays/usa-250-anniversary.asp" class="sidebar-nav__a-1">USA 250th Anniversary</a></li> 3024 <li class="sidebar-nav__li-1" data-key='D95F93A7C79D433DBBCF79852B279A20'><a href="patriotic_gifts/memorial-decorations.asp" class="sidebar-nav__a-1">Memorials</a></li> 3025 <li class="holidays sidebar-nav__li-1" data-key='ACE656679F4743BDBE49B43F17EB1890'><a href="customer_service/calendar-of-events-holidays.asp" class="sidebar-nav__a-1">Flag Events & Holidays</a> 3026 <ul class="sidebar-nav__ul-2"> 3027 <li class="sidebar-nav__li-2" data-key='1A6E4459B9A54F189125D897AD69DFCB'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#jan" class="sidebar-nav__a-2">January</a> 3028 <ul class="sidebar-nav__ul-3"> 3029 <li class="sidebar-nav__li-3" data-key='4731E844791F4FCEA6C950980AA12525'><a href="holidays/new_years_flags_and_decorations.asp" class="sidebar-nav__a-3">New Year's Day</a></li> 3030 <li class="sidebar-nav__li-3" data-key='F89841273E4E4ECD804BCDCEF872A557'><a href="holidays/georgia_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Georgia State Birthday</a></li> 3031 <li class="sidebar-nav__li-3" data-key='2693867D8EDA412982513A3DED2A8BB2'><a href="holidays/alaska_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Alaska State Birthday</a></li> 3032 <li class="sidebar-nav__li-3" data-key='FD60C098A50F44DCBE411FC128E2B859'><a href="holidays/utah_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Utah State Birthday</a></li> 3033 <li class="sidebar-nav__li-3" data-key='F00517D919F7467F948B2E7B7664A5EF'><a href="holidays/new_mexico_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">New Mexico State Birthday</a></li> 3034 <li class="sidebar-nav__li-3" data-key='C2FA4FE61C0C449B83921C1D9A844982'><a href="holidays/connecticut_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Connecticut State Birthday</a></li> 3035 <li class="sidebar-nav__li-3" data-key='D549AB90F9A243FEA607D257B4C44077'><a href="holidays/religious_freedom_day.asp" class="sidebar-nav__a-3">Religious Freedom Day</a></li> 3036 <li class="sidebar-nav__li-3" data-key='240A2F84EB0E4A18B4053310BE00E63E'><a href="holidays/presidential_inauguration_day.asp" class="sidebar-nav__a-3">Inauguration Day</a></li> 3037 <li class="sidebar-nav__li-3" data-key='399BD548DCFC4C0CA39802965C4A1B9D'><a href="holidays/martin_luther_king_jr_day.asp" class="sidebar-nav__a-3">Martin Luther King Jr. Day</a></li> 3038 <li class="sidebar-nav__li-3" data-key='71F7A86F30E644F9B155776898F32EF4'><a href="holidays/michigan_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Michigan State Birthday</a></li> 3039 <li class="sidebar-nav__li-3" data-key='54077A6B7D3B4F02850807D68BBF948C'><a href="holidays/kansas_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Kansas State Birthday</a></li> 3040 </ul></li> 3041 <li class="sidebar-nav__li-2" data-key='C18829F06FF84309B2541CC1747510E4'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#feb" class="sidebar-nav__a-2">February</a> 3042 <ul class="sidebar-nav__ul-3"> 3043 <li class="sidebar-nav__li-3" data-key='F5F3C5BE88F84790A0C222B944D0E8C5'><a href="holidays/black_history_month.asp" class="sidebar-nav__a-3">Black History Month</a></li> 3044 <li class="sidebar-nav__li-3" data-key='BBAFCB66009247E79F0B313D8456162F'><a href="holidays/spring_flags_and_decorations.asp" class="sidebar-nav__a-3">Spring Season</a></li> 3045 <li class="sidebar-nav__li-3" data-key='45C14DDA4B1E4205B103730D7F9FBABE'><a href="holidays/massachusetts_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Massachusetts State Birthday</a></li> 3046 <li class="sidebar-nav__li-3" data-key='C48F4C0277F443729351727642E5577C'><a href="holidays/chinese_new_year.asp" class="sidebar-nav__a-3">Chinese New Year</a></li> 3047 <li class="sidebar-nav__li-3" data-key='D783B7C10A6D4476BA7E280F28DB293C'><a href="holidays/valentines_day_banner_and_gift_ideas.asp" class="sidebar-nav__a-3">Valentine's Day</a></li> 3048 <li class="sidebar-nav__li-3" data-key='4AB291DF43944FFDBEDDE33A59C0D143'><a href="holidays/oregon_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Oregon State Birthday</a></li> 3049 <li class="sidebar-nav__li-3" data-key='3FF66375F5474BCF89CA66058D629BD3'><a href="holidays/arizona_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Arizona State Birthday</a></li> 3050 <li class="sidebar-nav__li-3" data-key='1B452D48C6FC4F458F2F392D08BDCD53'><a href="holidays/presidents_day_decorations.asp" class="sidebar-nav__a-3">President's Day</a></li> 3051 </ul></li> 3052 <li class="sidebar-nav__li-2" data-key='1418E6C2D97E4E15A9F47982A12F328A'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#mar" class="sidebar-nav__a-2">March</a> 3053 <ul class="sidebar-nav__ul-3"> 3054 <li class="sidebar-nav__li-3" data-key='1C6EF57B25664168A9980242F8D6E163'><a href="holidays/mardi_gras_flags_decorations_and_gifts.asp" class="sidebar-nav__a-3">Mardi Gras</a></li> 3055 <li class="sidebar-nav__li-3" data-key='5D4A5978A89E4B14BE491574C01335E7'><a href="holidays/irish_american_heritage_month.asp" class="sidebar-nav__a-3">Irish American Heritage Month</a></li> 3056 <li class="sidebar-nav__li-3" data-key='6AB09F297F4A4B7DBBEE4AE0E4FEA152'><a href="holidays/national_womens_history_month.asp" class="sidebar-nav__a-3">Women's History Month</a></li> 3057 <li class="sidebar-nav__li-3" data-key='481A3FD6844248D9A368EE31E822D7DD'><a href="banners/college_sports_banners.asp" class="sidebar-nav__a-3">March Madness</a></li> 3058 <li class="sidebar-nav__li-3" data-key='165635D99C064F85953BAA3CF04260C7'><a href="holidays/ohio_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Ohio State Birthday</a></li> 3059 <li class="sidebar-nav__li-3" data-key='C759519445924B65977CF16ABD4E7023'><a href="holidays/nebraska_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Nebraska State Birthday</a></li> 3060 <li class="sidebar-nav__li-3" data-key='CA12DD1161374978A400F60B0F4F48E6'>
3060<a href="holidays/florida_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Florida State Birthday</a></li> 3061 <li class="sidebar-nav__li-3" data-key='E9B47B7C4542465CA5CAB05ED666CA32'><a href="holidays/vermont_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Vermont State Birthday</a></li> 3062 <li class="sidebar-nav__li-3" data-key='8ECF481DC2A741B69C087E403195EEDF'><a href="holidays/remember_the_alamo_day.asp" class="sidebar-nav__a-3">Remember The Alamo Day</a></li> 3063 <li class="sidebar-nav__li-3" data-key='98CE6CFBB4BA450690D00AEB912E9013'><a href="holidays/st_patricks_day.asp" class="sidebar-nav__a-3">St. Patrick's Day</a></li> 3064 <li class="sidebar-nav__li-3" data-key='43C4DE8D61C94940B0A588658A383D39'><a href="holidays/maine_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Maine State Birthday</a></li> 3065 </ul></li> 3066 <li class="sidebar-nav__li-2" data-key='60D65D20FBB04F94B6EF83D11A9849FF'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#apr" class="sidebar-nav__a-2">April</a> 3067 <ul class="sidebar-nav__ul-3"> 3068 <li class="sidebar-nav__li-3" data-key='E337C3059EEE49738AC01740057B5CEC'><a href="holidays/easter_flags_banners_and_decorations.asp" class="sidebar-nav__a-3">Easter</a></li> 3069 <li class="sidebar-nav__li-3" data-key='C1CCB4AA3558426498092AEBC4722DA1'><a href="holidays/prevention_of_cruelty_to_animals_month.asp" class="sidebar-nav__a-3">Prevention of Cruelty to Animals Month</a></li> 3070 <li class="sidebar-nav__li-3" data-key='C228E574D57643A5BDBD40A3256BB7FD'><a href="holidays/earth_day.asp" class="sidebar-nav__a-3">Earth Day</a></li> 3071 <li class="sidebar-nav__li-3" data-key='A88B295C179341C7A35DC8BFFC16D6A9'><a href="holidays/maryland_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Maryland State Birthday</a></li> 3072 <li class="sidebar-nav__li-3" data-key='A549B6391BE8489EAE55A0AD9777A423'><a href="holidays/louisiana_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Louisiana State Birthday</a></li> 3073 </ul></li> 3074 <li class="sidebar-nav__li-2" data-key='92DDBBCBF3104C3E968DE771FB5EA2C1'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#may" class="sidebar-nav__a-2">May</a> 3075 <ul class="sidebar-nav__ul-3"> 3076 <li class="sidebar-nav__li-3" data-key='636043C839824FBBA2CE40BFC9FCF1F6'><a href="holidays/jewish_american_heritage_month.asp" class="sidebar-nav__a-3">Jewish American Heritage Month</a></li> 3077 <li class="sidebar-nav__li-3" data-key='758D712CB666468E858ADF8578E64959'><a href="holidays/asian_pacific_american_heritage_month.asp" class="sidebar-nav__a-3">Asian Pacific American Month</a></li> 3078 <li class="sidebar-nav__li-3" data-key='7C89EA4D7E49450997F7C98AF16CF3E6'><a href="holidays/arkansas_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Arkansas Heritage Month</a></li> 3079 <li class="sidebar-nav__li-3" data-key='5198FC59E4584FBABA0A65C52449B295'><a href="holidays/firefighter_flags_and_gifts.asp" class="sidebar-nav__a-3">International Firefighter's Day</a></li> 3080 <li class="sidebar-nav__li-3" data-key='5B08CA47ECC34825ADD0C1F4B1B94175'><a href="holidays/cinco_de_mayo.asp" class="sidebar-nav__a-3">Cinco De Mayo</a></li> 3081 <li class="sidebar-nav__li-3" data-key='7024C28074F54E5094ADFA0744B44F75'><a href="holidays/national_teacher_day.asp" class="sidebar-nav__a-3">National Teacher's Day</a></li> 3082 <li class="sidebar-nav__li-3" data-key='088F399CF52B48F9A5CCDFCAF99C5FBB'><a href="holidays/minnesota_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Minnesota State Birthday</a></li> 3083 <li class="sidebar-nav__li-3" data-key='BCBF548F5A96423E903209B4F6B1AF71'><a href="holidays/mothers_day.asp" class="sidebar-nav__a-3">Mother's Day</a></li> 3084 <li class="sidebar-nav__li-3" data-key='996E5A40D510427C84B7EF75AD25F0FA'><a href="flags/service-persons-flags.asp" class="sidebar-nav__a-3">National Fallen Firefighters Memorial Service</a></li> 3085 <li class="sidebar-nav__li-3" data-key='A614E757A650424CACB2958DE95B47BE'><a href="holidays/peace_officers_memorial_day.asp" class="sidebar-nav__a-3">Peace Officer's Memorial Day</a></li> 3086 <li class="sidebar-nav__li-3" data-key='E152245ABD14463E8993D0D729EB108C'><a href="holidays/armed_forces_flags_and_gifts.asp" class="sidebar-nav__a-3">Armed Forces Day</a></li> 3087 <li class="sidebar-nav__li-3" data-key='D7E180401EEA4CFEA693CD41CF25D488'><a href="holidays/south_carolina_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">South Carolina State Birthday</a></li> 3088 <li class="sidebar-nav__li-3" data-key='C61F31D843964256B802D79ED92CF964'><a href="holidays/memorial_day.asp" class="sidebar-nav__a-3">Memorial Day</a></li> 3089 <li class="sidebar-nav__li-3" data-key='D4D32FF9906A4FE4A1983E75ECA08EB3'><a href="holidays/rhode_island_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">
3089Rhode Island State Birthday</a></li> 3090 <li class="sidebar-nav__li-3" data-key='A619F3D8354D4931B9D6694ADD88A867'><a href="holidays/wisconsin_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Wisconsin State Birthday</a></li> 3091 <li class="sidebar-nav__li-3" data-key='17D14B63652D4C46BA3D6E8ECC31A613'><a href="holidays/graduations.asp" class="sidebar-nav__a-3">Graduation</a></li> 3092 </ul></li> 3093 <li class="sidebar-nav__li-2" data-key='F87138435C7445CCB106E0DB29A78D54'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#jun" class="sidebar-nav__a-2">June</a> 3094 <ul class="sidebar-nav__ul-3"> 3095 <li class="sidebar-nav__li-3" data-key='04096D76569C41FFA0966E29C7C9D2A1'><a href="holidays/summer_flags_and_decorations.asp" class="sidebar-nav__a-3">Summer Season</a></li> 3096 <li class="sidebar-nav__li-3" data-key='6E53E81707194497969ADCBA5E143B24'><a href="holidays/adopt-a-cat_month.asp" class="sidebar-nav__a-3">Adopt A Cat Month</a></li> 3097 <li class="sidebar-nav__li-3" data-key='7AE80E1DE44243B9BBE9F7B24C289AF7'><a href="holidays/lgbt-pride-month.asp" class="sidebar-nav__a-3">Gay and Lesbian Heritage Month</a></li> 3098 <li class="sidebar-nav__li-3" data-key='D32FD4CCA6F94BEBBB4C60EE4E673703'><a href="holidays/cancer_survivor_day.asp" class="sidebar-nav__a-3">Cancer Survivor Day</a></li> 3099 <li class="sidebar-nav__li-3" data-key='C349863B756647D9867ECFEA1CE06C93'><a href="flags/nba-flags.asp" class="sidebar-nav__a-3">NBA Finals</a></li> 3100 <li class="sidebar-nav__li-3" data-key='E5E9FC398C264E65999EBF330D227E3B'><a href="holidays/kentucky_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Kentucky State Birthday</a></li> 3101 <li class="sidebar-nav__li-3" data-key='02D93D9AC4814338BADDBD8C4598026A'><a href="holidays/tennessee_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Tennessee State Birthday</a></li> 3102 <li class="sidebar-nav__li-3" data-key='303D141FAD7849EBBE73B428EC398E76'><a href="holidays/remember_d-day.asp" class="sidebar-nav__a-3">D-Day Remembrance Day</a></li> 3103 <li class="sidebar-nav__li-3" data-key='BCABD3E95A7C4C9897F6831996011370'><a href="holidays/king_kamehameha_day.asp" class="sidebar-nav__a-3">King Kamehameha Day</a></li> 3104 <li class="sidebar-nav__li-3" data-key='F867C179DF1C4FA9AB9BB5F9D098D67D'><a href="holidays/iowa_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Iowa State Birthday</a></li> 3105 <li class="sidebar-nav__li-3" data-key='1003A945629A480480467BC543A63DE2'><a href="flags/soccer-flags.asp" class="sidebar-nav__a-3">FIFA World Cup</a></li> 3106 <li class="sidebar-nav__li-3" data-key='95CAD4E4E62F4D7C8717B55BD89944F2'><a href="holidays/arkansas_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Arkansas State Birthday</a></li> 3107 <li class="sidebar-nav__li-3" data-key='592853446F42495DA35E7B51094408B6'><a href="holidays/army_flags_and_gifts.asp" class="sidebar-nav__a-3">Army Birthday</a></li> 3108 <li class="sidebar-nav__li-3" data-key='7A0EE41DF0704B2999CD9B05B888D24D'><a href="holidays/american_flag_day.asp" class="sidebar-nav__a-3">American Flag Day</a></li> 3109 <li class="sidebar-nav__li-3" data-key='24658D8450B549A1AC6DD739AD888371'><a href="holidays/fathers_day.asp" class="sidebar-nav__a-3">Father's Day</a></li> 3110 <li class="sidebar-nav__li-3" data-key='3822863E9C904FD0B6D0D73728161C9A'><a href="flags/nhl-flags.asp" class="sidebar-nav__a-3">Stanley Cup</a></li> 3111 <li class="sidebar-nav__li-3" data-key='1531D990BE9446488F7EB703E1D53593'><a href="holidays/west_virginia_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">West Virginia State Birthday</a></li> 3112 <li class="sidebar-nav__li-3" data-key='D3BF23C2E56B46F3910B41DDA3BBB8BC'><a href="holidays/new_hampshire_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">New Hampshire State Birthday</a></li> 3113 <li class="sidebar-nav__li-3" data-key='24AD0DBD7A9548F3B2C64DEC9755BDF5'><a href="holidays/virginia_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Virginia State Birthday</a></li> 3114 <li class="sidebar-nav__li-3" data-key='364E9818F42D46159400635C861CDAC0'><a href="holidays/world_war_1_anniversary.asp" class="sidebar-nav__a-3">World War 1 Day</a></li> 3115 </ul></li> 3116 <li class="sidebar-nav__li-2" data-key='5837BA3D65CA4B119292B5962F4CD6F5'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#jul" class="sidebar-nav__a-2">July</a> 3117 <ul class="sidebar-nav__ul-3"> 3118 <li class="sidebar-nav__li-3" data-key='4BD00A715CB64220A5804689E5168E61'><a href="holidays/canada_day.asp" class="sidebar-nav__a-3">Canada Day</a></li> 3119 <li class="sidebar-nav__li-3" data-key='6C71FF9806DF4CF1AD7E3422A235B90D'><a href="holidays/idaho_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Idaho State Birthday</a></li> 3120 <li class="sidebar-nav__li-3" data-key='D1E8EDBFFAD34955B1B6269F90F5694C'><a href="holidays/4th-of-july.asp" class="sidebar-nav__a-3">USA Independence Day</a></li> 3121 <li class="sidebar-nav__li-3" data-key='1AFCC6F08D3145C59D4DADF2B4CFBABC'><a href="holidays/wyoming_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Wyoming State Birthday</a></li> 3122 <li class="sidebar-nav__li-3" data-key='D8F7855C7CE84C23A9C172A06913CACF'><a href="holidays/bastille_day.asp" class="sidebar-nav__a-3">Bastille Day</a></li> 3123 <li class="sidebar-nav__li-3" data-key='975C7C6FD4D84CE49D71B83BF37B8A7C'><a href="holidays/new_york_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">New York State Birthday</a></li> 3124 <li class="sidebar-nav__li-3" data-key='AFB69FB05E6545819CD97114EF8AA369'><a href="holidays/korean_war_veterans_day.asp" class="sidebar-nav__a-3">Korean War Veterans Day</a></li> 3125 </ul></li> 3126 <li class="sidebar-nav__li-2" data-key='FABC577BC7B34A77B331EAFC7C12AEC6'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#aug" class="sidebar-nav__a-2">August</a> 3127 <ul class="sidebar-nav__ul-3"> 3128 <li class="sidebar-nav__li-3" data-key='BBF7F36125D24F1E8A92B84013A31634'><a href="holidays/arkansas_razorback_flags_gifts_and_apparel.asp" class="sidebar-nav__a-3">Razorback Football Season</a></li> 3129 <li class="sidebar-nav__li-3" data-key='6C9D567C2B6341228B46D3105FFB60B5'><a href="holidays/back_to_school_ideas_for_teachers_and_parents.asp" class="sidebar-nav__a-3">Back to School</a></li> 3130 <li class="sidebar-nav__li-3" data-key='981DC0CBC4204140B7A1AC80D99E3CD2'><a href="holidays/colorado_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Colorado State Birthday</a></li> 3131 <li class="sidebar-nav__li-3" data-key='B232AB2ED2E24D169CEFB9576D6A643D'><a href="holidays/coast_guard_flags_and_gifts.asp" class="sidebar-nav__a-3">Coast Guard Birthday</a></li> 3132 <li class="sidebar-nav__li-3" data-key='6CA6A3D8722540F6A1D2FCB9BE05E2B7'><a href="holidays/missouri_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Missouri State Birthday</a></li> 3133 <li class="sidebar-nav__li-3" data-key='0E9EE350EDE0413188E9C4696F9578AD'><a href="holidays/hawaii_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Hawaii State Birthday</a></li> 3134 <li class="sidebar-nav__li-3" data-key='453849654A3344BDBFDF4450A7451ECE'><a href="holidays/womens_equality_day.asp" class="sidebar-nav__a-3">Women's Equality Day</a></li> 3135 </ul></li> 3136 <li class="sidebar-nav__li-2" data-key='3C49B89CD0724AB991723E592BEA14CC'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#sep" class="sidebar-nav__a-2">September</a> 3137 <ul class="sidebar-nav__ul-3"> 3138 <li class="sidebar-nav__li-3" data-key='9DB9AFCC70FA439B91A89E88C88E12CD'><a href="holidays/autumn_flags_and_decorations.asp" class="sidebar-nav__a-3">Fall Season</a></li> 3139 <li class="sidebar-nav__li-3" data-key='EC4F88FB714C4C4384F0E5B4343FF10E'><a href="holidays/latino_and_hispanic_heritage_month.asp" class="sidebar-nav__a-3">Latino and Hispanic Month</a></li> 3140 <li class="sidebar-nav__li-3" data-key='AD284C8A78CF40D4AAE8920E6E726088'><a href="holidays/labor_day_decorations.asp" class="sidebar-nav__a-3">Labor Day</a></li> 3141 <li class="sidebar-nav__li-3" data-key='389F4B49103E45CEA47315DDC15E7022'><a href="holidays/california_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">California State Birthday</a></li> 3142 <li class="sidebar-nav__li-3" data-key='0804F1CACB9646AD90345B3832A6A571'><a href="holidays/patriot_day_and_9-11-01_remembrance_day_flags.asp" class="sidebar-nav__a-3">Patriot Day</a></li> 3143 <li class="sidebar-nav__li-3" data-key='B5D7196696A34114847CE0F8FA7D9D4C'><a href="holidays/constitution_and_citizenship_day_gifts_and_decorations.asp" class="sidebar-nav__a-3">
3143Constitution & Citizenship Day</a></li> 3144 <li class="sidebar-nav__li-3" data-key='FFD0868A32D047F09B7A54CE73B2DBA8'><a href="holidays/pirate_day_flags_banners_and_decorations.asp" class="sidebar-nav__a-3">Talk Like A Pirate Day</a></li> 3145 <li class="sidebar-nav__li-3" data-key='2B1D8E55455E4B319CA88843FF1C2CA6'><a href="holidays/air_force_flags_and_gifts.asp" class="sidebar-nav__a-3">Air Force Birthday</a></li> 3146 <li class="sidebar-nav__li-3" data-key='2CDF65AF00A04AE89235621FA733D596'><a href="holidays/gold_star_mothers_day_flags_and_gifts.asp" class="sidebar-nav__a-3">Gold Star Mother's Day</a></li> 3147 </ul></li> 3148 <li class="sidebar-nav__li-2" data-key='8FAC320548314EF89B66F2783DE3FF6C'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#oct" class="sidebar-nav__a-2">October</a> 3149 <ul class="sidebar-nav__ul-3"> 3150 <li class="sidebar-nav__li-3" data-key='DB53EE3547EF4D99B74DF60C3C9418C6'><a href="holidays/adopt-a-dog_month.asp" class="sidebar-nav__a-3">Adopt a Dog Month</a></li> 3151 <li class="sidebar-nav__li-3" data-key='0932810F468548418C7D31DB4E7E29EC'><a href="holidays/diversity_month.asp" class="sidebar-nav__a-3">Diversity Month</a></li> 3152 <li class="sidebar-nav__li-3" data-key='617EF1596D1A4B588E8D61E2D812093A'><a href="holidays/national_day.asp" class="sidebar-nav__a-3">National Day</a></li> 3153 <li class="sidebar-nav__li-3" data-key='9D6C3E33CE7846809C890BB876D86915'><a href="holidays/german-american_day.asp" class="sidebar-nav__a-3">German-American Day</a></li> 3154 <li class="sidebar-nav__li-3" data-key='A4663DA6A1B348228F373A8B58ABC33A'><a href="holidays/leif_erikson_day.asp" class="sidebar-nav__a-3">Leif Erikson Day</a></li> 3155 <li class="sidebar-nav__li-3" data-key='0770355C86604885BDDBCB37B17D79A5'><a href="holidays/navy_flags_and_gifts.asp" class="sidebar-nav__a-3">Navy Birthday</a></li> 3156 <li class="sidebar-nav__li-3" data-key='271F5F663E0B4D8D9780D5A1AFC5DCBC'><a href="holidays/pink_ribbon_and_breast_cancer_awareness.asp" class="sidebar-nav__a-3">Breast Cancer Awareness & Race for the Cure</a></li> 3157 <li class="sidebar-nav__li-3" data-key='29BF06E0719249FCA7C8FD53AE418A81'><a href="holidays/united_nations_day.asp" class="sidebar-nav__a-3">United Nations Day</a></li> 3158 <li class="sidebar-nav__li-3" data-key='5D5CE7CC50E247199FE582C0A5EA635C'><a href="holidays/nevada_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Nevada State Birthday</a></li> 3159 <li class="sidebar-nav__li-3" data-key='758F1582FBA64FD8BCB00C0C4CD81A50'><a href="holidays/halloween_decorations.asp" class="sidebar-nav__a-3">Halloween</a></li> 3160 </ul></li> 3161 <li class="sidebar-nav__li-2" data-key='206F748E52F54F1EBFB0342831C4936D'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#nov" class="sidebar-nav__a-2">November</a> 3162 <ul class="sidebar-nav__ul-3"> 3163 <li class="sidebar-nav__li-3" data-key='8958AC3F254140D6A497FF3B41DE3001'><a href="holidays/national_alaska_native_and_american_indian_heritage_month.asp" class="sidebar-nav__a-3">Alaska Native & American Indian Month</a></li> 3164 <li class="sidebar-nav__li-3" data-key='D9C398FCAD4F4859B7B4C2F3CD3CDD77'><a href="holidays/north_dakota_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">North Dakota State Birthday</a></li> 3165 <li class="sidebar-nav__li-3" data-key='A1C9241ABDB04575B8A442A5B00C5679'><a href="holidays/south_dakota_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">South Dakota State Birthday</a></li> 3166 <li class="sidebar-nav__li-3" data-key='E4844CE01E8A43FA93609F52BCC2BAA3'><a href="holidays/political_party_election.asp" class="sidebar-nav__a-3">Presidential Election</a></li> 3167 <li class="sidebar-nav__li-3" data-key='F7A0B47D6C1A4F34A4B49CD2F7E4DD1E'><a href="holidays/montana_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Montana State Birthday</a></li> 3168 <li class="sidebar-nav__li-3" data-key='B98C787F204A4B2FA3DB15A5D6AC1717'><a href="holidays/marine_corps_flags_and_gifts.asp" class="sidebar-nav__a-3">Marine Corps Birthday</a></li> 3169 <li class="sidebar-nav__li-3" data-key='F9BDF238E4BF4CE098CE1FF9ADBEE462'><a href="holidays/veterans_day.asp" class="sidebar-nav__a-3">Veterans Day</a></li> 3170 <li class="sidebar-nav__li-3" data-key='1DB133BBA82C4A4FBD89FFC515FB2A21'><a href="holidays/washington_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Washington State Birthday</a></li> 3171 <li class="sidebar-nav__li-3" data-key='2F65FE2F3EDE4AFDBC82FA2BD7B2335A'><a href="holidays/oklahoma_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Oklahoma State Birthday</a></li> 3172 <li class="sidebar-nav__li-3" data-key='357C38894C6E432886A90667AC07664B'><a href="holidays/north_carolina_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">North Carolina State Birthday</a></li> 3173 <li class="sidebar-nav__li-3" data-key='2C1106290BDC4B5E82D24BEE399AD58C'><a href="holidays/thanksgiving_and_harvest.asp" class="sidebar-nav__a-3">Thanksgiving</a></li> 3174 </ul></li> 3175 <li class="sidebar-nav__li-2" data-key='E0AC2701ABC84C0CB58139B15926793B'><a href="https://www.flagandbanner.com/customer_service/calendar-of-events-holidays.asp#dec" class="sidebar-nav__a-2">December</a> 3176 <ul class="sidebar-nav__ul-3"> 3177 <li class="sidebar-nav__li-3" data-key='0534F178B49B48EAA0AF463D2AEC3019'><a href="holidays/winter_flags_and_decorations.asp" class="sidebar-nav__a-3">Winter Season</a></li> 3178 <li class="sidebar-nav__li-3" data-key='726182A5767449DABB52C770F3F826B6'><a href="holidays/world_aids_awareness_day.asp" class="sidebar-nav__a-3">World AIDS Awareness Day</a></li> 3179 <li class="sidebar-nav__li-3" data-key='003FEDD536D848CFB8F85E2F8DA1357B'><a href="holidays/illinois_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Illinois State Birthday</a></li> 3180 <li class="sidebar-nav__li-3" data-key='A0A0C8664B954066ACD815230B9E2EDB'><a href="holidays/delaware_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Delaware State Birthday</a></li> 3181 <li class="sidebar-nav__li-3" data-key='9C0979EA81054331BD656B0DF42A7CDB'><a href="holidays/mississippi_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Mississippi State Birthday</a></li> 3182 <li class="sidebar-nav__li-3" data-key='98DB9146BC2742FFB179F4711DC9A326'><a href="holidays/indiana_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Indiana State Birthday</a></li> 3183 <li class="sidebar-nav__li-3" data-key='BD12DCAA1B6C4BF1B1CA87383D428060'><a href="holidays/national_poinsettia_day.asp" class="sidebar-nav__a-3">National Poinsettia Day</a></li> 3184 <li class="sidebar-nav__li-3" data-key='9BA578C1E38A459E860314A676ADC72D'><a href="holidays/pennsylvania_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Pennsylvania State Birthday</a></li> 3185 <li class="sidebar-nav__li-3" data-key='FCDA37C658C546418DDE8F4E8B0C5191'><a href="holidays/alabama_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Alabama State Birthday</a></li> 3186 <li class="sidebar-nav__li-3" data-key='67C04B5C1B3946518502BD5F0BA8200D'><a href="holidays/new_jersey_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">New Jersey State Birthday</a></li> 3187 <li class="sidebar-nav__li-3" data-key='6FA497953EAB4109B685B3600EC55D6B'><a href="holidays/pearl_harbor_remembrance_day.asp" class="sidebar-nav__a-3">Pearl Harbor Remembrance Day</a></li> 3188 <li class="sidebar-nav__li-3" data-key='7B036C8FFDA94548B61141A1AE8B7B33'><a href="holidays/chanukah-flags-and-banners.asp" class="sidebar-nav__a-3">Chanukah</a></li> 3189 <li class="sidebar-nav__li-3" data-key='038F32AA24AB4B758CDA5851AC416C68'><a href="patriotic_gifts/boutique_christmas.asp" class="sidebar-nav__a-3">Christmas</a></li> 3190 <li class="sidebar-nav__li-3" data-key='17E0CE9191BE42AA94D018B197193217'><a href="holidays/texas_state_birthday_flags_and_gifts.asp" class="sidebar-nav__a-3">Texas State Birthday</a></li> 3191 <li class="sidebar-nav__li-3" data-key='A3353A9AA3CE4E5E8E9FDE1950C4B526'><a href="holidays/new_years_flags_and_decorations.asp" class="sidebar-nav__a-3">New Year's Eve</a></li> 3192 </ul></li> 3193 </ul></li> 3194 <li class="sidebar-nav__li-1" data-key='522C2211B0764D9D9C5C8BE3A818A3A8'><a href="holidays/whats_new.asp" class="sidebar-nav__a-1">What's New</a></li> 3195 <li class="best-sellers sidebar-nav__li-1" data-key='80C4BF7D38A146BD901CCE4375B2DB4E'><a href="products/best-sellers.asp" class="sidebar-nav__a-1">Best Sellers</a></li> 3196 <li class="sidebar-nav__li-1" data-key='BA5E78DF24B24390A8F0EEB26902C060'><a href="patriotic_gifts/clearance.asp" class="sidebar-nav__a-1">Clearance</a></li> 3197 <li class="sidebar-nav__li-1" data-key='931530C891434A3DB122FB578DB350E9'><a href="flags/flag_alerts.asp" class="sidebar-nav__a-1">Join Our Mail List</a></li> 3198 <li class="sidebar-nav__li-1" data-key='635CD37A5493419FBC1520CE7796D7F7'><a href="flags/half-staff.asp" class="sidebar-nav__a-1">American Flag Status</a></li> 3199</ul> 3200 </div> 3201 3202 <div class="layout__main"> 3203 3204 3205 <div id="page-main" class="page-main"> 3206 <div class="container-fluid"> 3207
3208<script> 3209var timerStart = Date.now(); 3210var lastElapsed = 0; 3211var pageHitDate = new Date(); 3212var pageLoad = { 3213 pageHitKey: '56643338C5024B7F929A093D18BFFFC6', 3214 sessionId: 'DCABF2A60CB54D4CA796FBEA91F9B757', 3215 orderId: '', 3216 createDate: (pageHitDate.getMonth()+1) + "/" 3217 + pageHitDate.getDate() + "/" 3218 + pageHitDate.getFullYear() + " " 3219 + pageHitDate.getHours() + ":" 3220 + pageHitDate.getMinutes() + ":" 3221 + pageHitDate.getSeconds(), 3222 priorTimeFrom: '', 3223 priorTime: '', 3224 urlRoot: 'www.flagandbanner.com', 3225 pageName: 'Custom-Flag-Pricing.asp', 3226 uri: window.location.href, 3227 querystring: 'rewrite=true&p_key=B5C8B43721D042E3BE244C0AC84508EA&pagetype=webpage', 3228 logs: [], 3229 clientTime: 0, 3230 serverTime: 0, 3231 totalTime: 0, 3232 dbReadCount: 0, 3233 dbWriteCount: 0 3234}; 3235 3236function addTimer(s) { 3237 var elapsed = (Date.now()-timerStart); //KEEP milliseconds 3238 var log = { 3239 source: 3, 3240 stepWithinSource: pageLoad.logs.filter( function(obj) { obj.source === 3 }).length, 3241 nickname: s, 3242 stepTime: elapsed - lastElapsed, 3243 cumulativeTime: elapsed 3244 }; 3245 pageLoad.logs.push(log); 3246 lastElapsed = elapsed; 3247} 3248 3249function logPageLoad() { 3250 if(pageLoad.logs.length > 0) { 3251 //sum the server-side, object, & client-side times onto the header. 3252 var serverTime=0; 3253 var maxClientSide=0; 3254 var len = pageLoad.logs.length-1; 3255 $.each(pageLoad.logs,function(i,o){ 3256 if(o.source==0) { //server-side` 3257 serverTime=serverTime+o.cumulativeTime; 3258 pageLoad.dbReadCount += o.dbReadCount; 3259 pageLoad.dbWriteCount += o.dbWriteCount; 3260 /*} 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. */ 3261 } else if(o.source==3 && o.cumulativeTime > maxClientSide) { // on the last client-side record 3262 maxClientSide=o.cumulativeTime; 3263 } 3264 }); 3265 var pt = pageLoad.priorTime; 3266 if(pt != "" && !isNaN(pt)){ 3267 pageLoad.priorTime = parseFloat(pt); 3268 } else { 3269 pageLoad.priorTime = 0; 3270 } 3271 pageLoad.serverTime = serverTime; 3272 pageLoad.clientTime = maxClientSide 3273 pageLoad.totalTime = parseInt(serverTime + maxClientSide + pageLoad.priorTime); //trim decimals 3274 $.ajax({
3275 url: '/api/timers/paymentpage/56643338C5024B7F929A093D18BFFFC6', 3276 data: JSON.stringify(pageLoad), 3277 type: "POST", 3278 contentType: "application/json" 3279 }); 3280 drawPageHitData(); 3281 pageLoad.logs = []; //<-- this is cleared so that the page hit isn't logged more than once.. See containing IF block... 3282 } 3283} 3284 3285function drawPageHitData() { 3286 3287} 3288 3289function toSecString(ms) { 3290 var s = (parseInt(ms*10)/10); //only keep 1 decimal 3291 s = parseInt(s) / 1000; 3292 3293 return s + "sec(s)"; 3294} 3295 3296function addPageLoadData(data) { 3297 /* 3298 OO data is an object with 3 props: reads, writes, details[] 3299 */ 3300 if(data.reads) { 3301 pageLoad.dbReadCount += data.reads; 3302 } 3303 if(data.writes) { 3304 pageLoad.dbWriteCount += data.writes; 3305 } 3306 if(data.details) { 3307 pageLoad.logs = pageLoad.logs.concat(data.details); 3308 } 3309} 3310 3311addTimer('master top'); 3312</script>
3312 3313 3314 <!-- Begin TVSquared Tracking Code --> 3315
3315<script type="text/javascript"> 3316 var _tvq = window._tvq = window._tvq || []; 3317 (function() { 3318 var u = (("https:" == document.location.protocol) ? 3319 "https://collector-48664.us.tvsquared.com/" 3320 : 3321 "http://collector-48664.us.tvsquared.com/" 3322 ); 3323 _tvq.push(['setSiteId', "TV-5418363654-1"]); 3324 _tvq.push(['setTrackerUrl', u + 'tv2track.php']); 3325 _tvq.push([function() { 3326 this.deleteCustomVariable(5, 'page') 3327 }]); 3328 _tvq.push(['trackPageView']); 3329 var d = document, 3330 g = d.createElement('script'), 3331 s = d.getElementsByTagName('script')[0]; 3332 g.type = 'text/javascript'; 3333 g.defer = true; 3334 g.async = true; 3335 g.src = u + 'tv2track.js'; 3336 s.parentNode.insertBefore(g, s); 3337 })(); 3338 </script>
3338 3339 <!-- End TVSquared Tracking Code --> 3340 3341 <a name="top" id="top"></a> 3342 3343 3344 3345 <div class="wpc_container"> 3346 3347 3348 <ul class="breadcrumb" vocab="http://schema.org/" typeof="BreadcrumbList"> 3349 <li property="itemListElement" typeof="ListItem"> 3350 <a href="/" property="item" typeof="WebPage"><span property="name">Home</span></a> 3351 <span class="divider">/</span> 3352 <meta property="position" content="1"> 3353 </li> 3354 3355 <li property="itemListElement" typeof="ListItem"> 3356 <a href="/custom_showroom/custom_flags_banners.asp" property="item" typeof="WebPage"><span property="name">Custom Flags, Banners and Pennants Home</span></a> 3357 <span class="divider">/</span> 3358 <meta property="position" content="1"> 3359 </li> 3360 <li property="itemListElement" typeof="ListItem" class="active"> 3361 <a href="/custom_showroom/Custom-Flag-Pricing.asp" property="item" typeof="WebPage"><span property="name">Custom Flags</span></a> 3362 <meta property="position" content="3"> 3363 </li> 3364 3365 </ul> 3366 <header class="page-header"> 3367 3368 <h1 class="wpc_page_title">Custom Flags</h1> 3369 </header> 3370 <div class="wpc_page_content"> 3371 <p>With over 45 years in the flag making business, we are the experts. We customize in custom flags! Let us create your custom-made logo flags for advertising, events, decoration, information, identification or any other reason you can imagine! Our custom flags are made using high quality nylon that weathers well and files easily. Need an indoor or parade display? That’s easy! We can add a pole hem and gold fringe to any flag.</p> 3372<p>The categories below showcase our different styles and construction methods. While other flag manufacturers are phasing out more skilled artisan flag making techniques, we still proudly offer the traditional choices of applique and embroidery.</p> 3373<table border="0" width="100%" cellspacing="5" cellpadding="8" align="center"> 3374<tbody> 3375<tr> 3376<td style="text-align: center; vertical-align: middle; width: 400px;"> 3377<h2><a title="Custom Digital Flags" href="custom_showroom/digital-flags.asp"><img src="images/digital-flag-button-3.png" alt="Custom Digital Flags" width="400" height="259" border="0" /></a></h2> 3378<h2><a title="Custom Digital Flags" href="custom_showroom/digital-flags.asp">Custom Digital Flags</a></h2> 3379</td> 3380<td style="text-align: center; vertical-align: middle; width: 400px;"> 3381<h2><a title="Custom Applique Flags" href="custom_showroom/applique-flags.asp"><img src="images/appliqued-flag-button.png" alt="Custom Appliqued Flags" width="400" height="259" border="0" /></a></h2> 3382<h2><a title="Custom Applique Flags" href="custom_showroom/applique-flags.asp">Custom Applique Flags</a></h2> 3383</td> 3384</tr> 3385<tr style="text-align: left;"> 3386<td style="vertical-align: top; text-align: left; width: 400px;">Digitally Printing allows you to transfer a more complex image to your flag, with more color choices and with gradients. Our printed nylon flag is perfect for outdoor use and for customers ordering multiple quantities.</td> 3387<td style="vertical-align: top; text-align: left; width: 400px;">Much like quilting, each color of the design and/or individual letters are hand cut and sewn on the front and back of the Appliquéd Flag. This is an elegant process for small run orders and is often used when making large flags.</td> 3388</tr> 3389</tbody> 3390</table> 3391<table style="float: left;" border="0" width="100%" cellspacing="5" cellpadding="8" align="center"> 3392<tbody> 3393<tr> 3394<td style="text-align: center; vertical-align: middle; width: 400px;"> 3395<h2><a title="Custom Embroidered Flags" href="custom_showroom/embroidered-flags.asp"><img src="images/embroidered-flag-button.png" alt="Custom Embroidered Flags" width="400" height="259" border="0" /></a></h2> 3396<h2><a title="Custom Embroidered Flags" href="custom_showroom/embroidered-flags.asp">Custom Embroidered Flags</a></h2> 3397</td> 3398<td style="text-align: center; vertical-align: middle; width: 400px;"> 3399<h2><a title="Custom Guidons" href="custom_showroom/guidons.asp"><img src="images/guidon-button1.png" alt="Custom Guidons" width="400" height="259" border="0" /></a></h2> 3400<h2><a title="Custom Guidon Flags" href="custom_showroom/guidons.asp">Custom Guidon Flags</a></h2> 3401</td> 3402</tr> 3403<tr> 3404<td style="vertical-align: top; text-align: left; width: 400px;"><span>The design on an Embroidered Flag is created using thread that is looped and layered to form a raised image on the flag. For a ceremonial appearance, these handsome flags can be edged with gold fringe. This method is the crème’ da la crème’ of flag making.</span></td> 3405<td style="text-align: left; vertical-align: top; width: 400px;">A Military Guidon, also known as a military standard, are displayed and carried by all United States Armed Forces and other civil and service organizations. They are used to signify unit, squadron and/or corps affiliation.</td> 3406</tr> 3407</tbody> 3408</table> 3409<table style="float: left;" border="0" width="100%" cellspacing="5" cellpadding="8" align="center"> 3410<tbody> 3411<tr> 3412<td style="text-align: center; vertical-align: middle; width: 665px;"> 3413<h2><a title="Custom Burgee Flags" href="custom_showroom/burgee-flags.asp"><img src="images/burgee-button2.png" alt="Custom Burgees" width="400" height="259" border="0" /></a></h2> 3414<h2><a title="Custom Burgee Flags" href="custom_showroom/burgee-flags.asp">Custom Burgee Flags</a></h2> 3415</td> 3416<td style="text-align: center; vertical-align: middle; width: 665px;"> 3417<h2><a title="Custom Pennant Flags" href="custom_showroom/pennant-flags.asp"><img src="images/pennant-flag-button.png" alt="Custom Pennant Flags" width="400" height="259" border="0" /></a></h2> 3418<h2><a title="Custom Pennant Flags" href="custom_showroom/pennant-flags.asp">Custom Pennant Flags</a></h2> 3419</td> 3420</tr> 3421<tr> 3422<td style="width: 665px; vertical-align: top; text-align: left;">A burgee has a unique swallowtail flag shape. Often used in recreational boating. it is also the shape of the state flag of Ohio.</td> 3423<td style="width: 665px; text-align: left; vertical-align: top;">Pennant shaped flags are great for promotional, advertising, and special event use.</td> 3424</tr> 3425</tbody> 3426</table> 3427<table style="float: left;" border="0" width="100%" cellspacing="8" cellpadding="5" align="center"> 3428<tbody> 3429<tr> 3430<td style="text-align: center; vertical-align: middle; width: 400px;"> 3431<h2><a title="Custom Spirit Flags" href="custom_showroom/team-spirit-flags.asp"><img src="images/spirit-flag-button1.png" alt="Custom Spirit Flags" width="402" height="259" border="0" /></a></h2> 3432<h2><a title="Custom Spirit Flags" href="custom_showroom/team-spirit-flags.asp">Custom Spirit Flags</a></h2> 3433</td> 3434<td style="text-align: center; vertical-align: middle; width: 400px;"> 3435<h2><a title="Custom Feather Flags" href="custom_showroom/feather-flag.asp"><img src="images/feather-flag-button.png" alt="Custom Feather Flags" width="400" height="259" border="0" /></a></h2> 3436<h2><a title="Custom Feather Flags" href="custom_showroom/feather-flag.asp">Custom Feather Flags</a></h2> 3437</td> 3438</tr> 3439<tr> 3440<td style="width: 400px; vertical-align: top; text-align: left;">Spirit flags are great for rallying your team to victory. These beautifully made flags will promote team spirit at pep rallies, games, homecoming and other team events.</td> 3441<td style="width: 400px; text-align: left; vertical-align: top;"><span>Feather flags are great attention-getters and crowd stoppers on
3441sidewalks, parking lots or event booths.</span></td> 3442</tr> 3443<tr> 3444<td style="width: 400px; vertical-align: top; text-align: center;"> 3445<h2><a title="Custom Blade Flags" href="custom_showroom/blade-flag.asp"><img src="images/blade-button.png" alt="Custom Blade Flags" width="400" height="259" border="0" /></a></h2> 3446<h2><a title="Custom Blade Flags" href="custom_showroom/blade-flag.asp">Custom Blade Flags</a></h2> 3447<span style="font-weight: 400;"></span></td> 3448<td style="width: 400px; text-align: left; vertical-align: top;"> 3449<h2><a title="Custom Teardrop Flags" href="custom_showroom/teardrop-flag.asp"><img style="display: block; margin-left: auto; margin-right: auto;" src="images/teardrop-button2.png" alt="Custom Teardrop Flags" width="400" height="259" border="0" /></a></h2> 3450<h2 style="text-align: center;"><a title="Custom Teardrop Flags" href="custom_showroom/teardrop-flag.asp">Custom Teardrop Flags</a></h2> 3451</td> 3452</tr> 3453<tr> 3454<td style="width: 400px; vertical-align: top; text-align: left;">Blade flags are popular at sporting events, real estate offices, car lots, gas stations and pop-up events. /td></td> 3455<td style="width: 400px; text-align: left; vertical-align: top;">Teardrop Flags are popular because of their ‘readability.’ With a rotating ground spike, your message receives 360° of visibility.</td> 3456</tr> 3457<tr> 3458<td style="width: 400px; vertical-align: top; text-align: center;"> 3459<h2><a title="Custom Car Flags" href="custom_showroom/car-flags.asp"><img src="images/custom-car-flag-button1.png" alt="Custom Car Flags" width="400" height="259" border="0" /></a></h2> 3460<h2><a title="Custom Car Flags" href="custom_showroom/car-flags.asp">Custom Car Flags</a></h2> 3461</td> 3462<td style="width: 400px; vertical-align: top; text-align: center;"> 3463<h2><a title="Custom Miniature Flags" href="custom_showroom/miniature-flags.asp"><img src="images/miniature-flag-button.png" alt="Custom Miniature Flags" width="400" height="259" border="0" /></a></h2> 3464<h2><a title="Custom Miniature Flags" href="custom_showroom/miniature-flags.asp">Custom Miniature Flags</a></h2> 3465</td> 3466</tr> 3467<tr> 3468<td style="width: 400px; vertical-align: top; text-align: left;"><span>Car flags are great for school spirit, parades, auto dealers, and fundraising. </span></td> 3469<td style="width: 400px; text-align: left; vertical-align: top;">Miniature Flags are great handouts or decorations for both professional and personal occasions.</td> 3470</tr> 3471</tbody> 3472</table> 3473<p> </p> 3474<p style="text-align: center;"> </p> 3475<p style="text-align: center;"> </p> 3476<p style="text-align: center;"> </p> 3477<p style="text-align: center;"> </p> 3478<p style="text-align: center;"> </p> 3479<p style="text-align: center;"> </p> 3480<p style="text-align: center;"> </p> 3481<p style="text-align: center;"> </p> 3482<p style="text-align: center;"> </p> 3483<p style="text-align: center;"> </p> 3484<p style="text-align: center;"> </p> 3485<p style="text-align: center;"> </p> 3486<p style="text-align: center;"> </p> 3487<p style="text-align: center;"> </p> 3488<p style="text-align: center;"><br />Don't know where to start? <strong> </strong><a href="mailto:[email protected]?subject=Question%20about%20custom%20orders">E-mail</a> or call 800-445-0653 to get expert advice and free quotes.<strong> </strong></p> 3489<p style="text-align: left;"> </p> 3490<p style="text-align: center;"><a title="Custom Quote Form" href="customer_service/Custom-Order-Request.asp"><img src="images/orangequotebutton.png" alt="Click here for a free quote!" /></a></p> 3491<p> </p> 3492 </div> 3493 3494 3495 <div id="slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" class="carousel slide"> 3496 <div id="carousel_slide" class="carousel-inner"> 3497 3498 <div class="item active" > 3499 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust9.png?v=3997506342" alt="" class=""> 3500 3501 3502 </div> 3503 3504 <div class="item " > 3505 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust10.png?v=3997506342" alt="" class=""> 3506 3507 3508 </div> 3509 3510 <div class="item " > 3511 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust11.png?v=3997506342" alt="" class=""> 3512 3513 3514 </div> 3515 3516 <div class="item " > 3517 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-1a.jpg?v=3997506342" alt="" class=""> 3518 3519 3520 </div> 3521 3522 <div class="item " > 3523 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-2a.jpg?v=3997506342" alt="" class=""> 3524 3525 3526 </div> 3527 3528 <div class="item " > 3529 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-3a.jpg?v=3997506342" alt="" class=""> 3530 3531 3532 </div> 3533 3534 <div class="item " > 3535 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-4a.jpg?v=3997506342" alt="" class=""> 3536 3537 3538 </div> 3539 3540 <div class="item " > 3541 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-5a.jpg?v=3997506342" alt="" class=""> 3542 3543 3544 </div> 3545 3546 <div class="item " > 3547 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-6a.jpg?v=3997506342" alt="" class=""> 3548 3549 3550 </div> 3551 3552 <div class="item " > 3553 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-7a.jpg?v=3997506342" alt="" class=""> 3554 3555 3556 </div> 3557 3558 <div class="item " > 3559 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-8a.jpg?v=3997506342" alt="" class=""> 3560 3561 3562 </div> 3563 3564 <div class="item " > 3565 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust2.png?v=3997506342" alt="" class=""> 3566 3567 3568 </div> 3569 3570 <div class="item " > 3571 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos10a.jpg?v=3997506342" alt="" class=""> 3572 3573 3574 </div> 3575 3576 <div class="item " > 3577 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos9a.jpg?v=3997506342" alt="" class=""> 3578 3579 3580 </div> 3581 3582 <div class="item " > 3583 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust-logos-11a.jpg?v=3997506342" alt="" class=""> 3584 3585 3586 </div> 3587 3588 <div class="item " > 3589 <img src="https://d3jy065g9mm97j.cloudfront.net/images/customerlogos-12919.jpg?v=3997506342" alt="" class=""> 3590 3591 3592 </div> 3593 3594 <div class="item " > 3595 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust3.png?v=3997506342" alt="" class=""> 3596 3597 3598 </div> 3599 3600 <div class="item " > 3601 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust4.png?v=3997506342" alt="" class=""> 3602 3603 3604 </div> 3605 3606 <div class="item " > 3607 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust5.png?v=3997506342" alt="" class=""> 3608 3609 3610 </div> 3611 3612 <div class="item " > 3613 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust6.png?v=3997506342" alt="" class=""> 3614 3615 3616 </div> 3617 3618 <div class="item " > 3619 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust7.png?v=3997506342" alt="" class=""> 3620 3621 3622 </div> 3623 3624 <div class="item " > 3625 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust8.png?v=3997506342" alt="" class=""> 3626 3627 3628 </div> 3629 3630 <div class="item " > 3631 <img src="https://d3jy065g9mm97j.cloudfront.net/images/customer-goldbergs.png?v=3997506342" alt="" class=""> 3632 3633 3634 </div> 3635 3636 <div class="item " > 3637 <img src="https://d3jy065g9mm97j.cloudfront.net/images/customers-astrazeneca.png?v=3997506342" alt="" class=""> 3638 3639 3640 </div> 3641 3642 <div class="item " > 3643 <img src="https://d3jy065g9mm97j.cloudfront.net/images/customers-seahawks.png?v=3997506342" alt="" class=""> 3644 3645 3646 </div> 3647 3648 <div class="item " > 3649 <img src="https://d3jy065g9mm97j.cloudfront.net/images/del-taco-slide.png?v=3997506342" alt="" class=""> 3650 3651 3652 </div> 3653 3654 <div class="item " > 3655 <img src="https://d3jy065g9mm97j.cloudfront.net/images/cust1.jpg?v=3997506342" alt="" class=""> 3656 3657 3658 </div> 3659 3660 <div class="item " > 3661 <img src="https://d3jy065g9mm97j.cloudfront.net/images/madam-secretary-logo.jpg?v=3997506342" alt="" class=""> 3662 3663 3664 </div> 3665 3666 <div class="item " > 3667 <img src="https://d3jy065g9mm97j.cloudfront.net/images/netflix-customer-logo.png?v=3997506342" alt="" class=""> 3668 3669 3670 </div> 3671 3672 <div class="item " > 3673 <img src="https://d3jy065g9mm97j.cloudfront.net/images/pet-food-express-slide.png?v=3997506342" alt="" class=""> 3674 3675 3676 </div> 3677 3678 <div class="item " > 3679 <img src="https://d3jy065g9mm97j.cloudfront.net/images/sinise-foundation-sli
3679de.jpg?v=3997506342" alt="" class=""> 3680 3681 3682 </div> 3683 3684 <div class="item " > 3685 <img src="https://d3jy065g9mm97j.cloudfront.net/images/tonight-show-slide.jpg?v=3997506342" alt="" class=""> 3686 3687 3688 </div> 3689 3690 </div> 3691 3692 3693 <a href="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" class="carousel-control left" data-slide="prev">‹</a> 3694 <a href="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" class="carousel-control right" data-slide="next">›</a> 3695 3696 <ol class="carousel-indicators"> 3697 <li class="active" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="0"> 3698 </li> 3699 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="1"> 3700 </li> 3701 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="2"> 3702 </li> 3703 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="3"> 3704 </li> 3705 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="4"> 3706 </li> 3707 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="5"> 3708 </li> 3709 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="6"> 3710 </li> 3711 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="7"> 3712 </li> 3713 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="8"> 3714 </li> 3715 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="9"> 3716 </li> 3717 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="10"> 3718 </li> 3719 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="11"> 3720 </li> 3721 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="12"> 3722 </li> 3723 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="13"> 3724 </li> 3725 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="14"> 3726 </li> 3727 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="15"> 3728 </li> 3729 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="16"> 3730 </li> 3731 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="17"> 3732 </li> 3733 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="18"> 3734 </li> 3735 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="19"> 3736 </li> 3737 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="20"> 3738 </li> 3739 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="21"> 3740 </li> 3741 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="22"> 3742 </li> 3743 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="23"> 3744 </li> 3745 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="24"> 3746 </li> 3747 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="25"> 3748 </li> 3749 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="26"> 3750 </li> 3751 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="27"> 3752 </li> 3753 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="28"> 3754 </li> 3755 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="29"> 3756 </li> 3757 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-sli
3757de-to="30"> 3758 </li> 3759 <li class="" data-target="#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D" data-slide-to="31"> 3760 </li> 3761 </ol> 3762 3763 </div> 3764 3765
3765<script> 3766 $(function(){ 3767 $('#slide_show_DDEECD5E7CC949C5B643CA8A14A5AB4D').carousel({interval:3000}); 3768 }); 3769 </script>
3769 3770 3771 </div><!--/#wpc_container--> 3772 </div> 3773 </div> 3774 </div> 3775</div> 3776<footer id="retail-footer-0" class="retail-footer-0 print-hide"> 3777 <div id="template-social"> 3778 <a class="twitter" href="https://twitter.com/flagandbanner" target="_blank"></a> 3779 <a class="facebook" href="https://www.facebook.com/Flagandbannercom" target="_blank"></a> 3780 <a class="youtube" href="https://www.youtube.com/user/FlagandBannerVideos" target="_blank"></a> 3781 <a class="instagram" href="https://www.instagram.com/flagandbanner" target="_blank"></a> 3782 <a class="pinterest" href="https://www.pinterest.com/flagandbanner" target="_blank"></a> 3783 </div> 3784 3785 <div id="footer-newsletter"> 3786 <a href='flags/flag_alerts.asp'>Sign Up For Our Flag Alerts</a> 3787 </div> 3788 3789 <div id="template-footer"> 3790 <div class="container-fluid"> 3791 <ul id="footer-nav" class="footer-nav footer-nav__ul-1"> 3792 <li class="footer-nav__li-1" data-key='0FE1A5E77AEB467CA76F0D8E2E128523'><div class="nav-header"><a href="#" class=""></a></div> 3793 <ul class="footer-nav__ul-2"> 3794 <li class="footer-nav__li-2" data-key='D5B490440A714C8C8D19B1E1BE9CB5B6'><div class="nav-header"><a href="#" class=""></a></div> 3795 <ul class="footer-nav__ul-3"> 3796 <li class="footer-nav__li-3" data-key='A7164488F5DA464DBC4BE92848D1823F'><div class="nav-header"><a href="#" class="">FlagandBanner.com - Main</a></div></li> 3797 <li class="footer-nav__li-3" data-key='4A87C0368AA741159277A2583CB606AE'><div class="nav-header"><a href="#" class="">Arkansas Flag & Banner, Inc.</a></div></li> 3798 <li class="footer-nav__li-3" data-key='A433AC5CC8E5446CA2AF15B72A19E4B7'><div class="nav-header"><a href="#" class="">800 W 9th Street</a></div></li> 3799 <li class="footer-nav__li-3" data-key='FFD717432B4E43369ACA2BC26074FA3E'><div class="nav-header"><a href="#" class="">Little Rock, Arkansas 72201</a></div></li> 3800 <li class="footer-nav__li-3" data-key='930E7A9F77CA41899193B21AA26614AC'><div class="nav-header"><a href="#" class="">TF: 800-445-0653</a></div></li> 3801 <li class="footer-nav__li-3" data-key='10C7636B975A4AAB8E80A311C2F91178'><div class="nav-header"><a href="#" class="">PH: 501-375-7633</a></div></li> 3802 <li class="footer-nav__li-3" data-key='5EA3D3EF5FB942279861E32E83D263F6'><div class="nav-header"><a href="#" class="">FX: 501-375-7638</a></div></li> 3803 <li class="footer-nav__li-3" data-key='82679730E9D840B9A6B6676F0B9097F6'><a href="mailto:[email protected]" class="footer-nav__a-3">Customer Service</a></li> 3804 </ul></li> 3805 <li class="footer-nav__li-2" data-key='2CF62FB1DD184F2B99D350E1769BBE68'><div class="nav-header"><a href="#" class=""></a></div> 3806 <ul class="footer-nav__ul-3"> 3807 <li class="footer-nav__li-3" data-key='4B7F0CC07BA84D328FC9D5EA5EC4F073'><div class="nav-header"><a href="#" class="">FlagandBanner.com - North Miami</a></div></li> 3808 <li class="footer-nav__li-3" data-key='A6C1C18347164ED8ABFFB0E54A370767'><div class="nav-header"><a href="#" class="">13870 W Dixie Hwy</a></div></li> 3809 <li class="footer-nav__li-3" data-key='6617E5DB9ACB4E2FB65DDF0B533BB7F5'><div class="nav-header"><a href="#" class="">North Miami, Florida 33161</a></div></li> 3810 <li class="footer-nav__li-3" data-key='EA4D7F029AB34C9C87E1F4B3842A6F8A'><div class="nav-header"><a href="#" class="">PH: 305-981-9996</a></div></li> 3811 </ul></li> 3812 <li class="footer-nav__li-2" data-key='DD165B19265E4D65B1BAC5333F6BA589'><div class="nav-header"><a href="#" class=""></a></div> 3813 <ul class="footer-nav__ul-3"> 3814 <li class="footer-nav__li-3" data-key='8761E0E9CE454F92A2818BBC070167DA'><a href="content/site-directory.asp" class="footer-nav__a-3">Site Directory</a></li> 3815 </ul></li> 3816 </ul></li> 3817 <li class="footer-nav__li-1" data-key='75D1DBD8065F43D686F94D7DEFBDC464'><div class="nav-header"><a href="#" class=""></a></div> 3818 <ul class="footer-nav__ul-2"> 3819 <li class="footer-nav__li-2" data-key='97E5EA89567C4B6C824E740A90010C8F'><div class="nav-header"><a href="#" class=""></a></div> 3820 <ul class="footer-nav__ul-3"> 3821 <li class="footer-nav__li-3" data-key='02D924752B9F432DADEF8A882009108B'><a href="content/about-us.asp" class="footer-nav__a-3">About Us</a></li> 3822 <li class="footer-nav__li-3" data-key='406E0F6503364724807B5512F40E82F3'><a href="customer_service/helpful_documents.asp#faq" class="footer-nav__a-3">FAQ</a></li> 3823 <li class="footer-nav__li-3" data-key='30885403E2BD4535A7777E2458428DFE'><a href="customer_service/privacy-policy.asp 3824" class="footer-nav__a-3">Privacy Policy</a></li> 3825 <li class="footer-nav__li-3" data-key='E0E19EC9919E4CDCBFEB296657F578EC'><a href="customer_service/terms-and-conditions.asp 3826" class="footer-nav__a-3">Terms & Conditions</a></li> 3827 <li class="footer-nav__li-3" data-key='BE6D8FEF27CA4B75B718599203C93A0D'><a href="customer_service/helpful_documents.asp#custom 3828" class="footer-nav__a-3">Custom FAQ's</a></li> 3829 <li class="footer-nav__li-3" data-key='C8E0C3BA20904F359D29065FF65D255E'><a href="customer_service/helpful_documents.asp#manners" class="footer-nav__a-3">Etiquette</a></li> 3830 <li class="footer-nav__li-3" data-key='FB515FA9C6E0438586AF465D9365AB12'><a href="customer_service/helpful_documents.asp#howto" class="footer-nav__a-3">How To's</a></li> 3831 <li class="footer-nav__li-3" data-key='45CD2CFFEB674F30AB1221544503FAC4'><a href="customer_service/helpful_documents.asp#order" class="footer-nav__a-3">Order Information</a></li> 3832 <li class="footer-nav__li-3" data-key='AE1DCDB8F6CF4F22AF5CFD6FD17A0D23'><a href="customer_service/helpful_documents.asp#information" class="footer-nav__a-3">Flag Information</a></li> 3833 <li class="footer-nav__li-3" data-key='87BF440420BA454B95CCD39414A84636'><a href="customer_service/helpful_documents.asp#gallery" class="footer-nav__a-3">Galleries</a></li> 3834 <li class="footer-nav__li-3" data-key='5DBBAAF2F0E84D29A1F10D1566B86EB6'><a href="press-center/index.asp" class="footer-nav__a-3">Press Center</a></li> 3835 </ul></li> 3836 </ul></li> 3837</ul> 3838 </div> 3839 </div> 3840 3841 <div id="template-logos">
3842 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3843 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3844 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3845 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3846 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3847 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3848 <span class="template-logos__generated-logo"><!-- Generated Image --></span> 3849 <span><img src="https://d3jy065g9mm97j.cloudfront.net/images/fmaa_logo.jpg?v=3997506342" style="height: 66px;" alt="FMAA Certified" "=""></span> 3850 <span><a href="https://www.shopperapproved.com/reviews/flagandbanner.com" class="shopperlink new-sa-seals placement-385"><img src="//www.shopperapproved.com/seal/9380/385-sa-seal.gif" style="border-radius: 4px;" alt="Customer Reviews" oncontextmenu="var d = new Date(); alert('Copying Prohibited by Law - This image and all included logos are copyrighted by Shopper Approved \251 '+d.getFullYear()+'.'); return false;" /></a>
3850<script type="text/javascript">(function() { var js = window.document.createElement("script"); js.innerHTML = 'function openshopperapproved(o){var e="Microsoft Internet Explorer"!=navigator.appName?"yes":"no",n=screen.availHeight-90,r=940;return window.innerWidth<1400&&(r=620),window.open(this.href,"shopperapproved","location="+e+",scrollbars=yes,width="+r+",height="+n+",menubar=no,toolbar=no"),o.stopPropagation&&o.stopPropagation(),!1}!function(){for(var o=document.getElementsByClassName("shopperlink"),e=0,n=o.length;e<n;e++)o[e].onclick=openshopperapproved}();'; js.type = "text/javascript"; document.getElementsByTagName("head")[0].appendChild(js);var link = document.createElement('link');link.rel = 'stylesheet';link.type = 'text/css';link.href = "//www.shopperapproved.com/seal/385.css";document.getElementsByTagName('head')[0].appendChild(link);})();</script>
3850</span> 3851 <span>
3851<script type="text/javascript" src="https://sealserver.trustwave.com/seal.js?style=invert&code=873928560ca511e0b34b005056b201e5"></script>
3851</span> 3852 </div> 3853 <div id="template-colophon"> 3854 <div class="container-fluid"> 3855 <div id="copyright">©2026. FlagandBanner.com All rights reserved<br> <a href="https://www.flagandbanner.com/child_products.asp">Sitemap</a></div> 3856 <div id="pbwsp"> 3857 <p>Powered by <a href="https://www.cimcloud.com" rel="nofollow" target="_blank">CIMcloud</a></p></div> 3858 </div> 3859 </div> 3860</footer> 3861<div class="global-body-append"> 3862 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="hide"> 3863 <symbol id="icon-user-circle-o" viewBox="0 0 28 28"> 3864 <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> 3865 </symbol> 3866 <symbol id="icon-address-card" viewBox="0 0 32 28"> 3867 <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> 3868 </symbol> 3869 <symbol id="icon-building" viewBox="0 0 22 28"> 3870 <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> 3871 </symbol> 3872 <symbol id="icon-currency-dollar" viewBox="0 0 20 20"> 3873 <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> 3874 </symbol> 3875 <symbol id="icon-check-square" viewBox="0 0 24 28"> 3876 <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> 3877 </symbol> 3878 <symbol id="icon-life-bouy" viewBox="0 0 28 28"> 3879 <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.
3879641-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> 3880 </symbol> 3881 <symbol id="icon-calendar-plus-o" viewBox="0 0 26 28"> 3882 <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> 3883 </symbol> 3884 <symbol id="icon-sticky-note" viewBox="0 0 24 28"> 3885 <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> 3886 </symbol> 3887 <symbol id="icon-document-add" viewBox="0 0 32 32"> 3888 <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> 3889 </symbol>
3890 <symbol id="icon-document-add1" viewBox="0 0 32 32"> 3891 <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> 3892 </symbol> 3893</svg> 3894</div><div class="retail-scripts-bot"> 3895 <div class="global-scripts"> 3896
3896<script> 3897 3898 var jsConfig = { 3899 static_pages: { 3900 content_key: 'B5C8B43721D042E3BE244C0AC84508EA', 3901 content_type: 'webpage' 3902 } 3903 } 3904 if(processPageTitle){ 3905 //$('.page-header h1').html(' ').show(); 3906 var originalPageTitle = $('.page-header h1').html(); 3907 var originalSubmitText = $('.form-actions button').html(); 3908 var pageTitleText = ""; 3909 if(pageTitleText.trim() != ''){ 3910 $('.page-header h1').html(pageTitleText); 3911 $('.form-actions button').html( 'Save ' + pageTitleText); 3912 if(isWorkerDomain) pageTitleText = sitename.toUpperCase() + ' - ' + pageTitleText; 3913 document.title = pageTitleText; 3914 }else if (originalPageTitle){ 3915 pageTitleText = originalPageTitle; 3916 $('.form-actions button').html( 'Save ' + pageTitleText); 3917 if(isWorkerDomain) pageTitleText = sitename.toUpperCase() + ' - ' + pageTitleText; 3918 document.title = pageTitleText; 3919 } 3920 $('.page-header h1').show(); 3921 $('.form-actions button').show(); 3922 } 3923 </script>
3923 3924 3925
3925<script src="../hooks/js_custom_functions.js?4c33272"></script>
3925 3926
3926<script src="js/vendor/stretchy.min.js?4c33272" data-filter=".stretchy, .stretchy *"></script>
3926<!-- Google Tag Manager (noscript) --> 3927<noscript><iframe src="https://sgtm.flagandbanner.com/ns.html?id=GTM-TDD95N" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 3928<!-- End Google Tag Manager (noscript) --> 3929
3930<script> 3931"use strict"; 3932 3933 3934 3935window.addEventListener('DOMContentLoaded', function() { 3936 let url = new URL(window.location); 3937 let paramsToRemove = ["_gl", "gcl_au"]; 3938 3939 paramsToRemove.forEach(param => url.searchParams.delete(param)); 3940 3941 window.history.replaceState({}, document.title, url.pathname + url.search); 3942}); 3943 3944</script>
3944 3945 3946 <noscript class="noscript"> 3947 WARNING: You will not be able to place an order or use most features of this site with JavaScript disabled 3948 </noscript> 3949</div> 3950
3951<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>
3951 3952
3953<script src="/js/bundles/coreBot.js?4c332722dd6231439a1b8843ea4e6344b958c87f" ></script>
3953 3954 3955
3956<script src="/js/bundles/coreBotPlugins.js?4c332722dd6231439a1b8843ea4e6344b958c87f" ></script>
3956 3957
3957<script src="../js/retail.js?4c33272"></script>
3957 3958
3958<script> 3959 // Execute when DOM ready 3960 jQuery(function ($) { 3961 //Plus 3962 $('.linkset.plus li.link-parent').click(function (e) { 3963 3964 if (e.target == this) { 3965 if ($(this).hasClass('open')) { 3966 // Close this and children 3967 $(this).removeClass('open'); 3968 $(this).find('li').removeClass('open'); 3969 } else { 3970 $(this).siblings('li').removeClass('open'); 3971 $(this).siblings('li').find('li').removeClass('open'); 3972 $(this).addClass('open'); 3973 } 3974 } 3975 }); 3976 }); 3977</script>
3977 3978</div> 3979 3980<div id="appLoadingWidget" class="sk-three-bounce--full-screen app-loading hide"> 3981 <div class="sk-three-bounce"> 3982 <div class="sk-child sk-bounce1"></div> 3983 <div class="sk-child sk-bounce2"></div> 3984 <div class="sk-child sk-bounce3"></div> 3985 </div> 3986</div> 3987 3988 <!-- KO Templates --> 3989
3990<script> 3991 var oConfig = { 3992 3993 sessionData : { 3994 sc_id : "89D17E098FCD447A874C26E29C88E23B", 3995 sessionKey : "DCABF2A60CB54D4CA796FBEA91F9B757", 3996 storefrontUrl : "https://www.flagandbanner.com", 3997 orderfrontUrl : "https://www.flagandbanner.com", 3998 cdnUrl : "https://d3jy065g9mm97j.cloudfront.net", 3999 isSuperUserSession : false, 4000 cartPage : "showcart.asp" 4001 } 4002 }; 4003 4004 const additionalFields = [ 4005 'content1', 4006 'content2', 4007 'content3', 4008 'content4', 4009 'opt1', 4010 'opt2', 4011 'opt3', 4012 'opt4', 4013 'opt5', 4014 'opt6', 4015 'opt7', 4016 'opt8', 4017 'opt9' 4018 ]; 4019</script>
4019 4020<div class="catalog-templates-scripts"> 4021 4022 4023 4024 4025
4025<script> 4026 utils.isMainProduct = function (product) { 4027 return product && ko.unwrap(viewModel.mainProduct) === product; 4028 }; 4029 4030 utils.buildQuickAddLink = function(product){ 4031 var link = product.link(); 4032 var orderKey = utils.getParameter('o_key'); 4033 if(orderKey){ 4034 orderKey = '&o_key=' + orderKey; 4035 } 4036 if(link.includes('?')){ 4037 link += '&quickadd=true' + orderKey; 4038 }else{ 4039 link += '?quickadd=true' + orderKey; 4040 } 4041 return link; 4042 }; 4043 4044 utils.setCookie = function (name, value) { 4045 //need to also set expiry date? 4046 document.cookie = name + '=' + value + ';path=/;'; 4047 }; 4048 4049 // www.the-art-of-web.com/javascript/getcookie/ 4050 utils.getCookie = function (name) { 4051 var re = new RegExp('\\b' + name + '=([^;]+)'); 4052 var value = re.exec(document.cookie); 4053 return value ? unescape(value[1]) : undefined; 4054 }; 4055 4056 utils.isActiveQuote = ((utils.getParameter('modalaction') == 'addProduct' || utils.getParameter('modalaction', parent) == 'addProduct') && "".length == 32) && "" != "89D17E098FCD447A874C26E29C88E23B"; 4057 4058 //http://stackoverflow.com/questions/5999118/add-or-update-query-string-parameter 4059 utils.setParameter = function (key, value, uriArg) { 4060 var uri = uriArg || window.location.toString(); 4061 var re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i'); 4062 var separator; 4063 if (uri.indexOf('?') === -1) { 4064 separator = '?'; 4065 } else { 4066 if (uri[uri.length - 1] === '?') { 4067 separator = ''; 4068 } else { 4069 separator = '&'; 4070 } 4071 } 4072 if (uri.match(re)) { 4073 return uri.replace(re, '$1' + key + '=' + value + '$2'); 4074 } else { 4075 return uri + separator + key + '=' + value; 4076 } 4077 }; 4078 4079 utils.handleImageError = function (img) { 4080 handleImageError(img, oConfig.noImagePath); 4081 }; 4082 4083 utils.drawHidePriceMessage = function(){ 4084 return ""; 4085 } 4086 4087 utils.removeHTML = function(text){ 4088 return $(text).text(); 4089 } 4090 4091 utils.decodeHTML = function(text) { 4092 return $('<textarea>').html(text).text() 4093 }; 4094 4095 utils.getStoredBreadcrumbs = function() { 4096 try { 4097 return JSON.parse(localStorage.getItem('breadcrumbs')); 4098 } catch(e) { 4099 return null; 4100 } 4101 }; 4102 4103 utils.setStoredBreadcrumbs = function(obj) { 4104 try { 4105 localStorage.setItem('breadcrumbs', JSON.stringify(obj)); 4106 } catch(e) { 4107 // nothing to do if it didn't work 4108 console.error('failed to save breadcrumbs'); 4109 } 4110 }; 4111 4112 utils.breadCrumbProperty = function(link) { 4113 if(link == '' || link === null){ 4114 return ''; 4115 } else { 4116 return 'itemListElement'; 4117 } 4118 }; 4119 4120 utils.breadCrumbItemType = function(link) { 4121 if(link == '' || link === null){ 4122 return ''; 4123 } else { 4124 return 'ListItem'; 4125 } 4126 }; 4127 4128 utils.pageUrl = location.pathname + location.search; 4129 if(utils.pageUrl.charAt(0) == '/') { 4130 utils.pageUrl = utils.pageUrl.substring(1); 4131 } 4132 utils.loginUrl = 'security_logon.asp?autopage=' + encodeURIComponent(utils.pageUrl); 4133 4134 utils.formatMoney = (function (positiveExample, negativeExample) { 4135 /* 4136 This takes an example of a formatted currency and returns a function 4137 to format numbers in that same format. The first argument is the 4138 number 1111.2222 formatted with the desired default number of 4139 decimals. The second argument is the additive inverse of the first. 4140 For example: 4141 $1,111.22 4142 ¥ 1,111.22 4143 €1.111,22 4144 1 111,22F 4145 */ 4146 'use strict'; 4147 function buildFormatter(example) { 4148 var thousandsSeperator = getGroup(/1([^1]?)1/); 4149 var decimalSymbol = getGroup(/1([^12]?)2/); 4150 var decimalPlaces = (example.match(/2/g) || []).length; 4151 var thousandsRegex = /(\d)(?=(?:\d{3})+$)/g; 4152 4153 var escapedDecimalSymbol = _.escapeRegExp(decimalSymbol); 4154 var symbolRegex = new RegExp('^([^1' + escapedDecimalSymbol + ']*).+?([^12' + escapedDecimalSymbol + ']*)$'); 4155 var symbolMatch = symbolRegex.exec(example); 4156 var prefix = symbolMatch ? symbolMatch[1] || '' : ''; 4157 var suffix = symbolMatch ? symbolMatch[2] || '' : ''; 4158 var infoLost = 0; 4159 4160 function getGroup(pattern) { 4161 var match = pattern.exec(example) 4162 return match ? match[1] : ''; 4163 } 4164 4165 function decimalToString(decimal, places) { 4166 if (!places) { 4167 return ''; 4168 } else { 4169 var result = getZeroString(places); 4170 4171 if (decimal) {
4172 // Converting to an integer and rounding helps with 4173 // floating point errors. 4174 var int = Math.round(decimal * Math.pow(10, places)); 4175 // Because leading zeroes will be dropped after 4176 // converting to integer, the string needs to be 4177 // padded with zeroes after being converted to a 4178 // string. 4179 result = (result + int.toString()).slice(-places); 4180 } 4181 if(int==Math.pow(10,places)) { 4182 // in this case, we have to track a +1 to add to the result because "100" sliced down to 2 places loses info 4183 /* 4184 * 2020-07-22 - EJ - More info: This is due to things like utils.formatPrice(1.995, 2) returning 1.00 instead 4185 * of 2.00 or utils.formatPrice(1.9995, 3) returning 1.000 instead of 2.000 4186 * This is because the whole number is truncated, then the decimal is rounded and only the decimal portion 4187 * is added back to the whole number portion. 4188 * This means the rounded decimal portion is always 1 or less. If it's less than 1 (ex .89) this works. 4189 * However, if it's 1.000, it would "lose" 1 since only the decimal portion is added back. 4190 * PS - Don't ask me about the original design, I didn't design it that way. I only corrected the "if" 4191 * statement above where it was hard-coded to 100 to be Math.pow(10,places) so it would work when 4192 * rounded to something other than 2 decimal places. 4193 */ 4194 infoLost = 1; 4195 } else { 4196 infoLost = 0; 4197 } 4198 4199 return decimalSymbol + result; 4200 } 4201 } 4202 4203 function getZeroString(length) { 4204 var pow = Math.pow(10, length); 4205 return pow.toString().slice(1); 4206 } 4207 4208 function addThousandsSeperator(integer) { 4209 return (integer + infoLost).toString().replace(thousandsRegex, '$1' + thousandsSeperator); 4210 } 4211 4212 return function (value, places) { 4213 places = typeof places === 'undefined' ? decimalPlaces : parseInt(places); 4214 4215 // Truncate the value to get the integer portion. 4216 var integer = value | 0; 4217 var decimal = decimalToString( ((value * 1000) % (1 * 1000)) / 1000, places); //do first because we need to know if info was lost. 4218 var number = addThousandsSeperator(integer) + decimal; 4219 return prefix + number + suffix; 4220 } 4221 } 4222 4223 var formatPositive = buildFormatter(positiveExample); 4224 var formatNegative = buildFormatter(negativeExample); 4225 4226 return function (value, places) { 4227 value = parseFloat(ko.unwrap(value)); 4228 if (isNaN(value)) return value.toString(); 4229 return (value < 0 ? formatNegative : formatPositive)(Math.abs(value), places); 4230 } 4231 }('$1,111.22', '($1,111.22)')); 4232 4233 utils.formatPrice = _.partialRight(utils.formatMoney, parseInt(2) || 2); 4234 4235 utils.plural = function (singularForm, quantifier, includeQuantity) { 4236 var quantifierValue = ko.unwrap(quantifier); 4237 var quantity = _.isArray(quantifierValue) ? quantifierValue.length : quantifier; 4238 return (includeQuantity ? quantity + ' ' : '') + attache.plural(singularForm, quantity); 4239 }; 4240 4241 utils.atcListButtonText = function() { 4242 if(utils.isActiveQuote) { 4243 return 'Add to ' + oConfig.labels.savedCarts; 4244 } else { 4245 return oConfig.labels.addToCartList || 'Add to Cart'; 4246 } 4247 }; 4248 4249 utils.resetATCForm = function() { 4250 if(!runHook('catalogTemplatesOverrideResetATCForm', { utils: this })) { 4251 document.getElementById("atc_form").reset(); 4252 _.forEach(viewModel.results(), function(result) { 4253 if (setSelectedQty()) { 4254 result.selectedQty(result.minQty() || 1); 4255 }else{ 4256 result.selectedQty(undefined); 4257 } 4258 result.selectedQty.notifySubscribers(); 4259 }); 4260 } 4261 } 4262 4263 utils.addToCart = function (details, cart, parentKey, useInstances) { 4264 4265 function getQueryStringParameters() { 4266 var params = { 4267 type : 'v200add', 4268 sc_id : oConfig.overrideCartKey || oConfig.sessionData.sc_id, 4269 s_key : oConfig.sessionData.sessionKey, 4270 s_url : oConfig.sessionData.storefrontUrl, 4271 o_url : oConfig.sessionData.orderfrontUrl, 4272 createsessioncookie : '1', 4273 noredirect : '1', 4274 l_ws_key : '', 4275 mobile : 'no', 4276 action : 'postlogic', 4277 modal : utils.getParameter("modal"), 4278 modalaction : utils.getParameter("modalaction"), 4279 useinstances: useInstances, 4280 postProcess: true 4281 }; 4282 4283 // Only one order detail can be edited at a time, so if there 4284 // are more than one, choose an arbitrary one to edit.
4285 var editedOrderDetail = _.find(details, 'configuratorEditData'); 4286 if (editedOrderDetail) params.odeditkey = editedOrderDetail.configuratorEditData.od_id; 4287 4288 if (cart) { 4289 _.assign(params, { 4290 type: 'add-to-saved-cart', 4291 o_id: cart.key, 4292 nickname: cart.nickname 4293 }); 4294 } 4295 4296 return params; 4297 } 4298 4299 function getPostData() { 4300 var data = {}; 4301 var productKeys = []; 4302 var instanceKeys = []; 4303 var instancesWithKeys = {}; 4304 4305 //' Force use instances on if it's off / undefined and we detect duplicate p_keys 4306 if(!useInstances && details.length) { 4307 var distinctProductKeys = details.reduce(function(distinctValues, detail, index) { 4308 if(distinctValues.indexOf(detail.key()) < 0) 4309 { 4310 distinctValues.push(detail.key()); 4311 } 4312 return distinctValues; 4313 }, []); 4314 4315 if(distinctProductKeys && distinctProductKeys.length !== details.length) { 4316 //' Always use instances if we're adding the same product key to cart in one post 4317 useInstances = true; 4318 } 4319 } 4320 4321 buildConfiguratorData = function(product) { 4322 4323 /* config_json field example: 4324 { 4325 "question":"F4E82B1A5F5A4A3F915B6618A766754F", 4326 "questionText":"STRIKE (required)", 4327 "name":"6800_000_10", 4328 "answer":"790BA1B41D6E48ECB2A825CB02EDAB93", 4329 "answerText":"A - 4-7/8 ASA Strike", 4330 "question_erp_code":"10_001", 4331 "answer_erp_code":"01", 4332 "question_status":"True" 4333 } 4334 4335 Full config_json structure: 4336 { choices: [ 4337 { field1 }, 4338 { field2 } 4339 ], 4340 configType: 'cartoptions' // or 'configurator' 4341 } 4342 */ 4343 4344 /* 4345 ' We're setting configType based on the customForm value, 4346 ' but we should never hit this code if it's true until we 4347 ' put configurator in KO. This is here just in case or 4348 ' for future use. 4349 ' customForm not be ndefined if not on the product detail page. 4350 */ 4351 if(oConfig.showProductConfigurator && typeof customForm !== 'undefined' && !!customForm) { 4352 configType = 'configurator'; 4353 } else { 4354 configType = 'cartoptions'; 4355 } 4356 var configJson = { 4357 choices: [], 4358 configType: configType 4359 }; 4360 var cartOptions = ''; 4361 if(product.questions && product.questions().length > 0) { 4362 product.questions().forEach(function(question) { 4363 configJsonQuestion = { 4364 question: question.q_key(), 4365 name: question.questionText(), 4366 questionText: question.questionText(), 4367 answerText: question.selectedAnswer(), 4368 question_status: true 4369 }; 4370 if(question.erpCode()) { 4371 configJsonQuestion["question_erp_code"] = question.erpCode(); 4372 } 4373 configJson.choices.push(configJsonQuestion); 4374 cartOptions += question.questionText() + "~" + question.selectedAnswer() + "|" 4375 }); 4376 } 4377 return { 4378 configJson: configJson, 4379 cartOptions: cartOptions.slice(0, -1) // trim trailing pipe 4380 }; 4381 } 4382 4383 handleAddOnProducts = function(item){ 4384 addOnProducts = []; 4385 if(item.selectedProduct().selectedAddOn && item.selectedProduct().selectedAddOn()){ 4386 addOnProducts.push(item.selectedProduct().selectedAddOn()); 4387 }else if(item.selectedProduct().selectedAddOns && item.selectedProduct().selectedAddOns().length > 0){ 4388 _.forEach(item.selectedProduct().selectedAddOns(), function(item){ 4389 addOnProducts.push(item); 4390 }) 4391 } 4392 4393 _.forEach(addOnProducts, function(item){ 4394 //handle the add to cart for addons 4395 prepareAddToCart(item); 4396 }) 4397 } 4398 4399 prepareAddToCart = function(product){ 4400 var productKey = product.key(); 4401 var minQty = product.minQty() || 1; 4402 var uom = ko.toJS(product.selectedUom()); 4403 var lineKey = productKey; 4404 4405 if(useInstances) { 4406 lineKey = utils.createGuid(); 4407 var tempInstanceKey = product.instance || utils.createGuid(); 4408 4409 product.instanceKey = tempInstanceKey; 4410 product.lineKey = lineKey; 4411 4412 instanceKeys.push(tempInstanceKey); 4413 4414 if(!instancesWithKeys[tempInstanceKey]) { 4415 instancesWithKeys[tempInstanceKey] = []; 4416 } 4417 4418 instancesWithKeys[tempInstanceKey].push(lineKey); 4419 4420 data['instance_' + lineKey] = tempInstanceKey; 4421 data['p_id_' + lineKey] = productKey; 4422 data['instance_key_set'] = '1'; 4423 4424 if(product.isCarrier){ 4425 data["row_display_case_" + lineKey] = "group-parent"; 4426 data['remove_type_' + lineKey] = 'instance'; 4427 }else if(product.carrier && product.carrier.trim() != ''){ 4428 data["remove_type_" + lineKey] = "hide"; 4429 data["qty_display_type_" + lineKey] = "text"; 4430 data["row_display_case_" + lineKey] = "group-child"; 4431 if(product.qtyType == 'ratio') { 4432 data['qty_control_from_' + lineKey] = 'parent'; 4433 data['multiplier_on_parent_qty_' + lineKey] = product.qtyMultiplier; 4434 } 4435 }else{ 4436 data['remove_type_' + lineKey] = 'instance'; 4437 } 4438 } 4439 4440 data['qty_' + lineKey] = product.selectedQty() || minQty;
4441 if(!!uom){ 4442 data['uom_' + lineKey] = uom.description; 4443 if(uom.hasOwnProperty("UomId")) data['uom_id_' + lineKey] = uom.UomId; 4444 data['uom_conversion_' + lineKey] = uom.uom_conversion ?? 1.0; 4445 } 4446 data['pw_id_' + lineKey] = ko.unwrap(product.selectedWarehouse().key) || oConfig.defaultWarehouse; 4447 4448 if(product.type == 'child') { 4449 if(parentKey && product.key() !== parentKey) { 4450 data['parent_p_id_' + lineKey] = parentKey; 4451 } else if(product.parents && product.parents().length > 0){ 4452 data['parent_p_id_' + lineKey] = product.parents()[0].key(); 4453 } 4454 } 4455 4456 4457 data['url_' + lineKey] = product.link(); 4458 data['minqty_' + lineKey] = product.minOrderQty(); 4459 data['maxqty_' + lineKey] = product.maxOrderQty(); 4460 data['qty_increment_' + lineKey] = product.stepQty(); 4461 4462 _.assign(data, buildConfiguratorPostData(productKey)); 4463 if (minQty && minQty != oConfig.defaultMinimumQuantity) data['min_order_qty_' + lineKey] = product.minOrderQty(); 4464 4465 if(product.configuratorEditData && product.configuratorEditData.lineNumber) { 4466 data['line_number_' + lineKey] = product.configuratorEditData.lineNumber; 4467 } 4468 4469 if(product.configuratorEditData && product.configuratorEditData.minQty) { 4470 data['minqty_' + lineKey] = product.configuratorEditData.minQty; 4471 } 4472 4473 if(product.configuratorEditData && product.configuratorEditData.maxQty) { 4474 data['maxqty_' + lineKey] = product.configuratorEditData.maxQty; 4475 } 4476 4477 if(product.configuratorEditData && product.configuratorEditData.qtyIncrement) { 4478 data['qty_increment_' + lineKey] = product.configuratorEditData.qtyIncrement; 4479 } 4480 4481 if(product.configuratorEditData && product.configuratorEditData.removeType) { 4482 data['remove_type_' + lineKey] = product.configuratorEditData.removeType; 4483 } 4484 4485 if(product.configuratorEditData && product.configuratorEditData.priceCalcType) { 4486 data['price_calc_type_' + lineKey] = product.configuratorEditData.priceCalcType; 4487 if(product.configuratorEditData.priceCalcType == 'fixed') { 4488 data['price_' + lineKey] = product.configuratorEditData.price; 4489 } 4490 } 4491 4492 if(product.questions && product.questions().length > 0 && product.hasCartOptions()) { 4493 var configData = buildConfiguratorData(product); 4494 data['config_json_' + lineKey] = JSON.stringify(configData.configJson); 4495 data['cart_option_' + lineKey] = configData.cartOptions; 4496 } 4497 4498 if (product.pic) { 4499 data['pic_t_' + lineKey] = product.pic; 4500 } 4501 4502 additionalFields.forEach(function(field){ 4503 if(product[field] != ''){ 4504 data[field+'_'+lineKey] = product[field]; 4505 } 4506 }); 4507 4508 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 4509 } 4510 4511 _.forEach(details, function (item) { 4512 4513 if(oConfig.detailConfig.useAddOnProducts && item.showAddOns){ 4514 handleAddOnProducts(item); 4515 } 4516 4517 prepareAddToCart(item.selectedProduct()); 4518 runHook('getPostDataBeforeReturn', { self: self, data: data, product: item.selectedProduct(), productKeys: productKeys }); 4519 }); 4520 4521 data.keys = _.uniq(productKeys).join(','); 4522 4523 if(instanceKeys.length) { 4524 data.instances = _.uniq(instanceKeys).join(','); 4525 4526 for(key in instancesWithKeys) { 4527 data[key + '_keys'] = instancesWithKeys[key].join(','); 4528 } 4529 } 4530 4531 return data; 4532 } 4533 4534 function getAjaxConfig() { 4535 return { 4536 url: 'i_i_add_to_cart.asp?' + $.param(getQueryStringParameters()), 4537 type: 'POST', 4538 data: $.param(getPostData(), true), // true forces jquery to not add brackets to array keys 4539 headers: { 4540 'X-Requested-With': 'XMLHttpRequest', 4541 'Accept': 'application/json, text/plain, * / *', 4542 'Content-Type': 'application/x-www-form-urlencoded' 4543 } 4544 }; 4545 } 4546 4547 function logSummary() { 4548 var cartName = cart ? ' "' + cart.nickname + '"' : ''; 4549 console.log('Products added to cart' + cartName + ':\n' + _.map(detail
4549s, function (product) { 4550 return '\tQty: ' + (product.selectedQty() || 1) + ' - ' + product.name(); 4551 }).join('\n')); 4552 } 4553 4554 function successHandler(responseData, status, request) { 4555 var cartLines = JSON.parse(responseData)[1].detailLines; 4556 var newCart = []; 4557 _.each(cartLines, function(line){ 4558 newCart.push({ 4559 prod_key: line.productID, 4560 parent_p_id: line.parentProductID, 4561 qty: line.qty, 4562 od_key: line.orderDetailKey 4563 }) 4564 }); 4565 4566 if((oConfig.t_ga4 && oConfig.t_ga4_analytics != '') || (!oConfig.t_ga4_in_gtm && oConfig.t_gtm)) { 4567 try{ 4568 var gtmProducts = []; 4569 var line_total = 0; 4570 _.each(details, function(item){ 4571 4572 var gtmProduct = { 4573 item_id: item.sku(), 4574 item_name: item.name(), 4575 currency: "USD", 4576 price: Number(item.unitPrice()), 4577 quantity: Number(item.selectedQty()) 4578 } 4579 gtmProducts.push(gtmProduct); 4580 4581 line_total = Number(item.selectedQty()) * item.unitPrice(); 4582 }); 4583 4584 if (gtmProducts.length >= 1) { 4585 4586 window.dataLayer = window.dataLayer || []; 4587 function gtag(){dataLayer.push(arguments);} 4588 4589 gtag("event", "add_to_cart", { 4590 currency: "USD", 4591 value: line_total, 4592 items: gtmProducts 4593 }); 4594 } 4595 } catch (err){ 4596 console.log(err); 4597 } 4598 }else if(oConfig.t_gtm) { 4599 var gtmProducts = []; 4600 _.forEach(details, function (item) { 4601 4602 var gtmProduct = { 4603 'name': item.name(), 4604 'id': item.sku(), 4605 'price': item.unitPrice(), 4606 'quantity': Number(item.selectedQty()) 4607 } 4608 gtmProducts.push(gtmProduct); 4609 }); 4610 4611 if (gtmProducts.length >= 1) { 4612 window.dataLayer.push({ 4613 'event': oConfig.t_gtm_add_to_cart_event_name, 4614 'ecommerce': { 4615 'currencyCode': 'USD', 4616 'add': { 4617 'products': gtmProducts 4618 } 4619 }, 4620 'customer': { 4621 'email': cimcloud.session.email, 4622 'firstname': cimcloud.session.firstName, 4623 'lastname': cimcloud.session.lastName 4624 } 4625 }); 4626 } 4627 } 4628 4629 if(oConfig.isModal) { 4630 parent.modal.done([newCart]); 4631 try{ 4632 parent.fncReloadCartWindow(); 4633 }catch(err){ 4634 } 4635 4636 var page = window.parent ? window.parent.location.pathname.split("/").pop() : window.location.pathname.split("/").pop(); 4637 if(!page.includes("payment.asp")) {
4638 parent.top.utils.toastrATC(details, newCart); 4639 } 4640 }else{ 4641 viewModel.activeCart(newCart); 4642 4643 if(viewModel.mainProduct && viewModel.mainProduct.configuratorEditData) { 4644 window.location = oConfig.sessionData.cartPage; 4645 return; 4646 } 4647 if(!cart) { 4648 try{ 4649 fncReloadCartWindow(); 4650 }catch(err){ 4651 4652 } 4653 if(typeof ofConfig === "undefined" || !ofConfig.stopToastrATC) { 4654 utils.toastrATC(details, cart); 4655 } 4656 } else { 4657 utils.modalATC(cart, data, details); 4658 } 4659 if(oConfig.pageName == 'pc_combined_results.asp' && isActiveLayout('list')) { 4660 utils.resetATCForm(); 4661 } 4662 4663 logSummary(); 4664 4665 toggleLoadingWidget(false); 4666 4667 //render promo messaging template and display if applicable. 4668 element = utils.renderTemplateToContainer('catalog.promo_bar', data); 4669 4670 runHook('addToCartSuccessHandler', { self: self, responseData: responseData, details: details }); 4671 } 4672 } 4673 4674 function errorHandler(responseData, status, request) { 4675 logSummary(); 4676 4677 var errorToastrConfig = { 4678 'closeButton': true, 4679 'newestOnTop': true, 4680 'positionClass': 'toast-top-right', 4681 'preventDuplicates': false, 4682 'showDuration': 200, 4683 'hideDuration': 1000, 4684 'tapToDismiss': true, 4685 'timeOut': 3000, 4686 'extendedTimeOut': 1000 4687 } 4688 4689 toggleLoadingWidget(false); 4690 4691 console.log(responseData); 4692 4693 toastr.error( 4694 'Unable to add product to cart', 4695 'There was an error', 4696 errorToastrConfig 4697 ); 4698 4699 } 4700 var bPass = true; 4701 4702 // TODO: add UoM support (qty_display, etc). Fields aren't available on the UoM Price objects yet. 4703 if (!_.isArray(details)) { 4704 details = [ details ]; 4705 } 4706 var data = { 4707 details: details, 4708 cart: cart 4709 }; 4710 4711 var questionsValid = true; 4712 4713 details.some(function(detail) { 4714 if(detail.hasOwnProperty("questionsHaveValidAnswers")) { 4715 questionsValid = detail.questionsHaveValidAnswers(); 4716 4717 if(!questionsValid) { 4718 detail.atcErrorText("Required option fields missing."); 4719 } else { 4720 detail.atcErrorText(""); 4721 } 4722 4723 if(!questionsValid && detail.hasOwnProperty("currentParent")) { 4724 detail.currentParent().rowsAtcAttempted(true); 4725 } 4726 } 4727 return !questionsValid; 4728 }); 4729 4730 if(!questionsValid) { 4731 return false; 4732 } 4733 4734 if(details.length > 0 && details[0].useConfigurator && details[0].useConfigurator()){ 4735 /* 4736 doing an [eval] on an undefined throws an error. 4737 so, we have to try-catch. 4738 The template may be overriden to allow a product (with configurator) 4739 to be added to cart w/o any config options selected. 4740 */ 4741 try { 4742 if(!eval('formValidation' + oConfig.formValidationKey).check()){ 4743 bPass = false; 4744 } 4745 } catch(e) { 4746 //not using FormBuilder 4747 } 4748 }else if(details.length <= 0) { 4749 bPass = false; 4750 } 4751 4752 if(bPass){ 4753 toggleLoadingWidget(true); 4754 cart = ko.toJS(cart); 4755 4756 var promise = $.ajax(getAjaxConfig()) 4757 .error(errorHandler) 4758 .done(successHandler); 4759 4760 return promise; 4761 4762 }else{ 4763 return false; 4764 } 4765 }; 4766 4767 utils.toastrATC = function(details, cart) { 4768 if(utils.isActiveQuote){ 4769 var sPage = oConfig.sessionData.orderfrontUrl + '/' + "payment.asp?o_key=" + oConfig.overrideCartKey; 4770 }else{ 4771 var sPage = oConfig.sessionData.orderfrontUrl + '/' + oConfig.sessionData.cartPage + "?o_key=" + oConfig.sessionData.sc_id; 4772 } 4773 4774 if(utils.isActiveQuote && oConfig.isModal){ 4775 sPage = "javascript:window.history.back();" 4776 } 4777 var confirmToastrConfig = { 4778 'closeButton': true, 4779 'newestOnTop': true, 4780 'onclick': function() { 4781 window.location = sPage; 4782 }, 4783 'positionClass': 'toast-top-right', 4784 'preventDuplicates': false, 4785 'showDuration': 200, 4786 'hideDuration': 1000, 4787 'tapToDismiss': false, 4788 'timeOut': 3000, 4789 'extendedTimeOut': 1000 4790 } 4791 4792 if(cart && utils.isActiveQuote) { 4793 var confirmTextConfig = {title: utils.plural(oConfig.labels.savedCartsLabels.itemText, details, true) + ' ' + oConfig.labels.savedCartsLabels.modalConfirmationHeader } 4794 }else{ 4795 if(utils.isActiveQuote){ 4796 var confirmTextConfig = { title: utils.plural(' product', details, true) + ' added to ' + oConfig.labels.savedCarts } 4797 }else{ 4798 var confirmTextConfig = { title: utils.plural(' product', details, true) + ' added to Cart'} 4799 } 4800 }; 4801 4802 runHook('toastrATCConfiguration', { confirmToastrConfig: confirmToastrConfig, confirmTextConfig: confirmTextConfig }); 4803 4804 utils.popToastr( 4805 confirmTextConfig.title, 4806 'Click or tap to view', 4807 confirmToastrConfig 4808 ); 4809 } 4810 4811 utils.modalATC = function(cart, data, details) { 4812 var modalConfig = cart && utils.isActiveQuote ? 4813 { 4814 body: 'catalog.saved_cart_confirmation_body', 4815 size: '', 4816 title: utils.plural(oConfig.labels.savedCartsLabels.itemText, details, true) + ' ' + oConfig.labels.savedCartsLabels.modalConfirmationHeader 4817 } : 4818 { 4819 body: 'catalog.atc_body', 4820 footer: 'catalog.atc_popup_buttons', 4821 size: getATCModalSize(), 4822 title: utils.plural(' Product', details, true) + ' Added to Cart' 4823 }; 4824 4825 runHook('modalATCAfterConfiguration', { self: self, cart: cart, modalConfig: modalConfig, details: details }); 4826 4827 utils.openModal(modalConfig, data); 4828 } 4829 4830 utils.renderTemplateToContainer = function (template, data) { 4831 var surrogate = document.createElement('div');
4832 var $container = $('<div>').append(surrogate); 4833 4834 ko.renderTemplate( 4835 template, 4836 data, 4837 null, 4838 surrogate, 4839 'replaceNode' 4840 ); 4841 4842 return $container; 4843 }; 4844 4845 utils.getSavedCart = function (carts, callback) { 4846 var selectedCart = ko.observable(); 4847 selectedCart.subscribe(callback); 4848 4849 var data = { savedCarts: carts, selectedCart: selectedCart }; 4850 utils.openModal({ 4851 body: oConfig.savedCartPopupTemplate, 4852 size: 'small', 4853 title: oConfig.labels.savedCartsLabels.modalHeader, 4854 backdrop: 'static' 4855 }, data); 4856 }; 4857 4858 utils.createGuid = function () { 4859 // https://stackoverflow.com/a/8809472 4860 var d = new Date().getTime(); 4861 if(window.performance && typeof window.performance.now === "function"){ 4862 d += performance.now(); //use high-precision timer if available 4863 } 4864 var guid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 4865 var r = (d + Math.random()*16)%16 | 0; 4866 d = Math.floor(d/16); 4867 return (c=='x' ? r : (r&0x3|0x8)).toString(16); 4868 }); 4869 return guid.toUpperCase(); 4870 }; 4871 4872 // Generates a unique ID and returns it twice in a row. Intended for use with the `for` 4873 // attribute on `label` elements. 4874 (function () { 4875 var previousId; 4876 4877 utils.labelId = function () { 4878 var id = previousId || utils.createGuid(); 4879 previousId = previousId ? null : id; 4880 return id; 4881 }; 4882 }()); 4883 4884 utils.openModal = function (options, data) { 4885 _.forEach(['header', 'body', 'footer'], function (prop) { 4886 if (options[prop]) { 4887 options[prop] = utils.renderTemplateToContainer(options[prop], data); 4888 } 4889 }); 4890 modal.open(options); 4891 }; 4892 4893 var productModel = function (product) { 4894 var self = this; 4895 4896 var productCollectionMapping = { 4897 create: function (options) { 4898 return new productModel(options.data); 4899 } 4900 } 4901 4902 ko.mapping.fromJS(product, { 4903 copy: [ 4904 'tab2_html', 4905 'opt1', 4906 'opt2', 4907 'opt3', 4908 'opt4', 4909 'opt5', 4910 'opt6', 4911 'opt7', 4912 'opt8', 4913 'opt9', 4914 'accountHistory', 4915 'reviews', 4916 'tabs', 4917 'type', 4918 'promoDescriptions', 4919 'configuratorEditData', 4920 'calc_inv_message', 4921 'use_cart_options', 4922 'showAddOns', 4923 'addOnLabel', 4924 'addOnDisplay', 4925 'showPrice' 4926 ], 4927 related: productCollectionMapping, 4928 secondRelated: productCollectionMapping, 4929 children: productCollectionMapping, 4930 alsoBought: productCollectionMapping, 4931 addOns: productCollectionMapping 4932 }, self); 4933 4934 self.children.extend({ deferred: true }); 4935 4936 self.atcButtonText = ko.observable(''); 4937 self.atcErrorText = ko.observable(''); 4938 4939 if(oConfig.isModal && !ko.unwrap(self.link).includes("modal=1")) { 4940 self.link((function() { 4941 var processedLink = ko.unwrap(self.link); 4942 if(processedLink.indexOf('?') > -1) { 4943 processedLink += "&"; 4944 } else { 4945 processedLink += "?"; 4946 } 4947 processedLink += 'modal=1&modalaction=' + utils.getParameter("modalaction"); 4948 4949 return processedLink; 4950 })()); 4951 } 4952 4953 if(utils.getParameter('quickadd') == 'true' && self.type === 'parent'){ 4954 self.childDisplayType('droplist'); 4955 } 4956 4957 self.updateAtcButtonText = function() { 4958 if(self.configuratorEditData && self.configuratorEditData.od_id) { 4959 self.atcButtonText(oConfig.labels.updateCartItem || 'Update'); 4960 } else if (utils.isActiveQuote) { 4961 self.atcButtonText('Add To ' + oConfig.labels.savedCarts); 4962 } else { 4963 self.atcButtonText(oConfig.labels.addToCart || 'Add'); 4964 } 4965 }; 4966 4967 self.updateAtcButtonText(); 4968 4969 var accordionDisplaySetting = self.tabGroupAccordionDisplay(); 4970 4971 // set defaultTabAccordionState based for first tab 4972 var defaultTabAccordionState = accordionDisplaySetting === 'open-first' || accordionDisplaySetting === 'open-all'; 4973 self.tabs.forEach(function(tab) { 4974 tab.open = ko.observable(defaultTabAccordionState); 4975 // set defaultTabAccordionState for remaining tabs (after first) 4976 defaultTabAccordionState = accordionDisplaySetting === 'open-all'; 4977 }); 4978 4979 self.hasCartOptions = ko.computed(function() { 4980 if(!oConfig.useCartOptions){ 4981 return false; 4982 }else{ 4983 if(self.questions && self.questions() && self.questions().length && (self.type === 'parent' || self.useCartOptions())) { 4984 return true; 4985 } else { 4986 if(self.children && self.children().length) { 4987 return self.children().reduce(function(hasQuestions, child) { 4988 return hasQuestions || (!!child.questions && !!child.questions() && !!child.questions().length && child.useCartOptions()); 4989 }, false); 4990 } else { 4991 return false; 4992 } 4993 } 4994 } 4995 }); 4996 4997 self.requireInfoForAtc = ko.computed(function () { 4998 return !!( 4999 self.childDisplayType() || 5000 self.useConfigurator() || 5001 ( oConfig.useCartOptions && self.hasCartOptions() ) || 5002 (self.showAddOns && oConfig.detailConfig.useAddOnProducts && oConfig.searchConfig.requireAddOnSelection) 5003 ) && oConfig.pageName == 'pc_combined_results.asp'; 5004 }); 5005 5006 self.priceDisplay = ko.observable(function () { 5007 var template = 'catalog.details_link'; 5008 if(oConfig.pageName == 'pc_product_detail.asp'){ 5009 template = 'catalog.selected_product_price_display'; 5010 }else if (self.useConfigurator()){ 5011 template = 'catalog.configurator_price_display'; 5012 }else if (self.requireInfoForAtc() && self.childStartingPrice()) { 5013 template = 'catalog.price_start_at' 5014 } else if (!self.requireInfoForAtc()) { 5015 template = 'catalog.selected_product_price_display'; 5016 } 5017 5018 //Manually check for template overrides since this is dynamically returned. 5019 //Need to convert this to a function and use any time template names are returned. 5020 if(document.getElementById(template + '_custom')){ 5021 return template + '_custom'; 5022 }else{ 5023 return template; 5024 } 5025 5026 }()); 5027 5028 self.selectedQty = ko.observable(function() { 5029 if(self.configuratorEditData) { 5030 return self.configuratorEditData.qty; 5031 }else if(self.qty){ 5032 return self.qty; 5033 } else { 5034 return undefined; 5035 } 5036 }()); 5037 5038 self.isQtyValid = ko.observable(true); 5039 5040 self.selectedWarehouse = ko.observable(_.find(self.inventory.warehouses(), function(wh){ return wh.isDefault() } ) || [] ); 5041 5042 if(self.configuratorEditData && self.configuratorEditData.pw_id) { 5043 self.selectedWarehouse(_.find(self.inventory.warehouses(), function(wh){ return wh.key() == self.configuratorEditData.pw_id } ) || [] ); 5044 } 5045 5046 _.each(self.uomPrice(),function(uom){ 5047 uom.isDefault( (oConfig.useSalesUomAsDefault && uom.uom() == "uom_sales") || (!oConfig.useSalesUomAsDefault && uom.uom() == "uom_std")) 5048 5049 var bHasBreaks = false; 5050 bHasBreaks = uom.breaks && uom.breaks() && uom.breaks().length > 0;
5051 uom.hasBreaks(bHasBreaks); 5052 }); 5053 5054 if(oConfig.useSalesUom) 5055 { 5056 var salesUomIndex = self.uomPrice().findIndex(function (uom) { return uom.uom() == "uom_sales"}); 5057 if(salesUomIndex > -1) { 5058 for(i = self.uomPrice().length -1; i > 0; i--) { 5059 if(i != salesUomIndex) { 5060 self.uomPrice.splice(i, 1); 5061 } 5062 } 5063 } 5064 } 5065 5066 self.selectedUom = ko.observable( 5067 (function () { 5068 var uom = undefined; 5069 5070 // It's possible that this is a parent product and the configurator 5071 // edit data will not match a uom on the parent, however the selectedProduct 5072 // has not been set at this point, so we can't just use selectedProduct 5073 // With the previous version of this code, this would make the selectedUom 5074 // undefined and break other parts of the code because it skipped all other 5075 // checks if configuratorEditData had a uom value. Now it will check the 5076 // other conditions if the configuratorEditData doesn't match an available uom. 5077 // There's certainly a better way to handle this, but this will do for now. 5078 if(self.configuratorEditData && self.configuratorEditData.uom) { 5079 uom = _.find(self.uomPrice(), function (price) { 5080 return price.description() == self.configuratorEditData.uom; 5081 }); 5082 } 5083 5084 if(!uom) { 5085 uom = _.find(self.uomPrice(), function (price) { 5086 if (price.hasOwnProperty("isDefault")){ 5087 return price.isDefault(); //set from SSJS 5088 } else if(typeof price.IsDefault() === "undefined"){ 5089 return price.ConversionRate() === 1; //fallback 5090 } else{ 5091 return price.IsDefault() || price.ConversionRate() === 1 || price.ConversionRate() === 12; //returned from COM 5092 } 5093 }); 5094 } 5095 5096 if(!uom && self.uomPrice().length > 0) { 5097 //if still no match then take the first one 5098 uom = self.uomPrice()[0]; 5099 } 5100 5101 return uom; 5102 })()); 5103 5104 // Set the selected quantity back to the default if the UOM changes 5105 self.selectedUom.subscribe(function(newValue) { 5106 var defaultQty = newValue.minQty() || newValue.step() || 1; 5107 self.selectedQty(defaultQty); 5108 }); 5109 5110 self.processedBreaks = ko.computed(function() { 5111 if (!( self.selectedUom() && self.selectedUom().hasBreaks() )) { 5112 return []; 5113 } 5114 5115 var processed = []; 5116 var data = self.selectedUom().breaks(); 5117 5118 //converted from price break popup window to properly display single breaks that actually have multiple break records 5119 if(data[data.length -1].qty() == '1000000' || data[data.length -1].qty() == '100000000'){ 5120 data.pop(); 5121 } 5122 5123 //If there's only one break we will skip showing the price break information 5124 if(data.length == 1) { 5125 return []; 5126 } 5127 5128 processed = data.map(function(lineBreak) { 5129 var price, startQ, endQ, range, qty, proceed; 5130 price = lineBreak.price(); 5131 startQ = lineBreak.qty(); 5132 endQ = lineBreak.qtyEnd(); 5133 proceed = true; 5134 5135 if (endQ != '0') { 5136 range = startQ + ' - ' + endQ; 5137 } else { 5138 range = startQ + '+'; 5139 } 5140 5141 if(proceed){ 5142 return { 5143 price: price, 5144 range: range 5145 } 5146 }else{ 5147 return {} 5148 } 5149 }); 5150 return processed.filter( function(value){ return JSON.stringify(value) !== '{}'; }); 5151 }); 5152 5153 self.configPrice = buildConfiguratorPriceObservable(self.key()); 5154 5155 self.unitPrice = ko.computed(function () { 5156 if(oConfig.useListPriceOverride){ 5157 return self.selectedUom().suggestedPrice() 5158 } 5159 5160 if(self.configuratorEditData && self.configuratorEditData.priceCalcType == 'fixed') { 5161 return self.configuratorEditData.price; 5162 } 5163 return self.selectedUom().price() + self.configPrice(); 5164 }); 5165 5166 self.priceTrace = ko.computed(function() { 5167 var bPriceErrorMessage = 'Price trace is not available'; 5168 return self.selectedUom().priceTrace 5169 ? self.selectedUom().priceTrace() 5170 : bPriceErrorMessage; 5171 }); 5172 5173 self.youSavePercent = ko.computed(function () { 5174 return (((self.selectedUom().suggestedPrice() - self.selectedUom().price()
5174) / self.selectedUom().suggestedPrice()) * 100).toFixed(oConfig.youSaveDecimalPlaces) + '%'; 5175 }); 5176 5177 self.suggestedPrice = ko.computed(function () { 5178 return self.selectedUom().suggestedPrice(); 5179 }); 5180 5181 self.showYouSave = ko.computed(function () { 5182 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; 5183 }); 5184 5185 self.childView = function () { 5186 // return (self.childDisplayType() || 'stand-alone') + '-layout'; 5187 return 'stand-alone-layout'; 5188 }(); 5189 5190 if(!self.mapPriceType() && oConfig.defaultPriceDisplayType) { 5191 self.mapPriceType(oConfig.defaultPriceDisplayType); 5192 } 5193 5194 self.showAtc = function () { 5195 var primary1 = self.inventory.showAtc() && oConfig.searchConfig.showAtc && self.mapPriceType() !== 'show_message'; 5196 var secondary1 = oConfig.isLoggedIn || self.mapPriceType() !== 'require_login_for_atc'; 5197 var secondary2 = oConfig.isLoggedIn || self.mapPriceType() !== 'require_login_for_price_and_atc'; 5198 var tertiary1 = self.mapPriceType() === 'require_atc' || (self.mapPriceType() === 'require_login_or_atc' && !oConfig.isLoggedIn); 5199 var tertiary2 = self.mapPriceType() !== 'hide' && (self.showProdAtc() != 0); 5200 var quaternary1 = !(self.type === 'parent' && self.childDisplayType() == 'droplist' && oConfig.pageName != 'pc_combined_results.asp') 5201 5202 return primary1 && 5203 (secondary1) && 5204 (secondary2) && ( 5205 (tertiary1) || 5206 (tertiary2) 5207 ) 5208 && quaternary1; 5209 }(); 5210 5211 self.showQuickAtc = ko.computed(function () { 5212 var showQuickAtc = self.showAtc && !self.requireInfoForAtc() && self.type !== "parent"; //initial setting 5213 if(oConfig.showChildrenSelection && self.type === "child" ){ 5214 if(self.unitPrice() > 0 && self.showAtc){ 5215 showQuickAtc = true; 5216 } 5217 else{ 5218 showQuickAtc = false; 5219 } 5220 } 5221 5222 return showQuickAtc; //(self.showAtc && !self.requireInfoForAtc()) 5223 }); 5224 5225 self.allowQuickAddModal = ko.computed(function() { 5226 if (oConfig.pageName == 'pc_product_detail.asp') return false; 5227 5228 var exceptions = ['exploded-view', 'input-qty']; 5229 if (exceptions.includes(self.childDisplayType())) return false; 5230 5231 return true; 5232 }); 5233 5234 self.isInCart = ko.computed(function(){ 5235 var cartCount = 0; 5236 if(viewModel.activeCart && viewModel.activeCart().length){ 5237 var product = _.filter(viewModel.activeCart(), function(cart){ 5238 return cart.prod_key == self.key() || cart.parent_p_id == self.key(); 5239 }); 5240 cartCount = product.length; 5241 } 5242 return cartCount; 5243 }); 5244 5245 self.showPrice = function () { 5246 if (typeof self.showPrice !== 'undefined') return self.showPrice; 5247 return self.type !== 'parent' && ( 5248 (self.mapPriceType() !== 'show_message') && 5249 !((self.mapPriceType() === 'require_login_for_price_and_atc') && !oConfig.isLoggedIn) && 5250 !(self.mapPriceType() === 'require_atc' || (self.mapPriceType() === 'require_login_or_atc' && !oConfig.isLoggedIn)) 5251 ) && 5252 (self.mapPriceType() !== 'hide') && (self.showProdPrice() != 0) && 5253 oConfig.showPricingOrderEntry; 5254 }(); 5255 5256 self.showBreaks = ko.observable(function(){ 5257 return oConfig.useBreaks && oConfig.useBreaksTable && oConfig.pageName == 'pc_product_detail.asp'; 5258 }()); 5259 5260 self.mapPriceMessage = function () { 5261 if (self.mapPriceType() === 'show_message') { 5262 return oConfig.mapBehaviorMessages.showMessage; 5263 } else if (self.mapPriceType() === 'require_login_for_price_and_atc' && !oConfig.isLoggedIn) { 5264 return oConfig.mapBehaviorMessages.requireLoginMessage; 5265 } else if (self.mapPriceType() === 'require_login_for_atc' && !oConfig.isLoggedIn) { 5266 return oConfig.mapBehaviorMessages.requireLoginAtcMessage; 5267 } else if (self.mapPriceType() === 'require_atc') { 5268 return oConfig.mapBehaviorMessages.requireAtcMessage; 5269 } else if (self.mapPriceType() === 'require_login_or_atc' && !oConfig.isLoggedIn) { 5270 return oConfig.mapBehaviorMessages.requireLoginOrAtcMessage; 5271 } else if (self.mapPriceType() !== 'hide') { 5272 return ''; 5273 } 5274 }(); 5275 5276 self.warehouseTemplate = function () { 5277 if (oConfig.showWarehouses && self.inventory.warehouses().length > 0 && self.inventory.inventoryStatus() === 'in') {
5278 if ((oConfig.allowWarehouseSelection && (oConfig.pageName == 'pc_combined_results.asp' && oConfig.searchConfig.hideAtcShowInv)) || (oConfig.allowWarehouseSelection && self.showQuickAtc())) { 5279 return 'warehouse_droplist'; 5280 } else if (oConfig.useWarehousesTable) { 5281 return 'warehouse_table'; 5282 } else { 5283 if(self.showQuickAtc()){ 5284 return 'warehouse_info'; 5285 }else{ 5286 return ''; 5287 } 5288 } 5289 } else { 5290 return 'warehouse_off'; 5291 } 5292 }(); 5293 5294 self.priceBreaksTemplate = function(){ 5295 if(oConfig.useBreaks){ 5296 if(oConfig.useBreaksTable && oConfig.pageName == 'pc_product_detail.asp'){ 5297 return 'catalog.qty_breaks_table'; 5298 }else{ 5299 return 'catalog.qty_breaks'; 5300 } 5301 }else{ 5302 return 'catalog.breaks_off'; 5303 } 5304 }(); 5305 5306 self.uomTemplate = ko.computed(function() { 5307 var template; 5308 if (self.selectedProduct().uomPrice().length > 1) { 5309 template = 'catalog.uom_select'; 5310 } else { 5311 template = 'catalog.uom_input'; 5312 } 5313 5314 if(document.getElementById(template + '_custom')){ 5315 return template + '_custom'; 5316 }else{ 5317 return template; 5318 } 5319 }); 5320 5321 self.documentsTemplate = function () { 5322 return 'catalog.documents'; 5323 }(); 5324 5325 self.qtyInputClick = function (key) { 5326 jQuery('#qty_'+key).focus(); 5327 jQuery('#qty_'+key).select(); 5328 }; 5329 5330 self.validateQtyInput = function (data) { 5331 if (utils.getCookie('productLayout') === 'list') { 5332 return ''; 5333 } else { 5334 return '1'; 5335 } 5336 }; 5337 5338 self.hideOnListView = function () { 5339 if ((isActiveLayout('list') && !oConfig.detailConfig.productKey ) || (self.type === 'child' && oConfig.detailConfig.productKey)) { 5340 return 'hide'; 5341 } 5342 }; 5343 5344 self.isChild = function () { 5345 if (self.type === 'child'){ 5346 return true; 5347 }else{ 5348 return false; 5349 } 5350 } 5351 5352 self.isParent = function() { 5353 if (self.type.toLowerCase() === 'parent'){ 5354 return true; 5355 }else{ 5356 return false; 5357 } 5358 } 5359 5360 self.minQty = ko.computed(function () { 5361 if (self.configuratorEditData && self.configuratorEditData.minQty) { 5362 self.selectedProduct().selectedUom().minQty(self.configuratorEditData.minQty); 5363 } 5364 if (oConfig.useMinimumQuantity) { 5365 return self.selectedProduct().selectedUom().minQty(); 5366 } else { 5367 return 0; 5368 } 5369 }); 5370 5371 self.stepQty = ko.computed(function () { 5372 if (self.configuratorEditData && self.configuratorEditData.qtyIncrement) { 5373 self.selectedProduct().selectedUom().step(self.configuratorEditData.qtyIncrement); 5374 } 5375 if (oConfig.useQuantityIncrement) { 5376 return self.selectedProduct().selectedUom().step(); 5377 } else { 5378 return oConfig.defaultQuantityIncrement; 5379 } 5380 }); 5381 5382 self.maxQty = ko.computed(function () { 5383 if (self.configuratorEditData && self.configuratorEditData.maxQty) { 5384 self.selectedProduct().selectedUom().maxQty(self.configuratorEditData.maxQty); 5385 } 5386 if (oConfig.useMaximumQuantity && self.selectedProduct().selectedUom().maxQty() > 0) { 5387 return self.selectedProduct().selectedUom().maxQty(); 5388 } else { 5389 return ''; 5390 } 5391 }); 5392 5393 self.recentlyViewedTabExists = ko.computed(function() { 5394 if (!Array.isArray(self.tabs) || self.tabs.length === 0) { 5395 return false; 5396 } 5397 return self.tabs.some(function(tab) { 5398 return tab.dynamicSource == "recently_viewed"; 5399 }); 5400 }); 5401 5402 self.customersAlsoBoughtExists = ko.computed(function() { 5403 if (!Array.isArray(self.tabs) || self.tabs.length === 0) { 5404 return false; 5405 } 5406 return self.tabs.some(function(tab) { 5407 return tab.dynamicSource == "customers_also_bought"; 5408 }); 5409 }); 5410 5411 self.hasQuantityRestrictions = ko.computed(function () { 5412 return (oConfig.useMinimumQuantity || oConfig.useMaximumQuantity || oConfig.useQuantityIncrement) && 5413 !!( 5414 (self.minQty() && self.minQty() !== oConfig.defaultMinimumQuantity) || 5415 ( (!self.selectedUom().uom_conversion() || self.selectedUom().uom_conversion() == 1) && self.stepQty() && self.stepQty() != oConfig.defaultQuantityIncrement) || 5416 self.maxQty() 5417 ); 5418 }); 5419 5420 self.quantityRestrictionsHtml = ko.computed(function () { 5421 var lines = []; 5422 5423 if (self.minQty() && self.minQty() !== oConfig.defaultMinimumQuantity) 5424 lines.push(oConfig.labels.minQtyPopover.replace(/<min_qty>/,self.minQty())); 5425 5426 if ( (!self.selectedUom().uom_conversion() || self.selectedUom().uom_conversion() == 1) && self.stepQty() && self.stepQty() != oConfig.defaultQuantityIncrement) 5427 lines.push('Qty Increment: ' + self.stepQty()); 5428 5429 if (self.maxQty()) 5430 lines.push('Maximum Qty: ' + self.maxQty()); 5431 5432 return lines.join('<br>'); 5433 }); 5434 5435 self.addToSavedCart = function () { 5436 utils.getSavedCart(viewModel.savedCarts(), function (cart) { 5437 if (cart) {
5438 if (!_.includes(viewModel.savedCarts(), cart)) { 5439 // Insert the new cart in sorted order, notifying exactly once. 5440 var index = _.sortedIndex(viewModel.savedCarts(), cart, 'nickname'); 5441 viewModel.savedCarts.splice(index, 0, cart); 5442 } 5443 5444 var parentKey; 5445 5446 if(self.type == 'child' && viewModel.mainProduct) { 5447 parentKey = ko.unwrap(viewModel.mainProduct).key(); 5448 } 5449 5450 utils.addToCart(self, cart, parentKey); 5451 } 5452 }); 5453 }; 5454 5455 self.addToCart = function () { 5456 var parentKey; 5457 5458 if(self.type == 'child' && viewModel.mainProduct) { 5459 parentKey = ko.unwrap(viewModel.mainProduct).key(); 5460 } 5461 5462 return utils.addToCart(self, undefined, parentKey); 5463 }; 5464 5465 self.atcPopupSuccess = function () { 5466 5467 }; 5468 5469 self.atcPopupFail = function () { 5470 5471 }; 5472 5473 self.searchfields = function() { 5474 var includedSearchfields = Object.keys(self).filter(function(key) { return key.startsWith('searchfield'); }).sort(); 5475 var searchfieldsObject = {}; 5476 includedSearchfields.forEach(function(searchfieldName) { 5477 if(searchfieldName == "searchfields") // The existing searchfields object 5478 { 5479 var originalKeys = Object.keys(self[searchfieldName]).filter(function(key) { return key.startsWith('searchfield'); }); 5480 //console.log(JSON.stringify(originalKeys)); 5481 originalKeys.forEach(function(key) {
5482 if(!searchfieldsObject[key]) { 5483 searchfieldsObject[key] = ko.unwrap(self[searchfieldName][key]) 5484 } 5485 }); 5486 } else { 5487 if(!oConfig.searchFieldsShell[searchfieldName]) { 5488 // because we can't use "?." until we stop trying to support IE 5489 // like: oConfig.searchFieldsShell[searchfieldName]?.label || '' 5490 oConfig.searchFieldsShell[searchfieldName] = { 5491 label: '', 5492 show: false 5493 }; 5494 } 5495 searchfieldsObject[searchfieldName] = { 5496 field: ko.observable(searchfieldName), 5497 value: ko.observable(ko.unwrap(self[searchfieldName])), 5498 label: ko.observable(oConfig.searchFieldsShell[searchfieldName].label || ''), 5499 show: ko.observable(!!ko.unwrap(self[searchfieldName]) && (oConfig.searchFieldsShell[searchfieldName].show || false)) 5500 } 5501 } 5502 }); 5503 return searchfieldsObject; 5504 }(); 5505 5506 self.selectFirstTab = function () { 5507 $('#tab1 > a').click(); 5508 }; 5509 5510 self.getWebPage = function (webPageId) { 5511 return 'page.asp?p_key=' + webPageId + ' .wpc_page_content'; 5512 }; 5513 5514 self.useTabs = function () { 5515 return oConfig.detailConfig.useAdvancedTabs && self.tabs && self.tabs.length && self.showTabs(); 5516 } 5517 5518 self.usingDownloadsTab = function() { 5519 var index = _.findIndex(self.tabs, function(t) { 5520 return t.dynamicSource == "downloads" 5521 }); 5522 return self.useTabs() && index > -1; 5523 } 5524 5525 self.getSmartListLinkOrderStats = function(parent){ 5526 if(!parent){ 5527 return 'product_history_detail.asp' 5528 } 5529 if(oConfig.detailConfig.useSkuDisplay && oConfig.detailConfig.useAliases) { 5530 return 'product_history_detail.asp?search2=(searchexact~p.sku_display~' + parent.sku() + '|OR|searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku() 5531 } 5532 else if(oConfig.detailConfig.useAliases){ 5533 return 'product_history_detail.asp?search2=searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku() 5534 } 5535 else if(oConfig.detailConfig.useSkuDisplay) { 5536 return 'product_history_detail.asp?search2=searchexact~p.sku_display~' + parent.sku() + '&s=' + parent.sku() 5537 }else{ 5538 return 'product_history_detail.asp?search2=searchexact~p.sku~' + parent.sku() + '&s=' + parent.sku() 5539 } 5540 }; 5541 5542 self.getSmartListLinkInvoiceStats = function(parent){ 5543 if(!parent){ 5544 return 'products_invoiced_detail.asp' 5545 } 5546 if(oConfig.detailConfig.useSkuDisplay && oConfig.detailConfig.useAliases) { 5547 return 'products_invoiced_detail.asp?search2=(searchexact~p.sku_display~' + parent.sku()+ '|OR|searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku() 5548 } 5549 else if(oConfig.detailConfig.useAliases){ 5550 return 'products_invoiced_detail.asp?search2=searchexact~pa.sku_alias~' + parent.sku() + '&s=' + parent.sku() 5551 } 5552 else if(oConfig.detailConfig.useSkuDisplay) { 5553 return 'products_invoiced_detail.asp?search2=searchexact~p.sku_display~' + parent.sku() + '&s=' + parent.sku() 5554 }else{ 5555 return 'products_invoiced_detail.asp?search2=searchexact~p.sku~' + parent.sku() + '&s=' + parent.sku() 5556 } 5557 }; 5558 5559 self.explodedViewHasQty = function(product){ 5560 hasQty = false; 5561 _.each(product.children(), function(child){ 5562 if(!hasQty && child.diagramQty() != ''){ 5563 hasQty = true; 5564 } 5565 }); 5566 return hasQty; 5567 }; 5568 5569 self.explodedViewHasNotes = function(product){ 5570 hasNotes = false; 5571 _.each(product.children(), function(child){ 5572 if(!hasNotes && child.diagramNotes() != ''){ 5573 hasNotes = true; 5574 } 5575 }); 5576 return hasNotes; 5577 }; 5578 5579 self.tableColumns = ko.computed( function () { 5580 var columns = Array.prototype.concat( 5581 [ 5582 { 5583 if: oConfig.showImgCol, 5584 label: oConfig.labels.imgCol, 5585 field: 'thumb', 5586 template: 'catalog.input_qty_thumb_display', 5587 cellClass: 'qty-input-table-thumb' 5588 }, 5589 { 5590 if: oConfig.showNameCol && self.childDisplayType() !== 'add-row', 5591 label: oConfig.labels.nameCol, 5592 field: 'nm', 5593 template: 'catalog.input_qty_nm_display' 5594 }, 5595 { 5596 label: 'SKU', 5597 field: 'sku', 5598 template: 'catalog.input_qty_sku_display' 5599 }, 5600 { 5601 if: oConfig.useCartOptions && self.hasCartOptions(), 5602 label: 'Options', 5603 field: 'questions', 5604 template: 'catalog.cart_options' 5605 }, 5606 { 5607 if: self.childDisplayType() == 'exploded-view' && self.explodedViewHasQty(self), 5608 label: oConfig.labels.qtyCol, 5609 field: 'diagramQty' 5610 }, 5611 { 5612 if: self.childDisplayType() == 'exploded-view' && self.explodedViewHasNotes(self), 5613 label: oConfig.labels.notesCol, 5614 field: 'diagramNotes' 5615 } 5616 5617 ], 5618 self.childDisplayType() !== 'add-row' ? self.childSelectors() || [] : [], 5619 [ 5620 { 5621 if: oConfig.usePromos, 5622 label: 'Promo', 5623 template: 'catalog.input_qty_promo_display' 5624 }, 5625 { 5626 if: oConfig.useIdp, 5627 label: 'Status', 5628 template: _.property('warehouseTemplate') 5629 }, 5630 { 5631 label: 'Price', 5632 headerClass: 'cell-right', 5633 cellClass: 'cell-right', 5634 field: 'unitPrice', 5635 format: utils.formatPrice, 5636 template: 'catalog.selected_product_price_display' 5637 }, 5638 { 5639 label: 'Actions', 5640 headerClass: 'cell-right', 5641 cellClass: 'cell-right', 5642 template: 'catalog.atc_qty_input', 5643 width: '1%' 5644 } 5645 ] 5646 ); 5647 5648 // diagram_number needs to be added to the child products using the pos field on the mapping table 5649 if (self.childDisplayType() == 'exploded-view') { 5650 columns.unshift({ 5651 label: oConfig.labels.idCol, 5652 field: 'diagramNumber' 5653 });
5654 } 5655 5656 return _.filter(columns, function (column) { 5657 return !('if' in column) || ko.unwrap(column.if); 5658 }); 5659 }); 5660 5661 runHook('productModelReviews', { self: self, product: product, reviews: self.reviews }); 5662 5663 self.reviews = new PagedArray(self.reviews, 3); 5664 5665 self.setupQuestions = function() { 5666 self.questions().forEach(function(question) { 5667 question.answers = ko.observableArray(); 5668 5669 if(question.type() === 'select') { 5670 if(question.useSelectOne()) { 5671 question.answers.push({ 5672 label: question.selectOneText(), 5673 value: '' 5674 }); 5675 } 5676 5677 if(question.answerList().length > 0) { 5678 var answersSplit = question.answerList().split('|'); 5679 answersSplit.forEach(function(answer) { 5680 var answerSet = answer.split('~'); 5681 question.answers.push( 5682 { 5683 label: answerSet[0], 5684 value: answerSet[0] 5685 }); 5686 }); 5687 } 5688 } 5689 }); 5690 } 5691 5692 self.rowCollection = ko.observableArray(); 5693 5694 self.addRows = function(numberOfRows) { 5695 numberOfRows = numberOfRows || 1; 5696 for(var i=0;i<numberOfRows;i++) { 5697 var row = { 5698 selectedChild: ko.observable(undefined) 5699 } 5700 //' Clone the children for the selector so that the child 5701 //' references across rows are not the same. 5702 row.children = self.children ? self.children().map( 5703 function(item) { 5704 var jsChild = ko.mapping.toJS(item); 5705 var koChild = ko.mapping.fromJS(jsChild, productMapping); 5706 5707 //' Add the currentParent back as the re-mapping rests it 5708 koChild.currentParent = ko.observable(self); 5709 5710 //' Add a new property for the current row index 5711 //' to make it easier to remove the items 5712 //' We use a guid to ensure it's always consistent. 5713 koChild.rowKey = utils.createGuid(); 5714 return koChild; 5715 }) 5716 : []; 5717 self.rowCollection.push(row); 5718 } 5719 } 5720 5721 self.setupAddRowView = function() { 5722 if(self.childDisplayType() === 'add-row') { 5723 self.addRows(); 5724 if(!!oConfig.childSkuMatch) { 5725 var matchedChild = self.rowCollection()[0].children.filter(function(child) { 5726 return oConfig.childSkuMatch === child.sku(); 5727 }); 5728 5729 if(matchedChild && matchedChild.length > 0){ 5730 self.rowCollection()[0].selectedChild( 5731 matchedChild[0] 5732 ); 5733 } 5734 } 5735 } 5736 } 5737 5738 self.childSelectors = ko.observableArray([]); 5739 5740 self.processChildren = function() { 5741 _.each(self.children(), function(child){ 5742 child.promoDescriptions = []; 5743 _.each(self.promoDescriptions, function(promo){ 5744 if(promo.targetKeys.indexOf(child.key()) > -1){ 5745 child.promoDescriptions.push(promo); 5746 } 5747 }); 5748 child.configuratorEditData = self.configuratorEditData; 5749 child.currentParent(self); 5750 child.updateAtcButtonText(); 5751 child.setupQuestions(); 5752 }); 5753 5754 _.forEach(self, function (value, key) { 5755 var keyString = String(key); 5756 var matched = keyString.match(/^opt(\d)$/); 5757 5758 if (matched && value) { 5759 var selector = {}; 5760 selector.field = matched[0]; 5761 selector.label = value; 5762 // _.sortByAll has been absorbed into _.sortBy in lodash 4.0.0+ 5763 var lodashSortBy = typeof(_.sortByAll) == 'function' ? _.sortByAll : _.sortBy; 5764 5765 selector.options = lodashSortBy( 5766 _.uniq( 5767 _.map(self.children(), function (child) { 5768 var optXsort = (typeof(child[matched[0] + '_sort']) == 'function' ? child[matched[0] + '_sort']() : child[matched[0] + '_sort']) || 0; 5769 var optSort = (typeof(child[matched[0]]) == 'function' ? child[matched[0]]() : child[matched[0]]) || 0; 5770 5771 var thisOpt = { 5772 option: child[matched[0]], 5773 sort: optXsort || optSort 5774 }; 5775 5776 runHook("selectorOptionsItemOverride", { key: key, option: thisOpt, product: child }); 5777 5778 return thisOpt; 5779 5780 }), 5781 'option' 5782 ), 5783 [ 'sort', 'option' ] 5784 ); 5785 selector.selectedOption = ko.observable(); 5786 if (oConfig.detailConfig.selectChildProductOnLoad) { 5787 selector.selectedOption(selector.options[0]); 5788 } 5789 5790 var childSku = oConfig.childSkuMatch || (!!self.configuratorEditData ? self.configuratorEditData.sku : '') || ''; 5791 5792 if (childSku){ 5793 var oChild = {}; 5794 _.each(self.children(),function(child){ 5795 if(childSku == child.sku()) { 5796 oChild = child; 5797 return false; 5798 } 5799 });
5800 _.each(selector.options,function(option){ 5801 if(option.option == oChild[selector.field]){ 5802 selector.selectedOption(option); 5803 } 5804 }) 5805 } 5806 selector.showSelector = ko.observable(true); 5807 self.childSelectors.push(selector); 5808 } 5809 }); 5810 5811 self.selectedOptions = ko.computed(function () { 5812 return _.map(ko.unwrap(self.childSelectors), function (item) { 5813 var selection = { option: '', sort: '' }; 5814 if (item.selectedOption()) { 5815 selection = item.selectedOption().option; 5816 } 5817 return { field: item.field, option: selection }; 5818 }); 5819 }); 5820 5821 self.selectedProduct = ko.computed(function () { 5822 var filter = {}; 5823 _.forEach(self.selectedOptions(), function (option) { 5824 filter[option.field] = option.option; 5825 }); 5826 var filteredChildren = _.filter(self.children(), filter); 5827 if (filteredChildren 5828 && filteredChildren.length === 1 5829 && self.childDisplayType() !== 'input-qty' 5830 && self.childDisplayType() !== 'exploded-view' 5831 && self.childDisplayType() !== 'matrix-all' 5832 && self.childDisplayType() !== 'add-row' 5833 ) { 5834 return filteredChildren[0]; 5835 } else { 5836 return self; 5837 } 5838 }); 5839 5840 self.setupQuestions(); 5841 self.setupAddRowView(); 5842 } 5843 5844 if (self.children && self.children().length) { 5845 self.processChildren(); 5846 } else { 5847 self.selectedProduct = ko.observable(self); 5848 } 5849 5850 self.loadNextSelector = function(optNumber, callback, asyncLoadOptions) { 5851 var selectedOpts = _.map(self.childSelectors().filter(function(selector) {return !!selector.selectedOption && !!selector.selectedOption();}), function(s) { 5852 return s.selectedOption().option; 5853 }).join('~'); 5854 $.ajax({
5855 url: oConfig.pageName, //current page. 5856 data: { 5857 ajax: 'get-product-opts', 5858 key: self.key(), 5859 optFields: selectedOpts, 5860 modal: 1, 5861 modalaction: utils.getParameter("modalaction") 5862 }, 5863 dataType: 'json', 5864 success: function(data) { 5865 var selector = self.childSelectors().find(function(selector) { 5866 return selector.field == 'opt' + optNumber; 5867 }); 5868 5869 if(!selector) { 5870 selector = { 5871 field: 'opt' + optNumber, 5872 label: self['opt' + optNumber], 5873 showSelector: ko.observable(oConfig.displayDroplistPlaceholdersForLazyLoad) 5874 } 5875 self.childSelectors.push(selector); 5876 } 5877 5878 selector.index = optNumber; 5879 selector.options = data.map(function(o) { 5880 return { 5881 option: o.opt, 5882 sort: 0, 5883 count: o.count, 5884 pKey: o.p_key 5885 } 5886 }); 5887 selector.loading = ko.observable(false); 5888 selector.selectedOption = ko.observable(); 5889 selector.showSelector(oConfig.displayDroplistPlaceholdersForLazyLoad || !!selector.options.length); 5890 5891 selector.selectedOption.subscribe(function(newValue) { 5892 //clear any selectors after this one 5893 self.childSelectors().forEach(function(s) { 5894 if(s.index > selector.index) { 5895 s.selectedOption(undefined); 5896 s.options.splice(0, s.options.length); 5897 s.selectedOption.notifySubscribers(); 5898 s.showSelector(oConfig.displayDroplistPlaceholdersForLazyLoad); 5899 } 5900 }); 5901 5902 self.childSelectors.notifySubscribers(); 5903 5904 if(self.children) self.children.removeAll(); 5905 // did we actually select something 5906 if (newValue) { 5907 selector.loading(true); 5908 var callback = function() { 5909 selector.loading(false); 5910 } 5911 if (selector.index < self.childSelectors().length) { 5912 self.loadNextSelector(selector.index + 1, callback, asyncLoadOptions); 5913 } else { 5914 //load the child 5915 if (asyncLoadOptions) asyncLoadOptions.done = true; 5916 self.loadChildProduct(newValue.pKey, callback); 5917 } 5918 }else{ 5919 self.selectedProduct(self); 5920 } 5921 }); 5922 self.childSelectors.notifySubscribers(); 5923 }, 5924 error: function() { 5925 utils.popToastrError('Error Loading List', 'There was an error loading the product drop list'); 5926 }, 5927 complete: function() { 5928 if (callback) callback(); 5929 if (asyncLoadOptions) { 5930 var asyncLoadOptionsArray = asyncLoadOptions.getArray(); 5931 var index = optNumber - 1; 5932 var option = self.childSelectors()[index]; 5933 var availableOptions = option.options; 5934 var selectedOption = null; 5935 if (index < asyncLoadOptionsArray.length) { 5936 _.forEach(availableOptions, function (value, key) { 5937 if (value.option == asyncLoadOptionsArray[index]) selectedOption = value; 5938 });
5939 } else if (oConfig.detailConfig.selectChildProductOnLoad) { 5940 selectedOption = availableOptions[0]; 5941 } 5942 option.selectedOption(selectedOption); 5943 } 5944 } 5945 }) 5946 } 5947 5948 self.loadChildProduct = function(pKey, callback) { 5949 $.ajax({ 5950 url: oConfig.pageName, //current page. 5951 data: { 5952 ajax: 'get-child-product', 5953 key: pKey, 5954 parentKey: oConfig.mainProductKey, 5955 modal: 1, 5956 modalaction: utils.getParameter("modalaction"), 5957 action: utils.getParameter("action") == 'showpricetrace' ? 'showpricetrace' : '' 5958 }, 5959 dataType: 'json', 5960 success: function(data) { 5961 var product = ko.mapping.fromJS(data.products[0], productMapping); 5962 product.type = "child"; 5963 // self.children.push(product); 5964 if(self.questions && self.questions().length && (oConfig.useCartOptions && product.useCartOptions() && !product.f_id())) { 5965 if(product.questions) { 5966 product.questions(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); 5967 } else { 5968 product.questions = ko.observableArray(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); 5969 } 5970 } 5971 product.setupQuestions(); 5972 product.configuratorEditData = self.configuratorEditData; 5973 product.updateAtcButtonText(); 5974 self.selectedProduct(product); 5975 runHook('productDetailLoadChildProductSuccess', { self: self, product: product }); 5976 }, 5977 error: function() { 5978 utils.popToastrError('Error Loading Product', 'There was an error loading the product'); 5979 }, 5980 complete: callback 5981 }); 5982 } 5983 5984 self.quantityRestrictionsHtml.subscribe(function(newValue) { 5985 var popoverElement = $('#pop-' + $.escapeSelector(self.sku().replace(/([^A-Za-z0-9[\]{}_.:-])\s?/g, '_'))); 5986 if(popoverElement){ 5987 var popoverData = popoverElement.data('popover'); 5988 if (popoverData) { 5989 popoverData.options.content = newValue; 5990 } 5991 } 5992 }); 5993 5994 self.lazyLoadingInProgress = ko.observable(false); 5995 5996 if (self.key() == oConfig.mainProductKey && self.type === 'parent' && self.children().length === 0 && getOriginalPageName() === 'pc_product_detail.asp' && self.childDisplayType() != 'droplist') { 5997 if (!runHook('productDetailGetChildProductsByParentKey', { self: self }, {}, this)) { 5998 self.lazyLoadingInProgress(true); 5999 $.ajax({
6000 url: oConfig.pageName, //current page. 6001 data: { 6002 ajax: 'get-child-products-by-parent-key', 6003 key: oConfig.mainProductKey, 6004 modal: 1, 6005 modalaction: utils.getParameter("modalaction") 6006 }, 6007 dataType: 'json', 6008 success: function(data) { 6009 data.forEach(function(childProduct) { 6010 var product = ko.mapping.fromJS(childProduct, productMapping); 6011 product.type = "child"; 6012 if(self.questions && self.questions().length && product.useCartOptions() && !product.f_id()) { 6013 if(product.questions) { 6014 product.questions(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); 6015 } else { 6016 product.questions = ko.observableArray(ko.mapping.fromJS(ko.mapping.toJS(self.questions))()); 6017 } 6018 //product.hasCartOptions(true); 6019 } 6020 product.configuratorEditData = self.configuratorEditData; 6021 product.updateAtcButtonText(); 6022 //self.selectedProduct(product); 6023 self.children.push(product); 6024 }); 6025 6026 self.processChildren(); 6027 /* 6028 if(self.childDisplayType() === 'matrix-all') { 6029 self.matrix(ko.unwrap(ko.mapping.fromJS(generateMatrixData(ko.mapping.toJS(self))))); 6030 } 6031 */ 6032 self.lazyLoadingInProgress(false); 6033 }, 6034 error: function() { 6035 utils.popToastrError('Error Loading Product', 'There was an error loading the product'); 6036 }, 6037 complete: function() { self.lazyLoadingInProgress(false); } 6038 }); 6039 } 6040 } 6041 6042 /* 6043 This function generates the display data for parent products whose 6044 childDisplayType is 'matrix-all'. It returns a data structure that 6045 looks like this: 6046 6047 [ 6048 { 6049 label: <<Label of row>>, 6050 swatch: <<Either an HTML color without the # or blank. E.g. 00ff44>>, 6051 thumb: <<A thumbnail image link to display if the swatch is blank>>, 6052 cols: [ 6053 { 6054 label: <<Label of column>>, 6055 product: <<This links to the product.children[x] data. When KO maps this, it will be its own self-contained ProductModel.>> 6056 }, 6057 { 6058 ... more columns 6059 } 6060 ] 6061 }, 6062 { 6063 ... more rows 6064 } 6065 ] 6066 */ 6067 6068 self.matrix = ko.computed(function () { 6069 if (self.childDisplayType() === 'matrix-all') { 6070 /***** Main method *****/ 6071 6072 // Initial vars 6073 var rowOpt = ''; 6074 var colOpt = ''; 6075 var swatchOpt = "color_code"; 6076 6077 // Build the matrix 6078 var rawChildren = self.children(); 6079 var bucketed = bucketChildren(rawChildren, rowOpt, colOpt, swatchOpt); 6080 bucketed.rowKeys = sortKeys(bucketed.rowKeys); 6081 bucketed.colKeys = sortKeys(bucketed.colKeys); 6082 6083 runHook('productDetailMatrixBeforeConstruction', { 6084 parent: self, 6085 configs: { 6086 rowOpt: rowOpt, 6087 colOpt: colOpt, 6088 swatchOpt: swatchOpt 6089 }, 6090 bucketed: bucketed 6091 }); 6092 6093 var matrix = constructMatrix(bucketed); 6094 6095 runHook('productDetailMatrixData', { 6096 parent: self, 6097 matrix: matrix 6098 }); 6099 6100 return matrix; 6101 } else { 6102 return []; 6103 } 6104 6105 /***** Helper functions *****/ 6106 6107 // Find the unique row and column values and their sorts, and index the children. 6108 function bucketChildren(rawChildren, rowOpt, colOpt, swatchOpt) { 6109 var initial = { 6110 products: {}, 6111 rowKeys: {}, 6112 colKeys: {} 6113 }; 6114 6115 var result = _.reduce(rawChildren, function(acc, cur) { 6116 var rowLabel = ko.toJS(cur[rowOpt]); 6117 var rowSort = ko.toJS(cur[rowOpt + '_sort']); 6118 var rowSwatch = ko.toJS(cur[swatchOpt]); 6119 var rowThumb = ko.toJS(cur['thumb']); 6120 var colLabel = ko.toJS(cur[colOpt]); 6121 var colSort = ko.toJS(cur[colOpt + '_sort']); 6122 6123 // Index the child 6124 if (!acc.products[rowLabel]) { 6125 acc.products[rowLabel] = {}; 6126 } 6127 acc.products[rowLabel][colLabel] = cur; 6128 6129 // Keep track of the unique row values 6130 if (!acc.rowKeys[rowLabel]) { 6131 acc.rowKeys[rowLabel] = { 6132 label: rowLabel, 6133 sort: rowSort, 6134 swatch: rowSwatch, 6135 thumb: rowThumb 6136 }; 6137 } 6138 6139 // Make sure we have a swatch and thumb 6140 if (!acc.rowKeys[rowLabel].swatch) { 6141 acc.rowKeys[rowLabel].swatch = rowSwatch; 6142 } 6143 if (!acc.rowKeys[rowLabel].thumb) { 6144 acc.rowKeys[rowLabel].thumb = rowThumb; 6145 } 6146 6147 // Keep track of the unique column values 6148 acc.colKeys[colLabel] = { 6149 label: colLabel, 6150 sort: colSort 6151 }; 6152 6153 runHook('productDetailMatrixReduce', { 6154 parent: self, 6155 configs: { 6156 rowOpt: rowOpt, 6157 colOpt: colOpt, 6158 swatchOpt: swatchOpt 6159 }, 6160 acc: acc, 6161 cur: cur 6162 });
6163 6164 return acc; 6165 }, initial); 6166 6167 runHook('productDetailMatrixBucketed', { 6168 parent: self, 6169 configs: { 6170 rowOpt: rowOpt, 6171 colOpt: colOpt, 6172 swatchOpt: swatchOpt 6173 }, 6174 bucketed: bucketed 6175 }); 6176 6177 return result; 6178 } 6179 6180 // Sort the rowKeys and colKeys 6181 function sortKeys(obj) { 6182 var list = _.values(obj); 6183 var sorted = _.sortBy(list, 'sort'); 6184 return sorted; 6185 } 6186 6187 function constructMatrix(bucketed) { 6188 // Construct the matrix, one row at a time 6189 var matrix = _.map(bucketed.rowKeys, function(row) { 6190 // Get values 6191 var label = row.label || ''; 6192 var swatch = row.swatch || ''; 6193 var thumb = row.thumb || 'images/no-image.png'; 6194 6195 // Generate the columns 6196 var cols = constructColumns(bucketed, row); 6197 6198 // Return the results 6199 var row = { 6200 label: label, 6201 swatch: swatch, 6202 thumb: ko.observable(thumb), // Don't know why this is an observable, so leaving it 6203 cols: cols 6204 }; 6205 6206 runHook('productDetailMatrixRow', { 6207 parent: self, 6208 bucketed: bucketed, 6209 row: row 6210 }); 6211 6212 return row; 6213 }); 6214 6215 return matrix; 6216 } 6217 6218 function constructColumns(bucketed, row) { 6219 var columns = _.map(bucketed.colKeys, function(col) { 6220 // Find the product that sits at the intersection of row and col 6221 var product = bucketed.products[row.label][col.label]; 6222 6223 var col = { 6224 label: col.label, 6225 product: product 6226 }; 6227 6228 runHook('productDetailMatrixCol', { 6229 parent: self, 6230 bucketed: bucketed, 6231 row: row, 6232 col: col 6233 }); 6234 6235 return col; 6236 }); 6237 6238 return columns; 6239 } 6240 }).extend({ deferred: true }); 6241 6242 if ((self.key() == oConfig.mainProductKey || oConfig.mainProductKey == '') && self.type !== 'parent') { 6243 self.setupQuestions(); 6244 } 6245 6246 // 2019-07-05 EJ - This only needs to run on the mainProduct on 6247 // the product detail page so I added a mainProductKey 6248 // var and check it against the current product's key 6249 if (self.key() == oConfig.mainProductKey && self.type === 'parent' && self.childSelectors().length === 0 && getOriginalPageName() === 'pc_product_detail.asp' && self.childDisplayType() == 'droplist') { 6250 6251 if(!self.opt1 || self.opt1 == ''){ 6252 //force this to stand-alone because it has bad data setup. 6253 self.type = 'stand-alone'; 6254 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.'); 6255 }else{ 6256 var selectorCount = 0; 6257 _.forEach(self, function (value, key) { 6258 var keyString = String(key); 6259 var matched = keyString.match(/^opt(\d)$/); 6260 6261 if (matched && value) { 6262 selectorCount++; 6263 var selector = {}; 6264 selector.field = matched[0]; 6265 selector.label = value; 6266 selector.options = []; 6267 selector.selectedOption = ko.observable(); 6268 selector.loading = ko.observable(matched[0] === 'opt1'); 6269 selector.index = selectorCount; 6270 selector.showSelector = ko.observable(oConfig.displayDroplistPlaceholdersForLazyLoad); 6271 6272 self.childSelectors.push(selector); 6273 } 6274 }); 6275 6276 // as third option: 6277 // pass an array of options to do loading 6278 // pass a shorter array to load up to that point then load first option from then on 6279 // pass null/false to not do loading 6280 self.loadNextSelector(1, null, new (function() { // this is an inplace constructor 6281 this.array = oConfig.childOptionList, 6282 this.done = false; 6283 this.getArray = function() { 6284 if (this.done) return []; 6285 else return this.array; 6286 } 6287 })()); 6288 } 6289 } 6290 6291 self.removeRow = function(rowKey) { 6292 var index = _.findIndex(self.rowCollection(), function(row) { 6293 return row.selectedChild().rowKey === rowKey; 6294 }); 6295 6296 self.rowCollection.splice(index, 1); 6297 } 6298 6299 self.currentParent = ko.observable(function() { 6300 if(self.type !== 'child') { 6301 return self; 6302 } 6303 6304 if (self.currentparent && self.currentParent()) { 6305 return self.currentParent 6306 } 6307 6308 if (self.type === 'child' && viewModel && ko.unwrap(viewModel.mainProduct)) { 6309 var matchingParent = self.parents().find( 6310 function(parent) { 6311 return parent.key() === ko.unwrap(viewModel.mainProduct).key(); 6312 } 6313 ) 6314 return matchingParent ? ko.unwrap(viewModel.mainProduct) : self; 6315 } 6316 6317 return self; 6318 }()); 6319 6320 self.addRowsToCart = function() { 6321 var items = self.rowCollection().map( 6322 function(item) { 6323 return item.selectedChild(); 6324 } 6325 ).filter( 6326 function(item) { 6327 return item !== undefined 6328 }); 6329 6330 utils.addToCart(items, undefined, self.key(), true); 6331 } 6332 6333 self.rowsAtcAttempted = ko.observable(false); 6334
6335 self.questionsHaveValidAnswers = ko.computed(function() { 6336 var validOptions = true; 6337 6338 if(self.useCartOptions()) { 6339 self.questions().some(function(question) { 6340 var answer = question.selectedAnswer(); 6341 var answerPopulated = (answer !== '' && answer !== undefined); 6342 if(question.required() && !answerPopulated) { 6343 validOptions = false; 6344 } 6345 return !validOptions; 6346 }); 6347 } 6348 6349 return validOptions; 6350 }); 6351 6352 self.allRowsValid = ko.computed(function() { 6353 var rowsValid = true; 6354 6355 self.rowCollection().some(function(row) { 6356 rowsValid = row.selectedChild() === undefined || row.selectedChild().questionsHaveValidAnswers(); 6357 return !rowsValid; 6358 }); 6359 6360 return rowsValid; 6361 }); 6362 6363 // List of fields that will have legitimate HTML in them. Note - we 6364 // are intentionally not putting these in a site option in order to 6365 // force any changes to go through source control. 6366 var fieldsToDecode = [ 6367 'inventory.stockMessage', 6368 'description', 6369 'name', 6370 'tabs>staticContent', 6371 'thumbAltText', 6372 'picAltText', 6373 'addOnLabel', 6374 'opt1', 6375 'opt2', 6376 'opt3', 6377 'opt4', 6378 'opt5', 6379 'opt6' 6380 ]; 6381 6382 runHook('fieldsToDecodeFilter', { self: self, product: product, fieldsToDecode: fieldsToDecode }); 6383 6384 // Set each field in the above list to the decoded version of itself 6385 fieldsToDecode.forEach(function(propName) { 6386 //using a > to denote a property on an array. 6387 if(propName.indexOf('>') > -1){ 6388 //get the array and the property on that array to be decoded 6389 var collection = self[propName.split('>')[0]]; 6390 var propName = propName.split('>')[1]; 6391 6392 //now check to see if the array is observable before looping 6393 if(typeof collection == 'function'){ 6394 _.each(collection(), function(obj){ 6395 if (typeof obj()[propName] == 'function') { // If it is an observable 6396 obj()[propName](utils.decodeHTML(obj()[propName]()) ); 6397 } else if (typeof obj()[propName] == 'string') { // If it is a string 6398 obj()[propName] = utils.decodeHTML(obj()[propName]); 6399 } else { 6400 // Do nothing 6401 } 6402 }) 6403 }else{ 6404 _.each(collection, function(obj){ 6405 if (typeof obj[propName] == 'function') { // If it is an observable 6406 obj[propName](utils.decodeHTML(obj[propName]()) ); 6407 } else if (typeof obj[propName] == 'string') { // If it is a string 6408 obj[propName] = utils.decodeHTML(obj[propName]); 6409 } else { 6410 // Do nothing 6411 } 6412 }) 6413 } 6414 6415 }else{ 6416 var field = _.get(self, propName); 6417 6418 if (typeof field == 'function') { // If it is an observable 6419 field( utils.decodeHTML(field()) ); 6420 } else if (typeof field == 'string') { // If it is a string 6421 _.set(self, propName, utils.decodeHTML(field)); 6422 } else { 6423 // Do nothing 6424 } 6425 } 6426 }); 6427 6428 if(self.currentParent()) { 6429 6430 if(self.documents().length == 0 && self.currentParent().documents().length > 0 ){ 6431 self.documents(self.currentParent().documents()); 6432 } 6433 6434 if(!self.description() && self.currentParent().description()) { 6435 self.description(self.currentParent().description()) 6436 } 6437 6438 //Handle Tab Inheritance at the individual tab instead of the array of tabs 6439 var newTabs = []; 6440 for(i=1; i <= oConfig.detailConfig.numberOfProductTabs; i++){ 6441 var parentTab = _.filter(self.currentParent().tabs, function(tab){ return tab.index == i})[0]; 6442 var childTab = _.filter(self.tabs, function(tab){ return tab.index == i})[0]; 6443 if(childTab){ 6444 newTabs.push(childTab); 6445 }else if(!childTab && parentTab){ 6446 //Inherit from the parent 6447 newTabs.push(parentTab); 6448 } 6449 } 6450 if(newTabs){ 6451 self.tabs = newTabs;
6452 } 6453 6454 } 6455 6456 if (self.showAddOns) { 6457 if (self.addOnDisplay == 'checkboxes') 6458 self.selectedAddOns = ko.observableArray([]); 6459 else // ^ note difference in plural 6460 self.selectedAddOn = ko.observable(); 6461 } 6462 6463 self.addOnOptions = function(){ 6464 var options = []; 6465 6466 if(self.addOns){ 6467 options = _.map(self.addOns(), function(product){ 6468 product.selectedQty(product.minQty() || 1); 6469 return ko.observable(product) 6470 }) 6471 } 6472 return options; 6473 }(); 6474 6475 runHook('productModelBottom', { self: self, product: product }); 6476 }; 6477 6478 var productMapping = { 6479 create: function (options) { 6480 return new productModel(options.data); 6481 } 6482 }; 6483 6484 var searchResultsPropertiesModel = function (properties) { 6485 var self = this; 6486 6487 self.selectedSort = ko.observable(utils.getParameter('sortby') || oConfig.searchConfig.defaultSort); 6488 self.selectedRpp = ko.observable(utils.getParameter('rpp') || oConfig.searchConfig.rpp); 6489 self.startCount = ko.observable((oConfig.searchConfig.page - 1) * oConfig.searchConfig.rpp + 1); 6490 6491 self.endCount = ko.observable(function () { 6492 var rpp = (oConfig.searchConfig.rpp === 0) ? oConfig.searchConfig.total : oConfig.searchConfig.rpp; 6493 return Math.min(((oConfig.searchConfig.page - 1) * rpp) + rpp, oConfig.searchConfig.total); 6494 }()); 6495 6496 self.maxPage = ko.observable( 6497 Math.ceil(oConfig.searchConfig.total / oConfig.searchConfig.rpp) 6498 ); 6499 6500 self.selectedLayout = ko.observable( 6501 utils.getCookie('productLayout') 6502 ); 6503 6504 self.changeRpp = function (value) { 6505 var sUrl = utils.setParameter('rpp', value); 6506 sUrl = sUrl + '&page=1'; 6507 window.location = sUrl; 6508 }; 6509 6510 self.layoutTemplate = ko.computed(function () { 6511 utils.setCookie('productLayout', self.selectedLayout()); 6512 window.location.reload(); 6513 return 'catalog.' + self.selectedLayout() + '_view' 6514 }); 6515 6516 runHook('searchResultsPropertiesModelBottom', { self: self, properties: properties }); 6517 }; 6518 6519 function PagedArray(array, pageSize) { 6520 //' if array has already been processed, just return it 6521 if(array && array.all) { 6522 return array; 6523 } 6524 var self = this; 6525 self.all = ko.observableArray(array || []); 6526 self.pageSize = ko.observable(pageSize || 10); 6527 self.page = ko.observable(1).extend({ counter: 1 }); 6528 self.numPages = ko.computed(function () { 6529 return Math.ceil(self.size() / self.pageSize()); 6530 }); 6531 self.size = ko.computed(function () { 6532 return self.all().length; 6533 }); 6534 self.items = ko.computed(function () { 6535 var pageSize = self.pageSize(); 6536 var start = (self.page() - 1) * pageSize; 6537 return self.all.slice(start, start + pageSize); 6538 }); 6539 } 6540 </script>
6540 6541 6542
6543<script> 6544 $(function () { 6545 if(typeof(ko) != 'undefined'){ 6546 ko.applyBindings(); 6547 } 6548 }); 6549 6550</script>
6550 6551</div> 6552 6553<div class="cart-templates-scripts">
6554<script type="text/javascript"> 6555 6556 addTimer("start of ko model"); 6557 $( document ).ready(function() { 6558 6559 if('custom-flag-pricing.asp' == 'payment.asp' ){ 6560 $(document).on('hidden', '#global_modal', function () { 6561 if( $('#handle-modal-exit').val() == 'true'){ 6562 $('#handle-modal-exit').val(false); 6563 viewModel.genericModalComplete(); 6564 } 6565 }); 6566 } 6567 addTimer("cart_templates: document.ready"); 6568 6569 }); 6570 6571 function emptyHandler(){} 6572 6573 function scrollToSection(id) { 6574 $('html, body').animate({ 6575 // subtracting body padding-top accounts for toolbars with absolute 6576 // position, such as the SU bar 6577 scrollTop: $(id).offset().top - parseInt($("body").css('padding-top')) 6578 }, 300, 6579 function(){ 6580 $('html, body').clearQueue(); 6581 }); 6582 } 6583 6584 function reloadPage() { 6585 viewModel.processing(true); 6586 location.reload(); 6587 } 6588 6589 function sendError(message) { 6590 if (window['insightRUM']) { 6591 insightRUM.rawErrors.push(["Error", sPageName, 1, 1, new Error(message.substring(0,149))]); 6592 } 6593 } 6594 6595 function buildContinueShoppingUrl() { 6596 var url = ofConfig.continueShopPage; 6597 if (ofConfig.guestLoggedIn) { 6598 url = utils.setParameter('action', 'logout', url); 6599 } else if (ofConfig.superUserOrderFormMode) { 6600 url = ofConfig.createNewQuoteLink; 6601 } 6602 return url; 6603 } 6604 6605 function drawContinueShoppingLabel() { 6606 var label = '<i class="icon-shopping-cart"></i> Continue Shopping'; 6607 var su_workflow = ''; 6608 if (su_workflow === "quote") { 6609 label = '<i class="icon-plus"></i> Create New ' + su_workflow; 6610 } 6611 return label; 6612 } 6613 6614 function isValidRequestedDate(date) { 6615 try { 6616 isBusinessDay = businessDaySettings[1][""].work_days_of_week == undefined || businessDaySettings[1][""].work_days_of_week.indexOf(date.getDay()+1) > -1; 6617 isHoliday = businessDaySettings[1][""].holiday_dates != undefined && businessDaySettings[1][""].holiday_dates.indexOf(moment(date).format("MM/DD/YYYY")) > -1; 6618 if(isBusinessDay && !isHoliday) { 6619 return true; 6620 } else { 6621 return false; 6622 } 6623 } catch (error) { 6624 sendError("isValidRequestedDate: " + error.message); 6625 return true; 6626 } 6627 } 6628 6629 function calculateAdjustedLeadTimeDays(effectiveOrderDate, leadTimeDays) { 6630 /* 6631 EJ - 2016-11-10 - adding 1 initially due to JS interpreting the date from the db as UTC date 6632 when in fact it is a local date at midnight. This causes the date 6633 in JS to be the day before at 7pm (-5) or 8pm (-4) depending on time 6634 of year. 6635 Since we are only really concerned with the day, we can add one to 6636 compensate for this. 6637 */ 6638 var adjustedLeadTimeDays = leadTimeDays; 6639 6640 /* EJ - 2016-11-10 - This if block helps mitigate when the cuttoff time has passed, but the 6641 effective_order_date on the SelectedShipVia has not be recalced by the 6642 ordering object yet. It essentially checks the cutoff if the effective_order_date 6643 is today. Otherwise, there is no need to calculate it. 6644 */ 6645 if(moment(effectiveOrderDate).date() <= moment().date()) { 6646 var currentDateTime = new Date(); 6647 var currentUTCSeconds = currentDateTime.getUTCSeconds() + (60 * currentDateTime.getUTCMinutes()) + (60 * 60 * currentDateTime.getUTCHours()); 6648 6649 if(currentUTCSeconds > businessDaySettings[1][""].utc_cutoff_time_seconds) { 6650 adjustedLeadTimeDays += 1; 6651 } 6652 } 6653 6654 var startingDate = moment(); 6655 6656 for(var i = 1; i < adjustedLeadTimeDays + 1; i++) { 6657 if(!isValidRequestedDate(startingDate.add(1, "days").toDate())) { 6658 adjustedLeadTimeDays += 1;
6659 } 6660 } 6661 6662 return adjustedLeadTimeDays; 6663 } 6664 6665 function autoAllocateItems() { 6666 if((!viewModel.useMultiShipEditUI()) || (viewModel.shipments().length === 1 6667 && viewModel.shipments()[0].shipTo().key() != "" 6668 && viewModel.shipments()[0].shipTo().key() != null)) { 6669 if(viewModel.shipments()[0].details().length === 0) { 6670 viewModel.moveAllItemsToShipment(viewModel.shipments()[0]); 6671 } 6672 } 6673 } 6674 6675 //This div is contained in the SU dashboard bar. 6676 utils.setActiveQuote = function (orderKey) { 6677 if(orderKey != ofConfig.SessionOrderKey) { 6678 jQuery.ajax({ 6679 url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=setActiveQuote"e_id=' + orderKey + '&randomnum=' + new Date().getTime() 6680 , cache: false 6681 , success: function(data,status,request){ 6682 6683 } 6684 , error: function(data) { 6685 alert('Error posting Recurring Order Settings'); 6686 } 6687 , complete: function(data) { 6688 } 6689 }); 6690 } 6691 } 6692 6693 utils.removeActiveQuote = function (bStartNewQuote) { 6694 utils.setActiveQuote(''); 6695 if(bStartNewQuote){ 6696 window.location = 'payment.asp' + (ofConfig.isModal ? '?modal=1' : ''); 6697 }else{ 6698 $('.active-quote-message').hide(); 6699 } 6700 }; 6701 6702 var orderInfoPostUrl = 'payment.asp'; //'https://' + window.location.hostname + window.location.pathname; 6703 var orderInfoPostApiUrl = "/ordering/"; 6704 var countries = []; 6705 var newCustomer = false; 6706 var viewModel; 6707 var order; 6708 6709 function addAddressHandler() { 6710 viewModel.genericModalComplete(); 6711 //viewModel.allocateShipments(false); 6712 apiGetShippingAddresses(); 6713 } 6714 6715 function changeAddressFromFinder(response, object){ 6716 console.log(response); 6717 var address = new addressInfo({ key: response.sha_key.value, state: '', city: '', zipCode: '', country: '', name: response.sha_key_disp.value, address1: '', global: 0 }); 6718 object.shipTo(address); 6719 } 6720 6721 function getAddressOptFields(){ 6722 var addressOptFields = []; 6723 for(i=1; i <= 5; i++){ 6724 if(ofConfig['showAddressOpt'+i]){ 6725 addressOptFields.push(i); 6726 } 6727 } 6728 return addressOptFields; 6729 } 6730 6731 function apiGetShippingAddresses(editedKey) { 6732 $.ajax({
6733 url: orderInfoPostUrl + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=apiGetShippingAddresses', 6734 success: function(data) { 6735 // viewModel.shippingAddresses = processShippingAddresses(JSON.parse(data))(); 6736 // viewModel.shippingAddresses.notifySubscribers(); 6737 var newVarForTesting = processShippingAddresses(JSON.parse(data))(); 6738 var editedShaKey = editedKey || ''; 6739 var bFound; 6740 _.each(newVarForTesting, function(newItem){ 6741 _.each(viewModel.shippingAddresses(),function(oldItem){ 6742 if(editedShaKey != ''){ 6743 if(oldItem.key() == editedShaKey && newItem.key() == editedShaKey){ 6744 oldItem.name(newItem.name()); 6745 oldItem.phone(newItem.phone()); 6746 oldItem.address1(newItem.address1()); 6747 oldItem.address2(newItem.address2()); 6748 oldItem.address3(newItem.address3()); 6749 oldItem.address4(newItem.address4()); 6750 oldItem.address5(newItem.address5()); 6751 oldItem.city(newItem.city()); 6752 oldItem.state(newItem.state()); 6753 oldItem.zipCode(newItem.zipCode()); 6754 oldItem.opt1(newItem.opt1()); 6755 oldItem.opt2(newItem.opt2()); 6756 oldItem.opt3(newItem.opt3()); 6757 oldItem.opt4(newItem.opt4()); 6758 oldItem.opt5(newItem.opt5()); 6759 return false; 6760 } 6761 bFound = true; 6762 }else{ 6763 bFound = false; 6764 if(oldItem.key() == newItem.key()){ 6765 bFound = true; 6766 return false; 6767 } 6768 } 6769 }); 6770 if(!bFound && editedShaKey == ''){ 6771 viewModel.shippingAddresses.push(ko.mapping.fromJS(newItem, shippingAddressMappingOptions)); 6772 return false; 6773 } 6774 }); 6775 viewModel.availableAddresses = viewModel.shippingAddresses; 6776 }, 6777 error: function(){ 6778 alert('error getting shipping addresses'); 6779 } 6780 }); 6781 } 6782 6783 var shippingAddressMappingOptions = { 6784 create: function(options) { 6785 var address = new addressInfo(options.data); 6786 address.summaryLine = ko.computed(function() { 6787 var lineText = ''; 6788 6789 function separator(separatorText) { 6790 return lineText === '' ? '' : separatorText; 6791 } 6792 6793 function addField(field, separatorText) { 6794 if(!separatorText) { separatorText = ', '} 6795 lineText += field ? separator(separatorText) + field : ''; 6796 } 6797 6798 addField(address.name()); 6799 addField(address.company()); 6800 addField(address.attention()); 6801 addField(address.firstName()); 6802 addField(address.lastName(), address.firstName() ? ' ' : ''); 6803 addField(address.address1()); 6804 addField(address.address2()); 6805 addField(address.address3()); 6806 addField(address.address4()); 6807 addField(address.address5()); 6808 addField(address.global()); 6809 addField(address.city()); 6810 addField(address.state()); 6811 addField(address.zipCode(), ' '); 6812 addField(address.country()); 6813 6814 return lineText; 6815 }); 6816 return address; 6817 } 6818 } 6819 6820 function getNewAddress() { 6821 return { 6822 name: "", 6823 firstName: "", 6824 lastName: "", 6825 company: "", 6826 attention: "", 6827 address1: "", 6828 address2: "", 6829 address3: "", 6830 address4: "", 6831 address5: "", 6832 country: "USA", 6833 city: "", 6834 state: "", 6835 county: "", 6836 zipCode: "", 6837 phone: "", 6838 email: "", 6839 global: "0", 6840 opt1: "", 6841 opt2: "", 6842 opt3: "", 6843 opt4: "", 6844 opt5: "", 6845 key: utils.createGuid() 6846 } 6847 } 6848 6849 function getShippingFromBilling() { 6850 var newAddress = JSON.parse(ko.toJSON(viewModel.Account)); 6851
6852 newAddress.firstName = viewModel.Customer().firstName(); 6853 newAddress.LastName = viewModel.Customer().LastName(); 6854 newAddress.Email = viewModel.Customer().Email(); 6855 newAddress.Phone = viewModel.Customer().Phone(); 6856 newAddress.Name = ""; 6857 newAddress.Attention = viewModel.Customer().firstName() + ' ' + viewModel.Customer().LastName(); 6858 newAddress.key = utils.createGuid(); 6859 6860 return newAddress; 6861 } 6862 6863 function getNewShipment() { 6864 return new Shipment({ 6865 Key: utils.createGuid(), 6866 SelectedShipVia: {}, 6867 ShipViaChoices: [], 6868 Details: [], 6869 LeadTimeDays: null, 6870 ShipTo: getNewAddress(), 6871 Comments: "", 6872 availableAddresses: shippingAddresses 6873 }); 6874 } 6875 6876 function generateRefId(){ 6877 var today = new Date(); 6878 var dd = today.getDate(); 6879 var mm = today.getMonth()+1; //January is 0! 6880 var yyyy = today.getFullYear(); 6881 var rand = Math.floor(Math.random() * 1000000) 6882 6883 if(dd<10) { 6884 dd='0'+dd 6885 } 6886 6887 if(mm<10) { 6888 mm='0'+mm 6889 } 6890 6891 today = yyyy+mm+dd+'-'+rand; 6892 return today; 6893 } 6894 6895 var StateChoice = function(code, name) { 6896 var self = this; 6897 6898 var choice = {}; 6899 choice["code"] = code; 6900 choice["name"] = name; 6901 6902 ko.mapping.fromJS(choice, {}, self); 6903 } 6904 6905 var detailLineInstanceSort = function (a, b) { 6906 var aInstance = a.instance(); 6907 var bInstance = b.instance(); 6908 var aLineNum = a.orderDetailNum(); 6909 var bLineNum = b.orderDetailNum(); 6910 var aParentId = a.parentProductID().trim(); 6911 var bParentId = b.parentProductID().trim(); 6912 6913 if(aInstance == bInstance) { 6914 return (aParentId < bParentId) ? -1 : (aParentId > bParentId) ? 1 : 0; 6915 } else { 6916 return (aLineNum < bLineNum) ? -1 : 1; 6917 } 6918 } 6919 6920 var shipmentDetailsInstanceSort = function(a, b) { 6921 return detailLineInstanceSort(a.orderDetail, b.orderDetail); 6922 } 6923 6924 var addressInfo = function(addressData, addressType) { 6925 var self = this; 6926 6927 if(!addressData) { 6928 addressData = getNewAddress(); 6929 } 6930 6931 // Order JSON returns isGlobalAddress while the rest of the template loads in data relying on global 6932 if('isGlobalAddress' in addressData && !('global' in addressData)){ 6933 addressData.global = addressData.isGlobalAddress; 6934 } 6935 6936 addressData.addressType = ko.observable(addressType || 'shipping'); 6937 6938 ko.mapping.fromJS(addressData, {}, self); 6939 6940 if(!self.state()) { 6941 self.state(undefined); 6942 } 6943 6944 for(var prop in self) { 6945 if(self.hasOwnProperty(prop) && typeof self[prop] === 'function') { 6946 if(self[prop]() === null || self[prop]() === 'null') { 6947 self[prop](''); 6948 } 6949 } 6950 } 6951 6952 self.address1.extend({ required: true }); 6953 self.country.extend({ required: true }); 6954 self.city.extend({ required: false }); 6955 self.state.extend({ required: ofConfig.bRequireStateForShipping }); 6956 self.zipCode.extend({ required: ofConfig.bRequireZIPCodeForShipping }); 6957 6958 if(!self.country()) { 6959 self.country("USA"); 6960 } 6961 6962 self.stateChoices = ko.observableArray(); 6963 6964 self.editing = ko.observable(false); 6965 6966 self.loadStates = function() { 6967 countries.forEach(function(country) { 6968 if(country.iso3 === self.country()) { 6969 self.stateChoices(country.states); 6970 } 6971 }); 6972 if(!self.country()){ 6973 self.stateChoices.removeAll(); 6974 } 6975 } 6976 6977 self.country.subscribe(function() { 6978 self.loadStates(); 6979 }); 6980 6981 self.loadStates(); 6982 } 6983 6984 var detailMap = function(detailLine, shipment, order) { 6985 var self = this; 6986 self.detailLine = detailLine; 6987 self.shipment = shipment; 6988 self.totalOrderQty = ko.computed(function() { return detailLine.qty(); }); 6989 self.qtyToShip = ko.observable(); 6990 self.qtyInShipment = ko.observable(function() { 6991 self.qtyToShip(self.shipment.details().reduce(function(prev, curr, index, arr) { 6992 if(curr.orderDetailId() == detailLine.orderDetailKey()) { 6993 return prev + Number(curr.qtyToShip()); 6994 } else { 6995 return prev; 6996 } 6997 }, 0)); 6998 return self.qtyToShip(); 6999 }() 7000 ); 7001 7002 self.qtyInAllShipments = ko.computed(function() { 7003 var theKey = self.shipment.key(); 7004 var allShipmentsTotal = order.shipments().reduce(function(runningTotal, individualShipment) { 7005 var individualShipmentTotal = individualShipment.details().reduce(function(runningSubTotal, detail) { 7006 if(detail.orderDetailId() == detailLine.orderDetailKey()) { 7007 return runningSubTotal + Number(detail.qtyToShip() || 0); 7008 } else { 7009 return runningSubTotal; 7010 } 7011 }, 0); 7012 return runningTotal += individualShipmentTotal; 7013 }, 0); 7014 7015 var currentShipmentTotal = self.shipment.details().reduce(function(runningSubTotal, detail) { 7016 if(detail.orderDetailId() == detailLine.orderDetailKey()) { 7017 return runningSubTotal + Number(detail.qtyToShip() || 0); 7018 } else { 7019 return runningSubTotal; 7020 } 7021 }, 0) 7022 7023 var otherShipmentsTotal = allShipmentsTotal - currentShipmentTotal; 7024 7025 return otherShipmentsTotal + Number(self.qtyToShip() || 0); 7026 }); 7027 7028 self.unallocatedQty = ko.computed(function() { return self.detailLine.qty() - self.qtyInAllShipments(); }); 7029 self.toggleItemSelect = ko.computed({ 7030 read: function() { 7031 return this.qtyToShip() > 0; 7032 }, 7033 write: function(isChecked) { 7034 if(isChecked){ 7035 this.qtyToShip(1); 7036 } else { 7037 this.qtyToShip(0); 7038 } 7039 } 7040 }, self); 7041 7042 runHook('detailLineModelBottom', { self: self, detailLine: self }); 7043 }; 7044 7045 var Shipment = function(shipmentData) { 7046 var self = this; 7047 ko.mapping.fromJS(shipmentData, { 7048 shipTo : shippingAddressMappingOptions, 7049 shipViaChoices : { 7050 create: function(options) { 7051 if(options.data == null) { 7052 return ko.mapping.fromJS([]); 7053 } else { 7054 return ko.mapping.fromJS(options.data); 7055 } 7056 } 7057 }, 7058 selectedShipVia : { 7059 create: function(options) { 7060 if(options.data == null) { 7061 return ko.mapping.fromJS({requestDate: "0001-01-01T00:00:00"}); 7062 } else { 7063 return ko.mapping.fromJS(options.data); 7064 } 7065 } 7066 }, 7067 details: { 7068 create: function(options) { 7069 options.data.orderDetail.configuratorJson = options.data.orderDetail.configuratorJson ? JSON.parse(options.data.orderDetail.configuratorJson) : {}; 7070 if(options.data.orderDetail.configuratorJson && options.data.orderDetail.configuratorJson.choices) { 7071 options.data.orderDetail.configuratorJson.choices = options.data.orderDetail.configuratorJson.choices.sort(function(a, b) { 7072 if(a.pos == b.pos) { 7073 return 0; 7074 } 7075 return a.pos < b.pos ? -1 : 1; 7076 }); 7077 } 7078 if(options.data.orderDetail.configuratorJson) { 7079 options.data.orderDetail.configuratorJson.configType = options.data.orderDetail.configuratorJson.configType || 'configurator'; 7080 } 7081 options.data.orderDetail.parentProductID = options.data.orderDetail.parentProductID.trim() || ''; 7082 options.data.orderDetail.editing = false; 7083 7084 return ko.mapping.fromJS(options.data); 7085 } 7086 } 7087 }, self); 7088
7089 self.details().forEach(function(detail) { 7090 var detailLine = detail.orderDetail; 7091 detailLine.instanceChildren = self.details().filter(function(item) { 7092 return item.orderDetail.instance() == detailLine.instance() && item.orderDetail.parentProductID().trim() != '' && item.orderDetail != detailLine; 7093 }).map(function(item) { return item.orderDetail; }) || []; 7094 7095 var mainProductArray = self.details().filter(function(item) { 7096 return item.orderDetail.instance() == detailLine.instance() && item.orderDetail.removeType() == 'instance'; 7097 }); 7098 var mainProduct = mainProductArray.length > 0 ? mainProductArray[0].orderDetail : detailLine; 7099 7100 var mainProductQty = mainProduct.qty(); 7101 7102 detailLine.instanceUnitPrice = ko.observable(self.details().reduce(function(current, item) { 7103 if(!ofConfig.showProductDiscount){ 7104 item.orderDetail.priceBeforeAdjustment(item.orderDetail.price()); 7105 } 7106 if(item.orderDetail.instance() == detailLine.instance()) { 7107 //This IF block is attempting to account for calculating the unit price on "nested" configurator lines. Any other product type should fall into 7108 // The else block so it just pulls the quantity from the od lines. 7109 //TODO: Account for configurator products AND split by address as this calculation will likely not work in that scenario. 7110 // In this scenario, it should use the extended quantity on the shipment not the one from the OD line. 7111 if(item.orderDetail.parentProductID().trim() != '' && item.orderDetail.removeType() != 'instance' && item.orderDetail.removeType() != 'OD_Key') { 7112 return current += ((item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()) * item.qtyToShip()) / mainProductQty; 7113 } else { 7114 return current += (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()); 7115 } 7116 } else { 7117 return current; 7118 } 7119 },0)); 7120 7121 detailLine.instanceUnitPriceDisplay = ko.computed(function(){ 7122 return utils.formatMoney(detailLine.instanceUnitPrice(), utils.decimalPlacesOnUnitPrices); 7123 }); 7124 7125 detailLine.instanceExtPrice = ko.observable(self.details().reduce(function(current, item) { 7126 if(item.orderDetail.instance() == detailLine.instance()) { 7127 return current += (item.orderDetail.priceBeforeAdjustment() || item.orderDetail.price()) * item.qtyToShip(); 7128 // return current += item.orderDetail.extTotal(); 7129 } else { 7130 return current; 7131 } 7132 },0)); 7133 }); 7134 7135 self.details.sort(shipmentDetailsInstanceSort); 7136 7137 self.availableAddresses = shippingAddresses; 7138 7139 self.shipTo = ko.observable(self.shipTo); 7140 7141 self.availableAddresses().forEach(function(address,index){ 7142 if(!self.shipTo()){ 7143 self.shipTo(address); 7144 return false; 7145 } 7146 if(address.key() == self.shipTo().key()){ 7147 self.shipTo(address); 7148 } 7149 }); 7150 7151 self.earliestShipDate = ko.observable( 7152 function() { 7153 if(self.selectedShipVia && self.selectedShipVia.effectiveOrderDate) { 7154 var adjustedLeadTimeDays = calculateAdjustedLeadTimeDays(self.selectedShipVia.effectiveOrderDate(), self.leadTimeDays()); 7155 return moment(self.selectedShipVia.effectiveOrderDate()).add(adjustedLeadTimeDays, "days").format("MM/DD/YYYY"); 7156 } else { 7157 return moment(new Date(self.ExpectedShipDate)).format("MM/DD/YYYY"); 7158 } 7159 }() 7160 ); 7161 7162 self.requestedShipDate = ko.observable( 7163 function() { 7164 if(self.selectedShipVia && self.selectedShipVia.requestDate()) { 7165 if(self.selectedShipVia.requestDate() >= self.earliestShipDate()) { 7166 return moment(new Date(self.selectedShipVia.requestDate())).format("MM/DD/YYYY"); 7167 } else { 7168 return self.earliestShipDate(); 7169 } 7170 } else { 7171 if(self.selectedShipVia && self.selectedShipVia.effectiveOrderDate) { 7172 var adjustedLeadTimeDays = calculateAdjustedLeadTimeDays(self.selectedShipVia.effectiveOrderDate(), self.selectedShipVia.leadTimeDays()); 7173 return moment(self.selectedShipVia.effectiveOrderDate()).add(adjustedLeadTimeDays - 1, "days").format("MM/DD/YYYY"); 7174 } else { 7175 return moment(new Date(self.ExpectedShipDate)).format("MM/DD/YYYY"); 7176 } 7177 } 7178 }() 7179 ); 7180 7181 if(self.selectedShipVia && self.selectedShipVia.shippingAccountId){ 7182 self.selectedShipVia.shippingAccountId = ko.validatedObservable(self.selectedShipVia.shippingAccountId() || '').extend({ required: true, message: 'Please select a shipping account.'}); 7183 7184 self.selectedShipVia.shippingAccountId.subscribe(function(shippingAccountKey){ 7185 var postData = {}; 7186 var orderShipViaDetails = []; 7187 7188 orderShipViaDetails = [ 7189 { 7190 "osvd_key" : self.selectedShipVia.orderShipViaDetailKey(), 7191 "sa_id" : shippingAccountKey 7192 } 7193 ] 7194 7195 postData = 7196 { 7197 "Tables": [ 7198 { 7199 "TableName" : "orders_ship_via_details", 7200 "TableKeyField" : "osvd_key", 7201 "UserKeyField" : "osvd_key", 7202 "UserKeyIsPrimaryKey" : "True", 7203 "Data" : orderShipViaDetails 7204 } 7205 ] 7206 }; 7207 7208 postLogicJsonAjax(postData, true); 7209 }); 7210 }else{ 7211 self.selectedShipVia = {}; 7212 self.selectedShipVia.shippingAccountId = ko.observable(''); 7213 self.selectedShipVia.collectShippingAccount = ko.observable(false); 7214 self.selectedShipVia.name = ko.observable(''); 7215 self.selectedShipVia.description = ko.observable(''); 7216 self.selectedShipVia.total = ko.observable(0); 7217 self.selectedShipVia.shipViaChoiceID = ko.observable(''); 7218 self.selectedShipVia.sv_ref_id = ko.observable(''); 7219 }; 7220 7221 if(self.shipViaChoices && self.shipViaChoices().length > 0){ 7222 self.selectedShipViaChoice = ko.observable(self.shipViaChoices().find(function(choice) { 7223 return (choice.shipViaChoiceKey() == self.selectedShipVia.shipViaChoiceID() || choice.shipViaRefID() == self.selectedShipVia.sv_ref_id()); 7224 }) || self.shipViaChoices()[0]); 7225 }else{ 7226 self.selectedShipViaChoice = ko.observable(); 7227 } 7228 7229 self.shipToValid = ko.computed(function() { 7230 return ko.validatedObservable(self.shipTo()).isValid(); 7231 }); 7232 7233 self.saveShipToAddress = function(shipment) { 7234 7235 var shipmentArray = []; 7236 7237 var details = shipment.details().map(function(map, index, array) { 7238 return { 7239 orderDetailId : map.orderDetailId(), 7240 qtyToShip: map.qtyToShip() 7241 } 7242 }); 7243 7244 var shipmentInfo = { 7245 "Key": shipment.key(), 7246 "ShipmentId": shipment.key(), 7247 "ShipTo": { 7248 key : shipment.shipTo().key(), 7249 name : shipment.shipTo().name(), 7250 company : shipment.shipTo().company(), 7251 attention : shipment.shipTo().attention(), 7252 address1 : shipment.shipTo().address1(), 7253 address2 : shipment.shipTo().address2(), 7254 address3 : shipment.shipTo().address3(), 7255 address4 : shipment.shipTo().address4(), 7256 address5 : shipment.shipTo().address5(), 7257 city : shipment.shipTo().city(), 7258 state : shipment.shipTo().state(), 7259 zipCode : shipment.shipTo().zipCode(), 7260 county : shipment.shipTo().county(), 7261 country : shipment.shipTo().country(), 7262 email : shipment.shipTo().email(), 7263 firstName : shipment.shipTo().firstName(), 7264 lastName : shipment.shipTo().lastName(), 7265 phone : shipment.shipTo().phone(), 7266 global : shipment.shipTo().global(), 7267 opt1 : shipment.shipTo().opt1(), 7268 opt2 : shipment.shipTo().opt2(), 7269 opt3 : shipment.shipTo().opt3(), 7270 opt4 : shipment.shipTo().opt4(), 7271 opt5 : shipment.shipTo().opt5() 7272 }, 7273 "Details": details 7274 }; 7275 7276 shipmentArray.push(shipmentInfo); 7277 7278 var postOptions = { 7279 data: "shipmentJson=" + encodeURIComponent(JSON.stringify(shipmentArray)), 7280 success: function(data) { 7281 autoAllocateItems();
7282 self.showShippingAddressEdit(false); 7283 }, 7284 error: function() { 7285 alert('error saving shipping address'); 7286 } 7287 } 7288 7289 postInfo(postOptions, 'updateShipToAddress', shipment.key()); 7290 }; 7291 7292 self.setShippingToBilling = function(shipment) { 7293 var newAddress = getShippingFromBilling(); 7294 shipment.shipTo(ko.mapping.fromJS(newAddress,shippingAddressMappingOptions)); 7295 shipment.saveShipToAddress(shipment); 7296 } 7297 7298 self.showShippingAddressEdit = ko.computed({ 7299 read: function() { 7300 if(!self.shipToValid()) { 7301 self.shipTo().editing(true); 7302 } 7303 return self.shipTo().editing(); 7304 }, 7305 write: function(newValue) { 7306 if(!newValue && self.shipToValid()) { 7307 self.shipTo().editing(false); 7308 } else { 7309 self.shipTo().editing(true); 7310 } 7311 } 7312 }); 7313 7314 // self.EarliestShipDate.extend(); 7315 // self.RequestedShipDate.extend({ min: self.EarliestShipDate }); 7316 // self.RequestedShipDate.extend({ min: { params: self.EarliestShipDate, message: "The earliest ship date available is {0}" } }); 7317 7318 self.detailsMap = ko.observableArray([]); 7319 7320 self.valid = ko.computed(function() { 7321 return self.shipToValid() && self.details().length > 0; // && self.RequestedShipDate.isValid(); 7322 }); 7323 7324 self.itemsSelected = ko.computed(function() { 7325 return self.details().length > 0; 7326 }); 7327 7328 self.selectItemsComplete = function(shipment) { 7329 7330 var shipmentArray = []; 7331 7332 var lineMappings = shipment.detailsMap().map(function(map, index, array) { 7333 return { 7334 OrderDetailId : map.detailLine.orderDetailKey(), 7335 QtyToShip: map.qtyToShip() 7336 } 7337 }); 7338 7339 var shipmentInfo = { 7340 Key: shipment.key(), 7341 ShipmentId: shipment.key(), 7342 Details: [] 7343 }; 7344 shipmentInfo.Details = lineMappings; 7345 shipmentArray.push(shipmentInfo); 7346 7347 var postOptions = { 7348 data: "shipmentJson=" + encodeURIComponent(JSON.stringify(shipmentArray)), 7349 error: function() { 7350 alert('error saving item list on shipment'); 7351 } 7352 } 7353 7354 postInfo(postOptions, 'updateShipToAddress'); 7355 7356 $('#modal_add_prods[tabindex="-1"]:hidden').remove() 7357 $('#modal_add_prods').modal('hide'); 7358 }; 7359 7360 self.selectedShipViaChoice.subscribe(function(newShipViaChoiceValue) { 7361 var shipViaChoiceKey = newShipViaChoiceValue.shipViaChoiceKey(); 7362 var shipmentKey = self.key(); 7363 7364 var postOptions = { 7365 url: orderInfoPostUrl + '?ajax=true&pageaction=setShipmentShipVia&o_key=' + viewModel.orderKey() + '&shipViaChoiceKey=' + shipViaChoiceKey + '&shipmentKey=' + shipmentKey, 7366 error: function() { 7367 alert('error setting Shipping Method'); 7368 } 7369 } 7370 7371 postInfo(postOptions, 'setShipmentShipVia'); 7372 7373 }); 7374 7375 self.comments.subscribe(function(newComment) { 7376 7377 var shipmentCommentPostData = {}; 7378 7379 var shipmentInfo = [{ 7380 "os_key": self.key(), 7381 "comments": newComment 7382 }]; 7383 7384 shipmentCommentPostData = 7385 { 7386 "Tables": [ 7387 { 7388 "TableName" : "order_shipments", 7389 "TableKeyField" : "os_key", 7390 "UserKeyField" : "os_key", 7391 "UserKeyIsPrimaryKey" : "True", 7392 "Data" : shipmentInfo 7393 } 7394 ] 7395 }; 7396 7397 postLogicJsonAjax(shipmentCommentPostData); 7398 }); 7399 7400 self.requestedShipDate.subscribe(function(newRequestedShipDate) { 7401 7402 if (!(newRequestedShipDate instanceof Date) || isNaN(newRequestedShipDate.valueOf())) { 7403 console.log('requestedShipDate is not a date'); 7404 return; 7405 } 7406 7407 var postOptions = { 7408 data: "shipmentId=" + encodeURIComponent(self.key()) + "&requestedShipDate=" + encodeURIComponent(moment(newRequestedShipDate).format('MM/DD/YYYY')), 7409 error: function() { 7410 alert('error setting shipment requested ship date'); 7411 } 7412 } 7413 7414 postInfo(postOptions, 'setRequestedShipDate'); 7415 }); 7416
7417 self.details().forEach(function(thisLine) { 7418 thisLine.hasChildProducts = ko.observable(function() { 7419 return self.details().filter(function(outerLine) { 7420 return outerLine.orderDetail.instance() == thisLine.orderDetail.instance() 7421 && thisLine.orderDetail.removeType() != 'instance'; // main product has removeType of instance 7422 }).length > 1; 7423 }()); 7424 7425 thisLine.orderDetail.hasParentInCart = ko.observable(function() { 7426 return self.details().filter(function(outerLine) { 7427 return outerLine.orderDetail.orderDetailKey() != thisLine.orderDetail.orderDetailKey() 7428 && outerLine.orderDetail.instance() == thisLine.orderDetail.instance() 7429 && outerLine.orderDetail.removeType() == 'instance'; 7430 }).length > 0; 7431 }()); 7432 }); 7433 7434 if(ofConfig.useAccountDefaultShipVia && self.shipViaChoices && self.shipViaChoices().length > 0) { 7435 var filteredChoice = self.shipViaChoices().find(function(choice) { 7436 return choice.shipViaChoiceKey() == ofConfig.accountDefaultShipViaKey || 7437 choice.shipViaRefID() == ofConfig.accountDefaultShipViaCode 7438 }); 7439 7440 if(filteredChoice) { 7441 self.shipViaChoices([ filteredChoice ]); 7442 } 7443 } 7444 7445 self.shipTo.subscribe(function(shipTo) { 7446 if(viewModel && viewModel.setShipTo) { 7447 viewModel.setShipTo(self, shipTo); 7448 } 7449 }) 7450 7451 runHook('shipmentModelBottom', { self: self, shipmentData: shipmentData }); 7452 } 7453 7454 var Customer = function(customerData) { 7455 var self = this; 7456 7457 ko.mapping.fromJS(customerData, {}, self); 7458 7459 self.firstName.extend({ required: true }); 7460 self.lastName.extend({ required: true }); 7461 self.email.extend({ email: { message: 'A valid email address is required.', params: true }, required: { message: 'A valid email address is required.', params: true} }); 7462 self.phone.extend({ required: true }); 7463 } 7464 7465 /* 7466 var Account = function(accountData) { 7467 var self = this; 7468 7469 ko.mapping.fromJS(accountData, { 7470 create: function(options) { 7471 return new addressInfo(options.data); 7472 } 7473 }, self); 7474 7475 if(!self.Country()) { 7476 self.Country('USA'); 7477 } 7478 7479 self.Company.extend({ required: true }); 7480 self.Address1.extend({ required: true }); 7481 self.Country.extend({ required: true }); 7482 self.City.extend({ required: true }); 7483 if(!self.State()) { 7484 self.State(""); 7485 } 7486 self.State.extend({ required: true }); 7487 self.ZipCode.extend({ required: true }); 7488 } 7489 */ 7490 7491 var Order = function(orderData) { 7492 addTimer("start order mapping"); 7493 var self = this; 7494 7495 self.activeAjaxRequestCount = ko.observable(0); 7496 7497 ko.mapping.fromJS(orderData, { 7498 detailLines : { 7499 create: function(options) { 7500 options.data.configuratorJson = options.data.configuratorJson ? JSON.parse(options.data.configuratorJson) : {}; 7501 options.data.parentProductID = options.data.parentProductID.trim() || ''; 7502 options.data.editing = false; 7503 options.data.uomConversion = !options.data.uomConversion ? 1 : options.data.uomConversion; 7504 options.data.minQty = oConfig.convertMinQtyFromStdToSalesUom(options.data.minQty, options.data.uomConversion); 7505 options.data.maxQty = oConfig.convertMaxQtyFromStdToSalesUom(options.data.maxQty, options.data.uomConversion); 7506 options.data.qtyIncrement = (options.data.uomConversion == 0 || options.data.uomConversion === 1) ? (options.data.qtyIncrement || oConfig.defaultQuantityIncrement) : 0; 7507 return ko.mapping.fromJS(options.data); 7508 } 7509 }, 7510 orderActions : { 7511 create: function(options) { 7512 if(options.data) { 7513 if(!options.data.hasOwnProperty('showPaymentMethods')) { 7514 options.data.showPaymentMethods = true; 7515 } 7516 } 7517 return ko.mapping.fromJS(options.data); 7518 } 7519 }, 7520 shipments : { 7521 create: function(options) { 7522 return new Shipment(options.data); 7523 } 7524 }, 7525 customer : { 7526 create: function(options) { 7527 return options.data ? new Customer(options.data) : {}; 7528 } 7529 }, 7530 account : { 7531 create: function(options) { 7532 return new addressInfo(options.data); 7533 } 7534 }, 7535 paymentMethod : { 7536 create: function(options) { 7537 if(options.data == null || options.data == '') { 7538 return ko.mapping.fromJS({ 7539 paymentMethodKey: "", 7540 paymentType: "", 7541 }); 7542 } else { 7543 options.data.paymentType = (options.data.paymentType || "").toLowerCase(); 7544 return ko.mapping.fromJS(options.data); 7545 } 7546 } 7547 }, 7548 vaultedPayment : { 7549 create: function(options) { 7550 if(options.data == null) { 7551 return ko.mapping.fromJS({ 7552 key: "", 7553 vaultKey: "", 7554 nickName: "", 7555 nameOnCard: "", 7556 cardType: "", 7557 expMonth: 0, 7558 expYear: 0, 7559 first2: "0", 7560 last4: "0", 7561 address1: "", 7562 address2: "", 7563 city: "", 7564 state: "", 7565 zip: "", 7566 country: "", 7567 status: true, 7568 merchantId: "", 7569 customerId: "", 7570 accountId: "", 7571 gatewayInfoDirty: false, 7572 accountLast4: "", 7573 achAccountType: "", 7574 bankName: "", 7575 routingLast4: "", 7576 type: "", 7577 customerProfileId: "" 7578 }); 7579 } else { 7580 return ko.mapping.fromJS(options.data); 7581 } 7582 } 7583 }, 7584 roRunDate : { 7585 update: function(options) { 7586 //Quick fix to hide invalid expiration. 7587 //ToDo: update to check for other "invalid" dates. 7588 date = new Date(options.data); 7589 7590 var isValid = date instanceof Date && !isNaN(date); 7591 if(moment(date).format("MM/DD/YYYY") == '01/01/0001' || moment(date).format("MM/DD/YYYY") == '01/01/2001'){ 7592 isValid = false; 7593 } 7594 7595 if(!isValid) { 7596 return moment().format("MM/DD/YYYY"); 7597 } else { 7598 return moment(date).format("MM/DD/YYYY"); 7599 } 7600 } 7601 }, 7602 roRecCase : { 7603 update: function(options) { 7604 if(!options.data) { 7605 return 'month'; 7606 } else { 7607 return options.data; 7608 } 7609 } 7610 }, 7611 roRecQty : { 7612 update: function(options) { 7613 if(!options.data || options.data == 0) { 7614 return 1; 7615 } else { 7616 return options.data; 7617 } 7618 } 7619 }, 7620 'ignore': ["errorMessages"] 7621 }, self); 7622 7623 self.showCredits = ko.observable(false);
7624 self.allowQtyControls = ko.observable(false); 7625 self.disablePlaceOrder = ko.observable(false); 7626 7627 self.detailLines().forEach(function(detailLine) { 7628 // We can't debounce/trottle an observable 7629 // so we add a computed to track qty changes. 7630 // We use this in a subscription to call 7631 // update cart to update qty change in bulk atc 7632 // to avoid loading the qty change without posting 7633 // and updating the entire order model (for perf) 7634 detailLine.qtyTracker = ko.computed(function() { 7635 return detailLine.qty(); 7636 }).extend({throttle: 500}); 7637 detailLine.qtyTracker.subscribe(function (newQty) { 7638 self.postQtyUpdate(); 7639 }, detailLine); 7640 7641 detailLine.workerPriceTracker = ko.computed(function() { 7642 return detailLine.price(); 7643 }).extend({throttle: 500}); 7644 detailLine.workerPriceTracker.subscribe(function (newQty) { 7645 self.setWorkerPriceOverride(detailLine); 7646 }, detailLine); 7647 7648 detailLine.workerQtyLimitsTracker = ko.computed(function() { 7649 return { 7650 removeType: detailLine.removeType(), 7651 minQty: detailLine.minQty(), 7652 maxQty: detailLine.maxQty(), 7653 qtyIncrement: detailLine.qtyIncrement() 7654 }; 7655 }).extend({throttle: 500}); 7656 detailLine.workerQtyLimitsTracker.subscribe(function (newValue) { 7657 self.setWorkerQtyLimits(detailLine); 7658 }); 7659 7660 detailLine.instanceChildren = self.detailLines().filter(function(item) { 7661 return item.instance() == detailLine.instance() && item != detailLine; 7662 }) || []; 7663 7664 var mainProduct = self.detailLines().filter(function(item) { 7665 return item.instance() == detailLine.instance() && item.removeType() == 'instance'; 7666 })[0] || detailLine; 7667 7668 var mainProductQty = mainProduct.qty(); 7669 7670 detailLine.instanceUnitPrice = ko.observable(self.detailLines().reduce(function(current, item) { 7671 if(!ofConfig.showProductDiscount){ 7672 item.priceBeforeAdjustment(item.price()); 7673 } 7674 if(item.instance() == detailLine.instance()) { 7675 if(item.parentProductID().trim() != '' && item.removeType() != 'instance') { 7676 return current += ((item.priceBeforeAdjustment() || item.price()) * item.qty()) / mainProductQty; 7677 } else { 7678 return current += (item.priceBeforeAdjustment() || item.price()); 7679 } 7680 } else { 7681 return current; 7682 } 7683 },0)); 7684 7685 detailLine.instanceUnitPriceDisplay = ko.computed(function(){ 7686 return utils.formatMoney(detailLine.instanceUnitPrice(), utils.decimalPlacesOnUnitPrices); 7687 }); 7688 7689 detailLine.instanceExtPrice = ko.observable(self.detailLines().reduce(function(current, item) { 7690 if(item.instance() == detailLine.instance()) { 7691 return current += item.extTotal(); 7692 } else { 7693 return current; 7694 } 7695 },0)); 7696 7697 detailLine.hasQuantityRestrictions = ko.computed(function () { 7698 return !!( 7699 (detailLine.minQty() && detailLine.minQty() !== oConfig.defaultMinimumQuantity) || 7700 ((!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() !== oConfig.defaultMinimumQuantity) || 7701 detailLine.maxQty() 7702 ); 7703 }); 7704 7705 detailLine.quantityRestrictionsHtml = ko.computed(function () { 7706 var lines = []; 7707
7708 if (detailLine.minQty() && detailLine.minQty() != oConfig.defaultMinimumQuantity) 7709 lines.push(oConfig.labels.minQtyPopover.replace(/<min_qty>/,detailLine.minQty())); 7710 7711 if ( (!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() != oConfig.defaultQuantityIncrement) 7712 lines.push('Qty Increment: ' + detailLine.qtyIncrement()); 7713 7714 if (detailLine.maxQty()) 7715 lines.push('Maximum Qty: ' + detailLine.maxQty()); 7716 7717 return lines.join('<br>'); 7718 }); 7719 }); 7720 7721 self.needToChoosePromos = ko.observable(); 7722 7723 self.paymentMethodSelected = ko.observable(function() { 7724 return typeof self.paymentMethod.paymentType == 'function'; 7725 }() 7726 ); 7727 7728 self.termsAgreement = ko.observable(function() { 7729 return self.legalResponse() == 'agreed'; 7730 }() 7731 ); 7732 7733 self.detailLines.sort(detailLineInstanceSort); 7734 7735 self.shipments.sort(function(left, right) { 7736 return left.position() == right.position() ? 0 : (left.position() < right.position() ? -1 : 1); 7737 }); 7738 7739 self.processing = ko.observable(false); 7740 self.populatingShippingAddresses = ko.observable(false); 7741 self.availableShippingAddresses = ko.observableArray([]); 7742 self.newCouponCode = ko.observable(""); 7743 self.newGiftCertificate = ko.observable(""); 7744 if(!self.errorMessages) { 7745 self.errorMessages = ko.observableArray(); 7746 }; 7747 // self.orderPlaced = ko.observable(false); 7748 7749 self.orderPlaced = ko.computed(function() { 7750 return self.completed() 7751 }); 7752 7753 self.Customer = ko.validatedObservable(self.Customer); 7754 self.Account = ko.validatedObservable(self.Account); 7755 7756 self.shippingAddresses = shippingAddresses; 7757 7758 self.addressTypes = function(){ 7759 var addressTypes = []; 7760 addressTypes.push({ 7761 label: ofConfig.addressBookLabel, 7762 global: '0' 7763 }); 7764 if(ofConfig.useLocalPickup){ 7765 addressTypes.push({ 7766 label: ofConfig.localPickupLabel, 7767 global: '1' 7768 }) 7769 } 7770 return addressTypes; 7771 }; 7772 7773 self.defaultShaKey = function() { 7774 sShaKey = sDefaultShaKey; 7775 if (sShaKey == ''){ 7776 sShaKey = self.shippingAddresses()[0].sha_key; 7777 } 7778 return sShaKey; 7779 } 7780 self.billingSectionValid = ko.computed(function () { 7781 return self.Customer.isValid() && self.Account.isValid(); 7782 }); 7783 7784 self.toggleShowBillingEdit = function() { 7785 if(self.showBillingEdit()) { // && newCustomer) { 7786 var postData = new CreateCustomerPost(self); 7787 self.postBillingUpdate(postData); 7788 } else { 7789 self.showBillingEdit(!self.showBillingEdit()); 7790 } 7791 }; 7792 7793 self.postBillingUpdate = function(postData) { 7794 7795 var postUrl = orderInfoPostUrl + '?o_key=' + viewModel.orderKey() + '&origin=bill-ship'; 7796 var dataString; 7797 var keyCount = 0; 7798 7799 $.each(postData, function(key, value) { 7800 keyCount += 1; 7801 7802 if(keyCount > 1) { 7803 dataString += "&" 7804 } 7805 dataString += key + "=" + encodeURIComponent(value); 7806 }); 7807 7808 var postOptions = { 7809 url: postUrl, 7810 type: "POST", 7811 data: dataString, 7812 success: function(data) { 7813 self.showBillingEdit(!self.showBillingEdit()); 7814 }, 7815 error: function() { 7816 alert('error posting billing update'); 7817 } 7818 } 7819 7820 postInfo(postOptions, '', 'checkout_shipping'); 7821 } 7822 7823 self.editingBilling = ko.observable(false); 7824 self.showBillingEdit = ko.computed({ 7825 read: function() { 7826 if(!self.billingSectionValid()) { 7827 self.editingBilling(true); 7828 } 7829 return self.editingBilling(); // && !self.billingSectionValid(); 7830 }, 7831 write: function(newValue) { 7832 if(!newValue && self.billingSectionValid()) { 7833 self.editingBilling(false); 7834 } else { 7835 self.editingBilling(true); 7836 } 7837 } 7838 }); 7839 7840 self.moveAllItemsToShipment = function(shipment) { 7841 self.processing(true); 7842 7843 var shipmentArray = []; 7844 7845 var lineMappings = self.detailLines().map(function(map, index, array) { 7846 return { 7847 OrderDetailId : map.orderDetailKey(), 7848 QtyToShip: map.qty() 7849 } 7850 }); 7851 7852 var shipmentInfo = { 7853 Key: shipment.key(), 7854 ShipmentId: shipment.key(), 7855 Details: [] 7856 }; 7857
7858 self.shipments().forEach(function(otherShipment) { 7859 if(otherShipment.key() != shipment.key()) { 7860 shipmentArray.push({ 7861 key: otherShipment.key(), 7862 ShipmentId: otherShipment.key(), 7863 Delete: true 7864 }); 7865 } 7866 }); 7867 7868 shipmentInfo.Details = lineMappings; 7869 shipmentArray.push(shipmentInfo); 7870 7871 var postOptions = { 7872 data: "shipmentJson=" + encodeURIComponent(JSON.stringify(shipmentArray)), 7873 error: function() { 7874 alert('error moving all products to shipment'); 7875 }, 7876 complete: function() { 7877 self.processing(false); 7878 } 7879 } 7880 7881 postInfo(postOptions, 'updateShipToAddress'); 7882 7883 $('#modal_add_prods[tabindex="-1"]:hidden').remove() 7884 $('#modal_add_prods').modal('hide'); 7885 }; 7886 7887 self.isOverLineLimit = ko.observable(checkLineLimit(self)); 7888 7889 function checkLineLimit(vm){ 7890 //use the alternate ui (showcart.asp) when over the line limit threshold 7891 // Don't allow this to happen if using user create shipments since the showcart page doesn't support 7892 // Split shipping. 7893 if(oConfig.allowUserCreatedShipments){ 7894 return false; 7895 }else if (ofConfig.useTooManyLinesRestriction && vm.detailLines().length >= parseInt(ofConfig.tooManyLinesQuantity)){ 7896 return true; 7897 }else{ 7898 return false; 7899 } 7900 } 7901 7902 self.isMinimumOrderTotalMet = ko.observable(checkOrderTotal(self)); 7903 //moved definition to global scope 7904 7905 self.shippingComplete = ko.observable(isShippingComplete()); 7906 7907 function isShippingComplete(){ 7908 if ( self.completed() || self.lifecycleStage() == 'cancelled' || self.lifecycleStage() == 'punchout_punched_in') { 7909 return true; 7910 } 7911 7912 // force step 2 if there are no lines on the order. 7913 if (self.detailLines().length == 0){ 7914 return false; 7915 } 7916 7917 // force step 3 if the lines exceed the limit. 7918 if (self.isOverLineLimit()){ 7919 return true; 7920 } 7921 7922 // force step 2 if any shipments are missing an address. 7923 _.each(self.shipments(),function(shipment){ 7924 if(!shipment.shipTo().key()){ 7925 return false; 7926 } 7927 }); 7928 7929 if(!self.isMinimumOrderTotalMet()){ 7930 utils.setCookie(self.orderKey() + '-step', '2'); 7931 } 7932 7933 if(utils.getCookie(self.orderKey()+'-step') == undefined){ 7934 if(ofConfig.defaultShippingSectionOpen){ 7935 utils.setCookie(self.orderKey() + '-step', '2'); 7936 }else{ 7937 utils.setCookie(self.orderKey() + '-step', '3'); 7938 } 7939 } 7940 7941 if (utils.getCookie(self.orderKey() + '-step') == '2'){ 7942 return false; 7943 }else{ 7944 return true; 7945 } 7946 }; 7947 7948 self.shipmentsComplete = ko.observable(false || self.completed()); 7949 7950 self.shipmentsSectionsValid = ko.computed(function() { 7951 var result = true; 7952 self.shipments().forEach(function(shipment) { 7953 if(!shipment.valid() || (shipment.shipTo && shipment.shipTo().editing())) { 7954 result = false; 7955 } 7956 }); 7957 return result; 7958 }); 7959 7960 self.toggleShowShippingEdit = function() { 7961 self.showShippingEdit(!self.showShippingEdit()); 7962 if(!self.showShippingEdit()) { 7963 scrollToSection('#checkout_summary'); 7964 } 7965 }; 7966 7967 self.moveItemToNewShipTo = function(item){ 7968 self.itemShipToMap().push({ 7969 orderDetailKey: item.orderDetailKey, 7970 instance: ko.observable(item.instance()), 7971 key: ko.observable(item.orderDetailKey),
7972 qty: ko.observable(item.qtyIncrement() || 1), 7973 qtyControlledFrom: ko.observable(item.qtyControlledFrom()), 7974 minQty: ko.observable(item.minQty()), 7975 qtyIncrement: ko.observable(item.qtyIncrement()), 7976 getPrice: item.getPrice, 7977 suPrice: item.suPrice, 7978 shaKey: ko.observable(item.shaKey()), 7979 shipTo: ko.observable({}), 7980 moveItemToNewShipTo: self.moveItemToNewShipTo, 7981 removeItemToShipToMap: self.removeItemToShipToMap, 7982 availableAddresses: shippingAddresses, 7983 parentProductID: item.parentProductID 7984 }); 7985 item.qty(item.qty() - (item.qtyIncrement() || 1)); 7986 self.itemShipToMap.notifySubscribers(); 7987 }; 7988 7989 self.currentPackage = ko.observable(function(){ 7990 var item = new Object(); 7991 item.shippingAddressId = ko.observable(sDefaultShaKey); 7992 item.shipTo = ko.observable() 7993 item.details = ko.observableArray([]); 7994 return item; 7995 }()); 7996 7997 7998 self.toggleItemInCurrentPackage = function(item){ 7999 if(!_.contains(self.currentPackage().details(),item)){ 8000 self.currentPackage().details().push(item) 8001 }else{ 8002 _.pull(self.currentPackage().details(), item) 8003 } 8004 self.currentPackage.notifySubscribers(); 8005 }; 8006 8007 self.isInCurrentPackage = function(item){ 8008 return _.contains(self.currentPackage().details(),item); 8009 }; 8010 8011 self.removeItemToShipToMap = function(item){ 8012 _.pull(self.itemShipToMap(),item); 8013 self.itemShipToMap.notifySubscribers(); 8014 }; 8015 8016 self.getTotalQty = function(instance){ 8017 var totalQty = 0; 8018 var mappings = self.itemsOnOrder(); 8019 if(self.useMultiShipEditUI && self.useMultiShipEditUI()){ 8020 mappings = self.itemShipToMap(); 8021 } 8022 _.each(mappings, function(map){ 8023 if(map.instance() == instance && map.qtyControlledFrom() != 1){ 8024 totalQty += parseFloat(map.qty()); 8025 //exit after the first item is found so the carrier product qty will display. 8026 //or not - added && map.qtyControlledFrom() != 1 to account for config products 8027 // qtyControlledFrom is "1" when controlled by the parent 8028 //return false; 8029 } 8030 }); 8031 return totalQty; 8032 }; 8033 8034 self.getOrderDetailQty = function(instance){ 8035 var totalQty = 0; 8036 self.itemsOnOrder().forEach(function(map){ 8037 if(map.instance() == instance && map.qtyControlledFrom() != 1){ 8038 totalQty += parseFloat(map.qty()); 8039 } 8040 }); 8041 return totalQty; 8042 }; 8043 8044 self.setItemShipToMapPrice = function(data){ 8045 self.itemShipToMap().forEach(function(map){ 8046 if(map.instance() == data.instance()){ 8047 if(self.superUserRestrictMinPrice() & data.superUserMinPrice() != null && data.price() < data.superUserMinPrice()) { 8048 data.price(undefined); 8049 data.price(data.superUserMinPrice()); 8050 } 8051 map.suPrice = data.price(); 8052 } 8053 }); 8054 }; 8055 8056 self.setWorkerPriceOverride = function(data){ 8057 var orderDetail = []; 8058 8059 orderDetail.push({ 8060 orderDetailKey: data.orderDetailKey(), 8061 PriceCalculationType: 'fixed', 8062 Price: data.price(), 8063 PriceBeforeAdjustment: data.price() 8064 }); 8065 8066 var postOptions = { 8067 data: "orderDetail=" + encodeURIComponent(JSON.stringify(orderDetail)), 8068 success: function(data) { 8069 $('#cartAdvSettings.collapse').toggleClass('in'); 8070 $('#onOrderAdvBtn').toggleClass('active'); 8071 }, 8072 error: function() { 8073 alert('Error saving Unit Price'); 8074 } 8075 } 8076 8077 postInfo(postOptions, 'setOrderDetailFields'); 8078 } 8079 8080 self.setWorkerQtyLimits = function(data) { 8081 var orderDetail = []; 8082 8083 orderDetail.push({ 8084 orderDetailKey: data.orderDetailKey(), 8085 MinQty: data.minQty() * data.uomConversion(), 8086 MaxQty: data.maxQty() * data.uomConversion(), 8087 QtyIncrement: data.qtyIncrement(), 8088 RemoveType: data.removeType() 8089 }); 8090 8091 var postOptions = { 8092 data: "orderDetail=" + encodeURIComponent(JSON.stringify(orderDetail)), 8093 success: function(data) { 8094 $('#cartAdvSettings.collapse').toggleClass('in'); 8095 $('#onOrderAdvBtn').toggleClass('active'); 8096 toggleLoadingWidget(false); 8097 }, 8098 error: function() { 8099 alert('Error saving qty limits'); 8100 } 8101 } 8102 toggleLoadingWidget(true); 8103 postInfo(postOptions, 'setOrderDetailFields'); 8104 } 8105 8106 self.resetSuperUserPriceOverride = function(data){ 8107 var orderDetail = []; 8108 8109 orderDetail.push({ 8110 orderDetailKey: data.orderDetailKey(),
8111 PriceCalculationType: 'std' 8112 }); 8113 8114 var postOptions = { 8115 data: "orderDetail=" + encodeURIComponent(JSON.stringify(orderDetail)), 8116 success: function(data) { 8117 }, 8118 error: function() { 8119 alert('Error resetting Price Override'); 8120 } 8121 } 8122 8123 postInfo(postOptions, 'setOrderDetailFields'); 8124 }; 8125 8126 self.resetSuperUserShippingPrice = function(data){ 8127 var postOptions = { 8128 url: "payment.asp?o_key=" + viewModel.orderKey() + "&svc_key=" + data.shipViaChoiceKey() + '&ajax=true&pageaction=resetShippingPrice&randomnum=' + new Date().getTime() , 8129 success: function(data) { 8130 }, 8131 error: function() { 8132 alert('error resetting shipping price'); 8133 } 8134 } 8135 8136 postInfo(postOptions, 'resetSuperUserShippingPrice'); 8137 } 8138 8139 self.returnToPendingOrders = function() { 8140 window.location = 'quotes.asp?revert=1'; 8141 } 8142 8143 self.superUserOrderFormMode = ko.observable(ofConfig.superUserOrderFormMode && ofConfig.isSuperUserSession); 8144 8145 self.getOrderLabel = function(){ 8146 switch(self.recordType()){ 8147 case 'future-order': 8148 orderLabel = 'Future Order'; 8149 break; 8150 case 'recurring-order': 8151 orderLabel = 'Recurring Order'; 8152 break; 8153 case 'saved-cart': 8154 orderLabel = ofConfig.SavedCartLabel; 8155 break; 8156 default: 8157 if(self.superUserOrderFormMode()){ 8158 orderLabel = ofConfig.SavedCartLabel; 8159 }else{ 8160 orderLabel = 'Order'; 8161 } 8162 break; 8163 } 8164 //TODO: once we confirm this logic, return the calculated label instead of the Option. 8165 //return orderLabel; 8166 return ofConfig.SavedCartLabel; 8167 }; 8168 8169 self.superUserSetShipViaPrice = function(data, event){ 8170 var postOptions = { 8171 url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&svc_key=' + data.shipViaChoiceKey() + '&price=' + event.target.value + '&ajax=true&pageaction=setShippingPrice&randomnum=' + new Date().getTime(), 8172 success: function(data) { 8173 }, 8174 error: function() { 8175 alert('error resetting shipping price'); 8176 } 8177 }; 8178 postInfo(postOptions, 'setShippingPrice'); 8179 }; 8180 8181 self.postQtyUpdate = function() { 8182 8183 var postUrl = 'i_i_add_to_cart.asp' + '?ajax=qtyUpdate&modal=1&o_key=' + viewModel.orderKey(); 8184 var dataString = ''; 8185 var unqString = ''; 8186 var keyCount = 0; 8187 8188 self.detailLines().forEach(function(detailLine) { 8189 if(dataString.length) dataString += '&'; 8190 dataString += 'qty_' + detailLine.orderDetailKey() + '=' + detailLine.qty(); 8191 if(unqString.length) unqString +=','; 8192 unqString += detailLine.orderDetailKey(); 8193 }); 8194 8195 dataString += '&unqs=' + unqString; 8196 8197 var postOptions = { 8198 url: postUrl, 8199 type: "POST", 8200 data: dataString, 8201 success: function(data) { 8202 // 8203 }, 8204 error: function() { 8205 alert('error updating quantity'); 8206 } 8207 } 8208 8209 postInfo(postOptions, '',''); 8210 } 8211 8212 self.hasMultipleShipToAddresses = function() { 8213 var shaKeys = []; 8214 var hasMultipleAddresses = false; 8215 self.shipments().forEach(function(shipment) { 8216 var shaKey = shipment.shipTo().key(); 8217 if(shaKeys.indexOf(shaKey)) { 8218 shaKeys.push(shaKey); 8219 } 8220 if(shaKeys.length > 1) { 8221 hasMultipleAddresses = true; 8222 return; 8223 } 8224 }); 8225 return hasMultipleAddresses; 8226 }; 8227 8228 self.useMultiShipEditUI = ko.observable(self.hasMultipleShipToAddresses()); 8229 8230 self.allocateShipments = function(moveToNextStep){ 8231 var shipmentArray = []; 8232 var listOfShaKeys = []; 8233 var newShipmentKey; 8234 var orderDetail = []; 8235 8236 toggleLoadingWidget(true); 8237 8238 if(viewModel.useMultiShipEditUI()){ 8239 8240 //Get a unique list of shipping address keys
8241 self.itemShipToMap().forEach(function(item){ 8242 if ( listOfShaKeys.indexOf( item.shipTo().key() ) == -1 ){ 8243 listOfShaKeys.push(item.shipTo().key()); 8244 } 8245 }) 8246 8247 //Loop the sha_keys to create shipments for each 8248 var items = self.itemShipToMap(); 8249 var newShipmentCount = 0; 8250 listOfShaKeys.forEach(function(shaKey){ 8251 //reuse existing shipment keys if they exist. 8252 if( newShipmentCount+1 <= self.shipments().length ){ 8253 newShipmentKey = self.shipments()[newShipmentCount].key(); 8254 }else{ 8255 newShipmentKey = utils.createGuid(); 8256 } 8257 8258 var shipmentInfo = { 8259 Key: newShipmentKey, 8260 ShipmentId: newShipmentKey, 8261 ShippingAddressId: shaKey, 8262 Details: [] 8263 }; 8264 8265 //Loop the product - ship to mapping records to create shipment details 8266 var shipments = items; 8267 shipments.forEach(function(shipment){ 8268 if(shipment.shipTo().key() == shaKey){ 8269 shipmentInfo.Details.push( { 8270 OrderDetailId: shipment.orderDetailKey, 8271 QtyToShip: shipment.qty() 8272 }) 8273 } 8274 }); 8275 newShipmentCount++; 8276 shipmentArray.push(shipmentInfo); 8277 }); 8278 }else{ 8279 listOfShaKeys.push(self.shipments()[0].shipTo().key()); 8280 8281 //Single Shipping - reuse the first shipment key 8282 newShipmentKey = self.shipments()[0].key(); 8283 var shipmentInfo = { 8284 Key: newShipmentKey, 8285 ShipmentId: newShipmentKey, 8286 ShippingAddressId: self.shipments()[0].shipTo().key(), 8287 Details: [] 8288 }; 8289 8290 //JB - loop the items on order since we're in single shipment mode. 8291 viewModel.itemsOnOrder().forEach(function(item){ 8292 shipmentInfo.Details.push( { 8293 OrderDetailId: item.orderDetailKey(), 8294 QtyToShip: item.qty() 8295 }); 8296 }); 8297 shipmentArray.push(shipmentInfo); 8298 } 8299 8300 //Remove any orphaned shipments from the original data if the user is created shipments 8301 if(listOfShaKeys.length < self.shipments().length && oConfig.allowUserCreatedShipments){ 8302 var count = 0; 8303 _.eachRight(self.shipments(), function(oldShipment){ 8304 if( count + 1 <= (self.shipments().length - listOfShaKeys.length ) ){ 8305 shipmentArray.push({ 8306 Key: oldShipment.key(), 8307 Delete: true 8308 }); 8309 count++; 8310 } 8311 }); 8312 } 8313 8314 //Order Detail Field Updates 8315 var details = self.itemShipToMap() 8316 _.each(details, function(item){ 8317 var superUserPrice = parseFloat(item.suPrice); 8318 var getprice = parseFloat(item.getPrice()); 8319 8320 if( isNaN(superUserPrice)){ 8321 superUserPrice = getprice; 8322 } 8323 8324 if(viewModel.superUserOrderFormMode()) { 8325 if (getprice != superUserPrice) { 8326 //build OD object 8327 if(!_.find(orderDetail, {orderDetailKey: item.orderDetailKey}) ){ 8328 var obj = { 8329 orderDetailKey: item.orderDetailKey, 8330 Price: superUserPrice, 8331 PriceDisplay: getprice, 8332 PriceCalculationType: 'fixed' 8333 }; 8334 8335 if(ofConfig.useTradeAdjustmentOnSession){ 8336 obj.PriceBeforeAdjustment = superUserPrice; 8337 } 8338 orderDetail.push(obj); 8339 } 8340 } 8341 8342 var detail = _.find(orderDetail, {orderDetailKey: item.orderDetailKey}); 8343 8344 if(!detail) { 8345 detail = { 8346 orderDetailKey: item.orderDetailKey 8347 } 8348 orderDetail.push(detail); 8349 } 8350 8351 // var newValues = _.find(viewModel.itemsOnOrder(), {orderDetailKey: item.orderDetailKey}); 8352
8353 var itemOnOrder = viewModel.itemsOnOrder().reduce(function(returnItem, currentItem) { 8354 if(currentItem.orderDetailKey() == item.orderDetailKey) { 8355 returnItem = currentItem; 8356 } 8357 return returnItem; 8358 }) 8359 8360 detail.minQty = parseFloat(itemOnOrder.minQty ? itemOnOrder.minQty() : 0); 8361 detail.maxQty = parseFloat(itemOnOrder.maxQty ? itemOnOrder.maxQty() : 0); 8362 detail.qtyIncrement = parseFloat(itemOnOrder.qtyIncrement ? itemOnOrder.qtyIncrement() : oConfig.defaultQuantityIncrement); 8363 8364 // TODO: Need to track original removeType value - checking has children for now 8365 var defaultRemoveType = itemOnOrder.hasChildProducts() ? 'instance' : 'OD_Key'; 8366 8367 detail.removeType = itemOnOrder.removeType ? itemOnOrder.removeType() : defaultRemoveType; 8368 8369 runHook('allocateShipmentsOrderDetailUpdate', { itemOnOrder: itemOnOrder, detailLine: detail }); 8370 } 8371 toggleLoadingWidget(false); 8372 }); 8373 8374 var postOptions = { 8375 data: "shipmentJson=" + encodeURIComponent(JSON.stringify(shipmentArray)) + "&orderDetail=" + encodeURIComponent(JSON.stringify(orderDetail)), 8376 success: function(){ 8377 if(ofConfig.bUsePromotions){ 8378 jQuery.ajax({ 8379 url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=checkPromos&randomnum=' + new Date().getTime() 8380 , cache: false 8381 , type: 'GET' 8382 , success: function(data,status,request){ 8383 if(JSON.parse(data)){ 8384 viewModel.processing(true); 8385 8386 //redirect to reward selection page. 8387 //This is not opening in a modal for responsive reasons. 8388 var nextPage = encodeURIComponent('payment.asp?o_key=' + viewModel.orderKey() + (ofConfig.isModal ? '&modal=1' : '')); 8389 document.location = 'promo_reward_selection.asp?quickadd=1&next_page=' + nextPage + '&o_key=' + viewModel.orderKey() + (ofConfig.isModal ? '&modal=1' : ''); 8390 } 8391 } 8392 , error: function(data) { 8393 console.log('Error checking Promos'); 8394 } 8395 , complete: function(data) { 8396 } 8397 }); 8398 } 8399 }, 8400 error: function() { 8401 self.addShipment(); 8402 autoAllocateItems(); 8403 alert('error saving product list on shipment'); 8404 } 8405 } 8406 8407 postInfo(postOptions, 'updateShipToAddress'); 8408 if(moveToNextStep === undefined) { 8409 moveToNextStep=true; 8410 } 8411 if(self.isOverLineLimit()){ 8412 moveToNextStep = true; 8413 } 8414 console.log(self); 8415 self.shippingComplete(moveToNextStep); 8416 self.shippingComplete.notifySubscribers(); 8417 if(moveToNextStep) { 8418 utils.setCookie(self.orderKey() + '-step' , '3'); 8419 } 8420 }; 8421 8422 8423 self.showShippingEdit = ko.observable(!self.completed()); 8424 self.currentShipment = ko.observable(); 8425 8426 self.toggleMultiShip = function (data, event) { 8427 event.preventDefault(); 8428 self.useMultiShipEditUI(!self.useMultiShipEditUI()); 8429 8430 self.shippingComplete.notifySubscribers(); 8431 }; 8432 8433 self.toggleOrderPlaced = function (data, event) { 8434 event.preventDefault(); 8435 8436 var postData = {}; 8437 8438 if(viewModel.paymentMethod.paymentType() === 'cc') { 8439 8440 var defaultCcnChecked = $('#ccpm_default_ccn_id_selection').is(':checked'); 8441 8442 if(defaultCcnChecked) { 8443 postData.setDefaultCcn = 1 8444 } 8445 8446 postData.ccn_key = $('#ccpm_ccn_id').val(); 8447 postData.address = $('#ccpm_address_input').val(); 8448 postData.city = $('#ccpm_city_input').val(); 8449 postData.country = $('#ccpm_country_input').val(); 8450 postData.state = $('#ccpm_state_dropdown').prop('disabled') ? $('#ccpm_state_text').val() : $('#ccpm_state_dropdown').val(); 8451 postData.zip = $('#ccpm_zip_input').val(); 8452 8453 //oSavedPaymentMethodsCreditCard.saveBillingAddress(); 8454 } 8455 8456 var postOptions = { 8457 data: postData, 8458 success: function(data){ 8459 viewModel.updateOrderAccess(); 8460 var response = JSON.parse(data); 8461 if(Object.keys(response[0].Errors).length == 0) { 8462 //document.location = 'payment.asp?o_key=' + viewModel.orderKey() + '#checkout_confirmation'; 8463 scrollToSection('#checkout'); 8464 }else{ 8465 scrollToSection('#checkout'); 8466 } 8467 }, 8468 error: function(data) { 8469 alert('error placing order'); 8470 } 8471 } 8472 8473 8474 if ($.active > 0) { 8475 viewModel.processing(true); 8476 $( document ).one("ajaxStop", function(){ 8477 postInfo(postOptions, 'placeOrder'); 8478 }); 8479 } 8480 else { 8481 postInfo(postOptions, 'placeOrder'); 8482 } 8483 8484 }; 8485 8486 self.showItemSelector = function(shipment) { 8487 shipment.detailsMap([]);
8488 self.detailLines().forEach(function(detailLine, detailIndex, detailArray) { 8489 shipment.detailsMap().push(new detailMap(detailLine, shipment, self)); 8490 }); 8491 8492 self.currentShipment(shipment); 8493 $('#modal_add_prods').modal('show'); 8494 }; 8495 8496 self.addShipment = function() { 8497 8498 var newShipment = getNewShipment(); 8499 8500 var successFunction; 8501 8502 if(self.shipments().length === 0) { 8503 /* EJ - 2016-11-15 8504 I feel dirty about this, but it's a quick workaround for an odd issue 8505 happening on first load of the payment page for a new order, before the first 8506 shipment is added. The issue presents as a "corrupt" countries array (missing 8507 states for first country) and validation issues on Account form. 8508 8509 The only difference in code on client (verified with Arraxis Merge) is the orderPayload. 8510 The first page load doesn't have shipments or paymethods (empty array and null respectively), 8511 whereas the second and all subsequent page loads do. 8512 8513 The issue goes away once the first shipment is added, so I'm forcing a reload 8514 the first time a shipment is added, which was already happening already 8515 on first page load if there were no shipments on the order. 8516 8517 The first shipment being added needs to be moved to the ordering object eventually, 8518 which will negate the need for this code anyway, so I didn't spend more hours trying 8519 to find the root cause. 8520 */ 8521 8522 // so spinner stays active until location.reload happens 8523 self.activeAjaxRequestCount(self.activeAjaxRequestCount() + 1); 8524 8525 successFunction = function() { 8526 location.reload(); 8527 } 8528 } else { 8529 successFunction = autoAllocateItems; 8530 } 8531 8532 8533 var shipmentArray = []; 8534 8535 var shipmentInfo = { 8536 Key: newShipment.key(), 8537 ShipmentId: newShipment.key(), 8538 Details: [] 8539 }; 8540 8541 shipmentArray.push(shipmentInfo); 8542 8543 8544 var postOptions = { 8545 data: "shipmentJson=" + encodeURIComponent(JSON.stringify(shipmentArray)), 8546 error: function() { 8547 alert('error setting Shipping Method'); 8548 }, 8549 success: successFunction 8550 } 8551 8552 postInfo(postOptions, 'updateShipToAddress', newShipment.key(), self); 8553 8554 }; 8555 8556 self.deleteShipment = function(shipmentToDelete, e, index) { 8557 8558 var shipmentArray = []; 8559 8560 var shipmentInfo = { 8561 Key: shipmentToDelete.key(), 8562 Delete: true 8563 }; 8564 8565 shipmentArray.push(shipmentInfo); 8566 8567 var postOptions = { 8568 data: "shipmentJson=" + encodeURIComponent(JSON.stringify(shipmentArray)), 8569 error: function() { 8570 alert('error moving all items to shipment'); 8571 }, 8572 success: autoAllocateItems 8573 } 8574 8575 postInfo(postOptions, 'updateShipToAddress', 'checkout_shipping'); 8576 }; 8577 self.setShipTo = function(shipment, shipToAddress) { 8578 8579 var sha_id = shipToAddress.key(); 8580 var shipmentId = shipment.key(); 8581 8582 var postOptions = { 8583 data: "shipmentId=" + shipmentId + "&sha_id=" + sha_id, 8584 success: function(data) { 8585 autoAllocateItems(); 8586 self.shipmentsSectionsValid.notifySubscribers(); 8587 }, 8588 error: function() { 8589 alert('error saving shipping address'); 8590 } 8591 } 8592 8593 postInfo(postOptions, 'setSha'); 8594 8595 $('#modal_addressbook[tabindex="-1"]:hidden').remove() 8596 $('#modal_addressbook').modal('hide'); 8597 }; 8598 8599 self.showNewAddressForm = function(shipment) { 8600 shipment.shipTo(new addressInfo(getNewAddress())); 8601 8602 $('#modal_addressbook[tabindex="-1"]:hidden').remove() 8603 $('#modal_addressbook').modal('hide'); 8604 }; 8605 8606 self.showAddAddress = function(shipment){ 8607 8608 $('#modal_add_shipto').modal('show'); 8609 }; 8610
8611 self.shipments().forEach(function(shipment) { 8612 8613 self.detailLines().forEach(function(detailLine, detailIndex, detailArray) { 8614 shipment.detailsMap().push(new detailMap(detailLine, shipment, self)); 8615 }); 8616 }); 8617 8618 self.updatePoRequired = function() { 8619 if(self.paymentMethod && self.paymentMethod.paymentMethodKey() != ''){ 8620 var isReallyRequired = self.paymentMethod.poRequired() && self.paymentMethod.collectPO(); 8621 self.paymentMethod.poRequired(isReallyRequired); 8622 } 8623 } 8624 8625 self.updatePoRequired(); 8626 8627 self.poNumber.extend({ 8628 required: { 8629 onlyIf: function() { 8630 return viewModel && viewModel.paymentMethod.poRequired() 8631 } 8632 } 8633 }); 8634 8635 self.poNumber.subscribe(function(poNumber) { 8636 postOrderHeaderField("ponumber", poNumber); 8637 }); 8638 8639 self.comments.subscribe(function(newComments) { 8640 postOrderHeaderField("comment", newComments); 8641 }); 8642 8643 self.nickname.subscribe(function(nickname) { 8644 postOrderHeaderField("nickname", nickname); 8645 }); 8646 8647 self.orderCcEmail.subscribe(function(orderCcEmail) { 8648 postOrderHeaderField("order_cc_email", orderCcEmail); 8649 }); 8650 8651 self.isValidDate = function(date){ 8652 //Quick fix to hide invalid expiration. 8653 //ToDo: update to check for other "invalid" dates. 8654 8655 // Parse the date parts to integers 8656 var parts = date.split("-"); 8657 var day = parseInt(parts[2], 10); 8658 var month = parseInt(parts[1], 10); 8659 var year = parseInt(parts[0], 10); 8660 8661 // Check the ranges of month and year 8662 if(year < 1000 || year > 3000 || month == 0 || month > 12) 8663 return false; 8664 8665 var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; 8666 8667 // Adjust for leap years 8668 if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) 8669 monthLength[1] = 29; 8670 8671 // Check the range of the day 8672 return day > 0 && day <= monthLength[month - 1]; 8673 }; 8674 8675 self.getMinimumRecurringOrderDate = function(){ 8676 var today = moment(); 8677 var minimumDate = moment(today).add(1, 'days'); 8678 return moment(minimumDate).format("MM/DD/YYYY"); 8679 } 8680 8681 self.roRunDate.subscribe(function(roRunDate) { 8682 postOrderHeaderField("ro_rundate", roRunDate); 8683 }); 8684 8685 self.roRecCase.subscribe(function(roRecCase) { 8686 postOrderHeaderField("ro_rec_case", roRecCase); 8687 }); 8688 8689 self.roRecQty.subscribe(function(roRecQty) { 8690 postOrderHeaderField("ro_rec_qty", roRecQty); 8691 }); 8692 8693 self.updateRecurringType = function(data, event){ 8694 newValue = event.target.value; 8695 sOrderDetailKey = data.orderDetailKey(); 8696 switch(newValue){ 8697 case 'fixed': 8698 postOrderDetailFields(sOrderDetailKey, ['ro_recurring_type','ro_skip_next_runs'], ['fixed',0]); 8699 break; 8700 case 'recurring': 8701 postOrderDetailFields(sOrderDetailKey, ['ro_recurring_type','ro_skip_next_runs'], ['recurring',0]); 8702 break; 8703 case 'skipnext': 8704 postOrderDetailFields(sOrderDetailKey, ['ro_recurring_type','ro_skip_next_runs'], ['recurring',1]); 8705 break; 8706 case 'remove': 8707 viewModel.removeProduct(data); 8708 break; 8709 } 8710 8711 }; 8712 8713 self.getRecurringLabel = function(data){ 8714 var sMessage = ''; 8715 var sAction = data.orderDetail.roRecurringType(); 8716 var sSkipRuns = data.orderDetail.roSkipNextRuns(); 8717 switch(sAction){ 8718 case 'recurring': 8719 case '': 8720 if(sSkipRuns == 0){ 8721 //recurring 8722 sMessage = ofConfig.roRecurringItemLabel; 8723 }else{ 8724 //skip. 8725 sMessage = ofConfig.roSkippedItemLabel; 8726 } 8727 break; 8728 case 'fixed': 8729 sMessage = ofConfig.roOnetimeItemLabel; 8730 break; 8731 case 'disabled': 8732 sMessage = ofConfig.roDisabledItemLabel; 8733 break; 8734 } 8735 return sMessage; 8736 }; 8737 self.customerComment = ko.observable(''); 8738 8739 self.noteBook = ko.observable(); 8740 8741 self.populateNoteBook = function(){ 8742 var noteBook = {}; 8743 var count = 0; 8744 8745 noteBook.notes = ko.observableArray([]); 8746 8747 if(noteBookPayload.length > 0 ){ 8748 8749 noteBook.nbKey = noteBookPayload[0].nb_key; 8750 noteBook.id = noteBookPayload[0].id; 8751 noteBook.refId = noteBookPayload[0].ref_id; 8752 8753 _.each(noteBookPayload,function(note){ 8754 if(note.internal_notes || note.external_notes) { 8755 count++; 8756 item = {}; 8757 8758 item.internalNotes = note.internal_notes; 8759 item.externalNotes = note.external_notes; 8760 item.postedByName = note.c_f_nm + ' ' + note.c_l_nm; 8761 item.postedByUsername = note.username; 8762 item.createDate = note.create_date; 8763 noteBook.notes.push(ko.observable(item)); 8764 } 8765 }); 8766 } 8767 8768 self.noteBook(noteBook);
8769 }(); 8770 8771 self.buildOrderHeaderFields = function(aFields) { 8772 //Available order header fields that can be POSTed using this function 8773 var orderHeaderFields = { 8774 "UseMultipleShipments": viewModel.useMultipleShipments(), 8775 "Nickname" : viewModel.nickname(), 8776 "QuoteExpirationDate": viewModel.expirationDate() 8777 }; 8778 8779 var orderHeaderFieldsJson = {}; 8780 8781 //Add only the field(s) that are passed in aFields. 8782 _.forEach(aFields, function(sField) { 8783 orderHeaderFieldsJson[sField] = orderHeaderFields[sField]; 8784 }); 8785 8786 self.setOrderHeaderFields(orderHeaderFieldsJson); 8787 8788 }; 8789 8790 self.setOrderHeaderFields = function(orderHeaderFieldsJson) { 8791 8792 var postOptions = { 8793 data: "orderHeaderFields=" + encodeURIComponent(JSON.stringify(orderHeaderFieldsJson)), 8794 error: function(data) { 8795 alert('error setting Order Header fields'); 8796 } 8797 }; 8798 8799 postInfo(postOptions, 'setOrderHeaderFields'); 8800 }; 8801 8802 if(self.shipments().length === 0) { 8803 //self.addShipment(); 8804 } 8805 8806 self.setPaymentMethod = function(paymentMethod) { 8807 if(paymentMethod.refID() != viewModel.paymentMethod.refID()){ 8808 var postOptions = { 8809 data: "pm_id=" + paymentMethod.paymentMethodKey(), 8810 error: function(data) { 8811 alert('error setting pm'); 8812 }, 8813 success: function() { 8814 $('#ccpm_container').removeClass('hide'); 8815 viewModel.updatePoRequired(); 8816 } 8817 } 8818 8819 postInfo(postOptions, 'setPmId'); 8820 } 8821 } 8822 8823 self.ccn_id.subscribe(function(newCCN) { 8824 if(newCCN !== '') { 8825 var payload = 'ccn_id=' + newCCN; 8826 var postOptions = { 8827 data: payload, 8828 error: function(data) { 8829 alert('error setting CCN'); 8830 } 8831 } 8832 8833 postInfo(postOptions, 'setCCN'); 8834 } 8835 }); 8836 8837 self.SetCouponCode = function(couponCode) { 8838 var payload = 'couponcode=' + encodeURIComponent(couponCode); 8839 var postOptions = { 8840 data: payload, 8841 error: function(data) { 8842 alert('error applying coupon'); 8843 } 8844 } 8845 8846 postInfo(postOptions, 'setCoupon'); 8847 } 8848 8849 self.SetGiftCertificate = function(giftCertCode) { 8850 var payload = 'giftCertCode=' + encodeURIComponent(giftCertCode); 8851 var postOptions = { 8852 data: payload, 8853 error: function(data) { 8854 alert('error applying gift certificate'); 8855 } 8856 } 8857 8858 postInfo(postOptions, 'setGiftCertCode'); 8859 }; 8860 8861 self.allItemsAllocated = ko.computed(function() { 8862 var totalItemCount = self.detailLines().reduce(function(previous, current) { 8863 return previous + current.qty(); 8864 }, 0); 8865 8866 var allocatedItemCount = 0; 8867 self.shipments().forEach(function(shipment) { 8868 allocatedItemCount += shipment.details().reduce(function(previous, current) { 8869 return previous + current.qtyToShip(); 8870 }, 0); 8871 }); 8872 8873 return totalItemCount === allocatedItemCount; 8874 }); 8875 8876 self.itemsOnOrder = ko.computed(function() { 8877 var items = []; 8878 self.detailLines().forEach(function(detailLine) { 8879 detailLine.hasChildProducts = ko.observable(function() { 8880 return self.detailLines().filter(function(outerLine) { 8881 return outerLine.instance() == detailLine.instance() 8882 && detailLine.removeType() != 'instance' 8883 }).length > 1 8884 }()); 8885 8886 detailLine.hasParentInCart = ko.observable(function() { 8887 return self.detailLines().filter(function(outerLine) { 8888 return outerLine.orderDetailKey() != detailLine.orderDetailKey() 8889 && outerLine.instance() == detailLine.instance() 8890 && detailLine.removeType() == 'instance' 8891 }).length > 0 8892 }()); 8893 8894 detailLine.instanceChildren = self.detailLines().filter(function(item) { 8895 return item.instance() == detailLine.instance() && item.removeType() != 'instance' && item.parentProductID().trim() != '' && item != detailLine; 8896 }) || []; 8897 8898 var mainProduct = self.detailLines().filter(function(item) { 8899 return item.instance() == detailLine.instance() && item.removeType() == 'instance'; 8900 })[0] || detailLine; 8901 8902 var mainProductQty = mainProduct.qty(); 8903 8904 detailLine.superUserMinPrice = ko.observable(detail
8904Line.commodity[ofConfig.superUserMinPriceProperty]() || 0); 8905 8906 detailLine.instanceUnitPrice = ko.observable(self.detailLines().reduce(function(current, item) { 8907 if(!ofConfig.showProductDiscount){ 8908 item.priceBeforeAdjustment(item.price()); 8909 } 8910 if(item.instance() == detailLine.instance()) { 8911 if(item.parentProductID().trim() != '' && item.removeType() != 'instance') { 8912 return current += ((item.priceBeforeAdjustment() || item.price()) * item.qty()) / mainProductQty; 8913 } else { 8914 return current += (item.priceBeforeAdjustment() || item.price()); 8915 } 8916 } else { 8917 return current; 8918 } 8919 },0)); 8920 8921 detailLine.instanceUnitPriceDisplay = ko.computed(function(){ 8922 return utils.formatMoney(detailLine.instanceUnitPrice(), utils.decimalPlacesOnUnitPrices); 8923 }); 8924 8925 detailLine.instanceExtPrice = ko.observable(self.detailLines().reduce(function(current, item) { 8926 if(item.instance() == detailLine.instance()) { 8927 return current += item.extTotal(); 8928 } else { 8929 return current; 8930 } 8931 },0)); 8932 8933 detailLine.allocatedQty = ko.observable(function() { 8934 var runningTotal = 0; 8935 self.shipments().forEach(function(shipment) { 8936 shipment.details().forEach(function(shipDetail) { 8937 if(shipDetail.orderDetailId() === detailLine.orderDetailKey()) { 8938 runningTotal += shipDetail.qtyToShip(); 8939 } 8940 }); 8941 }); 8942 return runningTotal; 8943 }()); 8944 8945 detailLine.minGrossMarginPercent = ko.computed(function() { 8946 if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() != null) 8947 { 8948 return ( (detailLine.superUserMinPrice() - detailLine.commodity.cost()) / detailLine.superUserMinPrice() * 100 ).toFixed(); 8949 } else { 8950 return undefined; 8951 } 8952 }); 8953 8954 detailLine.grossMarginPercent = ko.computed({ 8955 write: function(newVal) { 8956 var localGrossMarginPercent = parseInt(detailLine.minGrossMarginPercent() || 0); 8957 var val = parseInt(newVal); 8958 if(val < localGrossMarginPercent) { 8959 val = localGrossMarginPercent; 8960 } 8961 var marginPercent = val / 100; 8962 var markup = marginPercent / (1 - marginPercent); 8963 var newPrice = (detailLine.commodity.cost() * (1 + markup)).toFixed(2); 8964 detailLine.price(undefined); 8965 detailLine.price(newPrice); 8966 detailLine.priceCalculationType('fixed'); 8967 }, 8968 read: function() { 8969 var marginPercent = (detailLine.price() - detailLine.commodity.cost()) / detailLine.price(); 8970 return (marginPercent * 100).toFixed(0); 8971 }, 8972 deferEvaluation: true 8973 }); 8974 8975 detailLine.minMarkupPercent = ko.computed(function() { 8976 if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() != null) 8977 { 8978 return ( detailLine.superUserMinPrice() / detailLine.commodity.cost() - 1 ).toFixed(); 8979 } else { 8980 return undefined; 8981 } 8982 }); 8983 8984 detailLine.markupPercent = ko.computed({ 8985 write: function(newVal) {
8986 var minMarkupPercent = parseInt(detailLine.minMarkupPercent || 0); 8987 var val = parseInt(newVal); 8988 if(val < minMarkupPercent) { 8989 val = minMarkupPercent; 8990 } 8991 var markup = val / 100; 8992 var newPrice = (detailLine.commodity.cost() * (1 + markup)).toFixed(2); 8993 detailLine.price(undefined); 8994 detailLine.price(newPrice); 8995 detailLine.priceCalculationType('fixed'); 8996 }, 8997 read: function() { 8998 var markup = (detailLine.price() - detailLine.commodity.cost()) / detailLine.commodity.cost(); 8999 return (markup * 100).toFixed(0); 9000 }, 9001 deferEvaluation: true 9002 }); 9003 9004 detailLine.maxDiscountPercent = ko.computed(function() { 9005 if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() != null) 9006 { 9007 return (100 * (1 - (detailLine.superUserMinPrice() / detailLine.commodity.retailPrice()))).toFixed(); 9008 } else { 9009 return undefined; 9010 } 9011 }); 9012 9013 detailLine.discountPercent = ko.computed({ 9014 write: function(newVal) { 9015 var maxDiscountPercent = parseInt(detailLine.maxDiscountPercent() || 100); 9016 var val = parseInt(newVal); 9017 if(val > maxDiscountPercent) { 9018 val = maxDiscountPercent; 9019 } 9020 var discount = val / 100; 9021 var newPrice = (detailLine.commodity.retailPrice() * (1 - discount)).toFixed(2); 9022 detailLine.price(undefined); 9023 detailLine.price(newPrice); 9024 detailLine.priceCalculationType('fixed'); 9025 }, 9026 read: function() { 9027 var discount = 1 - detailLine.price() / detailLine.commodity.retailPrice(); 9028 return (discount * 100).toFixed(0); 9029 }, 9030 deferEvaluation: true 9031 }); 9032 9033 detailLine.minGrossMarginAmount = ko.computed(function() { 9034 if(self.superUserRestrictMinPrice() & detailLine.superUserMinPrice() != null) 9035 { 9036 return detailLine.superUserMinPrice() - detailLine.commodity.cost(); 9037 } else { 9038 return undefined; 9039 } 9040 }); 9041 9042 detailLine.grossMarginAmount = ko.computed({ 9043 write: function(newVal) { 9044 var localMminGrossMarginAmount = parseInt(detailLine.minGrossMarginAmount() || 0); 9045 var val = parseInt(newVal); 9046 if(val < localMminGrossMarginAmount) { 9047 val = localMminGrossMarginAmount; 9048 } 9049 var grossMargin = parseFloat(val); 9050 var newPrice = (detailLine.commodity.cost() + grossMargin).toFixed(2); 9051 detailLine.price(undefined); 9052 detailLine.price(newPrice); 9053 detailLine.priceCalculationType('fixed'); 9054 }, 9055 read: function() { 9056 return (detailLine.price() - detailLine.commodity.cost()).toFixed(2); 9057 }, 9058 deferEvaluation: true 9059 }); 9060 9061 detailLine.allowDeletes = ko.computed({ 9062 write: function(val) { 9063 // TODO: need to store previous value for removeType (od_key, hide, instance) - checking child prods for now 9064 if(val) { 9065 detailLine.hasChildProducts() ? detailLine.removeType('instance') : detailLine.removeType('OD_Key'); 9066 } else { 9067 detailLine.removeType('hide'); 9068 } 9069 }, 9070 read: function() { 9071 return !(detailLine.removeType() == 'hide') 9072 } 9073 }); 9074 9075 detailLine.suMinQty = ko.computed({ 9076 write: function(val) { 9077 val = parseFloat(val); 9078 if(isNaN(val)) { 9079 val = detailLine.minQty(); 9080 } 9081 if(!detailLine.maxQty() == 0 && val > detailLine.maxQty()) { 9082 detailLine.minQty(detailLine.maxQty()); 9083 } else { 9084 detailLine.minQty(val); 9085 } 9086 detailLine.suMaxQty(detailLine.maxQty()); 9087 detailLine.suMinQty.notifySubscribers(); 9088 }, 9089 read: function() { 9090 return detailLine.minQty(); 9091 } 9092 }); 9093 9094 detailLine.suMaxQty = ko.computed({ 9095 write: function(val) { 9096 var originalValue = detailLine.maxQty();
9097 var newValue = parseFloat(val);; 9098 9099 if(isNaN(newValue)) { 9100 newValue = originalValue; 9101 } 9102 if(newValue > 0) { 9103 if(detailLine.minQty() > 0 && newValue < detailLine.minQty()) { 9104 newValue = detailLine.minQty(); 9105 } else { 9106 var diff = ( (newValue-detailLine.minQty()) * 1000 ) % ( (detailLine.qtyIncrement() || 1) * 1000 ) / 1000; 9107 newValue = newValue - diff; 9108 newValue = detailLine.minQty() > 0 && newValue < detailLine.minQty() ? detailLine.minQty() : newValue; 9109 } 9110 } else { 9111 newValue = 0; 9112 } 9113 9114 // reset maxQty to workaround KO bug that causes 9115 // underlying value to be changed, but the UI to 9116 // not update if the end value is the same as the 9117 // original value 9118 /* - not a bug, need to notifySubscribers UI was broken 9119 detailLine.maxQty(99); 9120 detailLine.maxQty(0); 9121 */ 9122 9123 // set valid newValue 9124 detailLine.maxQty(newValue); 9125 }, 9126 read: function() { 9127 return detailLine.maxQty(); 9128 } 9129 }); 9130 9131 detailLine.suQtyIncrement = ko.computed({ 9132 write: function(val) { 9133 val = parseFloat(val); 9134 if(isNaN(val)) { 9135 val = detailLine.qtyIncrement(); 9136 } 9137 detailLine.qtyIncrement(val); 9138 detailLine.suMaxQty(detailLine.maxQty()); 9139 detailLine.suQtyIncrement.notifySubscribers(); 9140 }, 9141 read: function() { 9142 return detailLine.qtyIncrement(); 9143 } 9144 }); 9145 9146 detailLine.selectedRoAction = ko.computed(function(){ 9147 var sAction = detailLine.roRecurringType(); 9148 var skipNextRuns = detailLine.roSkipNextRuns(); 9149 if( sAction == '' || sAction == 'recurring'){ 9150 if( skipNextRuns == 0){ 9151 sAction = 'recurring'; 9152 }else{ 9153 sAction = 'skipnext'; 9154 } 9155 } 9156 return sAction; 9157 }); 9158 9159 detailLine.hasQuantityRestrictions = ko.computed(function () { 9160 return !!( 9161 (detailLine.minQty() && detailLine.minQty() !== oConfig.defaultMinimumQuantity) || 9162 ((!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() !== oConfig.defaultMinimumQuantity) || 9163 detailLine.maxQty() 9164 ); 9165 }); 9166 9167 detailLine.quantityRestrictionsHtml = ko.computed(function () { 9168 var lines = []; 9169 9170 if (detailLine.minQty() && detailLine.minQty() != oConfig.defaultMinimumQuantity) 9171 lines.push(oConfig.labels.minQtyPopover.replace(/<min_qty>/,detailLine.minQty())); 9172 9173 if ( (!detailLine.uomConversion() || detailLine.uomConversion() == 1) && detailLine.qtyIncrement() && detailLine.qtyIncrement() != oConfig.defaultQuantityIncrement) 9174 lines.push('Qty Increment: ' + detailLine.qtyIncrement()); 9175 9176 if (detailLine.maxQty()) 9177 lines.push('Maximum Qty: ' + detailLine.maxQty()); 9178 9179 return lines.join('<br>'); 9180 }); 9181 9182 items.push(detailLine); 9183 }); 9184 9185 runHook('ItemsOnOrderArrayBeforeReturn', { detailLines: items }); 9186 9187 return items; 9188 }); 9189 9190 self.detailLines.subscribe(function(){ 9191 self.isMinimumOrderTotalMet(checkOrderTotal(self)); 9192 }); 9193 self.itemsOnOrder.subscribe(function(){ 9194 self.isMinimumOrderTotalMet(checkOrderTotal(self)); 9195 }); 9196 9197 self.itemShipToMap = ko.computed(function(){ 9198 var items = [];
9199 self.shipments().forEach(function(shipment) { 9200 oShipTo = shipment.shipTo(); 9201 9202 shipment.details().forEach(function(shipDetail) { 9203 var item = new Object(); 9204 item.shaKey = ko.observable(oShipTo.key()); 9205 item.key = ko.observable(shipDetail.orderDetailId()); 9206 item.orderDetailKey = shipDetail.orderDetailId(); 9207 item.instance = ko.observable(shipDetail.orderDetail.instance()); 9208 item.qty = ko.observable(shipDetail.qtyToShip()); 9209 item.qtyControlledFrom = ko.observable(shipDetail.orderDetail.qtyControlledFrom()); 9210 item.qtyIncrement = ko.observable(shipDetail.orderDetail.qtyIncrement()); 9211 item.getPrice = shipDetail.orderDetail.price, 9212 item.suPrice = shipDetail.orderDetail.price, 9213 item.minQty = ko.observable(shipDetail.orderDetail.minQty()); 9214 item.moveItemToNewShipTo = self.moveItemToNewShipTo; 9215 item.removeItemToShipToMap = self.removeItemToShipToMap; 9216 item.availableAddresses = shippingAddresses; 9217 item.shipTo = ko.observable({}); 9218 item.parentProductID = shipDetail.orderDetail.parentProductID(); 9219 item.availableAddresses().forEach(function(address,index){ 9220 if( address.key() == oShipTo.key()){ 9221 item.shipTo(address); 9222 } 9223 }); 9224 9225 if(shipDetail.orderDetail.instanceChildren.length > 0){ 9226 item.shipTo.subscribe(function(newValue) { 9227 items.forEach(function(map) { 9228 if(map.instance() == item.instance() && map.shipTo().key() != item.shipTo().key()) { 9229 map.shipTo(item.shipTo()); 9230 } 9231 }) 9232 }); 9233 } 9234 9235 items.push(item); 9236 }) 9237 }); 9238 9239 return items; 9240 }); 9241 9242 _.each(self.itemShipToMap(), function(item){ 9243 item.qty.subscribe(function () { 9244 self.isMinimumOrderTotalMet(checkOrderTotal(self)); 9245 }); 9246 }); 9247 9248 self.selectedOrderActionRefId = ko.observable( 9249 function(){ 9250 if(self.orderActions().length > 0 ){ 9251 return self.orderActions()[0].refID(); 9252 }else{ 9253 return ''; 9254 } 9255 }() 9256 ); 9257 9258 self.selectedOrderAction = ko.computed( 9259 function(){ 9260 var action = _.find(self.orderActions(), function(action){ 9261 if( action.refID() == self.selectedOrderActionRefId() ){ 9262 return action; 9263 } 9264 }); 9265 if(action && action.refID()){ 9266 return action; 9267 }else if(self.orderActions().length > 0 ){ 9268 return self.orderActions()[0]; 9269 }else{ 9270 return { 9271 showPaymentMethods: ko.observable(true), 9272 showRecurringOrderSettings: ko.observable(false) 9273 }; 9274 } 9275 } 9276 ); 9277 9278 self.showOrderActionButton = function(data, parent) { 9279 //override this function for custom logic to show custom buttons 9280 var sSelectedRefId = self.selectedOrderAction() && self.selectedOrderActionRefId(); 9281 var bShow = data.showButton() && (data.refID() == sSelectedRefId || parent.orderActions().length == 1); 9282 9283 return bShow; 9284 }; 9285 9286 self.getAddressFinderId = function(id, data, parent){ 9287 selector = id + '_' + parent.orderDetailKey + '_' + ($.isEmptyObject(data) ? 0 : data.key()); 9288 return selector; 9289 }; 9290 9291 self.selectedLifecycleStage = ko.computed(function(){ 9292 var stage = _.find(self.lifecycleStages(), function(stage){ 9293 if( stage.refID() == self.lifecycleStage() ){ 9294 return stage; 9295 } 9296 }); 9297 if(stage){ 9298 return stage; 9299 }else{ 9300 return { 9301 alwaysShowMessage: ko.observable(false), 9302 confirmationMessage: ko.observable('') 9303 }; 9304 } 9305 }); 9306 9307 if(self.lifecycleStage() == 'cancelled' || self.lifecycleStage() == 'punchout_punched_in'){ 9308 self.completed(true); 9309 } 9310 9311 self.showConfirmationMessage = ko.observable(function(){ 9312 return (self.completed() || self.lifecycleStage() == 'pending' || self.lifecycleStage() == 'cancelled' || self.selectedLifecycleStage().alwaysShowMessage()); 9313 }()) 9314 9315 self.allowAccountEdits = ko.observable(self.allowAccountEdits() && ofConfig.AllowAccountEdits); 9316 self.allowShaEdits = ko.observable(self.allowShaEdits() && ofConfig.AllowShippingEdits);
9317 self.allowWarehouseSelection = ko.observable(ofConfig.allowWarehouseSelection ); 9318 self.superUserRestrictMinPrice = ko.observable(ofConfig.superUserRestrictMinPrice); 9319 9320 self.postOrderToGoogleAnalytics = function() { 9321 9322 if (self.completed() && self.tracked() != '1' ) { 9323 9324 if(oConfig.t_ga4 && oConfig.t_ga4_analytics != '') { 9325 try { 9326 9327 var items = []; 9328 9329 for(var i = 0; i < self.detailLines().length; i++) { 9330 var line = self.detailLines()[i]; 9331 9332 var item = { 9333 item_id: line.sku(), 9334 item_name: line.name(), 9335 currency: "USD", 9336 price: line.price(), 9337 quantity: Number(line.qty()), 9338 index: i 9339 } 9340 items.push(item); 9341 } 9342 9343 if (items.length >= 1) { 9344 9345 window.dataLayer = window.dataLayer || []; 9346 function gtag(){dataLayer.push(arguments);} 9347 9348 gtag("event", "purchase", { 9349 transaction_id: self.orderNumber(), 9350 affiliation: ofConfig.t_tracking_company, 9351 value: self.orderTotal(), 9352 tax: self.taxTotal(), 9353 shipping: self.shippingTotal(), 9354 currency: "USD", 9355 coupon: self.couponCode(), 9356 items: items 9357 }); 9358 } 9359 } catch(err) { 9360 console.log(err); 9361 } 9362 }else if(ofConfig.t_gtm) { 9363 try { 9364 var productsOrdered = []; 9365 var transactionProducts = []; 9366 var transactionItems = []; 9367 9368 for(var i = 0; i < self.detailLines().length; i++) { 9369 var line = self.detailLines()[i]; 9370 9371 productsOrdered.push({ 9372 'orderNumber': self.orderNumber(), 9373 'name': self.customer.firstName() + ' ' + self.customer.lastName(), 9374 'sku': line.sku(), 9375 'category': line.searchfield1(), 9376 'brand': line.searchfield5(), 9377 'unitPrice': line.price(), 9378 'quantityOrdered': line.qty() 9379 }); 9380 9381 // id is used for Enhanced Ecommerce 9382 // sku is used for Google Analytics (non-EE) 9383 transactionProducts.push({ 9384 'id': line.sku(), 9385 'sku': line.sku(), 9386 'name': line.name(), 9387 'category': line.searchfield1(), 9388 'price': line.price(), 9389 'quantity': line.qty() 9390 }); 9391 9392 transactionItems.push({ 9393 'item_id': line.sku(), 9394 'item_name': line.name(), 9395 'price': line.price(), 9396 'quantity': line.qty() 9397 }); 9398 } 9399 9400 window.dataLayer.push({ 'pageType' : 'confirmation' }); 9401 window.dataLayer.push({ 'orderNumber' : self.orderNumber() }); 9402 window.dataLayer.push({ 'storeName' : ofConfig.t_tracking_company }); 9403 window.dataLayer.push({ 'productTotal' : self.productTotal() }); 9404 window.dataLayer.push({ 'shippingTotal' : self.shippingTotal() }); 9405 window.dataLayer.push({ 'taxTotal' : self.taxTotal() }); 9406 window.dataLayer.push({ 'orderTotal' : self.orderTotal() }); 9407 window.dataLayer.push({ 'customerName' : self.customer.firstName() + ' ' + self.customer.lastName() }); 9408 window.dataLayer.push({ 'customerFirstname' : self.customer.firstName() }); 9409 window.dataLayer.push({ 'customerLastName' : self.customer.lastName() }); 9410 window.dataLayer.push({ 'customerCity' : self.account.city() }); 9411 window.dataLayer.push({ 'customerState' : self.account.state() }); 9412 window.dataLayer.push({ 'customerCountry' : self.account.country() }); 9413 window.dataLayer.push({ 'customerEmail' : self.customer.email() }); 9414 window.dataLayer.push({ 'couponCode' : self.couponCode() }); 9415 window.dataLayer.push({ 'couponAmount' : self.couponDiscountTotals.totalDiscount() }); 9416 window.dataLayer.push({ 'paymentMethod' : self.paymentMethod.name() }); 9417 window.dataLayer.push({ 'sessionIP' : ofConfig.SessionIP }); 9418 9419 // For Google Analytics (non-EE) 9420 window.dataLayer.push({ 9421 'transactionId': self.orderNumber(), 9422 'transactionAffiliation': ofConfig.t_tracking_company, 9423 'transactionTotal': self.orderTotal(), 9424 'transactionTax': self.taxTotal(), 9425 'transactionShipping': self.shippingTotal(), 9426 'transactionProducts': transactionProducts, 9427 'transactionItems': transactionItems 9428 }); 9429 9430 // For Enhanced Ecommerce 9431 window.dataLayer.push({ 9432 'event': ofConfig.t_gtm_transaction_event_name, 9433 'ecommerce': { 9434 'purchase': { 9435 'actionField': { 9436 'id': self.orderNumber(), 9437 'affiliation': ofConfig.t_tracking_company, 9438 'revenue': self.orderTotal(), 9439 'tax': self.taxTotal(), 9440 'shipping': self.shippingTotal(), 9441 'coupon': self.couponCode() 9442 }, 9443 'products': transactionProducts, 9444 'items': transactionItems 9445 } 9446 } 9447 }); 9448 9449 window.dataLayer.push({ 'productsOrdered' : productsOrdered }); 9450 9451 } catch(err) {} 9452 9453 } 9454 9455 if(ofConfig.t_adwords && ofConfig.t_adwords_analytics && ofConfig.t_adwords_conversion){ 9456 9457 window.dataLayer = window.dataLayer || []; 9458 function gtag(){dataLayer.push(arguments);} 9459 9460 gtag('event', 'conversion', { 9461 'send_to': ofConfig.t_adwords_analytics + '/' + ofConfig.t_adwords_conversion, 9462 'value': self.orderTotal(), // Total 9463 'currency': 'USD', 9464 'transaction_id': self.orderNumber(), // Order ID 9465 'shipping' : self.shippingTotal(), // Shipping 9466 'tax' : self.taxTotal() // Tax 9467 }); 9468 9469 } 9470 9471 if(ofConfig.t_facebook && ofConfig.t_facebook_analytics){ 9472 9473 fbq('track', 'Purchase', { 9474 value: self.orderTotal(), 9475 currency: 'USD' 9476 }); 9477 9478 } 9479 9480 if(ofConfig.t_bing && ofConfig.t_bing_analytics){ 9481 9482 var items = []; 9483 var item_ids = []; 9484 9485 for(var i = 0; i < self.detailLines().length; i++) { 9486 var line = self.detailLines()[i]; 9487 var item_id = line.sku(); 9488 9489 var item = { 9490 id: line.sku(), 9491 item_name: line.name(), 9492 price: line.price(), 9493 quantity: Number(line.qty()) 9494 } 9495 items.push(item); 9496 item_ids.push(item_id); 9497 } 9498 9499 if (items.length >= 1) { 9500 window.uetq = window.uetq || []; 9501 window.uetq.push('event', 'purchase', { 9502 'transaction_id': self.orderNumber(), 9503 'ecomm_prodid': item_ids, 9504 'ecomm_pagetype': 'purchase', 9505 'revenue_value': self.orderTotal(), // Value of the conversion 9506 'currency': 'USD', 9507 'items': items 9508 }); 9509 } 9510 9511 } 9512 } 9513 } 9514 9515 self.updateOrderAccess = function(){ 9516 if( self.completed() || self.lifecycleStage() == 'cancelled' || self.lifecycleStage() == 'punchout_punched_in'){ 9517 self.allowAccountEdits( false ); 9518 self.allowContactEdits( false ); 9519 self.allowShaEdits( false ); 9520 self.allowWarehouseSelection( false ); 9521 self.allowProductAdds( false ); 9522 self.allowShipViaEdits( false ); 9523 self.allowPayMethodEdits( false ); 9524 self.allowCcnChanges( false ); 9525 self.allowPlaceOrder( false );
9526 self.allowQtyControls( false ); 9527 self.disablePlaceOrder( true ); 9528 }else if(self.superUserOrderFormMode()){ 9529 self.allowAccountEdits(self.allowAccountEdits() && ofConfig.superUserAllowAccountEdits); 9530 self.allowContactEdits(self.allowContactEdits() && ofConfig.superUserAllowContactEdits); 9531 self.allowShaEdits(self.allowShaEdits() && ofConfig.superUserAllowShaEdits); 9532 self.allowWarehouseSelection(ofConfig.allowWarehouseSelection || ofConfig.superUserAllowWarehouseSelection ); 9533 self.allowProductAdds(true); 9534 self.allowShipViaEdits(self.allowShipViaEdits() || ofConfig.superUserAllowShipViaEdits); 9535 self.allowPayMethodEdits(self.allowPayMethodEdits() || ofConfig.superUserAllowPayMethodEdits); 9536 self.allowCcnChanges(self.allowCcnChanges() || ofConfig.superUserAllowCcnChanges); 9537 self.allowPlaceOrder(self.allowPlaceOrder() || ofConfig.superUserAllowPlaceOrder); 9538 self.allowQtyControls( ofConfig.superUserAllowQtyControls ); 9539 self.disablePlaceOrder( false ); 9540 }else{ 9541 self.allowAccountEdits( self.allowAccountEdits() && ofConfig.AllowAccountEdits ); 9542 self.allowContactEdits( self.allowContactEdits() && ofConfig.allowContactEdits ); 9543 self.allowShaEdits( self.allowShaEdits() && ofConfig.AllowShippingEdits ); 9544 self.allowWarehouseSelection( ofConfig.allowWarehouseSelection ); 9545 self.allowProductAdds( self.allowProductAdds() ); 9546 self.allowQtyControls( false ); 9547 self.disablePlaceOrder( false ); 9548 } 9549 9550 var inFocusTemplate = true; 9551 if(self.completed() && inFocusTemplate) { 9552 $('#focusHeaderExit').removeAttr("data-toggle"); 9553 $('#focusHeaderExit').attr("href" , "https://www.flagandbanner.com"); 9554 } 9555 }; 9556 9557 self.updateOrderAccess(); 9558 9559 self.continueProcessingForm = function(data) { 9560 var bContinueProcessing = true; 9561 9562 //TODO: Get this validation working using the validation plugin. 9563 //This is a quick 'fix' to prevent the page from processing the order action 9564 //when the shipping account is required but not set. 9565 _.each(viewModel.shipments(), function(shipment, index){ 9566 if(ofConfig.CollectShipAccount && shipment.selectedShipVia.collectShippingAccount() && !shipment.selectedShipVia.shippingAccountId.isValid() ){ 9567 //form is not valid 9568 scrollToSection('#shipping-account-info' + (index+1)); 9569 //jQuery('#shipping-account-select' + shipmentCount).addClass('control-group error'); 9570 bContinueProcessing = false; 9571 return false; 9572 } 9573 }); 9574 9575 if(viewModel.selectedOrderAction != undefined && viewModel.selectedOrderAction().showPaymentMethods()) { 9576 //TODO: Do CC validation in a less janky way 9577 //This is a quick 'fix' to prevent the page from processing the order action 9578 //when the CC billing address info is invalid 9579 //Currently doesn't provide any messaging 9580 if(viewModel.allowPayMethodEdits() && viewModel.paymentMethod.paymentType() === 'cc' && (data.placeOrderActionType() == 'place' || data.placeOrderActionType() == 'validate-only')) { 9581 9582 if( ($('#ccpm_cvv2_code').is(':visible') && !$('#ccpm_cvv2_code').val()) 9583 || !$('#ccpm_address_input').val() 9584 || !$('#ccpm_city_input').val() 9585 || !$('#ccpm_country_input').val() 9586 || !($('#ccpm_state_dropdown').prop('disabled') ? $('#ccpm_state_text').val() : $('#ccpm_state_dropdown').val()) 9587 || !$('#ccpm_zip_input').val() 9588 ) {
9589 // CC billing address form is not valid 9590 $("#ccpm_card_billing_address_section").addClass("in").css({ "height" : "auto" }); 9591 $("#ccpm_card_billing_address_section :input:visible:not('button')") 9592 .filter(function() { return $(this).val() == ""; }) 9593 .trigger("change"); 9594 $("#ccpm_cvv2_code").trigger("change"); 9595 scrollToSection('#payment_methods'); 9596 bContinueProcessing = false; 9597 return false; 9598 } 9599 } 9600 //Pretty much just following the same pattern as cc validation. 9601 //Need to stop the page from processing if the poNum is required and not entered. 9602 if(viewModel.paymentMethod.collectPO() && viewModel.paymentMethod.poRequired() && !$('#ponumber').val()) { 9603 jQuery('#controlgroup_invoice_ponumber').addClass('control-group error'); 9604 scrollToSection('#payment_methods'); 9605 bContinueProcessing = false; 9606 return false; 9607 } 9608 } 9609 9610 //hook for adding custom validation checks 9611 var config = { 9612 continueProcessing: bContinueProcessing 9613 }; 9614 runHook('cartTemplatesContinueProcessing', config); 9615 return config.continueProcessing; 9616 }; 9617 9618 self.processOrderAction = function(data){ 9619 var bContinueProcessing = self.continueProcessingForm(data); 9620 9621 if(bContinueProcessing){ 9622 9623 if( data.showComments() && viewModel.customerComment() != '' ){ 9624 self.saveCustomerComment(); 9625 } 9626 9627 if( !data.showOrderCcEmail() && viewModel.orderCcEmail() != ''){ 9628 //if the user entered an email then chose an OA that isn't showing the email input, blank it out. 9629 viewModel.orderCcEmail(''); 9630 } 9631 9632 if(data.showRecurringOrderSettings()){ 9633 self.saveRecurringOrderSettings(); 9634 } 9635 9636 var postData = {}; 9637 var bPost = true; 9638 postData.orderActionKey = data.orderActionKey(); 9639 9640 if(viewModel.paymentMethod.paymentType() === 'cc' && (viewModel.selectedOrderAction != undefined && viewModel.selectedOrderAction().showPaymentMethods())) { 9641 9642 var defaultCcnChecked = $('#ccpm_default_ccn_id_selection').is(':checked'); 9643 9644 if(defaultCcnChecked) { 9645 postData.setDefaultCcn = 1 9646 } 9647 9648 postData.ccn_key = $('#ccpm_ccn_id').val(); 9649 postData.cvv = $('#ccpm_cvv2_code').val(); 9650 postData.address = $('#ccpm_address_input').val(); 9651 postData.city = $('#ccpm_city_input').val(); 9652 postData.country = $('#ccpm_country_input').val(); 9653 postData.state = $('#ccpm_state_dropdown').prop('disabled') ? $('#ccpm_state_text').val() : $('#ccpm_state_dropdown').val(); 9654 postData.zip = $('#ccpm_zip_input').val(); 9655 postData.tsm_id = viewModel.paymentMethod.merchantId(); 9656 9657 }else if(viewModel.paymentMethod.paymentType() === 'paypal' && data.placeOrderActionType() == 'place'){ 9658 bPost = false; 9659 postPayPal(data.orderActionKey()); 9660 } 9661 9662 var postOptions = { 9663 data: postData, 9664 error: function() { 9665 alert('Error Processing Order Action'); 9666 } 9667 } 9668 9669 var scrollToId = 'checkout'; 9670 9671 runHook('cartTemplateOverridePostOptions', { postOptions: postOptions, data: data, self: self }); 9672 9673 if (bPost){ 9674 var postOrderAction = function() { 9675 if ($.active > 0) { 9676 viewModel.processing(true); 9677 $( document ).one("ajaxStop", function(){ 9678 postInfo(postOptions, 'processOrderAction', scrollToId); 9679 }); 9680 } 9681 else { 9682 postInfo(postOptions, 'processOrderAction', scrollToId); 9683 } 9684 } 9685 9686 if(data.placeOrderActionType() == 'punch-in'){ 9687 self.postPunchin(postOrderAction, postOptions); 9688 } else { 9689 postOrderAction(); 9690 } 9691 } 9692 } 9693 }; 9694 9695 self.postPunchin = function(fncPostOrderAction, orderActionPostOptions){ 9696 toggleLoadingWidget(true);
9697 var model = viewModel; 9698 model.activeAjaxRequestCount(model.activeAjaxRequestCount() + 1); 9699 model.processing(true); 9700 9701 var bPostPunchIn = false; 9702 var punchinXmlUrl = orderInfoPostUrl + '?o_key=' + model.orderKey() + '&ajax=true&pageaction=getPunchinXml'; 9703 var getPunchinXmlPostOptions = { 9704 url: punchinXmlUrl, 9705 data: { orderKey: viewModel.orderKey() }, 9706 success: function(data) { 9707 if (data.trim().startsWith('<?xml')) { 9708 $('input#cxml-urlencoded').val(data); 9709 orderActionPostOptions.success = function() { 9710 bPostPunchIn = true; 9711 } 9712 orderActionPostOptions.complete = function() { 9713 if(bPostPunchIn) { 9714 $('form#punch-in').submit(); 9715 } 9716 } 9717 fncPostOrderAction(); 9718 } else { 9719 alert('Error Processing Order Action: Unable to retrieve valid punchin data.'); 9720 } 9721 }, 9722 error: function() { 9723 alert('Error Processing Order Action: Unable to retrieve punchin data.'); 9724 }, 9725 complete: function() { 9726 model.activeAjaxRequestCount(model.activeAjaxRequestCount() - 1); 9727 if(model.activeAjaxRequestCount() < 1) { 9728 model.processing(false); 9729 } 9730 toggleLoadingWidget(false); 9731 } 9732 }; 9733 9734 if ($.active > 0) { 9735 viewModel.processing(true); 9736 $( document ).one("ajaxStop", function(){ 9737 $.ajax(getPunchinXmlPostOptions); 9738 }); 9739 } 9740 else { 9741 $.ajax(getPunchinXmlPostOptions); 9742 } 9743 }; 9744 9745 self.saveRecurringOrderSettings = function(){ 9746 var postData = []; 9747 var order = []; 9748 9749 var orderKey = viewModel.orderKey(); 9750 9751 var roRunDate = viewModel.roRunDate(); 9752 var roRecCase = viewModel.roRecCase(); 9753 var roRecQty = viewModel.roRecQty(); 9754 //This has to be set before processOrderAction or the OO will "unset" the values above when the record_type isn't set to recurring. 9755 var recordType = "recurring"; 9756 9757 9758 order.push({ 9759 "o_key" : orderKey, 9760 "ro_rundate": roRunDate, 9761 "ro_rec_case": roRecCase, 9762 "ro_rec_qty": roRecQty, 9763 "record_type": recordType 9764 }); 9765 9766 postData = 9767 { 9768 "Tables": [ 9769 { 9770 "TableName" : "orders", 9771 "TableKeyField" : "o_key", 9772 "UserKeyField" : "o_key", 9773 "UserKeyIsPrimaryKey" : "True", 9774 "Data" : order 9775 } 9776 ] 9777 } 9778 9779 jQuery.ajax({ 9780 url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=postLogicJSON&randomnum=' + new Date().getTime() 9781 , data: "postLogicJSON=" + encodeURIComponent(JSON.stringify(postData)) 9782 , cache: false 9783 , type: 'POST' 9784 , dataType: 'json' 9785 , success: function(data,status,request){ 9786 viewModel.roRunDate(roRunDate); 9787 viewModel.roRecCase(roRecCase); 9788 viewModel.roRecQty(roRecQty); 9789 } 9790 , error: function(data) { 9791 alert('Error posting Recurring Order Settings'); 9792 } 9793 , complete: function(data) { 9794 } 9795 }); 9796 }; 9797 9798 self.saveCustomerComment = function(){ 9799 9800 var postData = []; 9801 var noteBook = []; 9802 var note = []; 9803 var order = []; 9804 9805 var notebookTableName = ofConfig.useNewNotebooks ? 'Notebooks' : 'note_books'; 9806 var notebookKeyField = ofConfig.useNewNotebooks ? 'Id' : 'nb_key'; 9807 var notebookRefField = ofConfig.useNewNotebooks ? 'ReferenceId' : 'ref_id'; 9808 var ref_id = self.noteBook().refId || generateRefId();
9809 var n_key = utils.createGuid(); 9810 9811 if(ofConfig.useNewNotebooks) { 9812 var notebookId = parseInt(self.noteBook().id || 0) || ref_id; 9813 9814 noteBook.push({ 9815 "Id": notebookId, 9816 "ReferenceId": notebookId 9817 }); 9818 9819 order.push({ 9820 "o_key" : self.orderKey(), 9821 "NotebookId": notebookId 9822 }); 9823 9824 note.push({ 9825 "n_key" : n_key, 9826 "ref_id" : generateRefId(), 9827 "NotebookId" : notebookId, 9828 "a_id" : ofConfig.superUserAccountKey || ofConfig.AccountKey, 9829 "c_id" : ofConfig.superUserCustomerKey || ofConfig.CustomerKey, 9830 "create_date" : new Date().toDateString(), 9831 "external_notes" : self.customerComment() 9832 }); 9833 9834 } else { 9835 var nb_key = self.noteBook().nbKey || utils.createGuid(); 9836 9837 order.push({ 9838 "o_key" : self.orderKey(), 9839 "nb_id" : nb_key 9840 }); 9841 9842 noteBook.push({ 9843 "nb_key" : nb_key, 9844 "ref_id" : ref_id, 9845 "create_date" : new Date().toDateString(), 9846 "book_type" : 'order', 9847 "resource_c_id" : ofConfig.superUserCustomerKey || ofConfig.CustomerKey 9848 }); 9849 9850 note.push({ 9851 "n_key" : n_key, 9852 "ref_id" : generateRefId(), 9853 "nb_id" : nb_key, 9854 "a_id" : ofConfig.superUserAccountKey || ofConfig.AccountKey, 9855 "c_id" : ofConfig.superUserCustomerKey || ofConfig.CustomerKey, 9856 "create_date" : new Date().toDateString(), 9857 "external_notes" : self.customerComment() 9858 }); 9859 } 9860 9861 postData = 9862 { 9863 "Tables": [ 9864 { 9865 "TableName" : notebookTableName, 9866 "TableKeyField" : notebookKeyField, 9867 "UserKeyField" : notebookRefField, 9868 "UserKeyIsPrimaryKey" : "False", 9869 "Data" : noteBook 9870 }, 9871 { 9872 "TableName" : "orders", 9873 "TableKeyField" : "o_key", 9874 "UserKeyField" : "o_key", 9875 "UserKeyIsPrimaryKey" : "True", 9876 "Data" : order 9877 }, 9878 { 9879 "TableName" : "notes", 9880 "TableKeyField" : "n_key", 9881 "UserKeyField" : "ref_id", 9882 "UserKeyIsPrimaryKey" : "False", 9883 "Data" : note 9884 } 9885 ] 9886 } 9887 9888 jQuery.ajax({ 9889 url: 'payment.asp' + '?o_key=' + viewModel.orderKey() + '&ajax=true&pageaction=postLogicJSON&randomnum=' + new Date().getTime() 9890 , data: "postLogicJSON=" + encodeURIComponent(JSON.stringify(postData)) 9891 , cache: false 9892 , type: 'POST' 9893 , dataType: 'json' 9894 , success: function(data,status,request){ 9895 viewModel.updateNoteBook(note[0]); 9896 viewModel.customerComment(''); 9897 return data.PostedKeys[notebookTableName][0]; 9898 } 9899 , error: function(data) { 9900 alert('Error posting Comment'); 9901 } 9902 , complete: function(data) { 9903 } 9904 }); 9905 }; 9906 9907 self.updateNoteBook = function(note) { 9908 var item = {}; 9909 9910 item.internalNotes = note.internal_notes; 9911 item.externalNotes = note.external_notes; 9912 item.postedByName = ofConfig.superUserName || ofConfig.customerName; 9913 item.postedByUsername = ofConfig.superUserUsername || ofConfig.customerUsername; 9914 item.createDate = note.create_date; 9915 9916 viewModel.noteBook().notes.unshift(item); 9917 }; 9918 9919 self.genericModalComplete = function(data){ 9920 var postOptions = { 9921 success: function(data) { 9922 }, 9923 error: function() { 9924 alert('error reloading shipping accounts'); 9925 } 9926 } 9927 9928 postInfo(postOptions, 'getOrderJSON'); 9929 return true; 9930 }; 9931 9932 self.removeProduct = function(data){ 9933 if(ofConfig.bUseRemoveMsg){ 9934 var bRemove = confirm(ofConfig.sRemoveProductMessage); 9935 } 9936 else{ 9937 bRemove = true; 9938 } 9939 9940 if (bRemove) { 9941 viewModel.processing(true); 9942 var itemToDelete = data; 9943 var removeType = itemToDelete.removeType(); 9944 var orderDetailKey = itemToDelete.orderDetailKey(); 9945 var instance = itemToDelete.instance(); 9946 var sRemoveUrl = 'i_i_add_to_cart.asp?type=remove&unq=' + orderDetailKey + '&o_id=' + data.orderID() + '&modal=1'; 9947 9948 jQuery.ajax({ 9949 url: sRemoveUrl 9950 , cache: false 9951 , type: 'GET' 9952 , success: function(data,status,request){ 9953 //Calling getOrderJSON here to handle removing reward products 9954 // From the UI when the target is removed. 9955 viewModel.genericModalComplete(); 9956 } 9957 , error: function(data) { 9958 alert('Error removing item.'); 9959 viewModel.processing(false); 9960 } 9961 , complete: function(data) { 9962 viewModel.processing(false); 9963 } 9964 }); 9965 } 9966 }; 9967 9968 self.resetProductEdits = function(editingDetailLine) { 9969 viewModel.detailLines() 9970 .forEach(function(detailLine) { 9971 detailLine.editing(false); 9972 }); 9973 viewModel.shipments() 9974 .forEach(function(shipment) { 9975 shipment.details() 9976 .forEach(function(detail) { 9977 detail.orderDetail.editing(false); 9978 }); 9979 }); 9980 viewModel.mainProduct(undefined); 9981 utils.removeActiveQuote(); 9982 9983 if(editingDetailLine) { 9984 editingDetailLine.editing(true); 9985 } 9986 } 9987 9988 self.editProduct = function(data) { 9989 self.resetProductEdits(); 9990 var detailLine = data; 9991 if(data.orderDetail) { 9992 detailLine = data.orderDetail; 9993 } 9994 var detailKey = detailLine.orderDetailKey(); 9995 var productKey = detailLine.parentProductID().trim() || detailLine.productID();
9996 9997 var productInfo = { 9998 productKey: detailLine.productID(), 9999 productSku: detailLine.sku(), 10000 parentChildType: detailLine.commodity.parentChildType() || '', 10001 parentProductId: detailLine.parentProductID().trim() 10002 } 10003 10004 self.loadProductForEdit(productInfo, detailKey, detailLine) 10005 } 10006 10007 self.cancelEditProduct = function(data) { 10008 self.resetProductEdits(); 10009 } 10010 10011 self.loadProductForEdit = function(productInfo, detailLineId, detailLine) { 10012 viewModel.processing(true); 10013 self.resetProductEdits(detailLine); 10014 10015 var postOptions = { 10016 success: function(data) { 10017 var response = JSON.parse(data); 10018 var product = response.product; 10019 switch(product.childDisplayType) { 10020 case 'input-qty': 10021 case 'exploded-view': 10022 case 'matrix-all': 10023 case 'add-row': 10024 product.childDisplayType = 'droplist' 10025 break; 10026 default: 10027 }; 10028 10029 if(!!response.childSkuMatch) { 10030 oConfig.childSkuMatch = response.childSkuMatch; 10031 } 10032 10033 utils.setActiveQuote(viewModel.orderKey()); 10034 viewModel.mainProduct(ko.mapping.fromJS(product, productMapping)); 10035 viewModel.addToSavedCart(); 10036 }, 10037 url: orderInfoPostUrl + '?o_key=' + self.orderKey() + '&p_key=' + (productInfo.parentProductId || productInfo.productKey) + '&od_key=' + detailLineId + '&sku=' + productInfo.productSku + '&ajax=true&pageaction=getProductData&modal=1', 10038 type: 'GET', 10039 error: function() { 10040 alert('Error loading product data!'); 10041 } 10042 } 10043 10044 $.ajax({
10045 url : postOptions.url, 10046 success : postOptions.success, 10047 type : postOptions.type, 10048 error : postOptions.error, 10049 complete : function() { viewModel.processing(false); } 10050 }); 10051 } 10052 10053 self.productFinderSearchTerm = ko.observable(''); 10054 10055 self.productFinderUrl = ko.computed(function() { 10056 var searchTerm = self.productFinderSearchTerm(); 10057 var search2 = ofConfig.productFinderSearchstring.replace(/__query__/g, searchTerm); 10058 return 'bulk_atc.asp?find_product=1&s=' + searchTerm + '&search2=' + search2; 10059 }); 10060 10061 self.showRemoveLink = function(data){ 10062 if(!ofConfig.allowProductRemoves){ 10063 return false; 10064 } 10065 10066 var instanceKeys = viewModel.detailLines().reduce(function(instanceKeys, line) { 10067 if(instanceKeys.indexOf(line.instance()) == -1) { 10068 instanceKeys.push(line.instance()); 10069 } 10070 return instanceKeys; 10071 }, []); 10072 10073 if(!ofConfig.allowRemoveLastItem && instanceKeys.length < 2) { 10074 return false; 10075 } 10076 10077 if(data.removeType() == 'hide'){ 10078 return false; 10079 } 10080 return true; 10081 }; 10082 10083 self.breadcrumbMarkup = ko.computed(function(){ 10084 var thisIsCartPage = ofConfig.cartPage === getOriginalPageName(); 10085 var isComplete = self.completed() || (self.lifecycleStage() == 'punchout_punched_in') 10086 10087 var paymentCrumbLabel = "Payment"; 10088 if(!ofConfig.showPaymentMethodsSection) { 10089 paymentCrumbLabel = thisIsCartPage ? "Cart" : "Finalize" 10090 } 10091 var completeCrumbLabel = ofConfig.isPunchoutSession ? "Sent to Procurement" : "Order Placed"; 10092 10093 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>"; 10094 if(thisIsCartPage) { 10095 cartCrumb = ""; 10096 } 10097 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>"; 10098 var paymentCrumb = "<li class=\"" + (isComplete ? "" : "active") + "\"><i class=\"icon-lock\"></i> " + paymentCrumbLabel + " <span class=\"divider\"><i class=\"icon-chevron-right\"></i></span></li>"; 10099 var completeCrumb = "<li class=\"" + (isComplete ? "active" : "") + "\"><i class=\"icon-ok\"></i> " + completeCrumbLabel + "</li>"; 10100 10101 var dynamicBreadcrumbMarkup = "<ul class=\"breadcrumb breadcrumb-cart\">" + cartCrumb + accountCrumb + paymentCrumb + completeCrumb + "</ul>"; 10102 10103 if(self.cartType != 'recurring' && (thisIsCartPage || ofConfig.isPunchoutSession || !ofConfig.showPaymentMethodsSection)) { 10104 return dynamicBreadcrumbMarkup; 10105 } 10106 10107 if(self.recordType() == 'cart') { 10108 return ofConfig.sPaymentHeaderLabel; 10109 } else if (self.recordType() == 'recurring') { 10110 return '<ul class="breadcrumb breadcrumb-cart"><li class="active">Order</li><li><i class="icon-ok"></i> Order Placed</li></ul>'; 10111 } else { 10112 return '<ul class="breadcrumb breadcrumb-cart"><li class="active">Order</li><li><i class="icon-ok"></i> Order Placed</li></ul>'; 10113 } 10114 }); 10115 10116 self.expirationDate = ko.observable(function() { 10117 return new moment(self.quoteExpirationDate()).format("MM/DD/YYYY"); 10118 }()); 10119 10120 self.expirationDate.subscribe(function(newExpirationDate) { 10121 self.buildOrderHeaderFields(["QuoteExpirationDate"]); 10122 }); 10123 10124 // Used for Google Analytics and Tag Manager, etc 10125 /* 10126 Runs when order is completed but payment page doesn't re-fresh 10127 - Example user pays with a credit card or bill me payment option 10128 */ 10129 self.orderPlaced.subscribe(function() { 10130 self.postOrderToGoogleAnalytics(); 10131 postOrderHeaderField('tracked', '1'); 10132 self.tracked('1'); 10133 }); 10134 /* 10135 Runs when order is completed and the payment page re-freshes 10136 - Happens when user checks out with paypal and is re-directed back to payment page 10137 - with a completed order 10138 */ 10139 if (self.completed() && self.tracked() != '1' ) { 10140 self.postOrderToGoogleAnalytics(); 10141 postOrderHeaderField('tracked', '1'); 10142 self.tracked('1'); 10143 } 10144 10145 addTimer("orderModelBottom"); 10146 runHook('orderModelBottom', { self: self, order: self }); 10147 addTimer("end order mapping"); 10148 } // end of var Order = blah blah blah 10149 10150 function processShippingAddresses(data){ 10151 var addressArray = data; 10152 var newshippingAddresses; 10153 if(Array.isArray(addressArray)) { 10154 newshippingAddresses = addressArray.map(function(item, index, arr) { 10155 address = new addressInfo(); 10156 address.name(item.sha_nm); 10157 address.company(item.s_company || ''); 10158 address.attention(item.attention || ''); 10159 address.address1(item.s_add1 || ''); 10160 address.address2(item.s_add2 || ''); 10161 address.address3(item.s_add3 || ''); 10162 address.address4(item.s_add4 || ''); 10163 address.address5(item.s_add5 || ''); 10164 address.country(item.s_country || 'USA'); 10165 address.city(item.s_city || ''); 10166 address.state(item.s_state || undefined); 10167 address.zipCode(item.s_zip || ''); 10168 address.phone(item.s_phone || ''); 10169 address.email(item.em || ''); 10170 address.global(item.globaladdress || '0'); 10171 address.opt1(item.s_opt1 || ''); 10172 address.opt2(item.s_opt2 || ''); 10173 address.opt3(item.s_opt3 || ''); 10174 address.opt4(item.s_opt4 || ''); 10175 address.opt5(item.s_opt5 || ''); 10176 address.key(item.sha_key); 10177 address.editing(false); 10178 return address; 10179 }); 10180 } 10181 10182 /* 10183 Changing to an observable array (was an obeservable object that contained an array) 10184 */ 10185 var observableAryOfSHA = ko.observableArray([]);
10186 newshippingAddresses.forEach(function(obj){ 10187 observableAryOfSHA.push(ko.mapping.fromJS(obj, shippingAddressMappingOptions)); 10188 }); 10189 10190 return observableAryOfSHA; //ko.mapping.fromJS(newshippingAddresses, shippingAddressMappingOptions); 10191 } 10192 10193 var orderMapping = { 10194 create: function(options) { 10195 var newOrder = new Order(options.data); 10196 10197 return newOrder; // new Order(options.data); 10198 } 10199 } 10200 10201 //Build Json for order header field and optional additional tables. 10202 //Pass the Json to the Post Logic Ajax function 10203 var postOrderHeaderField = function(sOrderField, viewModelProperty, extraTablesJson, callbacks) { 10204 console.log(sOrderField); 10205 var postData = {}; 10206 var order = []; 10207 10208 order = [{ 10209 "o_key" : ofConfig.OKey 10210 }]; 10211 10212 order[0][sOrderField] = viewModelProperty; 10213 10214 postData = 10215 { 10216 "Tables": [ 10217 { 10218 "TableName" : "orders", 10219 "TableKeyField" : "o_key", 10220 "UserKeyField" : "o_key", 10221 "UserKeyIsPrimaryKey" : "True", 10222 "Data" : order 10223 } 10224 ] 10225 }; 10226 10227 //Optional additional tables on the order 10228 if (!!extraTablesJson) { 10229 postData["Tables"].push(extraTablesJson); 10230 } 10231 10232 self.postLogicJsonAjax(postData, false, callbacks); 10233 }; 10234 10235 var postOrderDetailFields = function(sOrderDetailKey, sDetailFields, viewModelProperties, callbacks) { 10236 10237 var postData = {}; 10238 var orderLine = []; 10239 10240 orderLines = [{ 10241 "od_key" : sOrderDetailKey 10242 }]; 10243 10244 for(var i = 0; i < sDetailFields.length; i++){ 10245 orderLines[0][sDetailFields[i]] = viewModelProperties[i]; 10246 } 10247 10248 postData = 10249 { 10250 "Tables": [ 10251 { 10252 "TableName" : "order_detail", 10253 "TableKeyField" : "od_key", 10254 "UserKeyField" : "od_key", 10255 "UserKeyIsPrimaryKey" : "True", 10256 "Data" : orderLines 10257 } 10258 ] 10259 }; 10260 self.postLogicJsonAjax(postData, false, callbacks); 10261 }; 10262 10263 //Posts Json directly to table(s) using Post Logic 10264 //Should be used for fields that do not affect other properties in the ViewModel (i.e. text areas) 10265 //No actions on success. 10266 var postLogicJsonAjax = function(postData, getOrderJSON, callbacks) { 10267 toggleLoadingWidget(true); 10268 callbacks = callbacks || {}; 10269 10270 jQuery.ajax({ 10271 url: 'payment.asp' + '?o_key=' + ofConfig.OKey + '&getorderJSON=' + getOrderJSON + '&ajax=true&pageaction=postLogicJSON&randomnum=' + new Date().getTime(), 10272 data: "postLogicJSON=" + encodeURIComponent(JSON.stringify(postData)), 10273 cache: false, 10274 type: 'POST', 10275 dataType: 'json', 10276 success: callbacks.success, 10277 error: function(jqXHR, textStatus, errorThrown) { 10278 console.log(jqXHR.status); 10279 if (typeof callbacks.error == 'function') { 10280 callbacks.error(jqXHR, textStatus, errorThrown); 10281 } else { 10282 if(jqXHR.status == 401){ 10283 location.href = 'showcart.asp?section=ValidateOrderOwnership&err=not-logged-in' 10284 }else{ 10285 alert('Error posting to ' + (postData["Tables"][0]["TableName"] || "postLogicJsonAjax") + '.'); 10286 } 10287 } 10288 }, 10289 complete: function(){ 10290 toggleLoadingWidget(false); 10291 } 10292 }); 10293 }; 10294 10295 10296 var apiRoutedPageActions = [ 10297 /* 10298 // can't be converted yet 10299 'placeOrder', 10300 'processOrderAction', 10301 */ 10302 'setSha', 10303 'setCCN', 10304 'setPmId', 10305 'setCoupon', 10306 'setGiftCertCode', 10307 'setOrderHeaderFields', 10308 'setRequestedShipDate', 10309 'setShippingPrice', 10310 'getOrderJSON', 10311 'resetShippingPrice', 10312 'setShipmentShipVia' 10313 ]; 10314 10315 apiRoutedPageActions = apiRoutedPageActions.concat([ 10316 'updateShipToAddress', 10317 'setOrderDetailFields', 10318 'assignOwnership' 10319 ]); 10320 10321 10322 var postInfo = function(ajaxOptions, pageAction, scrollToId, model) { 10323 toggleLoadingWidget(true); 10324 if(!model) {
10325 model = viewModel; 10326 } 10327 10328 model.activeAjaxRequestCount(model.activeAjaxRequestCount() + 1); 10329 10330 model.processing(true); 10331 10332 model.errorMessages.removeAll(); 10333 10334 var existingSuccess = ajaxOptions.success; 10335 var existingError = ajaxOptions.error; 10336 var existingComplete = ajaxOptions.complete; 10337 10338 var querystring; 10339 var comUrl; 10340 if(ajaxOptions.url){ 10341 querystring = ajaxOptions.url.substring(ajaxOptions.url.indexOf('?')) 10342 comUrl = orderInfoPostUrl + querystring; 10343 }else{ 10344 querystring = '?o_key=' + model.orderKey(); 10345 comUrl = orderInfoPostUrl + '?o_key=' + model.orderKey() + '&ajax=true&pageaction=' + pageAction; 10346 } 10347 var apiUrl = orderInfoPostApiUrl + pageAction + querystring; 10348 10349 if (apiRoutedPageActions.includes(pageAction)) { 10350 ajaxOptions.url = apiUrl; 10351 } else if (!ajaxOptions.url) { 10352 ajaxOptions.url = comUrl; 10353 } 10354 10355 if(!ajaxOptions.type) { 10356 ajaxOptions.type = 'POST'; 10357 } 10358 10359 ajaxOptions.success = function(data) { 10360 try{ 10361 var response = JSON.parse(data); 10362 } catch (error){ 10363 /* 10364 * if we get invalid json here, it's most likely a redirect due to 10365 * an expired session or other issue causing an html page to be 10366 * returned instead of processing the ajax request 10367 */ 10368 location.href = 'payment.asp?o_key=' + model.orderKey(); 10369 } 10370 if(Array.isArray(response) && Object.keys(response[0].Errors).length > 0) { 10371 for (var msg in response[0].Errors) { 10372 if(response[0].Errors.hasOwnProperty(msg)) { 10373 scrollToId = 'errorList'; 10374 10375 model.errorMessages.push( 10376 { 10377 "errorType": msg, 10378 "message": response[0].Errors[msg] 10379 } 10380 ); 10381 } 10382 } 10383 } 10384 10385 ko.mapping.fromJS(response[1], orderMapping, model); 10386 10387 model.updateOrderAccess(); 10388 if(model.isOverLineLimit()){ 10389 model.shippingComplete(true); 10390 } 10391 if(typeof existingSuccess === 'function') { 10392 existingSuccess(data); 10393 } 10394 10395 _.each(model.itemShipToMap(), function(item){ 10396 item.qty.subscribe(function () { 10397 model.isMinimumOrderTotalMet(checkOrderTotal(model)); 10398 }); 10399 }); 10400 10401 if(scrollToId) { 10402 model.showConfirmationMessage(true); 10403 scrollToSection('#' + scrollToId); 10404 } 10405 10406 model.detailLines().forEach(function(detailLine) { 10407 // We can't debounce/trottle an observable 10408 // so we add a computed to track qty changes. 10409 // We use this in a subscription to call 10410 // update cart to update qty change in bulk atc 10411 // to avoid loading the qty change without posting 10412 // and updating the entire order model (for perf) 10413 detailLine.qtyTracker = ko.computed(function() { 10414 return detailLine.qty(); 10415 }).extend({throttle: 500}); 10416 detailLine.qtyTracker.subscribe(function (newQty) { 10417 model.postQtyUpdate(); 10418 }, detailLine); 10419 detailLine.workerPriceTracker = ko.computed(function() { 10420 return detailLine.price(); 10421 }).extend({throttle: 500}); 10422 detailLine.workerPriceTracker.subscribe(function (newQty) { 10423 model.setWorkerPriceOverride(detailLine); 10424 }, detailLine); 10425 detailLine.workerQtyLimitsTracker = ko.computed(function() { 10426 return { 10427 removeType: detailLine.removeType(), 10428 minQty: detailLine.minQty(), 10429 maxQty: detailLine.maxQty(), 10430 qtyIncrement: detailLine.qtyIncrement() 10431 }; 10432 }).extend({throttle: 500}); 10433 detailLine.workerQtyLimitsTracker.subscribe(function (newValue) { 10434 model.setWorkerQtyLimits(detailLine); 10435 }); 10436 }); 10437 }; 10438 10439 ajaxOptions.error = function(jqXHR, textStatus, errorThrown) { 10440 if(jqXHR.status == 401){ 10441 location.href = 'showcart.asp?section=ValidateOrderOwnership&err=not-logged-in' 10442 } 10443 if (ajaxOptions.url != comUrl) { 10444 // if API call fails, retry with COM AJAX 10445 ajaxOptions.url = comUrl; 10446 $.ajax({
10447 url: orderInfoPostUrl + '?o_key=' + model.orderKey() + '&ajax=true&pageaction=logError&url=' + encodeURIComponent(apiUrl) + '&method=' + pageAction + '&message=API error (' + jqXHR.status + ')', 10448 success: function() { 10449 }, 10450 error: function(jqXHR, textStatus, errorThrown) { 10451 if(jqXHR.status == 401){ 10452 location.href = 'showcart.asp?section=ValidateOrderOwnership&err=not-logged-in' 10453 } 10454 } 10455 }); 10456 $.ajax(ajaxOptions); 10457 return; 10458 } 10459 if(typeof existingError === 'function') { 10460 existingError(); //data is not defined 10461 } 10462 }; 10463 10464 ajaxOptions.complete = function() { 10465 runHook('postInfoAjaxCompleteFunction', { model: model, ajaxOptions: ajaxOptions, pageAction: pageAction, scrollToId: scrollToId }); 10466 if(typeof existingComplete === 'function') { 10467 existingComplete(); 10468 } 10469 model.activeAjaxRequestCount(model.activeAjaxRequestCount() - 1); 10470 if(model.activeAjaxRequestCount() < 1) { 10471 model.processing(false); 10472 10473 /* EJ - 2016-11-14 10474 Ugly hack to get around ko.mapping not initializing the Account 10475 property correctly when re-mapping on existing object. I think 10476 it may have to do with manually converting the Account property 10477 to a validatedObservable the first time through. 10478 */ 10479 fixUpNulls(model.Account()); 10480 } 10481 toggleLoadingWidget(false); 10482 }; 10483 10484 $.ajax(ajaxOptions); 10485 } 10486 10487 var fixUpNulls = function(account) { 10488 for(var prop in account) { 10489 if(account.hasOwnProperty(prop) && typeof account[prop] === 'function') { 10490 if(account[prop]() === null || account[prop]() === 'null') { 10491 account[prop](''); 10492 } 10493 } 10494 } 10495 } 10496 10497 var postPayPal = function(orderActionKey) { 10498 viewModel.processing(true); 10499 10500 jQuery.ajax({ 10501 url: 'payment.asp' + '?paypal_order_submit=1&oa_id=' + orderActionKey + '&o_key=' + viewModel.orderKey() + '&randomnum=' + new Date().getTime() 10502 , data: "o_key=" + viewModel.orderKey() 10503 , cache: false 10504 , type: 'POST' 10505 , dataType: 'json' 10506 , success: function(data){ 10507 if(!data.status && data.message != ''){ 10508 viewModel.errorMessages.push( 10509 { 10510 "errorType": "payment_methods", 10511 "message": data.message 10512 } 10513 ); 10514 viewModel.processing(false); 10515 } 10516 else if(data.url != ''){ 10517 document.location = data.url; 10518 } 10519 10520 } 10521 , error: function(data) { 10522 alert('Error attempting PayPal checkout'); 10523 viewModel.processing(false); 10524 } 10525 , complete: function(data) { 10526 } 10527 }); 10528 } 10529 10530 var addFromProductFinder = function(productInfo) { 10531 viewModel.productFinderSearchTerm(''); 10532 10533 var productInfo = { 10534 productKey: productInfo.key, 10535 productSku: productInfo.sku, 10536 parentChildType: productInfo.parent_child_type, 10537 parentProductId: productInfo.parent_p_id 10538 } 10539 10540 viewModel.loadProductForEdit(productInfo, ''); 10541 } 10542 10543 var checkOrderTotal = function(model){ 10544 var orderTotalValid = true; 10545 var subTotal = 0; 10546 if(ofConfig.useMinimumOrderTotal && !model.completed()){ 10547 if(model.useMultiShipEditUI && model.useMultiShipEditUI()){ 10548 _.each(model.itemShipToMap(), function(item){ 10549 subTotal += (item.qty() * item.getPrice()); 10550 }); 10551 console.log('itemShipToMap'); 10552 }else if(model.itemsOnOrder){ 10553 _.each(model.itemsOnOrder(), function(item){ 10554 subTotal += (item.qty() * item.price()); 10555 }); 10556 }else{ 10557 var subTotal = model.productTotal(); 10558 } 10559 var minimumTotal = ofConfig.minimumOrderTotal; 10560 10561 if(ofConfig.useAccountMinimumOrderTotal && ofConfig.accountMinimumOrderTotal > 0){ 10562 minimumTotal = ofConfig.accountMinimumOrderTotal; 10563 } 10564 if(subTotal < minimumTotal){ 10565 orderTotalValid = false; 10566 } 10567 } 10568 return orderTotalValid; 10569 } 10570 10571 $(function() { 10572 if(getOriginalPageName() !== 'bulk_atc.asp') { 10573 addGlobalModalCompletionHandler($('#find_product'), addFromProductFinder); 10574 } 10575 10576 runHook('cartTemplatesDocumentReady', {self: viewModel}); 10577 });
10578 10579 addTimer("end of ko model"); 10580</script>
10580 10581</div> 10582
10583<script type="text/html" id="catalog.flags_custom"> 10584 <div class="marketing_flags_container"> 10585 <!-- ko foreach: productMarketingFlags() --> 10586 <span class ="flag" data-bind="text: flagText, attr: { class: 'flag ' + flagColor + ' flag_' + ($index() + 1)}"> </span> 10587 <!-- /ko --> 10588 </div> 10589</script>
10589 10590
10591<script type="text/html" id="catalog.flags_thumb_custom"> 10592 <!-- ko template: 'catalog.flags_custom' --><!-- /ko --> 10593</script>
10593 10594
10595<script type="text/html" id="catalog.detail_info_custom"> 10596 <!-- ko if:!isActiveLayout('list') --> 10597 <!-- ko if: selectedProduct().type !== 'parent' && currentParent().childDisplayType() !== 'droplist' --> 10598 <dl class="prod-searchfields"> 10599 <!-- ko template: 'catalog.sku_label' --><!-- /ko --> 10600 <!-- ko template: { name: 'catalog.searchfields', foreach: _.values(selectedProduct().searchfields) } --><!-- /ko --> 10601 </dl> 10602 <!-- /ko --> 10603 10604 10605 10606 <!-- ko if: selectedProduct().type == 'parent' && selectedProduct().childDisplayType() == 'input-qty' && oConfig.pageName == 'pc_product_detail.asp' --> 10607 <div class="prod-ds" data-bind=" 10608 html: selectedProduct().description, 10609 visible: oConfig.searchConfig.showDescription && selectedProduct().description()"> 10610 </div> 10611 <!-- /ko --> 10612 <!-- /ko --> 10613 10614</script>
10614 10615
10616<script type="text/html" id="catalog.searchfields_custom"> 10617 10618 <!-- ko if: oConfig.showSearchFields && $data && show() --> 10619 <div> 10620 <dt class="prod-searchfields__label" 10621 data-bind="html: label() + ':', 10622 attr: { class: 'prod-searchfields__label searchfield_' + $index() + ' ' + (oConfig.pageName == 'pc_product_detail.asp' ? ' product-detail-search-label ': '') }"></dt> 10623 <dd class="prod-searchfields__value" data-bind="html: value, attr: { class: 'prod-searchfields__value searchfield_' + $index()}"></dd> 10624 </div> 10625 <!-- /ko --> 10626</script>
vendor: 2 bytes, line 10626
10626
10627<script type="text/html" id="catalog.sku_label_custom"> 10628 <!-- ko if: oConfig.pageName == 'pc_product_detail.asp' --> 10629 <div> 10630 <dt class="product-sku-label product-detail-search-label" data-bind="html: oConfig.labels.sku + ':' "></dt> 10631 <dd itemprop="sku" data-bind="html: selectedProduct().sku"></dd> 10632 </div> 10633 <!-- /ko --> 10634 10635 <!-- ko if: oConfig.pageName != 'pc_product_detail.asp' --> 10636 <div> 10637 <span class="product-sku-label" data-bind="html: oConfig.labels.sku "></span> 10638 <span itemprop="sku" data-bind="html: selectedProduct().sku"></span> 10639 </div> 10640 <!-- /ko --> 10641</script>
10641 10642
10643<script type="text/html" id="catalog.reviews_custom"> 10644 <!-- ko if: oConfig.useReviews --> 10645 <h2 data-bind="html : oConfig.labels.reviews"></h2> 10646 <div 10647 id="reviews" 10648 itemprop="aggregateRating" 10649 itemscope 10650 itemtype="http://schema.org/AggregateRating" 10651 > 10652 <div id="review_header"></div><div id="product_page"></div><div id="review_image"><a href="http://www.shopperapproved.com/reviews/flagandbanner.com/" target="_blank" rel="nofollow"></a></div> 10653 </div> 10654 <!-- /ko --> 10655</script>
10655 10656
10657<script type="text/html" id="catalog.rating_score_custom"> 10658 <!-- ko if: oConfig.useReviews --> 10659 <!-- /ko --> 10660</script>
10660 10661 10662
10663<script type="text/html" id="catalog.configurator_custom"> 10664 <!-- ko if: useConfigurator --> 10665 <h3>Choose Options:</h3> 10666 <!-- /ko --> 10667 <form id="frmAddToCart"> 10668 <div id="configurator" data-bind="configurator: $data"></div> 10669 </form> 10670</script>
10670 10671
10672<script type="text/html" id="catalog.atc_full_custom"> 10673 <!-- ko if: selectedProduct().type == 'child' && currentParent().childDisplayType() == 'droplist' --> 10674 <dl class="prod-searchfields prod-droplist-sku"> 10675 <!-- ko template: 'catalog.sku_label' --><!-- /ko --> 10676 </dl> 10677 <!-- /ko --> 10678 <!-- ko ifnot: $data.type === 'parent' --> 10679 <!-- ko if: oConfig.useIdp --> 10680 <!-- ko template: 'catalog.inventory' --><!-- /ko --> 10681 <!-- /ko --> 10682 <fieldset id="cart_options" data-bind="visible: oConfig.useCartOptions && selectedProduct().hasCartOptions() "> 10683 <legend>Additional Options</legend> 10684 <!-- ko template: { name: 'catalog.cart_options', data: selectedProduct, if: selectedProduct().questions().length > 0 } --><!-- /ko --> 10685 </fieldset> 10686 <!-- ko if: oConfig.showProductConfigurator --> 10687 <!-- ko template: 'catalog.configurator' --><!-- /ko --> 10688 <!-- /ko --> 10689 <!-- ko if: oConfig.UseTaxExempt --> 10690 <!-- ko template: 'catalog.tax_exempt' --><!-- /ko --> 10691 <!-- /ko --> 10692 <!-- /ko --> 10693 <!-- ko if: $data.isDangerous --> 10694 <!-- ko template: 'catalog.hazmat' --><!-- /ko --> 10695 <!-- /ko --> 10696 <!-- ko if: oConfig.detailConfig.showSoftGoodAuthorizations --> 10697 <!-- template: 'catalog.softgoods' --> 10698 <!-- /ko --> 10699 10700 <div class="prod-pricing" data-bind="template: { name: priceDisplay, data: selectedProduct } "></div> 10701 <!-- ko if: utils.isMainProduct($data) ? showAtc : selectedProduct().showAtc --> 10702 <!-- ko template: { name: 'catalog.atc_form_submit', data: selectedProduct } --><!-- /ko --> 10703 <!-- /ko --> 10704 </script>
10704 10705
10706<script type="text/html" id="catalog.product_card_custom"> 10707 <div class="prod-card"> 10708 <!-- ko if: isActiveLayout('gallery') || oConfig.pageName == 'pc_product_detail.asp' --> 10709 <div class="prod-thumb" data-bind="visible: oConfig.searchConfig.showThumb, css: { '-using-flags': oConfig.usingFlags } "> 10710 <span class="prod-thumb-img" data-bind="template: 'catalog.image_link'"></span> 10711 <span class="prod-thumb-flags" data-bind="template: 'catalog.flags_thumb'"></span> 10712 </div> 10713 10714 <div class="prod-info"> 10715 <div class="prod-desc"> 10716 <div class="prod-nm"> 10717 <!-- ko template: 'catalog.name_link' --><!-- /ko --> 10718 </div> 10719 <!-- ko template: 'catalog.rating_score' --><!-- /ko --> 10720 </div> 10721 <div class="prod-details"> 10722 <!-- ko template: { name: 'catalog.detail_info' } --><!-- /ko --> 10723 </div> 10724 <!-- ko if: oConfig.showChildrenSelection && $data.children --> 10725 <div class="prod-children" data-bind= "template:{ 10726 name: 'catalog.children_selection', 10727 if: oConfig.showChildrenSelection && $data.children && children().length 10728 }"></div> 10729 <!-- /ko --> 10730 10731 <div class="prod-pricing" data-bind="template: { name: priceDisplay, data: selectedProduct } "></div> 10732 10733 <div class="prod-idp" data-bind="template: 'catalog.inventory', visible: inventory.isInventoryItem() && oConfig.useIdp"></div> 10734 <!-- ko if: $data.isDangerous --> 10735 <!-- ko template: 'catalog.hazmat' --><!-- /ko --> 10736 <!-- /ko --> 10737 <!-- ko template: { name: 'catalog.product_account_history_short',data: accountHistory, if: accountHistory && accountHistory.accountName }--><!-- /ko --> 10738 10739 <div class="prod-actions" data-bind="template: 'catalog.product_actions'"></div> 10740 10741 <!-- ko if: utils.getParameter('favorites') && oConfig.pageName == 'pc_combined_results.asp' --> 10742 <!-- ko template: 'catalog.remove_fav_button' --><!-- /ko --> 10743 <!-- /ko --> 10744 </div> 10745 <!-- /ko --> 10746 <!-- ko if: isActiveLayout('list') --> 10747 <div class="prod-thumb" data-bind="visible: oConfig.searchConfig.showThumb, css: { '-using-flags': oConfig.usingFlags } "> 10748 <span class="prod-thumb-img" data-bind="template: 'catalog.image_link'"></span> 10749 <span class="prod-thumb-flags" data-bind="template: 'catalog.flags_thumb'"></span> 10750 </div> 10751 <div class="prod-info"> 10752 <div class="prod-desc"> 10753 <div class="prod-nm"> 10754 <!-- ko template: 'catalog.name_link' --><!-- /ko --> 10755 </div> 10756 <div class="prod-ds" data-bind=" 10757 html: selectedProduct().searchfields.searchfield4.value"> 10758 </div> 10759 <!-- ko template: 'catalog.sku_label' --><!-- /ko --> 10760 <!-- ko template: 'catalog.rating_score' --><!-- /ko --> 10761 <div class="prod-details"> 10762 <!-- ko template: { name: 'catalog.detail_info' } --><!-- /ko --> 10763 </div> 10764 </div> 10765 </div> 10766 <!-- ko template: { name: 'catalog.product_account_history_short',data: accountHistory, if: accountHistory && accountHistory.accountName }--><!-- /ko --> 10767 <div class="prod-atc"> 10768 <div class="prod-idp" data-bind="template: 'catalog.inventory'"></div> 10769 <div class="prod-pricing" data-bind="template: { name: priceDisplay, data: selectedProduct } "></div> 10770 <!-- ko if: oConfig.showChildrenSelection && $data.children --> 10771 <div class="prod-children" data-bind= "template:{ 10772 name: 'catalog.children_selection', 10773 if: oConfig.showChildrenSelection && $data.children && children().length 10774 }"></div> 10775 <!-- /ko --> 10776 <div class="prod-actions" data-bind="template: 'catalog.product_actions'"></div> 10777 </div> 10778 <!-- ko if: utils.getParameter('favorites') && oConfig.pageName == 'pc_combined_results.asp' --> 10779 <!-- ko template: 'catalog.remove_fav_button' --><!-- /ko --> 10780 <!-- /ko --> 10781 <!-- /ko --> 10782 </div> 10783</script>
10783 10784 10785
10785<script type="text/html" id="catalog.name_link_custom"> 10786 <a class="detail_link" data-bind="attr: { href: link, title: utils.decodeHTML(name()), 'data-key': key }, html: name, click: function(data, event) { trackProductClick(data); return true; }"></a> 10787 </script>
10787 10788 10789
10789<script type="text/html" id="catalog.image_link_custom"> 10790 <a class="detail_link" data-bind="attr: { href: link, title: utils.decodeHTML(thumbAltText() || name()), 'data-key': key }, click: function(data, event) { trackProductClick(data); return true; }"> 10791 <img 10792 data-bind=" 10793 attr: { 10794 src: utils.buildImagePath(thumb() || parent_thumb()), 10795 alt: thumbAltText() || name(), 10796 width: oConfig.searchConfig[getActiveLayout() + 'ThumbnailWidth'], 10797 height: oConfig.searchConfig[getActiveLayout() + 'ThumbnailHeight'] 10798 }" 10799 onerror="utils.handleImageError(this)"> 10800 </a> 10801 </script>
10801 10802 10803
10804<script type="text/html" id="catalog.advanced_parent_layout_custom"> 10805 <!-- ko template: { name: "catalog.product_title", data: selectedProduct } --><!-- /ko --> 10806 <div id="product_view" class="product_view" data-bind="attr: { class: oConfig.detailConfig.gridRowClass }"> 10807 <div data-bind="attr: { class: oConfig.detailConfig.gridLeftColumnClass + ' product-detail__left' }"> 10808 <div id="product_images" data-bind="template: { name: 'catalog.image_gallery', data: selectedProduct }"></div> 10809 </div> 10810 <div data-bind="attr: { class: oConfig.detailConfig.gridRightColumnClass + ' product-detail__right' }"> 10811 <div class="product_view__share-code" data-bind="template: 'catalog.share_code'"></div> 10812 <span class="product_view__detail-info" data-bind="template: 'catalog.detail_info'" ></span> 10813 <span class="product_view__rating-detail" data-bind="template: 'catalog.rating_detail'"></span> 10814 <div data-bind=" 10815 template: { 10816 name: 'promotions.descriptions', 10817 if: promoDescriptions.length, 10818 data: { 10819 title: 'Product on Promotion', 10820 descriptions: promoDescriptions, 10821 selectedProduct: selectedProduct 10822 } 10823 } 10824 "> 10825 </div> 10826 <div class="detail-docs" data-bind="template: { if: oConfig.detailConfig.showDocuments && !selectedProduct().usingDownloadsTab(), name: 'catalog.documents', data: documents() }"></div> 10827 10828 <a class="btn btn-primary scroll-to" 10829 data-bind=" 10830 attr: { href: '#input-qty' }, 10831 html : oConfig.detailConfig.labels.inputQtyATCLabel, 10832 click: function() { 10833 scrollToTarget($element); 10834 return false; 10835 } 10836 "> 10837 </a> 10838 </div> 10839 </div> 10840 <!-- ko template: 'catalog.additional_info' --><!-- /ko --> 10841 <span data-bind="template: { name: 'catalog.add_ons', data: selectedProduct }"></span> 10842 <h2 id="input-qty" data-bind="html : oConfig.detailConfig.labels.inputQty"></h2> 10843 <div id="atcform" data-bind="visible: !lazyLoadingInProgress(), template: childDisplayType() === 'matrix-all' ? 'catalog.matrix_form' : childDisplayType() === 'add-row' ? 'catalog.add_row_form' : 'catalog.input_qty_form'"></div> 10844 <div data-bind="if: lazyLoadingInProgress"> 10845 <div class="sk-three-bounce" style="margin: 0 auto;"> 10846 <div class="sk-child sk-bounce1"></div> 10847 <div class="sk-child sk-bounce2"></div> 10848 <div class="sk-child sk-bounce3"></div> 10849 </div> 10850 <div class="text-center"> 10851 <small><em>Loading options...</em></small> 10852 </div> 10853 </div> 10854 10855</script>
10855 10856
10857<script type="text/html" id="catalog.results_custom"> 10858 <!-- ko ifnot: oConfig.searchConfig.pageType == 'category' && !$data.category --> 10859 <div id="list_wrap"> 10860 <div id="list_wrap_pad"> 10861 <div id="list_head" data-bind=" 10862 template: $data.category ? 10863 { name: 'catalog.category_header', data: category } : 10864 'catalog.page_title' 10865 "></div> 10866 <div id="products_header" class="list-toolbar products_header" data-bind="template: 'catalog.header'"></div> 10867 <div id="products_view" data-bind="attr : { 'data-layout' : getActiveLayout() }, template: getLayoutTemplate($data)"></div> 10868 <div id="products_footer" class="list-toolbar products_footer" data-bind="template: { name : 'catalog.footer' } "></div> 10869 </div> 10870 </div> 10871 <!-- ko if: typeof category !== 'undefined' && category && category.ds_alt --> 10872<div class="head_desc" data-bind="html: category.ds_alt"></div> 10873<!-- /ko --> 10874 <!-- /ko --> 10875 <!-- ko if: oConfig.searchConfig.pageType == 'category' && !$data.category --> 10876 <div id="list_wrap"> 10877 <div id="list_wrap_pad"> 10878 <div class="alert alert-warning" data-bind="html: oConfig.labels.categoryNotFound"></div> 10879 </div> 10880 </div> 10881 <!-- /ko --> 10882</script>
10882 10883
10884<script> 10885 registerHook({ 10886 name: 'productModelBottom', 10887 func: function(oArgs) { 10888 var self = oArgs.self; 10889 var product = oArgs.product; 10890 var tempFlags = []; 10891 10892 function getFlags(){ 10893 tempArr = []; 10894 if(self.marketingFlags() != ''){ 10895 tempFlags = self.marketingFlags().split('|'); 10896 _.forEach(tempFlags, function(result) { 10897 if(result.split('~').length == 2){ 10898 tempArr.push( 10899 { 10900 'flagText': result.split('~')[0], 10901 'flagColor': result.split('~')[1] 10902 } 10903 ) 10904 } 10905 }); 10906 } 10907 10908 return tempArr; 10909 } 10910 self.productMarketingFlags = ko.observableArray(getFlags()); 10911 10912 // Product click tracking function 10913 window.trackProductClick = function(product) { 10914 // Clear the previous ecommerce object 10915 if (typeof dataLayer !== 'undefined') { 10916 dataLayer.push({ ecommerce: null }); 10917 10918 // Push the product click event 10919 dataLayer.push({ 10920 event: "EEproductClick", 10921 ecommerce: { 10922 items: [ 10923 { 10924 item_id: product.sku(), 10925 item_name: product.name(), 10926 price: product.selectedProduct && product.selectedProduct().unitPrice ? 10927 product.selectedProduct().unitPrice() : 10928 (product.unitPrice ? product.unitPrice() : 0) 10929 } 10930 ] 10931 } 10932 }); 10933 } 10934 }; 10935 10936 // Product list impression tracking function 10937 window.trackProductListImpressions = function(products) { 10938 if (typeof dataLayer !== 'undefined' && products && products.length > 0) { 10939 // Clear the previous ecommerce object 10940 dataLayer.push({ ecommerce: null }); 10941 10942 // Build the items array for all visible products 10943 var items = products.map(function(product) { 10944 return { 10945 item_id: product.sku(), 10946 item_name: product.name(), 10947 price: product.selectedProduct && product.selectedProduct().unitPrice ? 10948 product.selectedProduct().unitPrice() : 10949 (product.unitPrice ? product.unitPrice() : 0) 10950 }; 10951 }); 10952 10953 // Push the product impression event 10954 dataLayer.push({ 10955 event: "EEproductImpression", 10956 ecommerce: { 10957 items: items 10958 } 10959 }); 10960 } 10961 }; 10962 10963 // Product view tracking function for product detail pages 10964 window.trackProductView = function(product) { 10965 if (typeof dataLayer !== 'undefined' && product) { 10966 // Clear the previous ecommerce object 10967 dataLayer.push({ ecommerce: null }); 10968 10969 // Push the product view event 10970 dataLayer.push({ 10971 event: "EEproductView", 10972 ecommerce: { 10973 currency: "USD", 10974 value: product.selectedProduct && product.selectedProduct().unitPrice ? 10975 product.selectedProduct().unitPrice() : 10976 (product.unitPrice ? product.unitPrice() : 0), 10977 items: [ 10978 { 10979 item_id: product.sku(), 10980 item_name: product.name(), 10981 price: product.selectedProduct && product.selectedProduct().unitPrice ? 10982 product.selectedProduct().unitPrice() : 10983 (product.unitPrice ? product.unitPrice() : 0) 10984 } 10985 ] 10986 } 10987 }); 10988 } 10989 }; 10990 10991 var storeUrl = oConfig.sessionData.orderfrontUrl 10992 10993 utils.buildImagePath = function(image){ 10994 if(image && image.indexOf("http") > -1){ 10995 imageUrl = image.replace(/http:/i, 'https:'); 10996 }else{ 10997 image = image.replace(oConfig.storefrontUrl, oConfig.sessionData.cdnUrl).toLowerCase(); 10998 if(!image){ 10999 imageUrl = oConfig.noImagePath || oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/images/' + oConfig.defaultImage.replace(/^\/+/, ''); 11000 } 11001 else if(image.indexOf("/") > -1){ 11002 imageUrl = oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/' + image.replace(/^\/+/, ''); 11003 } 11004 else{ 11005 imageUrl = oConfig.sessionData.cdnUrl.replace(/\/+$/, '') + '/images/' + image.replace(/^\/+/, ''); 11006 } 11007 } 11008 if (imageUrl.indexOf(storeUrl) > -1) { 11009 imageUrl + 'v=3997506342'; 11010 } 11011 return imageUrl; 11012 }; 11013 } 11014 }); 11015</script>
11015 11016
11017<script> 11018 registerHook({ 11019 name: 'afterGetData', 11020 func: function(oArgs) { 11021 var products = oArgs.products; 11022 11023 // Set up product list impression tracking to fire after DOM is ready and templates are rendered 11024 $(document).ready(function() { 11025 // Wait for the Knockout bindings to be applied and templates to render 11026 setTimeout(function() { 11027 // Check if we have products and the tracking function is available 11028 if (products && products.length > 0 && typeof window.trackProductListImpressions === 'function') { 11029 11030 // Convert plain JS objects to match what the tracking function expects 11031 var trackingProducts = products.map(function(product) { 11032 return { 11033 sku: function() { return product.sku || ''; }, 11034 name: function() { return product.name || ''; }, 11035 unitPrice: function() { return product.unitPrice || 0; } 11036 }; 11037 }); 11038 11039 window.trackProductListImpressions(trackingProducts); 11040 } 11041 }, 1500); // Longer delay to ensure Knockout templates are fully rendered 11042 11043 // Also set up tracking for when viewModel.results changes (pagination, etc.) 11044 // This will be available after ko.beforeApplyBindings runs 11045 setTimeout(function() { 11046 if (typeof viewModel !== 'undefined' && viewModel.results && ko.isObservable(viewModel.results)) { 11047 viewModel.results.subscribe(function(newResults) { 11048 if (newResults && newResults.length > 0) { 11049 setTimeout(function() { 11050 if (typeof window.trackProductListImpressions === 'function') { 11051 window.trackProductListImpressions(newResults); 11052 } 11053 }, 500); 11054 } 11055 }); 11056 } 11057 }, 2000); // Wait for viewModel to be fully initialized 11058 }); 11059 } 11060 }); 11061</script>
11061 11062
11063<script> 11064 registerHook({ 11065 name: 'productDetailBeforeHide', 11066 func: function(oArgs) { 11067 var viewModel = oArgs.viewModel; 11068 11069 // Track product view after the viewModel is ready 11070 $(document).ready(function() { 11071 // Small delay to ensure DOM is ready and product data is fully loaded 11072 setTimeout(function() { 11073 if (viewModel && viewModel.mainProduct && typeof window.trackProductView === 'function') { 11074 var product = viewModel.mainProduct; 11075 11076 // Call the tracking function with the main product 11077 window.trackProductView(product); 11078 } 11079 }, 500); // Small delay to ensure everything is ready 11080 }); 11081 } 11082 }); 11083 11084 // Function to fire GA4 add_shipping_info event 11085 function fireAddShippingInfoEvent(model, shipViaChoice, firstShipment) { 11086 var shipViaKey = shipViaChoice.shipViaChoiceKey ? shipViaChoice.shipViaChoiceKey() : null; 11087 11088 // Only push if this is a different shipping method than last time 11089 if (shipViaKey && shipViaKey !== window._lastPushedShipViaKey) { 11090 window._lastPushedShipViaKey = shipViaKey; 11091 11092 // Derive tracking fields from the model 11093 var currency = (window.ofConfig && ofConfig.CurrencyIso) || 'USD'; 11094 var coupon = (model.couponCode && model.couponCode()) || (model.coupon && model.coupon()) || undefined; 11095 var shippingTier = (shipViaChoice.name && shipViaChoice.name()) || 11096 (firstShipment.selectedShipVia && firstShipment.selectedShipVia.name && firstShipment.selectedShipVia.name()) || ''; 11097 var orderValue = (model.orderTotal && model.orderTotal()) || (model.total && model.total()) || 0; 11098 11099 // Build items array from current detail lines 11100 var items = []; 11101 if (model.detailLines && model.detailLines()) { 11102 items = model.detailLines().map(function(line) { 11103 return { 11104 item_id: line.sku ? line.sku() : (line.productID ? line.productID() : line.orderDetailKey()), 11105 item_name: line.name ? line.name() : (line.productName ? line.productName() : ''), 11106 price: line.price ? Number(line.price()) : 0, 11107 quantity: line.qty ? Number(line.qty()) : 0 11108 }; 11109 }); 11110 } 11111 11112 // GA4 event push 11113 window.dataLayer = window.dataLayer || []; 11114 window.dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object 11115 var ga4Event = { 11116 event: "add_shipping_info", 11117 ecommerce: { 11118 order_id: model.orderKey ? model.orderKey() : '', 11119 currency: currency, 11120 value: Number(orderValue), 11121 coupon: coupon, 11122 shipping_tier: shippingTier, 11123 items: items 11124 } 11125 }; 11126 window.dataLayer.push(ga4Event); 11127 } 11128 } 11129 11130 // Google Analytics 4 Add Shipping Info Event Hook - for page load default selection 11131 registerHook({ 11132 name: 'shipmentModelBottom', 11133 func: function(oArgs) { 11134 var shipment = oArgs.self; 11135 var shipmentData = oArgs.shipmentData; 11136 11137 // Check if this shipment has a default shipping method selected 11138 if (shipment.selectedShipViaChoice && shipment.selectedShipViaChoice()) { 11139 // Fire GA4 add_shipping_info event with a small delay to ensure viewModel is available 11140 setTimeout(function() { 11141 // Access the global viewModel for order data 11142 if (typeof viewModel !== 'undefined') { 11143 // Use the shared function to fire the event 11144 fireAddShippingInfoEvent(viewModel, shipment.selectedShipViaChoice(), shipment); 11145 } 11146 }, 100); // Small delay to ensure viewModel is available 11147 } 11148 } 11149 });
11150 11151// Function to track GA4 add_payment_info event for saved payment methods 11152function trackPaymentInfoEvent(oCreditCard, options, savedPaymentsManager) { 11153 // Initialize page load tracking if not already done 11154 if (typeof window._pageLoadTime === 'undefined') { 11155 window._pageLoadTime = Date.now(); 11156 } 11157 11158 var currentTime = Date.now(); 11159 11160 // Prevent events from firing within the first 3 seconds of page load 11161 if ((currentTime - window._pageLoadTime) < 3000) { 11162 return; 11163 } 11164 11165 // Create a global debounce key that's not card-specific to prevent any duplicate events 11166 var globalDebounceKey = 'global_payment_info_event'; 11167 11168 // Check if we've already fired ANY payment info event recently (within 3 seconds) 11169 if (window._lastPaymentInfoEvents && 11170 window._lastPaymentInfoEvents[globalDebounceKey] && 11171 (currentTime - window._lastPaymentInfoEvents[globalDebounceKey]) < 3000) { 11172 // Skip this event to prevent duplicates 11173 return; 11174 } 11175 11176 // Initialize the tracking object if it doesn't exist 11177 if (!window._lastPaymentInfoEvents) { 11178 window._lastPaymentInfoEvents = {}; 11179 } 11180 11181 // Record this event timestamp globally 11182 window._lastPaymentInfoEvents[globalDebounceKey] = currentTime; 11183 11184 // Try to get current order data from viewModel if available (during checkout) 11185 var orderData = null; 11186 var currency = 'USD'; 11187 var orderValue = 0; 11188 var coupon = undefined; 11189 var items = []; 11190 11191 // Check if we're in checkout context with viewModel 11192 if (typeof viewModel !== 'undefined' && viewModel.detailLines) { 11193 currency = (viewModel.currency && viewModel.currency()) || 11194 (window.ofConfig && ofConfig.CurrencyIso) || 'USD'; 11195 orderValue = (viewModel.orderTotal && viewModel.orderTotal()) || 11196 (viewModel.total && viewModel.total()) || 0; 11197 coupon = (viewModel.couponCode && viewModel.couponCode()) || 11198 (viewModel.coupon && viewModel.coupon()) || undefined; 11199 11200 // Build items array from current order 11201 if (viewModel.detailLines && viewModel.detailLines()) { 11202 items = viewModel.detailLines().map(function(line) { 11203 return { 11204 item_id: line.sku ? line.sku() : (line.productID ? line.productID() : ''), 11205 item_name: line.name ? line.name() : (line.productName ? line.productName() : ''), 11206 price: line.price ? Number(line.price()) : 0, 11207 quantity: line.qty ? Number(line.qty()) : 0 11208 }; 11209 }); 11210 } 11211 } 11212 11213 // Track GA4 add_payment_info event 11214 dataLayer.push({ 11215 event: 'add_payment_info', 11216 ecommerce: { 11217 order_id: (viewModel && viewModel.orderKey && viewModel.orderKey()) || '', 11218 currency: currency, 11219 value: Number(orderValue), 11220 coupon: coupon, 11221 payment_type: 'credit_card', 11222 items: items 11223 }, 11224 }); 11225} 11226 11227registerHook({ 11228 name: 'savedPaymentsAfterCardAdded', 11229 func: trackPaymentInfoEvent 11230}); 11231 11232registerHook({ 11233 name: 'savedPaymentsAfterCardSelected', 11234 func: trackPaymentInfoEvent 11235}); 11236 11237registerHook({ 11238 name: 'addToCartSuccessHandler', 11239 func: function(oArgs) { 11240 var responseData = oArgs.responseData; 11241 var details = oArgs.details; 11242 11243 // Parse the response to get order information 11244 var parsedResponse = JSON.parse(responseData); 11245 // Extract orderKey from the correct location in the response 11246 var orderKey = ''; 11247 if (parsedResponse && parsedResponse.length > 1) { 11248 // orderKey is in the second object of the array (index 1) 11249 orderKey = parsedResponse[1] && parsedResponse[1].orderKey ? parsedResponse[1].orderKey : ''; 11250 } 11251 11252 // Fire enhanced GA4 add_to_cart event with order_id 11253 if (typeof dataLayer !== 'undefined' && details && details.length > 0) { 11254 var gtmProducts = []; 11255 var line_total = 0; 11256
11257 details.forEach(function(item) { 11258 var gtmProduct = { 11259 item_id: item.sku(), 11260 item_name: item.name(), 11261 currency: "USD", 11262 price: Number(item.unitPrice()), 11263 quantity: Number(item.selectedQty()) 11264 }; 11265 gtmProducts.push(gtmProduct); 11266 line_total += Number(item.selectedQty()) * item.unitPrice(); 11267 }); 11268 11269 // Clear previous ecommerce data 11270 dataLayer.push({ ecommerce: null }); 11271 11272 // Push enhanced add_to_cart event with order_id 11273 dataLayer.push({ 11274 event: oConfig.t_gtm_add_to_cart_event_name || 'EEaddToCart', 11275 ecommerce: { 11276 order_id: orderKey, 11277 currency: "USD", 11278 value: line_total, 11279 items: gtmProducts 11280 }, 11281 customer: { 11282 email: cimcloud.session.email, 11283 firstname: cimcloud.session.firstName, 11284 lastname: cimcloud.session.lastName 11285 } 11286 }); 11287 } 11288 } 11289}); 11290</script>
11290 11291 11292 11293 11294
11295<script> 11296 registerHook({ 11297 name: 'bill_ship_custom_submit_click', 11298 func: function(oArgs, oRetVals) { 11299 11300 // Get order data from server-side function 11301 var orderData = {}; 11302 11303 dataLayer.push({ ecommerce: null }); 11304 dataLayer.push({ 11305 event: "begin_checkout", 11306 ecommerce: { 11307 order_id: orderData.order_id || '', 11308 currency: "USD", 11309 value: orderData.total || 0, 11310 coupon: orderData.coupon || undefined, 11311 items: orderData.items || [] 11312 } 11313 }); 11314 11315 // Return false to allow normal form submission to continue 11316 return false; 11317 }, 11318}); 11319</script>
11319 11320
11321<script type="text/html" id="cart.configOptions_custom"> 11322 <!-- ko if : configuratorJson.choices --> 11323 <div class="config-options"> 11324 <div class="config-options__title"> 11325 <button class="config-options__toggle" 11326 data-bind="click: 11327 function(e) { 11328 $('.config-options__content').slideToggle(); 11329 $('.config-options').toggleClass('-closed'); 11330 }"> 11331 <span class="config-options__type" style="font-weight: bold;" data-bind="text: configuratorJson.configType() === 'cartoptions' ? 'Options' : 'Configuration Options'"></span> 11332 <i class="fas fa-angle-down"></i> 11333 </button> 11334 <span class="config-options__details" data-bind="visible: configuratorJson.configType() !== 'cartoptions'"> 11335 <!-- ko template: { name: 'cart.productEditLink', data: { title: 'Edit Configuration', linkText: '<small>Edit</small>', detailLine: $data } } --><!-- /ko --> 11336 <!-- ko template: { name: 'cart.instanceCloneLink', data: { detailLine: $data }, visible: oConfig.showCloneInstanceLink } --><!-- /ko --> 11337 </span> 11338 </div> 11339 <div class="config-options__content"> 11340 <ul class="config-options__group" data-bind="foreach: configuratorJson.choices"> 11341 <!-- ko if: name() == 'upload_art_file' --> 11342 <li class="config-options__item"><strong><span data-bind="html: questionText"></span></strong> <span><img style="max-height:50px; max-width:50px;" data-bind="attr: {src: utils.buildImagePath(answerText())}" src="" onerror="utils.handleImageError(this)"/> </span></li> 11343 <!-- /ko --> 11344 <!-- ko ifnot: name() == 'upload_art_file' --> 11345 <li class="config-options__item"><strong><span data-bind="html: questionText"></span></strong> <span data-bind="text: answerText"></span></li> 11346 <!-- /ko --> 11347 11348 </ul> 11349 <!-- ko if: instanceChildren.length > 0 --> 11350 <table class="tablesaw cart-table config-options__cart-table" role="presentation"> 11351 <thead class="config-options__thead"> 11352 <th class="config-options__qty-title">Qty</th> 11353 <th class="config-options__price-title">Product Price</th> 11354 <th class="config-options__desc-title">Description</th> 11355 </thead> 11356 <tbody class="cart-row-std config-options__tbody" data-bind="foreach: instanceChildren"> 11357 <tr> 11358 <td class="config-options__qty-text" data-bind="text: qty"></td> 11359 <td class="config-options__price-text"><span data-bind="html: utils.formatMoney( (priceBeforeAdjustment() || price()) )"></span></td> 11360 <td class="config-options__desc-text" data-bind="html: name"></td> 11361 </tr> 11362 </tbody> 11363 </table> 11364 <!-- /ko --> 11365 </div> 11366 </div> 11367 <!-- /ko --> 11368</script>
11368 11369 11370 11371
11372<script type="text/html" id="cart.shipmentItemTable_custom"> 11373 <!-- ko if: details().length > 0 && !viewModel.isOverLineLimit() --> 11374 <!-- ko template: { afterRender: function() { $(document).trigger('enhance.tablesaw'); } } --> 11375 <table class="tablesaw cart-table" data-tablesaw-mode="stack" role="presentation"> 11376 <thead> 11377 <th class="cart-desc__th" data-bind="text: ofConfig.labels.cartDesc"></th> 11378 <th class="cart-qty__th" data-bind="text: ofConfig.labels.cartQty"></th> 11379 <!-- ko if: ofConfig.showPricingOrderEntry --> 11380 <th class="cart-price__th" data-bind="text: ofConfig.labels.cartItemPrice"></th> 11381 <!-- /ko --> 11382 <!-- ko if: ofConfig.showPricingOrderEntry --> 11383 <th class="cart-total__th" data-bind="text: ofConfig.labels.cartTotal"></th> 11384 <!-- /ko --> 11385 <!-- ko if: ofConfig.allowProductEditInFinalStep && viewModel.recordType() != 'recurring' --><!-- /ko --> 11386 </thead> 11387 <tbody class="cart-row-std" data-bind="foreach: details"> 11388 <!-- ko if: orderDetail.parentProductID().trim() == '' || !orderDetail.hasParentInCart() --> 11389 <tr> 11390 <td> 11391 <div class="media"> 11392 <img 11393 data-bind="visible: !oConfig.fastTrack, 11394 attr : { alt: orderDetail.sku() + ' - ' + orderDetail.name(), 11395 src: utils.buildImagePath(orderDetail.thumbnail()) }, 11396 css: { 'print-hide': !ofConfig.showProductImagesWhenPrinting }" 11397 class="media-object pull-left cart-item-pic" 11398 onerror="utils.handleImageError(this)"> 11399 <div class="media-body"> 11400 <div class="cart-item-sku" data-bind="text: orderDetail.sku, visible: !orderDetail.parentProductID().trim() || !orderDetail.hasParentInCart()"></div> 11401 <div class="cart-item-name" > 11402 <span data-bind="html: orderDetail.name"></span> 11403 <!-- ko template: { name: 'cart.backorderMessage', data: orderDetail, if: ofConfig.showBackorderMessage } --><!-- /ko --> 11404 <!-- ko template: { name :'cart.productLeadTimes', data: orderDetail} --><!-- /ko --> 11405 <!-- ko if: viewModel.recordType() === 'recurring' --> 11406 <div class="recurring-summary" data-bind="html: viewModel.getRecurringLabel($data)"></div> 11407 <!-- /ko --> 11408 <!-- ko if: orderDetail.promoID --> 11409 <span class="promo-icon" data-bind="attr: { 'title' : orderDetail.promoDescription() } ">P</span> 11410 <!-- /ko --> 11411 </div> 11412 <!-- ko template: { name: 'cart.softgoods', data: orderDetail, if: ofConfig.showSoftGoodAuthorizations } --><!-- /ko --> 11413 <p data-bind="if: ofConfig.AllowWarehouse && orderDetail.productWarehouse"> 11414 <span data-bind="html: ofConfig.warehouseLabel + ' ' + orderDetail.productWarehouse.name()"></span> 11415 </p> 11416 <!-- ko if : ofConfig.bShowCartOptions && orderDetail.cartOption --> 11417 <p data-bind="text: orderDetail.cartOption"></p> 11418 <!-- /ko --> 11419 <!-- ko template: { name: "cart.additionalDetailLineInfo", data: orderDetail } --><!-- /ko --> 11420 </div> 11421 </div> 11422 </td> 11423 <td class="instance-qty-ship__td">
11424 <span data-bind="visible: orderDetail.qtyDisplayType() != 'hide', text: qtyToShip"></span><span data-bind="if: ofConfig.showTotalQtyOnShipment"> of <span data-bind="text: orderDetail.qty"></span></span> 11425 <!-- ko if:ofConfig.showUom --> 11426 <span class="uom" data-bind="text: orderDetail.uom"></span> 11427 <!-- /ko --> 11428 </td> 11429 <!-- ko if: ofConfig.showPricingOrderEntry --> 11430 <td class="instance-unit-price__td"> 11431 <span data-bind="html: orderDetail.instanceUnitPriceDisplay()"></span> 11432 </td> 11433 <td class="instance-ext-price__td"> 11434 <span data-bind="html: utils.formatMoney(orderDetail.instanceExtPrice())"></span> 11435 </td> 11436 <!-- /ko --> 11437 11438 <!-- ko if: !ofConfig.showPricingOrderEntry --> 11439 <td class="instance-hidden-price__td" data-bind="html: utils.drawHidePriceMessage()"></td> 11440 <!-- /ko --> 11441 11442 <!-- ko if: ofConfig.allowProductEditInFinalStep && viewModel.recordType() != 'recurring' --> 11443 <td class="recurring__td"> 11444 <!-- ko template: { name: 'cart.productInlineEditLinks', data: orderDetail } --><!-- /ko --> 11445 </td> 11446 <!-- /ko --> 11447 </tr> 11448 11449 11450 <tr class="cart-row-std__config-row -no-border-top" data-bind="if: orderDetail.configuratorJson.choices"> 11451 <td class="cart-row-std__config-col" colspan="5"> 11452 <!-- ko template: { name: "cart.configOptions", data: orderDetail } --><!-- /ko --> 11453 </td> 11454 </tr> 11455 11456 11457 <!-- ko if:orderDetail.editing() && viewModel.mainProduct() --> 11458 <tr> 11459 <td colspan="5"> 11460 <div class="detail-child-selector"> 11461 <span data-bind="template: { name: 'catalog.child_selectors', if: viewModel.mainProduct().childSelectors, data: viewModel.mainProduct().childSelectors }"></span> 11462 </div> 11463 <!-- ko template: { name:'catalog.atc_full', data:viewModel.mainProduct().selectedProduct, if:viewModel.mainProduct } --><!-- /ko --> 11464 </td> 11465 </tr> 11466 <!-- /ko --> 11467 <!-- /ko --> 11468 </tbody> 11469 </table> 11470 <!-- /ko --> 11471 <!-- /ko --> 11472 <div style="padding: 10px;"> 11473 <a href="customer_service/terms-and-conditions.asp" target="_blank">Terms and Conditions</a> | 11474 <a href="customer_service/Shipping-Rates-and-Policies.asp" target="_blank">Return Policy</a> | 11475 <a href="customer_service/Privacy-Policy.asp" target="_blank">Privacy Policy</a> 11476 </div> 11477 <!-- ko if: viewModel.isOverLineLimit() --> 11478 <div class="well cart-table" data-bind="html: ofConfig.tooManyLinesMessage"></div> 11479 <!-- /ko --> 11480</script>
11480 11481 11482
11483<script type="text/html" id="cart.abovePaymentMethods_custom"> 11484 <!-- placeholder --> 11485 11486 <fieldset class="u-checkout-well" data-bind="visible: !completed() && !orderPlaced()"> 11487 <h3 class="checkout-review__fieldset-content u-checkout-well__title" data-bind="visible: !orderPlaced() ">Additional Information </h3> 11488 <div id="controlgroup_howhear" class="control-group well" > 11489 <label class="control-label" for="howhear-select" data-bind="text: salesRepQuestionLabel()"></label> 11490 <select class="input" data-bind=" 11491 attr: { id: 'howhear-select' 11492 }, 11493 options: viewModel.salesRepOptions(), 11494 optionsText: 'text', 11495 optionsValue: 'value', 11496 value: viewModel.salesRepValue"> 11497 </select> 11498 </div> 11499 </fieldset> 11500</script>
11500 11501 11502 11503 11504<iframe id="saIframe" style="display:none;"></iframe> 11505 11506 11507
11508<script> 11509 registerHook({ 11510 name: 'orderModelBottom', 11511 func: function(oArgs) { 11512 var self = oArgs.self; 11513 var order = oArgs.order; 11514 var tempFlags = []; 11515 var salesRepQuestion = [{"question_text":"Sales Rep Code","nm":"opt1","answers":"No Sales Rep~IS01|Gray~GRAY|Catherine~CB01|Nathan~ENLH|Grady~GM01|Jason~JC01|Kirk~KW01|Matthew~MSM1","default_answer":"IS01","q_key":"5EA532FE9B0D4F13AE50A1AE91E9CFE2"}][0]; 11516 11517 11518 11519 self.completed.subscribe(function(newValue) { 11520 if (newValue === true) { 11521 11522 var randomnumber = Math.floor(Math.random() * 1000); 11523 11524 var sa_draw = window.document.createElement('script'); 11525 sa_draw.setAttribute('src', 'https://shopperapproved.com/thankyou/sv-draw_js.php?site=9380&loadoptin=1&rnd=' + randomnumber); 11526 sa_draw.setAttribute('type', 'text/javascript'); 11527 11528 document.getElementsByTagName("head")[0].appendChild(sa_draw); 11529 11530 sa_draw.onload = function() { 11531 var iframe = document.getElementById('saIframe'); 11532 iframe.style.display = 'block'; 11533 iframe.src = 'https://shopperapproved.com/thankyou/sv-draw_js.php?site=9380&loadoptin=1&rnd=' + randomnumber; 11534 }; 11535 } 11536 }); 11537 11538 self.salesRepValue = ko.observable(self.opt1()); 11539 11540 self.salesRepQuestionLabel = ko.observable(salesRepQuestion.question_text); 11541 function salesRepQuestions(){ 11542 tempArr = []; 11543 tempArr = salesRepQuestion.answers.split('|'); 11544 11545 tempArr.forEach(function (item, index) { 11546 tempArr[index] = { 11547 text: item.split('~')[0], 11548 value: item.split('~')[1], 11549 id: index 11550 } 11551 }); 11552 return tempArr; 11553 } 11554 self.salesRepOptions = ko.observableArray(salesRepQuestions()); 11555 11556 self.salesRepValue.subscribe(function(sSelectedVal){ 11557 $.ajax({
11558 url: "?ajax=setSalesRepCode&o_key=" + viewModel.orderKey() + "&modal=1&key=" + viewModel.accountId() + "&value=" + sSelectedVal, 11559 type: 'POST', 11560 dataType: 'json', 11561 beforeSend: function() { 11562 viewModel.processing(true) 11563 }, 11564 error: function(e) { 11565 viewModel.processing(false); 11566 alert("ERROR, Failed to set How Hear Answer.: " + e); 11567 }, 11568 success: function (oData) { 11569 viewModel.processing(false); 11570 } 11571 }); 11572 }); 11573 11574 11575 } 11576 }); 11577 11578 // Function to track remove from cart events 11579 function trackRemoveFromCart(productData) { 11580 if (typeof dataLayer !== 'undefined' && productData) { 11581 // Clear the previous ecommerce object 11582 dataLayer.push({ ecommerce: null }); 11583 11584 // Calculate total value 11585 var totalValue = (productData.price || 0) * (productData.quantity || 1); 11586 11587 // Push the remove from cart event 11588 dataLayer.push({ 11589 event: "EEremoveFromCart", 11590 ecommerce: { 11591 order_id: productData.order_id || "", 11592 currency: "USD", 11593 value: totalValue, 11594 coupon: productData.coupon || "", 11595 items: [ 11596 { 11597 item_id: productData.sku || "", 11598 item_name: productData.name || "", 11599 price: productData.price || 0, 11600 quantity: productData.quantity || 1 11601 } 11602 ] 11603 } 11604 }); 11605 } 11606 } 11607 11608 function fncConfirmRemoveHook(Row, Message, CartKey, isSVL) { 11609 var sUNQ = Row.id.slice(-32); 11610 var bUseRemoveMsg = true; 11611 var modal = ''; 11612 11613 var bRemove; 11614 if(bUseRemoveMsg) { 11615 bRemove = confirm(Message); 11616 } 11617 else { 11618 bRemove = true; 11619 } 11620 11621 if (bRemove) { 11622 // Extract product data from data attributes 11623 var productData = { 11624 order_id: Row.getAttribute('data-product-order-id') || '', 11625 sku: Row.getAttribute('data-product-sku') || '', 11626 name: Row.getAttribute('data-product-name') || '', 11627 price: parseFloat(Row.getAttribute('data-product-price')) || 0, 11628 quantity: parseInt(Row.getAttribute('data-product-quantity')) || 1, 11629 coupon: Row.getAttribute('data-product-cart-option') || '' 11630 }; 11631 11632 // Track the remove from cart event before navigating 11633 trackRemoveFromCart(productData); 11634 11635 var svlParameter = isSVL ? "&isSVL=1" : ""; 11636 var url; 11637 if (CartKey === "") { 11638 url = 'i_i_add_to_cart.asp?type=remove&unq=' + sUNQ + '&modal=' + modal + svlParameter; 11639 } else { 11640 url = 'i_i_add_to_cart.asp?type=remove&unq=' + sUNQ + '&o_id=' + CartKey + '&modal=' + modal + svlParameter; 11641 } 11642 11643 window.location = url; 11644 11645 // Return false to prevent default link behavior 11646 return false; 11647 } 11648 else { 11649 return false; 11650 } 11651 } 11652</script>
11652 11653 </body> 11654 11655</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.