if (!drs) { var drs = {}; drs.scriptName = "suite.js"; drs.script = null; drs.modal = null; drs.veil = null; drs.modalFrame = null; drs.baseSuiteURL = null; drs.baseApiURL = null; drs.basePageURL = null; drs.paymentWidgetServiceURL = null; drs.paymentResourceServiceURL = null; drs.mobileTargetLocation = null; drs.modalTimer = null; drs.widgetCount = 0; drs.embedFrames = null; drs.inited = false; drs.handlingScroll = false; drs.modalHeight = 0; drs.se = null; drs.paymentStyles = null; drs.paymentUI = null; drs.paymentUIRequest = null; drs.paymentWidgets = []; drs.paymentWidgetsRequested = 0; drs.batchPayments = {} drs.batchPaymentsSize = 0; drs.leaseHelpById = {}; drs.financeHelpById = {}; drs.vindex = navigator.userAgent.indexOf("MSIE"); // In compatibility mode, ie 8+ can show as older but Trident only shows on 8+ browsers. // The edge meta tag will assure ie uses the right engine to actually run suite. drs.supported = drs.vindex == -1 || navigator.userAgent.charAt(drs.vindex + 5) >= 8 || navigator.userAgent.indexOf("Trident") != -1; drs.PAYMENT = "p"; drs.SMALL_PAYMENT = "s"; drs.CUSTOM_BUTTON = "c"; drs.EMBED = "e"; drs.INHERIT = "inherit"; drs.DEPENDANT = "dependant"; drs.DYNAMIC = "dynamic"; drs.DEFAULT_PAYMENT_DETAIL_TOKEN = "#PaymentDetailsPlace:0:0"; drs.DEFAULT_BATCHED_SIZE = 5; drs.getQueryAttribute = function(attributeName, queryString) { var name = attributeName.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"); var results = regex.exec(queryString); return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, " ")); }; drs.getMaxBatchSize = function() { var result = parseInt(drs.getQueryAttribute("batchSize", location.search)); return isNaN(result) ? drs.DEFAULT_BATCHED_SIZE : result; }; drs.CANNED_IDENTIFIER = drs.getQueryAttribute("Canned-Identifier", location.search); drs.USE_CANNED_DATA = drs.getQueryAttribute("Canned-Data", location.search); drs.DATA_TYPE_INTEGER = "Integer"; drs.DATA_TYPE_DOUBLE = "Double"; drs.DATA_TYPE_BOOLEAN = "Boolean"; drs.DATA_TYPE_STRING = "String"; drs.DATA_TYPE_FINANCE_TYPE = "FinanceType"; drs.DATA_TYPE_VEHICLE_TYPE = "VehicleType"; drs.DATA_TYPE_PRICE = "Price"; drs.FINANCE_TYPE_LOAN = "LOAN"; drs.FINANCE_TYPE_LEASE = "LEASE"; drs.VEHICLE_TYPE_NEW = "NEW"; drs.VEHICLE_TYPE_USED = "USED"; drs.VEHICLE_TYPE_CERTIFIED = "CERTIFIED"; drs.VEHICLE_TYPE_DEMO = "DEMO"; drs.VEHICLE_TYPE_STRING = "type"; drs.VEHICLE_TYPE_BOOLEAN = "used"; drs.PRICE_LOAN = "price"; drs.PRICE_LEASE = "leasePrice"; drs.JSON_BATCH_PARAMETERS = { "accountId" : drs.DATA_TYPE_INTEGER, "dealerId" : drs.DATA_TYPE_STRING, "zip" : drs.DATA_TYPE_STRING, "financeType" : drs.DATA_TYPE_FINANCE_TYPE, "price" : drs.DATA_TYPE_PRICE, "msrp" : drs.DATA_TYPE_DOUBLE, "vehicleType" : drs.DATA_TYPE_VEHICLE_TYPE, "mileage" : drs.DATA_TYPE_INTEGER, "transmission" : drs.DATA_TYPE_STRING, "year" : drs.DATA_TYPE_INTEGER, "make" : drs.DATA_TYPE_STRING, "model" : drs.DATA_TYPE_STRING, "style" : drs.DATA_TYPE_STRING, "vin" : drs.DATA_TYPE_STRING, "styleId" : drs.DATA_TYPE_INTEGER, "kiaModelId" : drs.DATA_TYPE_STRING, "volvoModelId" : drs.DATA_TYPE_STRING, "modelRefresh" : drs.DATA_TYPE_BOOLEAN, "oemName" : drs.DATA_TYPE_STRING, "oemModelCode" : drs.DATA_TYPE_STRING }; drs.MAX_BATCHED_REQUESTS = drs.getMaxBatchSize(); drs.REQUEST_STATUS_FINISHED = 4; drs.HTTP_STATUS_OK = 200; drs.MIN_HEIGHT = 500; drs.MIN_WIDTH = 300; drs.MAX_WIDTH = 1200; drs.MAX_100PCT_WIDTH = 570; drs.PAYMENT_MIN_WIDTH = "225px"; drs.SMALL_PAYMENT_MIN_WIDTH = "130px"; drs.THIN_MAX_WIDTH = 550; drs.isMobile = false; var ua = window.navigator.userAgent.toLowerCase(); if (ua.indexOf('android') != -1 || (ua.indexOf('iphone') != -1 && ua.indexOf('ipad') == -1) || ua.indexOf('ipod') != -1 || ua.indexOf('blackberry') != -1) { drs.isMobile = true; } drs.isIpad = false; if (ua.indexOf('ipad') != -1) { drs.isIpad = true; } /* Get the att off the given el or the script if it's not on the el. */ drs.getAtt = function (el, key, ignoreDefault) { var v = el.getAttribute(key); if (v && v.length > 0) { return v; } else if (!ignoreDefault) { v = drs.script.getAttribute(key); if (v && v.length > 0) { return v; } else { return null; } } else { return null; } }; drs.getInt = function (s) { return s == null ? 0 : parseInt(s); }; drs.getEmbedHeight = function (suiteEl, embedParent) { return embedParent.clientHeight - drs.getInt(drs.getAtt(suiteEl, "widgetMarginT")) - drs.getInt(drs.getAtt(suiteEl, "widgetMarginB")); }; drs.init = function () { if (drs.inited) return; var scripts = document.getElementsByTagName("script"); for (var i = 0; i < scripts.length; i++) { var src = scripts[i].getAttribute("src"); if (src != null && src.substring(src.length - drs.scriptName.length) == drs.scriptName) { drs.script = scripts[i]; drs.processScript(scripts[i]); break; } } if (drs.supported) { if(drs.isMobile || drs.isIpad) drs.setMobileTargetLocation(); drs.addEventListener(window, "message", drs.receiveMessage); drs.addEventListener(window, "resize", drs.sizeAndPositionModal); drs.addEventListener(window, "resize", drs.autoAdjustWidth); } drs.inited = true; }; drs.givenOrDefault = function (given, def) { return given == 0 ? def : given; }; drs.buttonClicked = function (event) { if (!drs.supported) { alert("Your browser is not supported."); return; } drs.openSuite(drs.getEventSrc(event, true), drs.nextEmbedId()); }; drs.buildURL = function (suiteEl, embedId, isModal) { var url = drs.basePageURL + "?embedId=" + embedId; var suiteQS = drs.getSuiteQueryString(suiteEl); var hashIndex = suiteQS.indexOf('#'); var placeToken = ""; if (hashIndex >= 0) { placeToken = suiteQS.substring(hashIndex); suiteQS = suiteQS.substring(0, hashIndex); } url += "&" + suiteQS; if (isModal) url += "&modal=true"; if (!drs.isDynamicHeight(suiteEl)) url += "&fixedHeight"; var widget = drs.getWidget(suiteEl, false); if (widget != null && widget == drs.EMBED) { url += "&embedded" } if (drs.isPaymentWidget(widget)) { url += drs.DEFAULT_PAYMENT_DETAIL_TOKEN; } else { url += placeToken; } return url; }; drs.isPaymentWidget = function(widget) { return widget != null && (widget == drs.PAYMENT || widget == drs.SMALL_PAYMENT); }; drs.isDynamicHeight = function (suiteEl) { var heightPolicy = drs.getAtt(suiteEl, "heightPolicy", false); return heightPolicy == null || heightPolicy == drs.DYNAMIC; }; drs.getWidget = function (suiteEl, isScript) { var widget = drs.getAtt(suiteEl, "widget", false); if (widget != null) { switch (widget.charAt(0)) { case 'p' : widget = drs.PAYMENT; break; case 's' : widget = drs.SMALL_PAYMENT; break; case 'c' : widget = drs.CUSTOM_BUTTON; break; case 'e' : widget = drs.EMBED; } // Old impls wouldn't specify widget on a button el. Neither would embed scripts. } else if (isScript) { widget = drs.EMBED; } else { widget = drs.CUSTOM_BUTTON; } return widget; }; drs.nextEmbedId = function () { return "drsw" + drs.widgetCount++; }; /* Reset any fields that would otherwise pile up on subsequent calls to processSuiteElements. */ drs.reset = function () { drs.embedFrames = null; }; drs.processSuiteElements = function (node) { var c = node.childNodes; for (var i = 0; i < c.length; i++) { if (c[i].attributes != null && c[i].attributes.getNamedItem("suiteQueryString") != null) { drs.se = c[i]; if (drs.processSuiteElement(c[i])) { // The suite el was inserted before c[i], making that c[i] now the next one in the list. // Avoid an infinite loop. i++; } } else if (c[i].childNodes != null) { drs.processSuiteElements(c[i]); } } }; drs.applyTransitionDelay = function (el) { el.style.transition = "height .5s"; el.style.WebkitTransition = "height .5s"; el.style.MozTransition = "height .5s"; }; drs.verifyLoad = function (event) { var src = drs.getEventSrc(event, false); if ((event.currentTarget ? src.contentDocument : src.document).title.indexOf("Error report") != -1) { src.style.display = 'none'; } }; drs.processScript = function (suiteEl) { drs.setBaseUrls(); drs.basePageURL = drs.baseSuiteURL + "/index.html"; drs.paymentWidgetServiceURL = drs.baseApiURL + "/payments"; drs.paymentResourceServiceURL = drs.baseSuiteURL + "/rest/resource/payments"; drs.processCreditCallback( suiteEl ); drs.processSuiteElements(document.getElementsByTagName("body")[0]); }; drs.processCreditCallback = function ( suiteEl ) { var creditappCallback = drs.getAtt( suiteEl, "onCreditappComplete" ); if ( creditappCallback ) { drs.onCreditappComplete = window[creditappCallback]; } } /* Return true if the suiteEl was a script and the suite was inserted in the dom as a sibling before it. */ drs.processSuiteElement = function (suiteEl) { var isScript = suiteEl.tagName.toUpperCase() == "SCRIPT"; var widget = drs.getWidget(suiteEl, isScript); if (widget == drs.CUSTOM_BUTTON) { drs.addEventListener(suiteEl, "click", drs.buttonClicked); } else { // Don't load widgets for unsupported browsers. if (widget != drs.EMBED && !drs.supported) { return false; } var parent = isScript ? suiteEl.parentNode : suiteEl; var embedId = drs.nextEmbedId(); var src = drs.buildURL(suiteEl, embedId, false); var isPaymentWidget = drs.isPaymentWidget(widget); if (isPaymentWidget) { drs.buildPaymentWidget(embedId, widget, parent, suiteEl, isScript); } else { drs.buildEmbeddedFrame(embedId, widget, parent, src, suiteEl, isScript); } return isScript; } return false; }; drs.buildPaymentWidget = function(embedId, widget, parent, suiteEl, isScript) { var container = document.createElement("div"); container.setAttribute("id", embedId); container.setAttribute("widget", widget); container.setAttribute("suiteQueryString", drs.getSuiteQueryString(suiteEl)); //Store reference to this container to assign template to when it is loaded. drs.paymentWidgets[drs.paymentWidgets.length] = container; //Payment widget does not use a frame, so we pass suiteEl as frame argument since it is same thing. drs.injectSuiteNode(parent, suiteEl, container, isScript); if (drs.paymentUI == null) { //We don't want more than one of these requests and we don't want to lose track of any current request callback. if (drs.paymentUIRequest == null) { drs.paymentUIRequest = new XMLHttpRequest(); var uiUrl = drs.paymentResourceServiceURL + "/theme?widgetWidth=" + drs.getPaymentWidgetWidth(container, widget) + "&" + drs.getSuiteQueryString(suiteEl); drs.paymentUIRequest.onreadystatechange = function() { if (drs.paymentUIRequest.readyState == drs.REQUEST_STATUS_FINISHED) { if (drs.paymentUIRequest.status == drs.HTTP_STATUS_OK) { var response = JSON.parse(drs.paymentUIRequest.responseText); drs.getPaymentUiSuccess(response); } else { // TODO: This will not work as we don't have the call form payments from the UI. drs.setCallForPmts(embedId); } } } drs.paymentUIRequest.open("GET", uiUrl); drs.paymentUIRequest.setRequestHeader("Accept", "application/json"); drs.paymentUIRequest.send(); } } else { //If we already have UI, then just inject it into the container. drs.initializePaymentWidgetUI(container); } }; drs.getPaymentUiSuccess = function(response) { drs.parseAndStorePaymentStyle(response.style); drs.paymentUI = response.template; drs.injectPaymentWidgetTooltip(response.tooltip); drs.initializeWaitingPaymentWidgets(); }; drs.getPaymentWidgetWidth = function(container, widget) { var widgetWidth = 0; if (container.offsetWidth == 0) { var parentClassWidth = drs.getClassStyleValue("width", container.parentNode); if (parentClassWidth && (parentClassWidth.indexOf("px") > -1)) { widgetWidth = parentClassWidth; } else { widgetWidth = (widget == drs.SMALL_PAYMENT) ? drs.SMALL_PAYMENT_MIN_WIDTH : drs.PAYMENT_MIN_WIDTH; container.parentNode.style.width = widgetWidth; } widgetWidth = widgetWidth.substr(0, widgetWidth.indexOf("px")); } else { widgetWidth = container.offsetWidth; } return widgetWidth; }; drs.injectPaymentWidgetTooltip = function(tooltip) { var container = document.createElement("div"); container.innerHTML = tooltip; drs.setVisibility(container.firstChild, false); document.body.appendChild(container.firstChild); drs.addPaymentWidgetTooltipPopupEventHandler(); }; drs.initializeWaitingPaymentWidgets = function() { for (var i = 0; i < drs.paymentWidgets.length; i++) { drs.initializePaymentWidgetUI(drs.paymentWidgets[i]); } }; drs.initializePaymentWidgetUI = function(container) { container.innerHTML = drs.paymentUI; var embedId = container.getAttribute("id"); drs.setPaymentWidgetIds(embedId); drs.togglePaymentUI(embedId, false); drs.getPaymentsForWidget(embedId, container); }; drs.getDoubleValue = function(doubleValue) { if (doubleValue != null && (typeof doubleValue !== "string" || doubleValue.trim() !== "")) { doubleValue = +doubleValue; if (!isNaN(doubleValue)) { return doubleValue; } } return null; }; drs.getIntValue = function(intValue) { intValue = drs.getDoubleValue(intValue); if (intValue === parseInt(intValue)) { return intValue; } return null; }; drs.getBooleanValue = function(booleanValue) { if (booleanValue != null) { if (booleanValue === true || (typeof booleanValue === "string" && booleanValue.toLowerCase() === "true")) { return true } else if (booleanValue === false || (typeof booleanValue === "string" && booleanValue.toLowerCase() === "false")) { return false; } } return null; }; drs.getJSONRequest = function(financeType, queryString) { var request = {}; for (var parameterId in drs.JSON_BATCH_PARAMETERS) { var parameterType = drs.JSON_BATCH_PARAMETERS[parameterId]; if (parameterType === drs.DATA_TYPE_FINANCE_TYPE) { request[parameterId] = financeType; } else if (parameterType === drs.DATA_TYPE_PRICE) { var parameterValue; if (financeType === drs.FINANCE_TYPE_LOAN) { parameterValue = drs.getDoubleValue(drs.getQueryAttribute(drs.PRICE_LOAN, queryString)); } else if (financeType === drs.FINANCE_TYPE_LEASE) { parameterValue = drs.getDoubleValue(drs.getQueryAttribute(drs.PRICE_LEASE, queryString)); if (parameterValue == null) { parameterValue = drs.getDoubleValue(drs.getQueryAttribute(drs.PRICE_LOAN, queryString)); } } if (parameterValue != null) { request[parameterId] = parameterValue; } } else if (parameterType === drs.DATA_TYPE_VEHICLE_TYPE) { var parameterValue = drs.getQueryAttribute(drs.VEHICLE_TYPE_STRING, queryString); if (parameterValue != null) { if (parameterValue.toLowerCase() === drs.VEHICLE_TYPE_NEW.toLowerCase()) { parameterValue = drs.VEHICLE_TYPE_NEW; } else if (parameterValue.toLowerCase() === drs.VEHICLE_TYPE_USED.toLowerCase()) { parameterValue = drs.VEHICLE_TYPE_USED; } else if (parameterValue.toLowerCase() === drs.VEHICLE_TYPE_CERTIFIED.toLowerCase()) { parameterValue = drs.VEHICLE_TYPE_CERTIFIED; } else if (parameterValue.toLowerCase() === drs.VEHICLE_TYPE_DEMO.toLowerCase()) { parameterValue = drs.VEHICLE_TYPE_DEMO; } else { parameterValue = null; } } if (parameterValue == null) { parameterValue = drs.getBooleanValue(drs.getQueryAttribute(drs.VEHICLE_TYPE_BOOLEAN, queryString)); if (parameterValue === true) { parameterValue = drs.VEHICLE_TYPE_USED; } else if (parameterValue === false) { parameterValue = drs.VEHICLE_TYPE_NEW; } else { parameterValue = null; } } if (parameterValue != null) { request[parameterId] = parameterValue; } } else { var parameterValue = drs.getQueryAttribute(parameterId, queryString); if (parameterValue != null && parameterValue !== "") { if (parameterType === drs.DATA_TYPE_INTEGER) { parameterValue = drs.getIntValue(parameterValue); } else if (parameterType === drs.DATA_TYPE_DOUBLE) { parameterValue = drs.getDoubleValue(parameterValue); } else if (parameterType === drs.DATA_TYPE_BOOLEAN) { parameterValue = drs.getBooleanValue(parameterValue); } else if (parameterType === drs.DATA_TYPE_STRING) { // String just takes the value as is } else { parameterValue = null; } if (parameterValue != null) { request[parameterId] = parameterValue; } } } } return request; }; drs.getPaymentsForWidget = function(embedId, container) { drs.batchPayments[embedId + "_" + drs.FINANCE_TYPE_LOAN] = drs.getJSONRequest(drs.FINANCE_TYPE_LOAN, "?" + drs.getSuiteQueryString(container)); drs.batchPayments[embedId + "_" + drs.FINANCE_TYPE_LEASE] = drs.getJSONRequest(drs.FINANCE_TYPE_LEASE, "?" + drs.getSuiteQueryString(container)); drs.batchPaymentsSize++; drs.paymentWidgetsRequested++; if (drs.batchPaymentsSize == drs.MAX_BATCHED_REQUESTS || drs.paymentWidgetsRequested == drs.paymentWidgets.length) { drs.getBatchPayments(drs.batchPayments); drs.batchPayments = {}; drs.batchPaymentsSize = 0; } }; drs.getBatchPayments = function(batchRequest) { var multiPaymentRequest = new XMLHttpRequest(); multiPaymentRequest.onreadystatechange = function() { if (multiPaymentRequest.readyState == drs.REQUEST_STATUS_FINISHED) { if (multiPaymentRequest.status == drs.HTTP_STATUS_OK) { drs.getPaymentsSuccess(JSON.parse(multiPaymentRequest.responseText)); } else { drs.setBatchCallForPmts(batchRequest); } } }; multiPaymentRequest.open("POST", drs.paymentWidgetServiceURL + "/basic"); multiPaymentRequest.setRequestHeader("Content-type", "application/json"); if (drs.CANNED_IDENTIFIER != null) { multiPaymentRequest.setRequestHeader("Canned-Identifier", drs.CANNED_IDENTIFIER); } if (drs.USE_CANNED_DATA != null) { multiPaymentRequest.setRequestHeader("Canned-Data", drs.USE_CANNED_DATA); } multiPaymentRequest.send(JSON.stringify(batchRequest)); }; drs.getPaymentsSuccess = function(multiplePaymentsResponse) { for (var widgetId in multiplePaymentsResponse) { if (widgetId.indexOf("_" + drs.FINANCE_TYPE_LOAN, widgetId.length - ("_" + drs.FINANCE_TYPE_LOAN).length) !== -1) { widgetId = widgetId.substr(0, widgetId.length - (drs.FINANCE_TYPE_LOAN.length + 1)); drs.setPaymentWidgetPayments(widgetId, multiplePaymentsResponse[widgetId + "_" + drs.FINANCE_TYPE_LOAN], multiplePaymentsResponse[widgetId + "_" + drs.FINANCE_TYPE_LEASE]); } } }; drs.getSuiteQueryString = function(suiteEl) { var suiteQS = drs.getAtt(suiteEl, "suiteQueryString", true); if (!suiteQS && suiteEl.parentNode) { suiteQS = drs.getAtt(suiteEl.parentNode, "suiteQueryString", true); if (!suiteQS) { // recurse dom looking for suiteQueryString attribute suiteQS = drs.getSuiteQueryStringDeep(suiteEl, "suiteQueryString"); } } if (!suiteQS) { suiteQS = location.search.substring(1) + location.hash; } return suiteQS; }; drs.getSuiteQueryStringDeep = function(el, attr) { var nodes = el.children; var suiteQS = null; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; suiteQS = drs.getAtt(node, attr, true); if (suiteQS != null) { return suiteQS; } else { drs.getSuiteQueryStringDeep(node, attr); } } return null; // could not find SQS in any child elements }; drs.buildEmbeddedFrame = function(embedId, widget, parent, src, suiteEl, isScript) { var frame = document.createElement("iframe"); frame.setAttribute("id", embedId); frame.setAttribute("frameborder", "0"); frame.setAttribute("scrolling", "no"); frame.setAttribute("allowTransparency", "true"); frame.setAttribute("widget", widget); // set transition so we "slide" instead of "pop" when height adjusts drs.applyTransitionDelay(frame); var height = 0; frame.style.width = "100%"; if (drs.embedFrames == null) drs.embedFrames = new Array(); drs.embedFrames.push(frame); drs.addEventListener(window, "scroll", drs.handleScroll); if (suiteEl.getAttribute("heightPolicy") == drs.DEPENDANT) { var heightEls = suiteEl.getAttribute("heightEls"); if (heightEls != null && heightEls.length > 0) { var els = heightEls.split(','); for (var i = 0; i < els.length; i++) { var h = drs.getEmbedHeight(suiteEl, document.getElementById(els[i])); if (h > height) height = h; } } } else { height = drs.getEmbedHeight(suiteEl, parent); } drs.verifyDimensions(parent, frame, widget, drs.MIN_WIDTH, Math.max(height, drs.MIN_HEIGHT)); if (drs.supported) { frame.setAttribute("src", src); } else { frame.setAttribute("src", drs.baseSuiteURL + "/nosupport.html"); } drs.injectSuiteNode(parent, suiteEl, frame, isScript); }; drs.injectSuiteNode = function (parent, suiteEl, frame, insertBefore) { if (insertBefore) { parent.insertBefore(frame, suiteEl); } else { suiteEl.appendChild(frame); } }; drs.verifyDimensions = function (parentNode, frame, widget, minWidth, minHeight) { drs.adjustWidth(parentNode, minWidth); if ((parentNode.offsetHeight < minHeight && parentNode.style.height == "") || parseInt(parentNode.style.height.substr(0, parentNode.style.height.indexOf("px"))) < minHeight || parentNode.offsetHeight < minHeight) { if (widget != drs.EMBED) parentNode.style.height = minHeight + "px"; frame.style.height = minHeight + "px"; } else { frame.style.height = parentNode.offsetHeight + "px"; } }; drs.autoAdjustWidth = function (event) { if (drs.getWidget(drs.se, false) == drs.EMBED) drs.adjustWidth(drs.se, drs.MIN_WIDTH); }; drs.adjustWidth = function (parentNode, minWidth) { var curWidth = parseInt(parentNode.style.width.substr(0, parentNode.style.width.indexOf("px"))); var innerWidth = window.innerWidth || document.documentElement.clientWidth; if ((parentNode.offsetWidth < minWidth && parentNode.style.width == "") || (curWidth < minWidth)) { parentNode.style.width = minWidth + "px"; } else if (innerWidth > minWidth && curWidth == drs.MIN_WIDTH) { parentNode.style.width = ""; } }; drs.sizeAndPositionModal = function (widgetEl, opening) { if (drs.veil == null) return; // When sizeModal is called on window resize for currently showing modal, no widget is passed in. if (widgetEl instanceof Event) { widgetEl = drs.curModalWidget; } else { drs.curModalWidget = widgetEl; } var modalHeightPad = 25; var dynHeight = drs.isDynamicHeight(widgetEl); var innerWidth = window.innerWidth || document.documentElement.clientWidth; var innerHeight = window.innerHeight || document.documentElement.clientHeight; drs.veil.style.width = innerWidth + "px"; drs.veil.style.height = innerHeight + "px"; drs.modal.style.width = "100%"; drs.modal.style.left = "0"; if (dynHeight) { if (drs.modalHeight == 0) drs.modalHeight = drs.MIN_HEIGHT + modalHeightPad; drs.modal.style.height = drs.modalHeight + "px"; if (opening) { drs.setModalTop(drs.getWinTop()); } } else { var modalMarginT = drs.givenOrDefault(drs.getInt(drs.getAtt(widgetEl, "modalMarginT")), 50); var modalMarginB = drs.givenOrDefault(drs.getInt(drs.getAtt(widgetEl, "modalMarginB")), 50); var modalMaxH = drs.getInt(drs.getAtt(widgetEl, "modalMaxH")); var h = Math.max(innerHeight - modalMarginT - modalMarginB, drs.MIN_HEIGHT + modalHeightPad); var t = modalMarginT; if (modalMaxH != 0 && h > modalMaxH) { var dif = h - modalMaxH; h -= dif; t += dif / 2; } if (h < innerHeight) { if (h + t * 2 > innerHeight) drs.setModalTop(((innerHeight - h) / 2)); else drs.setModalTop(t); } else { drs.setModalTop(0); } drs.modalHeight = h; drs.modal.style.height = h + "px"; } }; drs.popModal = function (url, widgetEl) { if (drs.veil == null) { drs.veil = document.createElement("div"); drs.veil.setAttribute("class", "DTSuiteModalVeil"); drs.veil.setAttribute("style", "z-index:80; top:0; left:0; background-color:#000; position:fixed; opacity:.5; filter:alpha(opacity=50)"); document.body.appendChild(drs.veil); drs.modal = document.createElement("div"); drs.modal.style.zIndex = 82; drs.modal.setAttribute("class", "DTSuiteModal"); drs.modal.setAttribute("id", "DTSuiteModal"); document.body.appendChild(drs.modal); } if (drs.isDynamicHeight(widgetEl)) { drs.modal.style.position = "absolute"; drs.addEventListener(window, "scroll", drs.handleScroll); drs.applyTransitionDelay(drs.modal); } else { drs.modal.style.position = "fixed"; } drs.modalFrame = document.createElement("iframe"); drs.modalFrame.setAttribute("id", "DTSuiteModalFrame"); drs.modalFrame.setAttribute("frameborder", "0"); drs.modalFrame.setAttribute("scrolling", "no"); drs.modalFrame.setAttribute("allowtransparency", "true"); drs.modalFrame.style.width = "100%"; drs.modalFrame.style.height = "100%"; drs.modal.appendChild(drs.modalFrame); drs.sizeAndPositionModal(widgetEl, true); drs.modalFrame.setAttribute("src", url); drs.modalTimer = setTimeout(drs.clearModal, 15000); drs.veil.style.display = "block"; drs.modal.style.display = "block"; drs.modal.style.height = drs.MIN_HEIGHT + "px"; }; drs.clearModal = function () { // Remove it or ie will show the empty frame as a white box when we open it again. // When we set about:blank (so it doesn't show previous view) and even setting bg transparent on frame. drs.modal.removeChild(drs.modalFrame); drs.modal.style.display = "none"; drs.veil.style.display = "none"; drs.removeEventListener(window, "scroll", drs.handleScroll); }; drs.handleScroll = function () { drs.positionForScroll(true); }; drs.positionForScroll = function (fireParentScroll) { var winTop = drs.getWinTop(); var winHeight = drs.getWinHeight(); var winBot = winTop + winHeight; if (drs.modal != null) { var modalTop = drs.getPxVal(drs.modal.style.top); var modalBot = modalTop + drs.modalHeight; if (modalBot < winBot) { if (modalTop < winTop) { drs.setModalTop(Math.min(winTop, modalTop + (winBot - modalBot))); } } else if (modalTop > winTop) { drs.setModalTop(Math.max(winTop, modalTop + (winBot - modalBot))); } } if (fireParentScroll) { if (drs.modalFrame != null) { drs.postParentScroll(drs.modalFrame, winTop, winHeight); } if (drs.embedFrames != null) { for (var i = 0; i < drs.embedFrames.length; i++) { drs.postParentScroll(drs.embedFrames[i], winTop, winHeight); } } } }; drs.getWinTop = function () { return window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop; }; drs.getWinLeft = function () { return window.pageXOffset ? window.pageXOffset : document.documentElement.scrollLeft; }; drs.getWinHeight = function () { return window.innerHeight ? window.innerHeight : document.documentElement.offsetHeight; }; drs.getWinWidth = function() { return window.innerWidth ? window.innerWidth : document.documentElement.offsetWidth; }; drs.isThinSize = function() { return drs.getWinWidth() < drs.THIN_MAX_WIDTH; }; drs.setModalTop = function(position) { if (position < 0) {position = 0;} drs.modal.style.top = position + "px"; }; drs.postParentScroll = function (targetFrame, winTop, winHeight) { if (targetFrame == null || targetFrame == drs.modalFrame) { targetFrame = drs.modalFrame; targetEl = drs.modal; } else { targetEl = targetFrame; } targetFrame.contentWindow.postMessage('1,' + (targetEl.offsetTop - winTop) + ',' + winHeight, '*'); }; drs.getPxVal = function (pxString) { return new Number(pxString.substring(0, pxString.length - 2)); }; drs.solidifyModal = function () { clearTimeout(drs.modalTimer); }; drs.hideWidget = function (wId) { document.getElementById(wId).style.display = 'none'; }; drs.setDisclaimers = function (suiteEl, d) { var el = document.getElementById(drs.getAtt(suiteEl, "disclaimersId", true)); if (el != null) el.innerHTML = d; }; drs.scrollToSuiteY = function (targetFrame, suiteY) { var targetEl; if (targetFrame == null || targetFrame == drs.modalFrame) { targetEl = drs.modal; } else { targetEl = targetFrame; } var targetY = targetEl.offsetTop + suiteY; var winTop = drs.getWinTop(); if (targetY < winTop) { window.scrollTo(0, targetY - 100); } else { var winBot = drs.getWinHeight() + winTop; if (targetY > winBot) window.scrollTo(0, targetY + 100); } }; drs.hideIfPresent = function (id, vertical) { var el = document.getElementById(id); if (el) { el.style.WebkitTransition = "opacity .75s, height 1s, width 1s"; el.style.opacity = 0; if (vertical) { el.style.height = 0; } else { el.style.width = 0; } window.setTimeout(function () { el.style.display = 'none'; }, 1000); } }; drs.setEmbedToFullWidth = function () { for (var i = 0; i < drs.embedFrames.length; i++) { var frame = drs.embedFrames[i]; frame.style.width = "100%"; frame.parentElement.style.width = "100%"; } }; // Hides a wrapper frame, if one is present. // This should not be called for normal Suite embeds. drs.hideWrapper = function () { drs.hideIfPresent('wrapperTop', true); drs.hideIfPresent('wrapperBottom', true); drs.hideIfPresent('wrapperLeft', false); drs.hideIfPresent('wrapperRight', false); drs.setEmbedToFullWidth(); if (drs.hideWrapperExtension) drs.hideWrapperExtension(); }; drs.openSuite = function (suiteEl, embedId) { if (drs.isMobile || drs.isIpad) { if(!drs.openMobileTargetLocation()) { window.open(drs.buildURL(suiteEl, embedId, false), "drs"); } } else { drs.popModal(drs.buildURL(suiteEl, embedId, true), suiteEl); } }; drs.receiveMessage = function (event) { var args = event.data.split(','); switch (parseInt(args[0])) { case 1: var suiteEl = document.getElementById(args[1]).parentNode; if (suiteEl.getAttribute("suiteQueryString") == null) { // Legacy impl, suiteEl is a reference to the script itself. suiteEl = document.getElementById(args[1]).nextSibling; } drs.openSuite(suiteEl, args[1]); break; case 2: drs.clearModal(); break; case 3: drs.hideWidget(args[1]); break; case 4: drs.solidifyModal(); break; case 5: drs.resizeFrame(args[1], args[2].length > 0 ? args[2] : null, args[3] == 'true' ? true : false); break; case 6: drs.postParentScroll(document.getElementById(args[1]), drs.getWinTop(), drs.getWinHeight()); break; case 7: var html = args[2].replace(/#c#/g, ','); drs.setDisclaimers(document.getElementById(args[1]).parentNode, html); break; case 8: drs.scrollToSuiteY(document.getElementById(args[1]), new Number(args[2])); break; case 9: drs.hideWrapper(); break; case 10: drs.sendGAClientId(args[1], document.getElementById(args[2])); break; case 11: drs.setPaymentWidgetPayments(args[1], args[2], args[3]); break; case 12: if ( drs.onCreditappComplete ) { drs.onCreditappComplete( drs.parseNull( args[1] ), drs.parseNull( args[2] ) ); } } }; drs.parseNull = function ( val ) { return val == "null" ? undefined : val; } drs.sendGAClientId = function (propertyId, targetFrame) { if (ga) { ga(function (tracker) { targetFrame.contentWindow.postMessage('2,' + propertyId + ',' + (tracker == null ? 'x' : tracker.get('clientId')), '*'); }); } else { targetFrame.contentWindow.postMessage('2,' + propertyId + ',x', '*'); } }; drs.resizeFrame = function (wId, height, scrollToTop) { var el = document.getElementById(wId); var elTop = 0; if (drs.modal && drs.modalFrame && (!el || el.getAttribute("widget") == drs.PAYMENT || el.getAttribute("widget") == drs.SMALL_PAYMENT)) { // No widget (frame) for the given id, because the modal frame is being used, or the suite el is the payment // widget but the app frame for dyn height is in a modal. if (height != null) { drs.modalHeight = drs.getPxVal(height); drs.modal.style.height = height; drs.modalFrame.style.height = height; } elTop = drs.getPxVal(drs.modal.style.top); } else { if (height != null) el.style.height = height; elTop = el.offsetTop; } if (scrollToTop) { // Scroll to the top of the Suite. var winTop = drs.getWinTop(); if (elTop < winTop) { window.scrollBy(0, -1 * (winTop - elTop)); } } }; // Need this for ie8 with no event.currentTarget. drs.findSuiteEl = function (startEl) { if (startEl.hasAttribute("suiteQueryString")) { return startEl; } else { //alert(typeof el); return drs.findSuiteEl(startEl.parentNode); } }; drs.getEventSrc = function (event, traverse) { // We want currentTarget but in ie8 we'll have to traverse from srcElement and find it. return event.currentTarget ? event.currentTarget : traverse ? drs.findSuiteEl(event.srcElement) : event.srcElement; }; drs.addEventListener = function (target, event, listener) { if (document.addEventListener) { target.addEventListener(event, listener, false); } else { target.attachEvent('on' + event, listener); } }; drs.removeEventListener = function (target, event, listener) { if (document.removeEventListener) { target.removeEventListener(event, listener, false); } else { target.detachEvent('on' + event, listener); } }; drs.registerDocumentReadyListener = function (listener) { if (document.addEventListener) { // as soon as DOM is parsed, before resources fetch (IE9+) drs.addEventListener(document, "DOMContentLoaded", listener); } else if (document.attachEvent) { // about the same as onload, IE8 document.attachEvent("onreadystatechange", listener); } else { // really old browsers drs.addEventListener(document, "load", listener); } }; drs.registerDocumentReadyListener(drs.init); drs.parseAndStorePaymentStyle = function(style) { drs.paymentStyles = document.getElementsByTagName("style").item(0); if (drs.paymentStyles == null) { drs.paymentStyles = document.createElement("style"); drs.paymentStyles.setAttribute("type", "text/css"); var head = document.getElementsByTagName("head")[0].appendChild(drs.paymentStyles); } drs.injectStyle(style); }; drs.injectStyle = function(styleToInject) { if (drs.paymentStyles.styleSheet) { // For IE. var currentStyles = drs.paymentStyles.styleSheet.cssText; drs.paymentStyles.styleSheet.cssText = currentStyles + styleToInject; } else { drs.paymentStyles.appendChild(document.createTextNode(styleToInject)); } }; drs.setPaymentWidgetIds = function(embedId) { var widgetElement = document.getElementById(embedId); //Need to dig down to child element that holds payment and assign id for payment callback to reach and set value. widgetElement.querySelector("#drs_paymentWidget_wrapper").setAttribute("id", embedId + "_drs_paymentWidget_wrapper"); widgetElement.querySelector("#drs_paymentWidget_loadingContainer").setAttribute("id", embedId + "_drs_paymentWidget_loadingContainer"); widgetElement.querySelector("#drs_paymentWidget").setAttribute("id", embedId + "_drs_paymentWidget"); widgetElement.querySelector("#drs_paymentWidget_container").setAttribute("id", embedId + "_drs_paymentWidget_container"); var divider = widgetElement.querySelector("#drs_paymentWidget_divider"); if (divider != null) { divider.setAttribute("id", embedId + "_drs_paymentWidget_divider"); } widgetElement.querySelector("#drs_paymentWidget_finance_wrapper").setAttribute("id", embedId + "_drs_paymentWidget_finance_wrapper"); widgetElement.querySelector("#drs_paymentWidget_finance_value").setAttribute("id", embedId + "_drs_paymentWidget_finance_value"); widgetElement.querySelector("#drs_paymentWidget_finance_help").setAttribute("id", embedId + "_drs_paymentWidget_finance_help"); widgetElement.querySelector("#drs_paymentWidget_lease_wrapper").setAttribute("id", embedId + "_drs_paymentWidget_lease_wrapper"); widgetElement.querySelector("#drs_paymentWidget_lease_value").setAttribute("id", embedId + "_drs_paymentWidget_lease_value"); widgetElement.querySelector("#drs_paymentWidget_lease_help").setAttribute("id", embedId + "_drs_paymentWidget_lease_help"); widgetElement.querySelector("#drs_paymentWidget_cta").setAttribute("id", embedId + "_drs_paymentWidget_cta"); var loadBtn = widgetElement.querySelector("#drs_paymentWidget_button"); if (loadBtn != null) { loadBtn.setAttribute("id", embedId + "_drs_paymentWidget_button"); } }; drs.setPaymentWidgetPayments = function(embedId, buyOption, leaseOption) { buyOption = buyOption == null ? null : buyOption.response; leaseOption = leaseOption == null ? null : leaseOption.response; drs.displayMonthlyPayment(buyOption, embedId, embedId + "_drs_paymentWidget_finance_value", embedId + "_drs_paymentWidget_finance_wrapper"); drs.displayMonthlyPayment(leaseOption, embedId, embedId + "_drs_paymentWidget_lease_value", embedId + "_drs_paymentWidget_lease_wrapper"); if (buyOption != null) { drs.financeHelpById[embedId] = buyOption.disclosureText; } if (leaseOption != null) { drs.leaseHelpById[embedId] = leaseOption.disclosureText; } if (buyOption == null && leaseOption == null) { drs.setCallForPmts(embedId); } else { drs.addEventListener(document.getElementById(embedId).parentNode, "click", drs.buttonClicked); drs.addPaymentWidgetTooltipEventHandlers(embedId); drs.togglePaymentUI(embedId, true); } }; drs.displayMonthlyPayment = function(paymentOption, embedId, pmtNodeId, pmtWrapperId) { if (paymentOption != null) { var pmtNode = document.getElementById(pmtNodeId); pmtNode.innerHTML = drs._formatCurrency(paymentOption.monthlyPayment, "$", ","); } else { var paymentsContainer = document.getElementById(embedId + "_drs_paymentWidget_container"); var divider = paymentsContainer.querySelector("#" + embedId + "_drs_paymentWidget_divider"); if (divider != null) { paymentsContainer.removeChild(divider); } paymentsContainer.removeChild(document.getElementById(pmtWrapperId)); } }; drs._formatCurrency = function(amount, currencySymbol, groupDivider) { return currencySymbol + amount.replace(/(\d{1,3})(?=(\d{3})+$)/g, '$1' + groupDivider); }; drs.togglePaymentUI = function(embedId, showFullUI) { document.getElementById(embedId + "_drs_paymentWidget_loadingContainer").style.display = (showFullUI ? "none" : ""); document.getElementById(embedId + "_drs_paymentWidget").style.display = (showFullUI ? "" : "none"); }; drs.setBatchCallForPmts = function(batchRequest) { for (var widgetId in batchRequest) { if (widgetId.indexOf("_" + drs.FINANCE_TYPE_LOAN, widgetId.length - ("_" + drs.FINANCE_TYPE_LOAN).length) !== -1) { widgetId = widgetId.substr(0, widgetId.length - (drs.FINANCE_TYPE_LOAN.length + 1)); drs.setCallForPmts(widgetId); } } }; drs.setCallForPmts = function(embedId) { drs.togglePaymentUI(embedId, false); document.getElementById(embedId + "_drs_paymentWidget_loadingContainer").innerHTML = "Call For Payments"; }; drs.getClassStyleValue = function(style, element) { var selectors = element.className.split(/\s+/); for (var i = 0; i < selectors.length; i++) { var styleValue = drs.getStyleRuleValue(style, "." + selectors[i]); if (styleValue) { return styleValue; } } return null; }; drs.getStyleRuleValue = function(style, selector, sheet) { var sheets = typeof sheet !== 'undefined' ? [sheet] : document.styleSheets; for (var i = 0, l = sheets.length; i < l; i++) { var sheet = sheets[i]; try { if( !sheet.cssRules ) { continue; } for (var j = 0, k = sheet.cssRules.length; j < k; j++) { var rule = sheet.cssRules[j]; if (rule.selectorText && rule.selectorText.split(',').indexOf(selector) !== -1) { return rule.style[style]; } } } catch (e) { // We cannot access the css rules. break; } } return null; }; drs.openMobileTargetLocation = function() { if (drs.mobileTargetLocation != null) { window.open(drs.mobileTargetLocation + "?" + drs.getSuiteQueryString(drs.script)); return true; } return false; }; drs.setMobileTargetLocation = function() { if (drs.script.hasAttribute("mobileTargetLocation")) { drs.mobileTargetLocation = drs.script.getAttribute("mobileTargetLocation"); } }; drs.paymentWidgetFinanceTooltipShow = function(event) { drs.paymentWidgetTooltipShow(event, drs.financeHelpById); }; drs.paymentWidgetLeaseTooltipShow = function(event) { drs.paymentWidgetTooltipShow(event, drs.leaseHelpById); }; drs.paymentWidgetTooltipShow = function(event, helpById) { event.stopPropagation(); var helpButton = drs.getEventSrc(event, true); var embededId = helpButton.id.split("_")[0]; var popupTooltip = drs.getTooltip(); drs.setVisibility(popupTooltip, true); popupTooltip.innerHTML = helpById[embededId]; var margin = 10; popupTooltip.style.top = drs.getRelativeElementTop(helpButton, popupTooltip, margin); popupTooltip.style.left = drs.getRelativeElementLeft(helpButton, popupTooltip, margin); popupTooltip.focus(); }; drs.getRelativeElementTop = function(element, relativeElement, margin) { var winHeight = document.documentElement.clientHeight; var elementTop = element.getBoundingClientRect().top; var elementHeight = element.offsetHeight; var relativeElementHeight = relativeElement.offsetHeight; var top; if ( elementTop + elementHeight + margin + relativeElementHeight + margin > winHeight ) { top = elementTop - margin - relativeElementHeight; } else { top = elementTop + elementHeight + margin; } var position = relativeElement.style.position != "" ? relativeElement.style.position : window.getComputedStyle(relativeElement, null).getPropertyValue("position"); if (position != "fixed") { top += drs.getWinTop(); } return top + "px"; }; drs.getRelativeElementLeft = function(element, relativeElement, margin) { var winWidth = document.documentElement.clientWidth; var elementLeft = element.getBoundingClientRect().left; var relativeElementWidth = relativeElement.offsetWidth; var left; if (elementLeft + relativeElementWidth + margin > winWidth) { left = winWidth - relativeElementWidth - margin; } else { left = elementLeft; } left += drs.getWinLeft(); return left + "px"; }; drs.getTooltipPopupElement = function(event, tooltipIdSuffix) { var tooltipId = embededId + tooltipIdSuffix; return document.getElementById(tooltipId); }; drs.setVisibility = function(element, visible) { element.style.display = visible ? "block" : "none"; }; drs.removePaymentWidgetTooltip = function(event) { event.stopPropagation(); drs.setVisibility(drs.getTooltip(), false); }; drs.addPaymentWidgetTooltipEventHandlers = function(embedId) { drs.addPaymentWidgetTooltipEventHandler(embedId + "_drs_paymentWidget_finance_help", drs.paymentWidgetFinanceTooltipShow); drs.addPaymentWidgetTooltipEventHandler(embedId + "_drs_paymentWidget_lease_help", drs.paymentWidgetLeaseTooltipShow); }; drs.addPaymentWidgetTooltipEventHandler = function(helpBubbleId, listener) { var helpBubble = document.getElementById(helpBubbleId); if (helpBubble != null) { drs.addEventListener(helpBubble, "click", listener); } }; drs.addPaymentWidgetTooltipPopupEventHandler = function() { var popupBox = drs.getTooltip(); drs.addEventListener(popupBox, "click", drs.removePaymentWidgetTooltip); drs.addEventListener(popupBox, "blur", drs.removePaymentWidgetTooltip); }; drs.getTooltip = function() { return document.getElementById("drs_paymentWidget_tooltip"); } } drs.setBaseUrls = function () {drs.baseSuiteURL="https://ebusiness.dealertrack.com/Suite";drs.baseApiURL="https://ebusiness.dealertrack.com/Api";}