{"version":3,"file":"AE.ui.min.js","sources":["AE.ui.min.js"],"sourcesContent":["var AE = AE || {}; /* Add to Base object or create it if it doesn't exist. */\n/*\nThe AE.ui object will be the returned result of a self-invoked function. This allows us to expose methods\nfor use by other modules while protecting some variables in a closure. If the AE.ui object is already\ndefined then it's not altered. This prevents us from running the entire function each time one of its\ninternal methods are called.\n*/\nAE.ui = AE.ui || (function () {\n\t/*\n\tDEPENDENCIES: AE\n\t*/\n\n\tvar UI = {\n\t\t// Like resizeTasks in AE.js, these arrays are to be filled with functions to be executed...\n\t\tbodyClickTasks: [], // Delegated Tasks Triggered On Body Click\n\t\tbodyChangeTasks: [], // Delegated Tasks Triggered On Body Change\n\t\tinit: function () {\n\t\t\tvar prepMenusearch = prepMenusearch || false;\n\t\t\t/* Establish the props object only upon init. No need to do the work if the module isn't being called. */\n\t\t\tUI.props = {\n\t\t\t\tbodyEvent: '',\n\t\t\t\tclicksDisabled: false, // If set to true, then clicks will not be registered for matrix and results elements.\n\t\t\t\t// This property will be defined as the result of an IFFE (Individually Invoked Function Expression)\n\t\t\t\tappendTarget: (function () {\n\t\t\t\t\t// Used for the main search form. Most jQuery UI widgets have a property called \"appendTo\" which controls where widgets will\n\t\t\t\t\t// exist in the DOM. If the value is null then widgets will be attached to the body. Otherwise, the widget will be attached\n\t\t\t\t\t// to whatever selector or jQuery object is defined. This is important because we've put our content on a different branch of\n\t\t\t\t\t// the DOM than dialogs occupy, so we could have dropdowns or autocomplete widgets which don't scroll when they should.\n\t\t\t\t\t//\n\t\t\t\t\t// We have three possibilities for where the main search form may appear. The main page, modify or in a dialog. The value is\n\t\t\t\t\t// initially set to null, which means that the widgets will be appended to the body.\n\t\t\t\t\t// 1. MODIFY:\t\tThis is an inline form, but it doesn't have the same parent structure as the main page. The page is checked\n\t\t\t\t\t// \t\t\t\t\tto see if the user is on the modify page and sets the variable accordingly.\n\t\t\t\t\t// 2. HOME PAGE:\tSame as above, but due to the different structure the variable is set to a different ID.\n\t\t\t\t\t// 3. IN A DIALOG:\tDialogs are not on the same branch of the DOM, to prevent them from scrolling along with site content. For\n\t\t\t\t\t// \t\t\t\t\tthis case, the variable needs to be set to null so that widgets will be appended to the body.\n\n\t\t\t\t\tvar appendTo = null; // Default, mainly used for dialogs.\n\t\t\t\t\tif ($('body').hasClass('my-booking')) {\n\t\t\t\t\t\t// Modify page\n\t\t\t\t\t\tappendTo = '#search-form';\n\t\t\t\t\t} else if (!$('#ae-search').closest('.ui-dialog')[0]) {\n\t\t\t\t\t\t// Home page\n\t\t\t\t\t\tappendTo = '#top_search_form';\n\t\t\t\t\t}\n\t\t\t\t\treturn appendTo; //( $('#ae-search').closest('.ui-dialog')[0] ) ? null : '#top_search_form'\n\t\t\t\t})(),\n\n\t\t\t\tscrollContainer: $('#scroll-content'),\n\t\t\t\t$mainFooterTogglers: $('.main-footer__header'),\n\t\t\t\t$mainFooterTogglees: $('.main-footer__links'),\n\t\t\t\t$aeSearch: $(\"#ae-search\"),\n\t\t\t\t$menusearchEnabled: prepMenusearch,\n\t\t\t\t$tabContainers: $(\".tab_container\"),\n\t\t\t\t$accordionContainers: $(\".accordion_container\"),\n\t\t\t\t$accordionCollapsedContainers: $(\".accordion_container--collapsed\"),\n\t\t\t\t$dateInputs: $('input[class=\"datePickerInput\"]'),\n\t\t\t\t$autoPostForms: $('#trg-autoPostForm'),\n\t\t\t\t$currentDatePicker: null\n\t\t\t};\n\n\t\t\tUI.searchProps = {\n\t\t\t\troundTrip: true,\n\t\t\t\tcity: null, // City name for pickup\n\t\t\t\tcityr: null, // City name for dropoff\n\t\t\t\tpuloclist: null, // List of pickup locations\n\t\t\t\tdoloclist: null, // List of dropoff locations\n\t\t\t\tpucode: null, // country ISO code for pickup.\n\t\t\t\tdocode: null, // country ISO code for dropoff.\n\t\t\t\tpuCal: null, // Pickup date\n\t\t\t\tdoCal: null, // Dropoff date\n\t\t\t\tputime: null, // Pickup hour, must be 24 hour time, 0 - 23\n\t\t\t\tdotime: null, // dropoff hour, must be 24 hour time, 0 - 23\n\t\t\t\tsearchAge: 40, // checkbox for if the driver's age is between 25 and 70\n\t\t\t\tbookingstep: 'searchwait' // Set and done. Required for back-end.\n\t\t\t\t/* Conditional Properties\n\t\t\t\t\tmodUUID: Included when search form posts from Modify Page, ColdFusion UUID\n\t\t\t\t*/\n\t\t\t};\n\n\t\t\tUI.addBodyClickTask({\n\t\t\t\tfunc: UI.onBodyClick\n\t\t\t});\n\n\t\t\t//var bodyEvent = (AE.getSiteViewType() === 'palm' && $('html').hasClass('ua-ios')) ? 'click, touchend' : 'click';\n\t\t\t$('body').on('click', function (event) {\n\t\t\t\tUI.manageBodyClick(event);\n\t\t\t});\n\t\t\t//$('body').on('touchend', function(event){UI.manageBodyClick(event)});\n\n\t\t\t$('body').on('change', function (event) {\n\t\t\t\tUI.manageBodyChange(event)\n\t\t\t});\n\t\t\tUI.applyJQUI();\n\n\t\t\t// iOS patch for related links,\n\t\t\t// real solution would be to move\n\t\t\t// bodyevent from manage resize to props\n\t\t\tif ($('html').hasClass('ua-ios')) {\n\t\t\t\t$('body').on('touchend', function (event) {\n\t\t\t\t\tif ($(event.target).parent().hasClass('related__links')) {\n\t\t\t\t\t\tUI.manageBodyClick(event);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t/* Set padding-top to <5px to workaround WEBAE3-4259\n\t\t\t* This will cause jquery-ui _hasScroll() to return false to jquery-ui _scrollIntoView()\n\t\t\t* avoiding an uncaught exception inside the latter where the passed element is empty. \n\t\t\t\n\t\t\tWEBAE3-5178 - changed padding below from 4px to 2px and it seems to fix sporadic\n\t\t\tissue that breaks text inputs\n\t\t\t\n\t\t\t*/\n\t\t\tvar fractionalScrollHeightStyle = document.createElement('style');\n\t\t\tif (AE.props.siteCode == 'FCR') {\n\t\t\t\tfractionalScrollHeightStyle.appendChild( document.createTextNode('#ui-id-147,#ui-id-150{padding-top:2px!important}') );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfractionalScrollHeightStyle.appendChild( document.createTextNode('#ui-id-99,#ui-id-102{padding-top:2px!important}') );\n\t\t\t}\n\t\t\tdocument.head.appendChild(fractionalScrollHeightStyle);\n\n\t\t\n\t\t\t$('a').filter(function () {\n\t\t\t\t// Checking for external links and adding rel=\"noopener\" - Because we can't train marketing how to SEO good\n\t\t\t\tvar $a = $(this);\n\t\t\t\tvar _href = $a.attr('href') || false;\n\t\t\t\tvar _host = this.hostname || false;\n\t\t\t\n\t\t\t\t// test script to remove the no opener rel tag\n\t\t\t\tvar _langTag = $a.attr('hreflang');\n\t\t\t\tvar _href = $a.attr('href') || false;\n\t\t\t\n\t\t\t\tif (_langTag === 'zh-CN' || _langTag === 'tr-TR') {\n\t\t\t\t\t_href = false;\n\t\t\t\t}\n\n\t\t\t\tvar _location = (typeof (location) != 'undefined') ? location.hostname : false;\n\t\t\t\tvar _hrefStr = _href ? $a.attr('href').substring(0, 4) : _href;\n\t\t\t\n\t\t\t\tif (_host && _location && (_host === _location)) {\n\t\t\t\t\t_hrefStr = false;\n\t\t\t\t}\n\t\t\t\tif (_host && _location && (_host.substring(0, 3) === _location.substring(0, 3))) {\n\t\t\t\t\t_hrefStr = false;\n\t\t\t\t}\n\t\t\t\treturn (_hrefStr === 'http') ? this.hostname && this.hostname !== location.hostname : false;\n\t\t\t}).addClass(\"external\").attr({\n\t\t\t\trel: 'noopener'\n\t\t\t});\n\t\t\n\t\t\t// Manage resize\n\t\t\tAE.addResizeTask({\n\t\t\t\tfunc: function () {\n\t\t\t\t\tUI.manageResize();\n\t\t\t\t},\n\t\t\t\targs: []\n\t\t\t});\n\n\t\t\t// scroll task-Back to top-WEBAE3-3319\n\t\t\tAE.addScrollTask({\n \t\t\t\tfunc: function () {\t \t\t\t\t\t\n \t\t\t\t\tvar elm = document.getElementById(\"scroll_target\");\n \t\t\t\t\tvar distanceFromTop = elm.getBoundingClientRect().top; \n \t\t\t\t\tvar targetDistance = -1200; \n \t\t\t\t\tvar $b2t = $('#back2top'); \t\t\t\t\n\t\t\t\t\tif(distanceFromTop < targetDistance){\n \t\t\t\t\t$b2t.removeClass('visuallyhidden');\n \t\t\t\t}else{\n \t\t\t\t\t$b2t.addClass('visuallyhidden');\n \t\t\t\t} \t\t\t\t\n \t\t\t\t}\n \t\t\t});\n\t\t\n\t\t\t// Initiate UI modules, if they exist\n\t\t\tif (AE.ui.search && $(\"#ae-search\")[0]) {\n\t\t\t\tAE.ui.search.init();\n\t\t\t} else {\n\t\t\t\t$.each($('select.time--select'), function () {\n\t\t\t\t\t$(this).parent('.styled--select').removeClass('ui-searchform--custom-form-el ui-timeselect-rev ui-ready-waiting');\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (AE.ui.searchType && $(\"#ae-search\")[0]) {\n\t\t\t\tAE.ui.searchType.init();\n\t\t\t}\n\t\t\tif (AE.ui.dialog) {\n\t\t\t\tAE.ui.dialog.init();\n\t\t\t}\n\t\t\t/*\n\t\t\t * Timeselect and datepicker inits are now in AE.ui.searchType's init function\n\t\t\t *\n\t\t\t * if (AE.ui.timeselectmenu) { AE.ui.timeselectmenu.init(); }\n\t\t\t * if (AE.ui.datepicker) { AE.ui.datepicker.init(); }\n\t\t\t */\n\t\t\tif (AE.ui.modify && $('#aemodify')[0]) {\n\t\t\t\tAE.ui.modify.init();\n\t\t\t}\n\t\t\tif (AE.ui.tabcordion) {\n\t\t\t\tAE.ui.tabcordion.init();\n\t\t\t}\n\t\t\tif (AE.ui.carousel) {\n\t\t\t\tAE.ui.carousel.init();\n\t\t\t}\n\t\t\tif (AE.ui.selectmenu) {\n\t\t\t\tAE.ui.selectmenu.init();\n\t\t\t}\n\t\t\tif (AE.affiliate) {\n\t\t\t\tAE.affiliate.init();\n\t\t\t}\n\t\t\tif (AE.affiliate.terms) {\n\t\t\t\tAE.affiliate.terms.init();\n\t\t\t}\n\n\t\t\t// CAROUSEL FOR RAU/RNZ HERO CARDS\n\t\t\tvar slide = document.getElementsByClassName(\"hero_-slide\");// WEBAE3-3645 - disable test\n\n\t\t\tif(slide.length !== 0) {\n\t\t\t\tvar heroCardIndex = 0;\n\t\t\t\tfunction carousel() {\n\t\t\t\t\tvar i;\n\t\t\t\t\tslide[0].style.display = \"block\";\n\t\t\t\t\tfor (i = 0; i < slide.length; i++) {\n\t\t\t\t\t\tslide[i].style.display = \"none\";\n\t\t\t\t\t}\n\t\t\t\t\theroCardIndex++;\n\t\t\t\t\tif (heroCardIndex > slide.length) {heroCardIndex = 1}\n\t\t\t\t\t$(slide[heroCardIndex-1]).css('opacity', 1)\n\t\t\t\t\t\t\t\t.show('slide', {direction: 'right'}, 1500)\n\t\t\t\t\t\t\t\t.animate(\n\t\t\t\t\t\t\t\t\t{ opacity: 1 },\n\t\t\t\t\t\t\t\t\t{ queue: false, duration: 2000 }\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\tsetTimeout(carousel, 7000); // Change hero card every 7 seconds\n\t\t\t\t}\n\t\t\t\tcarousel();\n\t\t\t}\n\t\t},\n\t\tdisableClicks: function () {\n\t\t\tUI.props.clicksDisabled = true;\n\t\t},\n\t\tenableClicks: function () {\n\t\t\tUI.props.clicksDisabled = false;\n\t\t},\n\t\tmanageResize: function () {\n\t\t\tvar siteViewType = AE.getSiteViewType();\n\n\t\t\t// Changing the target event for body clicks, changing to touchend when using a mobile device.\n\t\t\tUI.props.bodyEvent = ($('html').hasClass('ua-mobile')) ? 'touchend' : 'click';\n\n\t\t\t/*\n\t\t\tNOTE: The $mainFooterTogglees start with the \"visuallyhidden\" class so they don't flash into view upon palm-sized page load. This is\n\t\t\tsorted out by the initial run of manageResize() so they will be properly visible on a desk-sized page load.\n\n\t\t\t* Added check if toggle was already open on resize to leave it at it's current state.\n\t\t\t*/\n\t\t\t$('.hasDatepicker')\n\t\t\t\t.datepicker('hide')\n\t\t\t\t.on('click', function () {\n\t\t\t\t\t$(this).datepicker('show')\n\t\t\t\t});\n\n\t\t\t/* Mobile toggles only work at lap and down sizes. */\n\t\t\t$('.toggler.toggler--portable')\n\t\t\t\t.each(function (index) {\n\t\t\t\t\tvar $togglee = $(this)\n\t\t\t\t\t\t.closest('.toggle')\n\t\t\t\t\t\t.find('.togglee');\n\n\t\t\t\t\tif (siteViewType === 'desk' || siteViewType === 'desk-wide') {\n\t\t\t\t\t\t$(this).addClass('open');\n\t\t\t\t\t\tUI.show($togglee);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(this).removeClass('open');\n\t\t\t\t\t\tUI.hide($togglee);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t/* Palm-only toggles only work at palm size, so they need to be closed initially. */\n\t\t\t$('.toggler.toggler--palm')\n\t\t\t\t.each(function (index) {\n\t\t\t\t\tvar $togglee = $('' + $(this).data('togglee') + '');\n\n\t\t\t\t\t// Insurance options Shenanigans with Plus and Minus state, different than other toggles\n\t\t\t\t\tvar insurance = ($(this).closest('#insuranceUI').length) ? true : false;\n\t\t\t\t\tvar pmOptionsStop = ($(this).hasClass('open') && !$togglee.hasClass('visuallyhidden')) ? false : true;\n\n\t\t\t\t\tif (siteViewType === 'palm') {\n\t\t\t\t\t\tif (insurance) {\n\t\t\t\t\t\t\tif (pmOptionsStop) {\n\t\t\t\t\t\t\t\thideToggle($(this), $togglee);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thideToggle($(this), $togglee);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!pmOptionsStop) {\n\t\t\t\t\t\t\t$(this).addClass('open');\n\t\t\t\t\t\t\tUI.show($togglee);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (insurance) {\n\t\t\t\t\t\t\tif (!pmOptionsStop) {\n\t\t\t\t\t\t\t\tshowToggle($(this), $togglee);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tshowToggle($(this), $togglee);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction hideToggle($toggler, $togglee) {\n\t\t\t\t\t\t$toggler.removeClass('open');\n\t\t\t\t\t\tUI.hide($togglee);\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction showToggle($toggler, $togglee) {\n\t\t\t\t\t\t$toggler.addClass('open');\n\t\t\t\t\t\tUI.show($togglee);\n\t\t\t\t\t}\n\n\t\t\t\t});\n\n\t\t\t/* Toggles for larger sizes don't work at this size, so they need to be opened. */\n\t\t\t$('.toggler.toggler--lap-and-up').each(function (index) {\n\t\t\t\tvar $togglee = $(this).closest('.toggle').find('.togglee');\n\n\t\t\t\t/* Open non-palm toggles upon resize in palm view. */\n\t\t\t\tif (siteViewType === 'palm') {\n\t\t\t\t\t$(this).addClass('open');\n\t\t\t\t\tUI.show($togglee);\n\t\t\t\t} else {\n\t\t\t\t\t$(this).removeClass('open');\n\t\t\t\t\tUI.hide($togglee);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t/*\n\t\t\t\tTogglees that need to be open and delay befor then closing.\n\t\t\t\tNOTE: Need to add data size on togglee to target delay by type or all\n\t\t\t*/\n\t\t\t$('.togglee--delay-close').each(function (index) {\n\t\t\t\tvar $togglee = $(this);\n\t\t\t\tvar deviceSize = ($togglee.data('size') !== undefined) ? $togglee.data('size') : '';\n\t\t\t\tvar palm = ($togglee.hasClass('delay--palm')) ? 'palm' : '';\n\t\t\t\tvar lap = ($togglee.hasClass('delay--lap')) ? 'lap' : '';\n\t\t\t\tvar desk = ($togglee.hasClass('delay--desk')) ? 'desk' : '';\n\n\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t_.each([palm, lap, desk], function (device) {\n\t\t\t\t\t\tif (AE.getSiteViewType() === device) {\n\t\t\t\t\t\t\tvar passSize = (deviceSize !== '') ? '--' + device : '';\n\t\t\t\t\t\t\tUI.hide($togglee, passSize);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}, 2000);\n\t\t\t});\n\t\t},\n\t\tonBodyClick: function (event, $target) {\n\n\t\t\t// Add scroll to top of this id selector\n\t\t\tif($target.hasClass('btn--back2top') || $($target.parent()).hasClass('btn--back2top')){\t\t\t\t\t\n \t\t\t\tdocument.getElementById('sticky-wrapper').scrollIntoView();\t\t\n \t\t\t}\n\n\t\t\t/* HANDLE TOGGLES:\n\t\t\t\tA container with a class of \".toggle\" contains a \".toggler\" and a \"togglee\". They don't have\n\t\t\t\tto be siblings. They can be in grids and other containers, so long as they can track upward to the same parent.\n\t\t\t\t\n\t\t\t\tFor manual toggles, use both classes: \"toggler\" and \"toggler--manual\". The toggler class will apply the proper\n\t\t\t\tCSS to the element, and the toggler--manual class will prevent it from functioning automatically.\n\t\t\t\t\n\t\t\t\tManual toggles require specific code to run the handleToggle() function, but they can add a callback function.\n\t\t\t\tSend in a jQuery collection of your toggler, the name of your function and an array of arguments.\n\t\t\t\t\n\t\t\t\tExample: AE.ui.handleToggle( $myToggler, myFunctionName, [arg1, arg2, arg3] );\n\t\t\t*/\n\t\t\tif ($target.hasClass('toggler') && !$target.hasClass('toggler--manual')) {\n\t\t\t\tUI.handleToggle($target);\n\t\t\t}else if($target.prop('tagName') !== 'INPUT' && !$target.hasClass('grid__item-ta-modifier')){// WEBAE3-3866 - don't run closeToggle when user clicks an input to start entering values - LJW\n\t\t\t\tvar $target = $(event.target);// now it's a jQuery object\n\t\t\t\tvar $toggleeContainer = $target.closest('.matrix_filter');\n\t\t\t\tvar $taModChildren = $target.find('.grid__item-ta-modifier');\n var checkout_process = $('body#options').length || $('body#upgrade').length|| $('body#checkout').length == 0;\n\t\t\t\tif($toggleeContainer.length == 0 && $taModChildren.length == 0 && !checkout_process) {\n\t\t\t\t\tUI.closeToggle();\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// Test environment for staging and production - QA1, QA2, QA3, QA4, and PTEST\n\t\t\tif ($target.hasClass('test_environment')) {\n\t\t\t\tAECookie.update('PTEST', 'no', 0); //remove the ptest cookie\n\t\t\t\tvar qaCookie = (AECookie.read('QA')) ? '?QA=false' : '';\n\t\t\t\twindow.location.href = '/'+qaCookie; //reset the stage/test environment back to the base\n\t\t\t}\n\t\t\t\n\t\t\t// ENABLER ELEMENT - toggle disabled property of a selected element\n\t\t\tif ($target.hasClass('trg__enabler') && $target.data('enablee')) {\n\t\t\t\tif ($target.hasClass('enabler--on')) {\n\t\t\t\t\t$($target.data('enablee')).prop('disabled', true);\n\t\t\t\t\t$target.removeClass('enabler--on');\n\t\t\t\t} else {\n\t\t\t\t\t$($target.data('enablee')).prop('disabled', false);\n\t\t\t\t\t$target.addClass('enabler--on');\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// Matrix Results, Utility bar, Modify & Optional Eq - More Info Tips\n\t\t\tif ($target.hasClass('more-info-tip')) {\n\t\t\t\t//WEBAE-4574 catch cancel modal triggers\n\t\t\t\tif ($target.attr('data-modalname')==\"cancelModal\"){\n\t\t\t\t\tAE.booking.cancelModal();\n\t\t\t\t\n\t\t\t\t}else{\n\t\t\t\tAE.ui.dialog.launch({\n\t\t\t\t\ttype: 'infoTip',\n\t\t\t\t\tpos: {\n\t\t\t\t\t\tmy: 'left top',\n\t\t\t\t\t\tat: 'left bottom+5',\n\t\t\t\t\t\tof: $target\n\t\t\t\t\t},\n\t\t\t\t\tselector: $target.children('.more-info-text')\n\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\n\t\t\t}\n\n\t\t\t// For pages which aren't part of the buyback or luxury portions of the booking system, we're going to have a special\n\t\t\t// link for \"iCommunicator Voice Over IP\". This is only shown on desktop, and opens a pop-up window.\n\t\t\tif ($target.hasClass('voip-link')) {\n\t\t\t\tAE.ga.gaArrayProcess([{\n\t\t\t\t\tGACATEGORY: 'VOIP',\n\t\t\t\t\tGAACTION: 'click'\n\t\t\t\t}]);\n\t\t\t\tvar clientID = $target.data('voipcode');\n\t\t\t\t\n\t\t\t\tif ($target.hasClass('icomm_direct') || (clientID == '8fb2338n0n5w2bj7' || clientID == 'ecz610fox8q57dgn' || clientID == 'o3lwm3e04730w06o')) {\n\t\t\t\t\twindow.open(\"http://client.icommconnect.com/Home/DirectCall?contactGuid=\" + clientID + \"\", \"\", \"scrollbars=yes,width=360, height=640\");\n\t\t\t\t} else {\n\t\t\t\t\t// hasClass 'icomm_directory'\n\t\t\t\t\twindow.open(\"http://client.icommconnect.com/Home/Call?clientSubscriptionGUId=\" + clientID + \"\", \"\", \"scrollbars=yes,width=360, height=640\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// 8x8 co-browsing\n\t\t\tif ($target.hasClass('co_browse_site')) {\n\t\t\t\treturn UI.call8x8CoBrowsing(event);\n\t\t\t}\n\t\t},\n\t\tmanageBodyClick: function (event) {\n\t\t\t/* Cycle through Body Click tasks */\n\t\t\tif (UI.props.clicksDisabled) {\n\t\t\t\treturn\n\t\t\t};\n\t\t\t// This module listens to 'click' and 'touchend' events to run this function. To prevent it from firing\n\t\t\t// twice, we keep a string in the props object to indicate which one to use. The event.type string in\n\t\t\t// the event object must match this module prop string in order to go forward. For example, if a tablet\n\t\t\t// registers both events, then the 'click' will cause this function to return, while the 'touchent' call\n\t\t\t// will run this function normally.\n\t\t\t//\n\t\t\t// This is important in case some brand of tablets decides to abandon click in favor of touchend. Since\n\t\t\t// the bodyEvent property initializes as an empty string, this line will also prevent toggles from working\n\t\t\t// until the property is populated by the name of the appropriate event.\n\t\t\t//if(event.type !== UI.props.bodyEvent) { return; }\n\n\t\t\tvar $target = $(event.target);\n\n\t\t\t// Run through all of the registered body click tasks in our codebase.\n\t\t\tfor (var i = 0; i < UI.bodyClickTasks.length; i++) {\n\t\t\t\t// Even if no arguments were passed in, the args array was still established as an empty array when\n\t\t\t\t// the task is added to the array. The first two arguments will be the event and target, with other\n\t\t\t\t// arguments following after. A new array is made with each loop iteration so that previous arguments\n\t\t\t\t// cannot carry over into subsequent iterations.\n\t\t\t\tvar arrArgs = [event, $target].concat(UI.bodyClickTasks[i].args);\n\n\t\t\t\t// Using the apply method, we'll pass in \"this\" from the perspective of this function, using the\n\t\t\t\t// arguments from the task object. So if you were to establish some sort of property like \"this.thing\"\n\t\t\t\t// then every bodyClick function in every module would have access to this.thing. We don't really do\n\t\t\t\t// that, however. Most of these functions simply require the event object and the first thing they\n\t\t\t\t// want to do is establish a jQuery collection of the event target. To save lines, we do this here\n\t\t\t\t// and pass it in.\n\t\t\t\tUI.bodyClickTasks[i].func.apply(this, arrArgs);\n\t\t\t};\n\t\t},\n\t\taddBodyClickTask: function (task) {\n\t\t\t/*\n\t\t\tAdds an object with a func property that is function taking the\n\t\t\tevent object as its ONLY argument to an array of functions.\n\t\t\tOn a body change event, these functions will be executed using\n\t\t\tthe apply() method in manageBodyClick() to pass in the correct target on each event.\n\n\t\t\tEach 'task' should start by performing logic on the event target to determine whether it should run.\n\n\t\t\tAE.ui.addBodyClickTask(\n\t\t\t\t{\n\t\t\t\tfunc:function(event){\n\t\t\t\t\tif(event meets criteria){\n\t\t\t\t\tdo stuff\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\t*/\n\n\t\t\t// Make sure that the args array is an array if it wasn't defined.\n\t\t\ttask.args = task.args || [];\n\t\t\tUI.bodyClickTasks.push(task);\n\t\t},\n\t\tmanageBodyChange: function (event) {\n\t\t\t/* Cycle through Body Change tasks */\n\t\t\t// Explanations for this code are documented above in body click management\n\t\t\tvar $target = $(event.target);\n\t\t\tfor (var i = 0; i < UI.bodyChangeTasks.length; i++) {\n\t\t\t\tvar arrArgs = [event, $target].concat(UI.bodyChangeTasks[i].args);\n\t\t\t\tUI.bodyChangeTasks[i].func.apply(this, arrArgs);\n\t\t\t};\n\t\t},\n\t\taddBodyChangeTask: function (task) {\n\t\t\t/*\n\t\t\tAdds an object with a func property that is function taking the\n\t\t\tevent object as its ONLY argument to an array of functions.\n\t\t\tOn a body change event, these functions will be executed using\n\t\t\tthe apply() method in manageBodyChange() to pass in the correct target on each event.\n\n\t\t\tEach 'task' should start by performing logic on the event target to determine whether it should run.\n\n\t\t\tAE.ui.addBodyChangeTask(\n\t\t\t\t{\n\t\t\t\tfunc:function(event){\n\t\t\t\t\tif(event meets criteria){\n\t\t\t\t\tdo stuff\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\t*/\n\t\t\ttask.args = task.args || [];\n\t\t\tUI.bodyChangeTasks.push(task);\n\t\t},\n\t\taddSpinner: function (selector, settings) {\n\t\t\t/*\n\t\t\tTurns an element into a relatively-positioned container for a spinner element, then adds the spinner. FontAwesome\n\t\t\tis used for the spinner itself, and it's rotated with CSS.\n\n\t\t\tExample call: AE.ui.addSpinner('.my-selector', { size:'5x', color: 'white' });\n\t\t\tThe size can be any size provided by FontAwesome. A value of '5x' results in a class of \"fa-5x\". The color can be\n\t\t\tthe default gray, white or black. Hex values may not be passed in because we don't want every developer to use a\n\t\t\tdifferent color every time. Three colors is plenty.\n\t\t\t*/\n\t\t\tvar $target = $(selector);\n\t\t\tsettings = settings || {};\n\t\t\tvar sizeClass = settings.size ? ' fa-ae-' + settings.size : '';\n\n\t\t\t/* If a color setting is passed in, white or black is used instead of relying upon the default gray in the CSS. */\n\n\t\t\t$target\n\t\t\t\t.addClass('spinner__container')\n\t\t\t\t.find('.spinner__div').parent()\n\t\t\t\t.remove()\n\t\t\t\t.end();\n\n\n\t\t\tif(AE.props.siteCode !== 'FCR') {\n\t\t\t\t$target.append('