/* Development Team: Ascension Technologies WebBased - IT Developed By: Budry, Derek Developed: 11 / 29 / 2018 Developer Instructions: To use this library, you must add the "PriceTransparency.js" script within the node or element that you want the content to dynamical load. The source will automatically identify the parent elemnent even if it is only the html < body > tag. This script will inject two select drop down menus as well as a data list and will be in the following order whereever the script tag is applied:
This script will also inject a style tag in the header with custom css3 styles for the modal window that must appear for the dislclaimer. It will also inject a modal window within the body of the document that will appear as:

*/ //================= VANILLA MODAL CODE BEGIN ================================================================== var vanillaCss = " \ .vanilla-overlay \ { \ position: fixed; \ z-index: 9998; \ top: 0; \ left: 0; \ opacity: 0; \ width: 100%; \ height: 100%; \ -webkit-transition: 1ms opacity ease; \ -moz-transition: 1ms opacity ease; \ -ms-transition: 1ms opacity ease; \ -o-transition: 1ms opacity ease; \ transition: 1ms opacity ease; \ background: rgba(0,0,0,.6); \ } \ \ .vanilla-modal \ { \ position: absolute; \ z-index: 9999; \ top: 50%; \ left: 50%; \ opacity: 0; \ width: 94%; \ padding: 24px 20px; \ -webkit-transition: 1ms opacity ease; \ -moz-transition: 1ms opacity ease; \ -ms-transition: 1ms opacity ease; \ -o-transition: 1ms opacity ease; \ transition: 1ms opacity ease; \ -webkit-transform: translate(-50%, -50%); \ -moz-transform: translate(-50%, -50%); \ -ms-transform: translate(-50%, -50%); \ -o-transform: translate(-50%, -50%); \ transform: translate(-50%, -50%); \ border-radius: 2px; \ background: #fff; \ } \ \ .vanilla-modal.vanilla-open.vanilla-anchored \ { \ top: 20px; \ -webkit-transform: translate(-50%, 0); \ -moz-transform: translate(-50%, 0); \ -ms-transform: translate(-50%, 0); \ -o-transform: translate(-50%, 0); \ transform: translate(-50%, 0); \ } \ \ .vanilla-modal.vanilla-open \ { \ opacity: 1; \ } \ \ .vanilla-overlay.vanilla-open \ { \ opacity: 1; \ \ } \ \ .vanilla-close \ { \ font-family: Helvetica, Arial, sans-serif; \ font-size: 24px; \ font-weight: 700; \ line-height: 12px; \ position: absolute; \ top: 5px; \ right: 5px; \ padding: 5px 7px 7px; \ cursor: pointer; \ color: #fff; \ border: 0; \ outline: none; \ background: #e74c3c; \ } \ \ .vanilla-close: hover \ { \ background: #c0392b; \ } \ \ .vanilla-overlay.zoom-and-spin \ { \ display: block; \ height: 0px; \ opacity: 0; \ } \ \ .vanilla-modal.zoom-and-spin \ { \ -webkit-transition: 500ms-webkit-transform ease; \ -moz-transition: 500ms-moz-transform ease; \ -ms-transition: 500ms-ms-transform ease; \ -o-transition: 500ms-o-transform ease; \ transition: 500ms transform ease; \ -webkit-transform: translate(-50 %, -50 %) scale(0) rotateX(0deg); \ -moz-transform: translate(-50 %, -50 %) scale(0) rotateX(0deg); \ -ms-transform: translate(-50 %, -50 %) scale(0) rotateX(0deg); \ -o-transform: translate(-50 %, -50 %) scale(0) rotateX(0deg); \ transform: translate(-50 %, -50 %) scale(0) rotateX(0deg); \ opacity: 1; \ display: block; \ } \ \ .vanilla-modal.zoom-and-spin.vanilla-open \ { \ -webkit-transition: 500ms-webkit-transform 500ms ease; \ -moz-transition: 500ms-moz-transform 500ms ease; \ -ms-transition: 500ms-ms-transform 500ms ease; \ -o-transition: 500ms-o-transform 500ms ease; \ transition: 500ms transform 500ms ease; \ -webkit-transform: translate(-50 %, -50 %) scale(1) rotateX(360deg);\ -moz-transform: translate(-50 %, -50 %) scale(1) rotateX(360deg); \ -ms-transform: translate(-50 %, -50 %) scale(1) rotateX(360deg); \ -o-transform: translate(-50 %, -50 %) scale(1) rotateX(360deg); \ transform: translate(-50 %, -50 %) scale(1) rotateX(360deg); \ } \ \ .vanilla-modal.zoom-and-spin.vanilla-open.vanilla-anchored \ { \ -webkit-transition: 500ms-webkit-transform 500ms ease; \ -moz-transition: 500ms-moz-transform 500ms ease; \ -ms-transition: 500ms-ms-transform 500ms ease; \ -o-transition: 500ms-o-transform 500ms ease; \ transition: 500ms transform 500ms ease; \ } \ \ .vanilla-overlay.zoom-and-spin.vanilla-open \ { \ top: 0; \ height: 100 %; \ -webkit-transition: 500ms all ease; \ -moz-transition: 500ms all ease; \ -ms-transition: 500ms all ease; \ -o-transition: 500ms all ease; \ transition: 500ms all ease; \ opacity: 1; \ } \ \ .vanilla-overlay.zoom-and-spin \ { \ -webkit-transition: 500ms all 500ms ease; \ -moz-transition: 500ms all 500ms ease; \ -ms-transition: 500ms all 500ms ease; \ -o-transition: 500ms all 500ms ease; \ transition: 500ms all 500ms ease; \ } \ \ .vanilla-footer \ { \ padding: 20px 0; \ } \ .vanilla-footer button \ { \ border:1px solid #cccccc; \ width: 100px; \ padding: 10px; \ margin: 0 10px; \ float: right; \ } "; // Create an immediately invoked functional expression to wrap our code (function () { // Define our constructor this.VanillaModal = function () { // Create global element references this.closeButton = null; this.modal = null; this.overlay = null; // Determine proper prefix this.transitionEnd = transitionSelect(); // Define option defaults var defaults = { autoOpen: false, autoInjectStyle: true, className: 'fade-and-drop', closeButton: true, headerRender: true, header: "", content: "", footerRender: true, footer: "", maxWidth: 600, minWidth: 280, overlay: true, overlayAllowDismiss: true }; // Create options by extending defaults with the passed in arugments if (arguments[0] && typeof arguments[0] === "object") { this.options = extendDefaults(defaults, arguments[0]); } if (this.options.autoOpen === true) this.open(); }; // Public Methods VanillaModal.prototype.close = function () { var _ = this; this.modal.className = this.modal.className.replace(" vanilla-open", ""); this.overlay.className = this.overlay.className.replace(" vanilla-open", ""); this.modal.addEventListener(this.transitionEnd, function () { _.modal.parentNode.removeChild(_.modal); }); this.overlay.addEventListener(this.transitionEnd, function () { if (_.overlay.parentNode) _.overlay.parentNode.removeChild(_.overlay); }); }; VanillaModal.prototype.open = function () { buildOut.call(this); initializeEvents.call(this); window.getComputedStyle(this.modal).height; this.modal.className = this.modal.className + (this.modal.offsetHeight > window.innerHeight ? " vanilla-open vanilla-anchored" : " vanilla-open"); this.overlay.className = this.overlay.className + " vanilla-open"; }; // Private Methods function buildOut() { var header,content,footer, contentHolder, docFrag; /* * If content is an HTML string, append the HTML string. * If content is a domNode, append its content. */ if (typeof this.options.header === "string") { header = this.options.header; } else { header = this.options.header.innerHTML; } if (typeof this.options.content === "string") { content = this.options.content; } else { content = this.options.content.innerHTML; } if (typeof this.options.footer === "string") { footer = this.options.footer; } else { footer = this.options.footer.innerHTML; } // Create a DocumentFragment to build with docFrag = document.createDocumentFragment(); // Create modal element this.modal = document.createElement("div"); this.modal.className = "vanilla-modal " + this.options.className; this.modal.style.minWidth = this.options.minWidth + "px"; this.modal.style.maxWidth = this.options.maxWidth + "px"; // If closeButton option is true, add a close button if (this.options.closeButton === true) { this.closeButton = document.createElement("button"); this.closeButton.className = "vanilla-close close-button"; this.closeButton.innerHTML = "×"; this.modal.appendChild(this.closeButton); } // If overlay is true, add one if (this.options.overlay === true) { this.overlay = document.createElement("div"); this.overlay.className = "vanilla-overlay " + this.options.className; docFrag.appendChild(this.overlay); } // Create Header area and append to modal if (this.options.headerRender) { contentHolder = document.createElement("div"); contentHolder.className = "vanilla-header"; contentHolder.innerHTML = header; this.modal.appendChild(contentHolder); } // Create content area and append to modal contentHolder = document.createElement("div"); contentHolder.className = "vanilla-content"; contentHolder.innerHTML = content; this.modal.appendChild(contentHolder); // Create Footer area and append to modal if (this.options.footerRender) { contentHolder = document.createElement("div"); contentHolder.className = "vanilla-footer"; contentHolder.innerHTML = footer; this.modal.appendChild(contentHolder); } // Append modal to DocumentFragment docFrag.appendChild(this.modal); // Append DocumentFragment to body document.body.appendChild(docFrag); if (this.options.autoInjectStyle) { var css = vanillaCss, head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'); style.type = 'text/css'; if (style.styleSheet) { // This is required for IE8 and below. style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); } } function extendDefaults(source, properties) { var property; for (property in properties) { if (properties.hasOwnProperty(property)) { source[property] = properties[property]; } } return source; } function initializeEvents() { if (this.closeButton) { this.closeButton.addEventListener('click', this.close.bind(this)); } if (this.overlay && this.overlayAllowDismiss) { this.overlay.addEventListener('click', this.close.bind(this)); } } function transitionSelect() { var el = document.createElement("div"); if (el.style.WebkitTransition) return "webkitTransitionEnd"; if (el.style.OTransition) return "oTransitionEnd"; return 'transitionend'; } }()); //================= VANILLA MODAL CODE END ================================================================== //================= PRICE TRANSPARENCY CODE BEGIN =========================================================== var priceTransparency = { details: { ajaxConnections: 0, confirmDisclaimer: true, allowQueryParam: false, parentElement: null, hospital: { url: 'https://pricetransparency.pub.cloud-03.pcf.ascension.org/api/Hospital', id: "ddlHospitals" }, department: { url: 'https://pricetransparency.pub.cloud-03.pcf.ascension.org/api/Department', id: "ddlDepartments" }, procedure: { url: 'https://pricetransparency.pub.cloud-03.pcf.ascension.org/api/Procedure', id: "dlProcedures" } }, initialize: function () { // Identify Script Element Position on document scripts = document.getElementsByTagName('script'); for (var i=0, end = scripts.length; i < end; i++) { if (scripts[i].src.indexOf("PriceTransparency") > -1) { // ControllerName >> No Index parentElement = scripts[i].parentNode; } } if (parentElement !== null) { // Create Housing Elements this.builder.initialize(this.details); // Add Event Listeners this.listeners.hospital(this); this.listeners.department(this); // does page contain querystring of pthospital? var pthospital = this.allowQueryParam ? this.utilities.getQuerystring("pthid") :""; // Call First Ajax pull this.utilities.getAjax(this.details.hospital.url + "/" + encodeURIComponent(pthospital), this.loadHospital, this); } else { //console.log("Unable to identify parent node for Price Transparency"); } }, builder: { initialize: function (details) { // Get Parent Container Element // Build Hospital Select this.buildElement(details.hospital.id, "select", parentElement); this.resetElement(document.getElementById(details.hospital.id)); // Build Department Select this.buildElement(details.department.id, "select", parentElement); this.resetElement(document.getElementById(details.department.id)); // Build Procedure Data List this.buildElement(details.procedure.id, "dl", parentElement); }, buildElement: function (id, elementType, parentElement) { var element = document.createElement(elementType); element.setAttribute("id", id); parentElement.appendChild(element); }, buildSelectOption: function (element, text, value) { var option = document.createElement('option'); option.setAttribute('value', value); var option_content = document.createTextNode(text); option.appendChild(option_content); element.appendChild(option); }, buildDlItem: function (element, dtText, ddText) { var dt = document.createElement('dt'); var dt_content = document.createTextNode(dtText); dt.appendChild(dt_content); var dd = document.createElement("dd"); var dd_content = document.createTextNode(ddText); dd.appendChild(dd_content); element.appendChild(dt); element.appendChild(dd); }, resetElement: function (element) { element.innerHTML = ""; element.disabled = true; } }, loadHospital: function (data, objThis) { try { hospitalElement = document.getElementById(objThis.details.hospital.id); hospitalElement.disabled = false; objThis.builder.buildSelectOption(hospitalElement, "Select Hospital", ""); // Can have two data results. Direct hit or the database table. Check which is which var directhit = data.cdm !== undefined ? true : false; if (!directhit) { for (var i in data) { objThis.builder.buildSelectOption(hospitalElement, data[i].value, data[i].key); } } else { objThis.builder.buildSelectOption(hospitalElement, data.name, data.cdm); hospitalElement.selectedIndex = 1; hospitalElement.dispatchEvent(new Event('change')); } } catch (err) { //console.log(err.message + " in loading hospital drop down list"); } }, loadHospitalDisclaimer: function (data, objThis) { try { var modalHeader = "

