NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Salesforce Addons // @namespace https://tehchy.net // @version 1.8.1 // @description // @author Tehchy // @copyright 2019, tehchy (https://openuserjs.org/users/tehchy) // @updateURL https://openuserjs.org/meta/tehchy/Salesforce_Addons.meta.js // @license MIT // @match *.visual.force.com/apex/yc_servicesLog* // @match *.visual.force.com/apex/contactIntakeForm* // @match *.salesforce.com/* // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js // @grant none // @run-at document-start // @history Fixed URLs // ==/UserScript== (function() { 'use strict'; var account; var color = '1797c0'; var settings = { qolChanges: true, newDesign: true, clickableCasenotes: true, dupeDetection: true, apptCounter: true, apptLimitIncrease: true, loadingScreen: true, changeLogo: true, intakeClear: true, intakeDisableCancel: true, intakeSearchOnEnter: true, quickNotes: true, contactDOBSelect: true, contactNameSelect: true, contactInfoChecker: true, volunteerTab:true, wip:false }; var volgId = '2bTUEgZwh3cHga0A3GhAR4eJlijKCc14'; var match = /^(https?:\/\/)?(www\.)?((pots--c||c).)?(\w+)\./.exec(location) || null; var server = 'na71'; if (match) { server = match[match.length - 1]; } try { window.addEventListener('load', function() {init();}, false); } catch (e) { console.log('Failed to load - ' + e); } function init() { Functions.init(); var page = Functions.getPageByPath(); //if (document.getElementById('noteTitle') || document.getElementById('00N37000005oBFz_ilecell') || document.getElementById('00N37000005e5YN_ilecell') || document.location.href.indexOf('a0D?rlid') > 0) // Contact if (['Note', 'Contact', 'Account', 'Income'].includes(page)) { Contact.init(page); } else if (Functions.getParameterByName('serviceType') || document.location.href.indexOf('yc_servicesLog') > 0) //Service logs { Functions.changeTableStyle(); Services.init(); } else if (Functions.getParameterByName('RecordType') || document.location.href.indexOf('contactIntakeForm') > 0) //Contact Intake { Intake.init(); } Functions.concourseLevel(); Functions.changeStyle(); } var Intake = { elementInfo: {}, loop: null, init: function() { color = '56458c'; Intake.elementInfo = Intake.getElementInfo(); Intake.insertSettings(); Functions.changeLogo(); Intake.resetInfo(); }, insertSettings: function() { if (Functions.insertedSettings) { return; } var info = [ ['New Design', 'newDesign'], ['Change Logo', 'changeLogo'], ['Clear Intake', 'intakeClear'], ['Volunteer Login Tab', 'volunteerTab'], ['Search On Enter', 'intakeSearchOnEnter'], ['Disable Cancel Button', 'intakeDisableCancel'] ]; var table = '<div class="sidebarModule htmlAreaComponentModule"><div class="sidebarModuleHeader brandPrimaryBgr"><h2 class="brandPrimaryFgr">Salesforce Addons Settings</h2></div><div class="sidebarModuleBody"><table border="0" cellpadding="0" cellspacing="0"><tbody>'; for (var i = 0; i < info.length; i++) { var val = settings[info[i][1]]; table += '<tr><th class="labelCol vfLabelColTextWrap" scope="row"><label for="sets_' + info[i][1] + '">' + info[i][0] + '</label></th><td class="data2Col"><input id="sets_' + info[i][1] + '" type="checkbox" value="' + (val ? 1 : 0) + '"' + (val ? ' checked' : '') + '></td></tr>'; } table += '</tbody></table><br><center><input class="btn" id="save_sets" value="Save Settings" type="button"></center></div></div>'; document.getElementById('sidebarDiv').innerHTML = table + document.getElementById('sidebarDiv').innerHTML; document.getElementById('save_sets').addEventListener("click", Intake.onSaveSettings); Functions.insertedSettings = true; }, onSaveSettings: function() { var info = [ ['New Design', 'newDesign'], ['Change Logo', 'changeLogo'], ['Clear Intake', 'intakeClear'], ['Volunteer Login Tab', 'volunteerTab'], ['Search On Enter', 'intakeSearchOnEnter'], ['Disable Cancel Button', 'intakeDisableCancel'] ]; for (var i = 0; i < info.length; i++) { settings[info[i][1]] = document.getElementById('sets_' + info[i][1]).checked ? true : false; } Functions.saveSettings(); }, insertClearButton: function() { if (!settings.intakeClear) { return false; } document.getElementsByClassName('detailList')[0].addEventListener('keydown', function(evt) { if (evt.keyCode == 13) { document.getElementById(Intake.elementInfo.BUTTONS).children[0].click(); } }); document.getElementById(Intake.elementInfo.BUTTONS).children[1].setAttribute('type', 'button'); document.getElementById(Intake.elementInfo.BUTTONS).innerHTML += '<input class="btn" id="clearinfo" value="Clear" type="button">'; document.getElementById('clearinfo').addEventListener('click', Intake.onClear); }, onClear: function() { document.getElementsByName(Intake.elementInfo.FIRST_NAME)[0].value = ''; document.getElementsByName(Intake.elementInfo.LAST_NAME)[0].value = ''; document.getElementsByName(Intake.elementInfo.BIRTH_DATE)[0].value = ''; }, disableCancel: function() { if (!settings.intakeDisableCancel) { return false; } document.getElementById(Intake.elementInfo.BUTTONS).children[1].setAttribute('type', 'button'); }, onKeyDown: function(evt) { if (evt.keyCode == 13 && settings.intakeSearchOnEnter) { document.getElementById(Intake.elementInfo.BUTTONS).children[0].click(); } }, searchOnEnter: function() { if (!settings.intakeSearchOnEnter) { return; } var EnterEvent = document.getElementsByClassName('detailList')[0]; if (EnterEvent && EnterEvent.removeEventListener) { EnterEvent.removeEventListener('keydown', Intake.onKeyDown); } EnterEvent.addEventListener('keydown', Intake.onKeyDown); }, onFormChange: function() { var gotChange = false; if (Intake.loop != null) { return; } Intake.loop = setInterval(function() { if (A4J.AJAX._requestsCounts['_viewRoot:status'] == 0 && gotChange) { // FUTURE PROOF clearInterval(Intake.loop); Intake.resetInfo(); Intake.loop = null; } else if (A4J.AJAX._requestsCounts['_viewRoot:status'] == 1) { gotChange = true; } }, 100); }, getElementInfo: function() { var info = {}; var dlist = document.getElementsByClassName('detailList')[0].rows; for (var i = 0; i < (dlist.length - 1); i++) { var id = dlist[i].cells[1].firstChild.id; id = id.slice(0, -1) + (parseInt(id.substr(-1)) + 1); var name = dlist[i].cells[0].textContent.replace(' ', '_').toUpperCase(); info[name] = id; } info.BIRTH_DATE = document.getElementsByClassName('dateInput dateOnlyInput')[0].firstChild.id; var fid = document.getElementsByClassName('apexp')[0].firstChild.firstChild.firstChild.id; info.FORM = fid; info.SEARCH_BUTTON = document.getElementById(fid + ":j_id" + (parseInt(fid.substr(-1)) + 1) + ':bottom').firstChild.id; info.BUTTONS = fid + ":j_id" + (parseInt(fid.substr(-1)) + 1) + ':bottom'; console.log(info); return info; }, resetInfo: function() { var FormEvent = document.getElementById(Intake.elementInfo.FORM); if (FormEvent && FormEvent.removeEventListener) { FormEvent.removeEventListener('change', Intake.onFormChange); } FormEvent.addEventListener('change', Intake.onFormChange); Intake.insertClearButton(); Intake.disableCancel(); Intake.searchOnEnter(); } }; var Contact = { id: null, page: null, init: function(page = null) { Contact.page = page; Contact.id = Contact.getId(); //if (document.getElementById('noteTitle'))// Checks for QuickNotes Title if (Contact.page == 'Note') { color = '56458c'; Contact.quickNotes(); } //else if (document.getElementById('00N37000005oBFz_ilecell') || document.getElementById('00N37000005e5YN_ilecell'))// Checks for Food Pantry Cert Date or Monthly Income else if (Contact.page == 'Contact' || Contact.page == 'Account') { Contact.selectFullName(); if (Contact.page != 'Account') Contact.selectDOB(); Contact.insertManageButton(Contact.page == 'Account' ? 'T' : '4'); if (Contact.page != 'Account') Contact.checkInfo(); color = Contact.page == 'Account' ? '236fbd' : '56458c'; //if (Contact.page == 'Contact') Contact.checkCaseNotes(); } //else if (document.location.href.indexOf('a0D?rlid') > 0)// Checks for Household Income else if (Contact.page == 'Income') { color = '236fbd'; Contact.manageIncomes(); } if (Contact.page && Contact.page != 'Note') { Contact.insertSettings(); } }, insertSettings: function() { if (Functions.insertedSettings) { return; } var info = [ ['New Design', 'newDesign'], ['Change Logo', 'changeLogo'], ['Quick Notes', 'quickNotes'], ['DOB Quick Select', 'contactDOBSelect'], ['Name Quick Select', 'contactNameSelect'], ['Info Checker', 'contactInfoChecker'], ['Volunteer Login Tab', 'volunteerTab'] ]; var table = '<div class="sidebarModule htmlAreaComponentModule"><div class="sidebarModuleHeader brandPrimaryBgr"><h2 class="brandPrimaryFgr">Salesforce Addons Settings</h2></div><div class="sidebarModuleBody"><table border="0" cellpadding="0" cellspacing="0"><tbody>'; for (var i = 0; i < info.length; i++) { var val = settings[info[i][1]]; table += '<tr><th class="labelCol vfLabelColTextWrap" scope="row"><label for="sets_' + info[i][1] + '">' + info[i][0] + '</label></th><td class="data2Col"><input id="sets_' + info[i][1] + '" type="checkbox" value="' + (val ? 1 : 0) + '"' + (val ? ' checked' : '') + '></td></tr>'; } table += '</tbody></table><br><center><input class="btn" id="save_sets" value="Save Settings" type="button"></center></div></div>'; document.getElementById('sidebarDiv').innerHTML = table + document.getElementById('sidebarDiv').innerHTML; document.getElementById('save_sets').addEventListener("click", Contact.onSaveSettings); Functions.insertedSettings = true; }, onSaveSettings: function() { var info = [ ['New Design', 'newDesign'], ['Change Logo', 'changeLogo'], ['Quick Notes', 'quickNotes'], ['DOB Quick Select', 'contactDOBSelect'], ['Name Quick Select', 'contactNameSelect'], ['Info Checker', 'contactInfoChecker'], ['Volunteer Login Tab', 'volunteerTab'] ]; for (var i = 0; i < info.length; i++) { settings[info[i][1]] = document.getElementById('sets_' + info[i][1]).checked ? true : false; } Functions.saveSettings(); }, quickNotes: function() { if (!settings.quickNotes) { return false; } var noteTitle = document.getElementById('noteTitle'); var noteContent = CKEDITOR.instances.editor; var buttons = document.getElementById('notes-save-container'); var select = Functions.htmlToElement('<select id="quicknotes" class="zen-btn"><option disabled="disabled" selected="selected">Choose Quick notes...</option><option>Recert Next Appt</option><option>Needs Intake</option></select>'); buttons.appendChild(select); select.addEventListener('change', function() { if (select.value != '') { noteTitle.value = select.value; if (!Sfdc.ChatterNotes) { parent.Sfdc.ChatterNotes.saveNote(); } else { Sfdc.ChatterNotes.saveNote(); } } }); }, manageIncomes: function() { var table = document.getElementsByClassName('list')[0]; table = table.rows; delete table[0]; if (table[1].innerText == 'No records to display.') { return; } for (var i = 0; i < table.length; i++) { if (table[i].childNodes[2].innerText.trim() == '$0.00') { console.log(table[i].childNodes[2].innerText); table[i].childNodes[0].children[1].removeAttribute("onclick"); table[i].childNodes[0].children[1].click(); return; } } }, selectFullName: function() { if (!settings.contactNameSelect) { return false; } document.getElementsByClassName('topName')[0].onclick = function () { window.getSelection().selectAllChildren(document.getElementsByClassName('topName')[0]); document.execCommand("copy"); } }, selectDOB: function() { if (!settings.contactDOBSelect) { return false; } document.getElementById('con7_ilecell').addEventListener('click', function() { window.getSelection().selectAllChildren(document.getElementById('con7_ileinner')); document.execCommand("copy"); }); }, checkInfo: function() { if (!settings.contactInfoChecker) { return false; } var textBlock = ''; textBlock += Contact.pastDue(document.getElementById('00N37000005oBFz_ileinner').innerText, 12) ? ' [R]' : ''; textBlock += Contact.pastDue(document.getElementById('00N37000005e607_ileinner').innerText, 12) ? ' [I]' : ''; var today = new Date([new Date().getMonth()+1, new Date().getDate(), new Date().getFullYear()].join('/')); var appt = Contact.getPantryAppointment(); console.log(today, new Date(appt[0])); textBlock += appt && (today > new Date(appt[0])) ? ' [M]' : ''; textBlock += appt && (Contact.pastDue(appt[0], 12)) ? ' [RR]' : ''; if (textBlock.length > 0) { document.getElementById('contactHeaderRow').appendChild(Functions.htmlToElement('<div class="textBlock"><h2 class="topName" style="color: red">' + textBlock.trim() + '</h2></div>')); } }, pastDue: function(oldDate, months) { if (oldDate.trim().length < 1) { return true; } var today = new Date(); var a = moment(oldDate,'M/D/YYYY'); var b = moment(today,'M/D/YYYY'); var diff = b.diff(a, 'months'); if (diff >= months) { return true; } return false; }, insertManageButton: function(end = '4') { document.getElementsByName('new00N37000005DTa' + end)[0].parentNode.innerHTML += '<input value="Manage Incomes" name="manage00N37000005DTa' + end + '" class="btn" onclick="navigateToUrl(\'/a0D?rlid=00N37000005DTa' + end + '&id=' + Contact.id + '\',\'RELATED_LIST\',\'manage00N37000005DTa'+ end + '\');" title="Manage Household Income" type="button">'; }, checkCaseNotes: function() { var rows = document.getElementById(Contact.id + '_00N37000005DELb_body').children[0].rows; if (!rows || rows.length < 1) { return; } for (var i = 0; i < rows.length; i++) { var logDate = rows[i].children[4].innerText, service = rows[i].children[5].innerText, status = rows[i].children[6].innerText; if (service == "Food Pantry") { console.log(rows[i].children); } } }, getPantryAppointment: function() { var rows = document.getElementById(Contact.id + '_00N37000005DELb_body').children[0].rows; if (!rows || rows.length < 1) { return false; } for (var i = 0; i < rows.length; i++) { var logDate = rows[i].children[4].innerText, service = rows[i].children[5].innerText, status = rows[i].children[6].innerText; if (service == "Food Pantry") { return [logDate, status]; } } return false; }, getId: function() { switch (Contact.page) { case 'Note': return Functions.getParameterByName('parentId'); break; case 'Contact': case 'Account': return document.querySelectorAll("div[data-entityId]")[0].getAttribute('data-entityId'); break; case 'Incomes': return Functions.getParameterByName('id'); break; } return null; } }; var Services = { service: null, elementInfo: {}, tableInfo: {}, liveChanges: false, caseNotePosition: null, appointmentTimes: {}, insertedSettings: false, currentDate: null, init: function() { Services.service = Services.getService(); Services.elementInfo = Services.getElementInfo(); Functions.changeLogo(); switch (Services.service) { case 'Food Pantry': Services.foodPantry(); break; case 'Community Dining Room': Services.diningRoom(); break; default: console.log(Services.service + ' is not 100% supported atm.'); break; } Services.insertSettings(); Services.resetInfo(); }, foodPantry: function() { console.log('Service log found: Food Pantry'); if (!settings.qolChanges) { return; } document.getElementById(Services.elementInfo.BUTTONS).innerHTML += '<select class="btn" id="changestatus"><option value="" disabled selected hidden>Change Status</option><option value="0">No Show All</option><option value="1">No Show All Ex Recv</option><option value="2">Scheduled All Ex Recv</option></select>' + '<select class="btn" id="filldate"><option value="" disabled selected hidden>Fill Date</option><option value="0">Staff Meeting</option><option value="1">Holiday</option></select><input class="btn" id="setuptabs" value="Setup Tabs" type="button">'; document.getElementById(Services.elementInfo.BUTTONS).parentNode.innerHTML += '<td class="pbHelp"><a title="Printable View (New Window)"><img src="/img/s.gif" id="printview" alt="Printable View (New Window)" class="printerIcon" onblur="this.className = \'printerIcon\';" onfocus="this.className = \'printerIconOn\';" onmouseout="this.className = \'printerIcon\';this.className = \'printerIcon\';" onmouseover="this.className = \'printerIconOn\';this.className = \'printerIconOn\';" title="Printable View (New Window)"></a>' + '<a href="javascript:alert(\'Created by Tehchy, Salesforce Addons makes tedious task much simpler. This does not directly edit salesforce it only uses what salesforce has to its advantage (with a little trickery)\');"><img src="/img/s.gif" alt="" class="helpIcon" title="Whats this?"></a></td>'; document.getElementById('changestatus').addEventListener('change', Services.onChangeStatus); document.getElementById('filldate').addEventListener('change', Services.onChangeFillDate); document.getElementById('printview').addEventListener('click', Services.onPrintView); document.getElementById('setuptabs').addEventListener('click', Services.onSetupTabs); document.addEventListener("keydown", Services.onKeyDown); }, diningRoom: function() { console.log('Service log found: Community Dining Room'); }, clickableCaseNotes: function() { if (!Services.elementInfo.CASE_NOTE || !settings.clickableCasenotes) { return false; } var table = document.getElementById(Services.elementInfo.TABLE).rows; var minLength = Services.service == 'Community Dining Room' ? 2:3; if (table.length < minLength) { return false; } table[0].children[2].innerHTML = 'Case Note'; for (var i = 1; i < table.length; i++) { var casenote = table[i].childNodes[Services.caseNotePosition]; if (casenote.innerText.length > 0) { casenote.firstChild.innerHTML = '<a target="_blank" href="https://pots.my.salesforce.com/_ui/search/ui/UnifiedSearchResults?sen=a07&str=' + casenote.innerText + '">' + casenote.innerText + '</a>'; } } }, appointmentTotals: function() { if (Services.service != 'Food Pantry') { return false; } var TimeEvent = document.getElementsByName(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.APPOINTMENT_TIME)[0]; if (TimeEvent && TimeEvent.removeEventListener) { TimeEvent.removeEventListener('change', Services.onTimeChange); } var totals = document.getElementsByClassName('pbSubsection')[0].childNodes[0].innerText.trim().split('\n'); if (totals.length > 0) { Services.appointmentTimes = []; for (var x = 0; x < totals.length; x++) { var totals2 = totals[x].split(' '); for (var i = 0; i < totals2.length; i++) { if ((i & 1) == 0) { var timeSplit = totals2[i+1].trim().split('/'); Services.appointmentTimes[totals2[i].trim()] = [parseInt(timeSplit[0]), parseInt(timeSplit[1])]; } } } } document.getElementsByName(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.APPOINTMENT_TIME)[0].addEventListener('change', Services.onTimeChange); }, loadTable: function() { if (Services.service != 'Food Pantry') { return false; } var table = document.getElementById(Services.elementInfo.TABLE); table = table.rows; if (table.length < 3) { return false; } delete table[0]; Services.tableInfo = {}; for (var i = 0; i < table.length; i++) { Services.tableInfo[i - 1] = [ table[i].childNodes[3].firstChild.value, table[i].childNodes[4].firstChild.value, table[i].childNodes[5].firstChild.value, table[i].childNodes[6].firstChild.value, table[i].childNodes[7].firstChild.value ]; } }, checkTableChanges: function() { if (Services.service != 'Food Pantry') { return false; } var table = document.getElementById(Services.elementInfo.TABLE); table = table.rows; if (table.length < 3) { return false; } delete table[0]; var changed = []; for (var i = 0; i < table.length; i++) { var row = [ table[i].childNodes[3].firstChild.value, table[i].childNodes[4].firstChild.value, table[i].childNodes[5].firstChild.value, table[i].childNodes[6].firstChild.value, table[i].childNodes[7].firstChild.value ]; for(var x = 0; x < Services.tableInfo[i - 1].length; x++) { if(table[i].childNodes[x + 3].firstChild.value !== Services.tableInfo[i - 1][x]) { changed.push(table[i].childNodes[x + 3].id); table[i].childNodes[x + 3].firstChild.style = 'border: 1px solid red'; } } } }, appointmentCounter: function() { if (Services.service != 'Food Pantry' || !settings.apptCounter) { return false; } var table = document.getElementById(Services.elementInfo.TABLE); table = table.rows; if (table.length < 3) { return false; } var thead = table[0]; delete table[0]; var tbody = table; var missed = 0, clients = 0, appts = 0, noshows = 0; document.getElementsByClassName('pbSubsection')[0].innerHTML = document.getElementsByClassName('pbSubsection')[0].innerHTML.replace(/last/g, ''); for (var i = 0; i < table.length; i++) { if (table[i].childNodes[4].firstChild.value == 'Received Service') { clients++; missed += table[i].childNodes[3].firstChild.value == '' ? 1 : 0; appts += table[i].childNodes[3].firstChild.value != '' ? 1 : 0; } else if (table[i].childNodes[4].firstChild.value == 'No Show') { noshows++; } } document.getElementsByClassName('pbSubsection')[0].firstChild.tBodies[0].appendChild(Functions.htmlToElement('<tr><th class="last labelCol vfLabelColTextWrap" scope=row><label>Missed&New - Appts / Seen</label></th><td class="last dataCol"><span id="missed_new">' + missed + ' - ' + appts + ' / ' + clients + '</span></td><th class="last labelCol vfLabelColTextWrap" scope=row><label>No Show</label></th><td class="last dataCol"><span id="noshow">' + noshows + '</span></td></tr>')); }, parse: function(e) { var dom = document.createRange().createContextualFragment(e); var table = dom.querySelectorAll('[class="detailList"]')[0]; table = table.rows; var arr = {}; for (var i = 0; i < table.length; i++) { var key = table[i].childNodes[0].innerText.replace(/\s+/g, '_').toUpperCase(); arr[key] = table[i].childNodes[1].innerText; } return arr; }, increaseLimits: function() { if (!settings.apptLimitIncrease) { return false; } var times = document.querySelectorAll('[id^="' + Services.elementInfo.FORM + ':totals:"]'); for (var i = 0; i < times.length; i++) { var splt = times[i].innerHTML.split('/'); splt[1] = splt[1].replace('14', '18'); times[i].innerHTML = splt.join(' / '); } }, markDuplicates: function() { if (Services.service != 'Food Pantry' || !settings.dupeDetection) { return false; } var table = document.getElementById(Services.elementInfo.TABLE); table = table.rows; if (table.length < 3) { return false; } delete table[0]; var names = {}; for (var i = 2; i < table.length; i++) { var n = table[i].childNodes[1].firstChild.firstChild.innerText; if (names[n]) { names[n].push(i); } else { names[n] = [i]; } } for (var key in names) { if (names[key].length > 1) { for (var x = 0; x < names[key].length; x++) { table[names[key][x]].childNodes[1].style = 'border: 1px solid red'; } } } }, fillDate: function() { if (Services.service != 'Food Pantry') { console.log('Not Pantry'); return false; } //var Settings = localStorage.getItem('FillDateSettings') ? JSON.parse(localStorage.getItem('FillDateSettings')) : false; var Settings = sessionStorage.getItem('FillDateSettings') ? JSON.parse(sessionStorage.getItem('FillDateSettings')) : false; if (Settings && Settings.Date) { if (document.getElementById(Services.elementInfo.LOG_DATE).value != Settings.Date) { DatePicker.insertDate(Settings.Date, Services.elementInfo.LOG_DATE, true); } else { Functions.toggleLoading(false); var Exist = setInterval(function() { if (A4J.AJAX._requestsCounts['_viewRoot:status'] == 0) { // FUTURE PROOF Functions.toggleLoading(true); clearInterval(Exist); if (!Settings.Slots || Settings.Slots.length < 1) { // Check if slots avaiable alert('Finished'); //localStorage.removeItem('FillDateSettings'); sessionStorage.removeItem('FillDateSettings'); return; } var FillTime = Object.keys(Settings.Slots)[0]; if (FillTime == 'undefined' || !Settings.Slots[FillTime] || Settings.Slots[FillTime] === null) { // Check if //localStorage.removeItem('FillDateSettings'); sessionStorage.removeItem('FillDateSettings'); return; } Settings.Slots[FillTime] = Settings.Slots[FillTime] - 1; if (Settings.Slots[FillTime] < 1) { delete Settings.Slots[FillTime]; } // localStorage.setItem('FillDateSettings', JSON.stringify(Settings)); sessionStorage.setItem('FillDateSettings', JSON.stringify(Settings)); document.getElementById(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.CONTACT).value = Settings.Contact.name; document.getElementById(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.STATUS).value = 'Scheduled'; document.getElementsByName(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.APPOINTMENT_TIME)[0].value = FillTime; document.getElementById(Services.elementInfo.SAVE_BUTTON).click(); } }, 100); } } }, changeTitle: function() { var today = document.getElementsByClassName('dateFormat')[0].children[0].innerText; var day = document.getElementById(Services.elementInfo.LOG_DATE).value document.title = (today == day ? 'Today' : (new Date(day).getDay() == 0) ? 'Missed Appointments ' + day : day) + ' - ' + Services.service; }, insertSettings: function() { if (Functions.insertedSettings) { return; } var info = [ ['Quality of Life Changes', 'qolChanges'], ['New Design', 'newDesign'], ['Clickable Casenotes', 'clickableCasenotes'], ['Duplicate Detection', 'dupeDetection'], ['Appointment Counter', 'apptCounter'], ['Appointment Limit Increase', 'apptLimitIncrease'], ['Loading Screen', 'loadingScreen'], ['Change Logo', 'changeLogo'], ['Volunteer Login Tab', 'volunteerTab'], ['Work In Progress Features', 'wip'] ]; var table = '<div class="sidebarModule htmlAreaComponentModule"><div class="sidebarModuleHeader brandPrimaryBgr"><h2 class="brandPrimaryFgr">Salesforce Addons Settings</h2></div><div class="sidebarModuleBody"><table border="0" cellpadding="0" cellspacing="0"><tbody>'; for (var i = 0; i < info.length; i++) { var val = settings[info[i][1]]; table += '<tr><th class="labelCol vfLabelColTextWrap" scope="row"><label for="sets_' + info[i][1] + '">' + info[i][0] + '</label></th><td class="data2Col"><input id="sets_' + info[i][1] + '" type="checkbox" value="' + (val ? 1 : 0) + '"' + (val ? ' checked' : '') + '></td></tr>'; } table += '</tbody></table><br><center><input class="btn" id="save_sets" value="Save Settings" type="button"></center></div></div>'; document.getElementById('sidebarDiv').innerHTML = table + document.getElementById('sidebarDiv').innerHTML; document.getElementById('save_sets').addEventListener("click", Services.onSaveSettings); Functions.insertedSettings = true; }, onSaveSettings: function() { var info = [ ['Quality of Life Changes', 'qolChanges'], ['New Design', 'newDesign'], ['Clickable Casenotes', 'clickableCasenotes'], ['Duplicate Detection', 'dupeDetection'], ['Appointment Counter', 'apptCounter'], ['Appointment Limit Increase', 'apptLimitIncrease'], ['Loading Screen', 'loadingScreen'], ['Change Logo', 'changeLogo'], ['Volunteer Login Tab', 'volunteerTab'], ['Work In Progress Features', 'wip'] ]; for (var i = 0; i < info.length; i++) { settings[info[i][1]] = document.getElementById('sets_' + info[i][1]).checked ? true : false; } Functions.saveSettings(); }, onSetupTabs: function() { var se = window.open('https://pots--c.' + server + '.visual.force.com/apex/yc_servicesLog?serviceType=Food%20Pantry', '_blank'); var ma = true; if (new Date().getDay() == 6) { ma = window.open('https://pots--c.' + server + '.visual.force.com/apex/yc_servicesLog?serviceType=Food%20Pantry', '_blank'); } var na = window.open('https://pots--c.' + server + '.visual.force.com/apex/contactIntakeForm?RecordType=01237000000EbeE', '_blank'); var vl = window.open('https://www.volgistics.com/ex/touch.dll/?ID=' + volgId, '_blank'); if (!se || !ma || !na || !vl) { alert("You must allow popups from this site for this function to work properly"); } }, onPrintView: function() { var printWindow = window.open('', '', ''); printWindow.document.open(); printWindow.document.write('<html>' + document.getElementsByTagName('html')[0].innerHTML + '</html>'); printWindow.document.close(); printWindow.focus(); printWindow.document.addEventListener("DOMContentLoaded", function(event) { var table = printWindow.document.getElementById(Services.elementInfo.TABLE); table.style.fontSize = "medium"; table.deleteRow(1); if (settings.wip) { Functions.sortTable(table); } table = table.rows; var thead = table[0]; delete table[0]; var tbody = table; var len = (tbody.length) - 32 > 0 ? (tbody.length) - 32 : tbody.length; var totalBlanks = 33 + (len % 33 > 0 ? 33 - (len % 33) : 0);//33 - ((tbody.length) % 33) : 0); var tbodyLen = tbody.length; for (var i = 0; i <= totalBlanks; i++) { var row = table[table.length - 1].parentNode.insertRow(-1); for (var x = 0; x < 7; x++) { row.insertCell(-1); } } var totalDifference = tbody.length - totalBlanks - 1; for (var i = 0; i < table.length; i++) { if (i < totalDifference) { if (Services.elementInfo.CASE_NOTE) { table[i].deleteCell(Services.caseNotePosition); table[i].deleteCell(Services.caseNotePosition + 1); } else { table[i].deleteCell(2); } table[i].deleteCell(0); table[i].insertCell(-1); table[i].insertCell(-1); } for (var x = 0; x < table[i].childNodes.length; x++) { if (x >= 0 && x < 5 && i < totalDifference) { table[i].childNodes[x].innerHTML = x == 0 ? table[i].childNodes[x].firstChild.firstChild.innerHTML : table[i].childNodes[x].firstChild.value; } table[i].childNodes[x].innerHTML = i > 0 && x == 5 ? '[R] [I] [CR] [IR]' : (i > 0 && x == 6 ? i + ':' : table[i].childNodes[x].innerHTML); table[i].childNodes[x].style.border = "1px solid black"; if (x == 0) { table[i].childNodes[x].style.fontSize = "75%"; } } } thead.childNodes[0].innerHTML = 'Contact'; thead.childNodes[1].innerHTML = 'Time/DOB'; thead.childNodes[2].innerHTML = 'Ad';//Adult thead.childNodes[3].innerHTML = 'Sr';//Senior thead.childNodes[4].innerHTML = 'Cd';//Child thead.childNodes[5].innerHTML = 'Updates';//new thead.childNodes[5].style.fontSize = "small"; thead.childNodes[6].innerHTML = 'Client Signature'; thead.childNodes[6].style.width = "35%"; Functions.removeElement('dateFormat', true, printWindow.document); if (printWindow.document.getElementById(Services.elementInfo.LOG_DATE).value.length < 1) { alert("Something went wrong with time"); return printWindow.close(); } printWindow.document.getElementsByClassName('dateInput dateOnlyInput')[0].innerHTML = printWindow.document.getElementById(Services.elementInfo.LOG_DATE).value; var dinfo = printWindow.document.getElementsByClassName('detailList')[1].innerText.replace(' ', ' ').replace('\n', ' '); if (dinfo.length < 1 || !dinfo || dinfo.length > 35) { alert("Something went wrong with time"); return printWindow.close(); } printWindow.document.getElementById(Services.elementInfo.FORM + ':ld').innerHTML = '<div class="pbSubheader brandTertiaryBgr tertiaryPalette"><h3>' + dinfo + '</h3></div>'; printWindow.document.body.innerHTML = printWindow.document.getElementsByClassName("apexp")[0].innerHTML; Functions.removeElement(Services.elementInfo.FORM + ':totals', false, printWindow.document); Functions.removeElements(['pbHeader', 'pbSubsection', 'pbBottomButtons'], true, printWindow.document); printWindow.document.title = "Food Pantry Clients"; printWindow.print(); printWindow.close(); }); }, onChangeStatus: function() { var type = document.getElementById('changestatus').value; document.getElementById('changestatus').selectedIndex = 0; var change = null, ex = null; switch (type) { case '0': //no show all change = 3; break; case '1': //no show all except recv change = 3; ex = 2; break; case '2': //Scheduled All Ex Recv change = 1; ex = 2; break; default: //something not listed return; } if (change != null) { for (var i = 1; i < document.getElementsByClassName('dataRow').length; i++) { var elm = document.getElementById(Services.elementInfo.TABLE + ':' + i + ':j_id' + Services.elementInfo.STATUS); elm.selectedIndex = ex ? (elm.selectedIndex != ex ? change : elm.selectedIndex) : change; } } }, onKeyDown: function(evt) { if (evt.shiftKey && evt.altKey) { if (evt.code === "KeyC") { Services.liveChanges = false; Services.markDuplicates(); } else if (evt.code === "KeyL") { Services.liveChanges = !Services.liveChanges; Services.markDuplicates(); if (Services.liveChanges) { document.getElementById(Services.elementInfo.TABLE).addEventListener('change', Services.markDuplicates); } else { document.getElementById(Services.elementInfo.TABLE).removeEventListener('change', Services.markDuplicates); } } } }, onSave: function() { console.log("Save Clicked"); var logDate = document.getElementById(Services.elementInfo.LOG_DATE).value; var titleDate = document.title.split(' -')[0].replace('Today', document.getElementsByClassName('dateFormat')[0].children[0].innerText).replace('Missed Appointments ', ''); if (logDate != titleDate) { alert('Date Merge Detected: ' + titleDate + ' -> ' + logDate); } Functions.toggleLoading(false); var start = Date.now(); var Exist = setInterval(function() { if (A4J.AJAX._requestsCounts['_viewRoot:status'] == 0) { // FUTURE PROOF Functions.toggleLoading(true); console.log("Save finished - Took " + Math.floor((Date.now() - start)/1000) + " seconds"); clearInterval(Exist); Services.init(); } }, 100); }, onDateChange: function() { Functions.toggleLoading(false); var Exist = setInterval(function() { if (A4J.AJAX._requestsCounts['_viewRoot:status'] == 0) { // FUTURE PROOF Functions.toggleLoading(true); clearInterval(Exist); Services.resetInfo(); } }, 100); }, onTimeChange: function() { var time = document.getElementsByName(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.APPOINTMENT_TIME)[0].value; if (Services.appointmentTimes[time] && (Services.appointmentTimes[time][0] + 1 > Services.appointmentTimes[time][1])) { //alert('You are over booking for ' + time); console.log('You are over booking for ' + time); } }, onFormChange: function() { }, onContactChange: function() { var Exist = setInterval(function() { if (A4J.AJAX._requestsCounts['_viewRoot:status'] == 0) { // FUTURE PROOF clearInterval(Exist); Services.resetInfo(true); } }, 100); }, onChangeFillDate: function() { var val = document.getElementById('filldate').value; document.getElementById('filldate').selectedIndex = 0; if (Services.service != 'Food Pantry') { console.log('Not Pantry'); return false; } if (!confirm('Are you sure you want to do this ' + account + '?')) { return false; } var Settings = {}; if (document.getElementById(Services.elementInfo.TABLE).rows.length > 2 && val != '2') { return alert('Im sorry ' + account + ' this date cannot be filled. (This is not a holiday or staff meeting date)'); } Settings.Date = document.getElementById(Services.elementInfo.LOG_DATE).value; switch (val) { case '0': //staff meeting Settings.Contact = {name: 'StaffMeeting Fake', id: '0033700000Wr3e7'}; Settings.Slots = {'09:00 AM': 18, '09:30 AM': 18, '10:00 AM': 18, '10:30 AM': 10, '11:00 AM': 10, '11:30 AM': 10}; break; case '1': //holiday Settings.Contact = {name: 'Holiday Fake', id: '0033700000HMBsQ'}; Settings.Slots = {'09:00 AM': 18, '09:30 AM': 18, '10:00 AM': 18, '10:30 AM': 10, '11:00 AM': 10, '11:30 AM': 10}; if (new Date(Settings.Date).getDay() == 6) { Settings.Slots = {'09:00 AM': 18, '09:30 AM': 18, '10:00 AM': 18, '10:30 AM': 10, '11:00 AM': 10, '11:30 AM': 10, '03:30 PM': 14, '04:00 PM': 14, '04:30 PM': 10, '05:00 PM': 10}; } break; case '2': //Delete Day Settings.Contact = {}; Settings.Delete = true; break; default: //something not listed return; } if (!Settings.Contact) { console.log('No Contact'); return; } //localStorage.setItem('FillDateSettings', JSON.stringify(Settings)); sessionStorage.setItem('FillDateSettings', JSON.stringify(Settings)); Services.fillDate(); }, getService: function() { console.log('Checking for service log.'); for (var i = 0; i < document.getElementsByClassName('mainTitle').length; i++) { if (document.getElementsByClassName('mainTitle')[i].innerHTML.includes('Services Log')) { return document.getElementsByClassName('mainTitle')[i].innerHTML.replace('Services Log ', ''); } } return null; }, getElementInfo: function() { var fid = document.getElementsByClassName('apexp')[0].firstChild.id; var telm = document.getElementsByClassName('list')[0].id; var thead = document.getElementById(telm).tHead.rows[0].cells; var info = {}; for (var i = 0; i < thead.length; i++) { var hid = parseInt(thead[i].id.split(':')[4].replace(/j_id|header/g, '')) + 1; var hname = thead[i].textContent.replace('# ', '').replace(' ', '_').toUpperCase(); if (hname.length == 0) { hname = "DEL"; } if (hname == "CONTACT") { info.SEARCH_CONTACT = hid + 2; } if (hname == "NAME" || hname == "CASE_NOTE") { hname = "CASE_NOTE"; Services.caseNotePosition = i; } info[hname] = hid; } info.FORM = fid; info.TABLE = telm; info.SAVE_BUTTON = document.getElementById(fid + ":j_id" + (parseInt(fid.substr(-2)) + 1)).firstChild.id; info.SAVE_BUTTON_BOTTOM = document.getElementById(fid + ":j_id" + (parseInt(fid.substr(-2)) + 1) + ":bottom").firstChild.id; info.BUTTONS = fid + ":j_id" + (parseInt(fid.substr(-2)) + 1); info.LOG_DATE = document.getElementsByClassName('dateInput dateOnlyInput')[0].firstChild.id; console.log(info); return info; }, resetInfo: function(cc = false) { var SaveEvent = document.getElementById(Services.elementInfo.SAVE_BUTTON); if (SaveEvent && SaveEvent.removeEventListener) { SaveEvent.removeEventListener('click', Services.onSave); } document.getElementById(Services.elementInfo.SAVE_BUTTON).addEventListener('click', Services.onSave); var SaveEventBottom = document.getElementById(Services.elementInfo.SAVE_BUTTON_BOTTOM); if (SaveEventBottom && SaveEventBottom.removeEventListener) { SaveEventBottom.removeEventListener('click', Services.onSave); } document.getElementById(Services.elementInfo.SAVE_BUTTON_BOTTOM).addEventListener('click', Services.onSave); //var FormEvent = document.getElementById(Services.elementInfo.FORM); //if (FormEvent && FormEvent.removeEventListener) { //FormEvent.removeEventListener('change', Services.onFormChange); //} //document.getElementById(Services.elementInfo.FORM).addEventListener('change', Services.onFormChange); if (Services.elementInfo.CONTACT) { var ContactEvent = document.getElementById(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.CONTACT); if (ContactEvent && ContactEvent.removeEventListener) { ContactEvent.removeEventListener('change', Services.onContactChange); } document.getElementById(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.CONTACT).addEventListener('change', Services.onContactChange); var ContactEvent2 = document.getElementById(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.CONTACT + '_lkid'); if (ContactEvent2 && ContactEvent2.removeEventListener) { ContactEvent2.removeEventListener('change', Services.onContactChange); } document.getElementById(Services.elementInfo.TABLE + ':0:j_id' + Services.elementInfo.CONTACT + '_lkid').addEventListener('change', Services.onContactChange); } if (!cc) { Functions.addLoadingScreen(); Services.appointmentTotals(); Services.increaseLimits(); } Services.clickableCaseNotes(); Services.loadTable(); Services.markDuplicates(); var DateEvent = document.getElementById(Services.elementInfo.LOG_DATE); if (DateEvent && DateEvent.removeEventListener) { DateEvent.removeEventListener('change', Services.onDateChange); } document.getElementById(Services.elementInfo.LOG_DATE).addEventListener('change', Services.onDateChange); Services.changeTitle(); if (!cc) { Services.fillDate(); Services.appointmentCounter(); } } }; var Functions = { insertedSettings: false, init: function() { account = Functions.getAccount(); Functions.loadSettings(); Functions.insertVolunteerButton(); }, getAccount: function() { return document.getElementById('userNavLabel') ? document.getElementById('userNavLabel').innerHTML.split(' ')[0] : 'Unknown'; }, loadSettings: function() { var json = localStorage.getItem('SASettings') ? JSON.parse(localStorage.getItem('SASettings')) : {}; json[account] = json[account] ? json[account] : {}; for (var s in settings) { settings[s] = s in json[account] ? json[account][s] : settings[s]; } console.log('Settings Loaded'); }, saveSettings: function() { var json = localStorage.getItem('SASettings') ? JSON.parse(localStorage.getItem('SASettings')) : {}; json[account] = json[account] ? json[account] : {}; for (var s in settings) { json[account][s] = settings[s]; } localStorage.setItem('SASettings', JSON.stringify(json)); console.log('Settings Saved'); alert('Change will not take affect till you refresh'); }, insertVolunteerButton: function() { if (!settings.volunteerTab) { return false; } if (document.getElementsByClassName('sidebarModuleBody').length > 0) { document.getElementsByClassName('sidebarModuleBody')[3].innerHTML = document.getElementsByClassName('sidebarModuleBody')[3].innerHTML.replace(' ', ''); document.getElementsByClassName('sidebarModuleBody')[3].appendChild(Functions.htmlToElement('<a href="https://www.volgistics.com/ex/touch.dll/?ID=' + volgId + '" target="_blank"><img alt="Volunteer Login" src="https://i.imgur.com/NQuJH6U.png"></a>')); } }, htmlToElement: function(html) { var template = document.createElement('template'); template.innerHTML = html; return template.content.firstChild; }, removeElement: function(id, isClass = false, dom = document) { var elem; if (isClass) { elem = dom.getElementsByClassName(id)[0]; } else { elem = dom.getElementById(id); } if (elem) { return elem.parentNode.removeChild(elem); } return false; }, removeElements: function(elements, isClass = false, dom = document) { for (var i = 0; i < elements.length; i++) { Functions.removeElement(elements[i], isClass, dom); } }, addLoadingScreen: function() { //if (!Functions.loadingScreen) if (!settings.loadingScreen) { return false; } var style = "#Loading { position: fixed; left: 0; top: 0; z-index: 999; width: 100%; height: 100%; overflow: visible; background: #333 url('https://i.imgur.com/bfkGrIm.gif') no-repeat center center; opacity:0.6; filter: invert(100%); -webkit-filter: invert(100%);}"; Functions.addStyle(style); var Loading = document.createElement('div'); Loading.style.display = "none"; Loading.setAttribute('id','Loading'); //document.getElementsByClassName('pbBody')[0].appendChild(Loading); document.body.appendChild(Loading); }, toggleLoading: function(display) { //if (!Functions.loadingScreen) if (!settings.loadingScreen) { return false; } document.getElementById('Loading').style.display = display ? 'none' : 'block'; }, addStyle: function(css) { var head = document.head || document.getElementsByTagName('head')[0]; if (head) { var style = document.createElement("style"); style.type = "text/css"; style.appendChild(document.createTextNode(css)); head.appendChild(style); } }, getParameterByName: function(name) { var url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }, getPageByPath: function() { var path = window.location.pathname; if (path.length <= 1) { return false; } switch (path.substring(1, 4)) { case '001': return 'Account'; break; case '003': return path.substring(4, 5) != '/' && path.length > 6 ? 'Contact' : false; break; case '069': return 'Note'; break; case 'a0D': return Functions.getParameterByName('rlid') ? 'Income' : false; break; default: return false; } }, changeStyle: function() { if (!settings.newDesign) { return false; } Functions.addStyle ( ` .homeTab .tertiaryPalette, .individualPalette .homeBlock .tertiaryPalette, .layoutEdit .individualPalette .homeBlock .tertiaryPalette { background-color: #` + color + `; border-color: #` + color + `; } body button, body .x-btn, body .btn, body .btnDisabled, body .btnCancel, body .menuButton .menuButtonButton { color: #333; margin: 1px; padding: 2px 3px; border: 1px solid #` + color + `; border-bottom-color: #` + color + `; background: #e8e8e9 url(/img/alohaSkin/btn_sprite.png) repeat-x right top; font-weight: bold; font-size: .9em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } ` ); }, changeTableStyle: function() { if (!settings.newDesign) { return false; } Functions.addStyle ( ` body .pbBody table.list tr.headerRow td, body .pbBody table.list tr.headerRow th { background: #f2f3f3; border-width: 0 0 1px 1px; border-color: #1797c0; color: #000; font-size: .9em; font-weight: bold; padding: 5px 2px 4px 5px; } body .bRelatedList .pbBody table.list, body .apexp .pbBody table.list { border: 1px solid #1797c0; } body .pbBody table.list tr th, body .pbBody table.list tr td { border: 1px solid #1797c0; color: #000; } ` ); }, changeLogo: function() { if (!settings.changeLogo) { return false; } document.getElementsByClassName('left')[0].innerHTML = '<div style="height:55px;"><img src="https://c.' + server + '.content.force.com/servlet/servlet.ImageServer?id=015370000002O6a&oid=00D37000000IlcA&lastMod=1445451910000" alt="" id="phHeaderLogoImage" onload="javascript:scaleImage(this, 55,300);this.scaled=true;" title="" width="42" height="55"></div>'; }, sortTable: function(table) { var rows, switching, i, x, y, shouldSwitch; switching = true; while (switching) { switching = false; rows = table.rows; for (i = 1; i < (rows.length - 1); i++) { shouldSwitch = false; x = rows[i].getElementsByTagName("TD")[3]; y = rows[i + 1].getElementsByTagName("TD")[3]; if (x.firstChild.value.toLowerCase() > y.firstChild.value.toLowerCase()) { shouldSwitch = true; break; } } if (shouldSwitch) { rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); switching = true; } } }, concourseLevel: function() { let items = document.getElementById('tsid-menuItems') || null; if (items) { items.insertAdjacentHTML('beforeend', '<hr class="menuSeparator"><a href="#" class="menuButtonMenuLink" id="setupTabs_basement">Concourse Level</a>'); document.getElementById('setupTabs_basement').addEventListener('click', () => { var sh = window.open('https://pots--c.' + server + '.visual.force.com/apex/yc_servicesLog?serviceType=Showers', '_blank'); var ma = window.open('https://pots--c.' + server + '.visual.force.com/apex/yc_servicesLog?serviceType=Mail', '_blank'); var cl = window.open('https://pots--c.' + server + '.visual.force.com/apex/yc_servicesLog?serviceType=Clothing', '_blank'); var hc = true; if ([2, 4].includes(new Date().getDay())) { hc = window.open('https://pots--c.' + server + '.visual.force.com/apex/yc_servicesLog?serviceType=Haircuts', '_blank'); } var cs = window.open('https://pots--c.' + server + '.visual.force.com/apex/contactIntakeForm?RecordType=01237000000EbeE', '_blank'); if (!ma || !sh || !hc || !cl || !cs) { alert("You must allow popups from this site for this function to work properly"); } }); } }, GET: function(url, callback) { Functions.xmlCall = callback; Functions.xmlHttp = new XMLHttpRequest(); Functions.xmlHttp.onreadystatechange = Functions.XHChange; Functions.xmlHttp.open('GET', url, true); Functions.xmlHttp.send(null); }, POST: function(url, params, callback) { Functions.xmlCall = callback; Functions.xmlHttp = new XMLHttpRequest(); Functions.xmlHttp.onreadystatechange = Functions.XHChange; Functions.xmlHttp.open('POST', url, true); Functions.xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); Functions.xmlHttp.send(params); }, XHChange: function(extra = null) { if(Functions.xmlHttp.readyState == 4 && Functions.xmlHttp.status == 200) { Functions.xmlCall(Functions.xmlHttp.responseText); } } }; })();