" + data.name + " Disclaimer:

"; var modalFooter = ""; var modalContent = data.disclaimer; var vmodal = new VanillaModal({ header: modalHeader, content: modalContent, footer: modalFooter, allowOverlayClose: false, closeButton: false }); vmodal.open(); document.getElementById("vanilla-button-ok").addEventListener("click", function () { var departmentUrl = objThis.details.department.url + "?hospital=" + encodeURIComponent(data.cdm); objThis.utilities.getAjax(departmentUrl, objThis.loadDepartment, objThis); vmodal.close(); }); document.getElementById("vanilla-button-cancel").addEventListener("click", function () { document.getElementById(objThis.details.hospital.id).selectedIndex = 0; vmodal.close(); }); } catch (err) { //console.log(err.message + " in loading hospital price disclaimer"); } }, loadDepartment: function (data, objThis) { try { departmentElement = document.getElementById(objThis.details.department.id); departmentElement.disabled = false; objThis.builder.buildSelectOption(departmentElement, "Select Department", ""); for (var i in data) { objThis.builder.buildSelectOption(departmentElement, data[i].value, data[i].key); } departmentElement.focus(); } catch (err) { //console.log(err.message + " in loading departments drop down list"); } }, loadProcedures: function (data, objThis) { try { procedureElement = document.getElementById(objThis.details.procedure.id); for (var i in data) { try { var primary_formated = objThis.utilities.formatMoney(data[i].primary); objThis.builder.buildDlItem(procedureElement, data[i].descr, "$" + primary_formated); } catch (err) { //console.log(err.message + " in formating procdure amount into currency"); } } } catch (err) { //console.log(err.message + " in loading departments drop down list"); } }, listeners: { hospital: function (objThis) { var hospitalElement = document.getElementById(objThis.details.hospital.id); var departmentElement = document.getElementById(objThis.details.department.id); var procedureElement = document.getElementById(objThis.details.procedure.id); hospitalElement.addEventListener("change", function () { // Reset Departments objThis.builder.resetElement(departmentElement); objThis.builder.resetElement(procedureElement); if (this.value.length) { if (objThis.details.confirmDisclaimer) { // If value is not null, get hospital disclaimer var hospitalUrl = objThis.details.hospital.url + "/" + encodeURIComponent(this.value); objThis.utilities.getAjax(hospitalUrl, objThis.loadHospitalDisclaimer, objThis); } else { // If value is not null, get departments var departmentUrl = objThis.details.department.url + "?hospital=" + encodeURIComponent(this.value); objThis.utilities.getAjax(departmentUrl, objThis.loadDepartment, objThis); } } }); }, department: function (objThis) { var hospitalElement = document.getElementById(objThis.details.hospital.id); var departmentElement = document.getElementById(objThis.details.department.id); var procedureElement = document.getElementById(objThis.details.procedure.id); departmentElement.addEventListener("change", function () { // Reset Procedures objThis.builder.resetElement(procedureElement); // If value is not null, get procedures if (this.value.length > 0) { var procedureUrl = objThis.details.procedure.url + "?hospital=" + encodeURIComponent(hospitalElement.options[hospitalElement.selectedIndex].value); procedureUrl += "&department=" + encodeURIComponent(this.value); objThis.utilities.getAjax(procedureUrl, objThis.loadProcedures, objThis); } }); } }, utilities: { formatMoney: function (n, c, d, t) { c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "." : d, t = t == undefined ? "," : t, s = n < 0 ? "-" : "", i = String(parseInt(n = Math.abs(Number(n) || 0).toFixed(c))), j = (j = i.length) > 3 ? j % 3 : 0; return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); }, getQuerystring: function (name) { name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); var results = regex.exec(location.search); return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); }, getAjax: function (url, callback, objThis) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { try { var data = JSON.parse(xmlhttp.responseText); } catch (err) { //console.log(err.message + " in " + xmlhttp.responseText); return; } objThis.details.ajaxConnections--; callback(data, objThis); } }; if (objThis.details.ajaxConnections === 0) { objThis.details.ajaxConnections++; xmlhttp.open("GET", url, true); xmlhttp.send(); } } } }; priceTransparency.initialize(); //================= PRICE TRANSPARENCY CODE END ===========================================================