Allscripts IntegrationMM

OpenEMR integration with Allscript ePrescribe

  1. // ==UserScript==
  2. // @name Allscripts IntegrationMM
  3. // @namespace http://jewelmirror.com
  4. // @version 0.2
  5. // @description OpenEMR integration with Allscript ePrescribe
  6. // @include https://eprescribe.allscripts.com/*
  7. // @include */openemr/interface/main/main_title.php
  8. // @include */openemr/interface/patient_file/summary/demographics.php*
  9. // @include */opendev/master/interface/main/main_title.php
  10. // @include */opendev/master/interface/patient_file/summary/demographics.php*
  11. // @require http://code.jquery.com/jquery-2.0.3.min.js
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @grant GM_setClipboard
  15. // @grant GM_xmlhttpRequest
  16. // ==/UserScript==
  17.  
  18. // +-----------------------------------------------------------------------------+
  19. // Copyright (C) 2013 IntegralEMR LLC <kevin.y@integralemr.com>
  20. //
  21. //
  22. // This program is free software; you can redistribute it and/or
  23. // modify it under the terms of the GNU General Public License
  24. // as published by the Free Software Foundation; either version 2
  25. // of the License, or (at your option) any later version.
  26. //
  27. //
  28. // This program is distributed in the hope that it will be useful,
  29. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  31. // GNU General Public License for more details.
  32. //
  33. //
  34. // A copy of the GNU General Public License is included along with this program:
  35. // openemr/interface/login/GnuGPL.html
  36. // For more information write to the Free Software
  37. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  38. //
  39. // Author: Kevin Yeh <kevin.y@integralemr.com>
  40. // Contributions: Marcin Matuszkiewicz <marcin@jewelmirror.com>
  41. //
  42. // +------------------------------------------------------------------------------+
  43.  
  44. var pages={
  45. interstitial: "/InterstitialAd.aspx",
  46. addPatient: "/AddPatient.aspx",
  47. def: "/default.aspx",
  48. allergy: "/PatientAllergy.aspx",
  49. search: "/SearchPatient.aspx",
  50. Login: "/Login.aspx",
  51. oemrMain: "/interface/main/main_title.php",
  52. oemrDemo: "/interface/patient_file/summary/demographics.php",
  53. oemrDemoFull: "/interface/patient_file/summary/demographics_full.php"
  54. };
  55.  
  56. var asContID={
  57. lblPatientName: "ctl00_lblPatientName",
  58. lblGenderDOB: "ctl00_lblGenderDob",
  59. txtPatLNAME: "ctl00_ContentPlaceHolder1_PatientSearch_txtLastName",
  60. txtPatFNAME: "ctl00_ContentPlaceHolder1_PatientSearch_txtFirstName",
  61. txtPatDOB: "ctl00_ContentPlaceHolder1_PatientSearch_rdiDOB",
  62. tblViewPatients: "ctl00_ContentPlaceHolder1_grdViewPatients_ctl00",
  63. btnSearch: "ctl00_ContentPlaceHolder1_PatientSearch_btnSearch"
  64. };
  65.  
  66.  
  67.  
  68. function resetInfo()
  69. {
  70. GM_setValue("OpenEMR Server","");
  71. GM_setValue("OpenEMR Session","");
  72. // Patient Info
  73. GM_setValue("patientFNAME","");
  74. GM_setValue("patientLNAME","");
  75. GM_setValue("patientDOBYear","");
  76. GM_setValue("patientDOBMonth","");
  77. GM_setValue("patientDOBDay","");
  78. // Prescription Info
  79. GM_setValue("MedName",""); // The Med Name
  80. GM_setValue("MedSTR",""); // The Med Strength
  81. GM_setValue("MedSIG",""); // The Med SIG
  82. GM_setValue("searchState","not found");
  83. }
  84.  
  85. //TODO: Can I add a dialog div that displays the drugs from OpenEMR?
  86.  
  87. function setOEMRDOB(DOB)
  88. {
  89. var DOBParts;
  90. var DOBYear;
  91. var DOBMonth;
  92. var DOBDay;
  93. if(DOB.indexOf("-")===4)
  94. {
  95. DOBParts=DOB.split("-");
  96. DOBYear=DOBParts[0].substr(0,4);
  97. DOBMonth=DOBParts[1].substr(0,2);
  98. DOBDay=DOBParts[2].substr(0,2);
  99. }
  100. else if(DOB.indexOf("/")==2)
  101. {
  102. DOBParts=DOB.split("/");
  103. DOBMonth=DOBParts[0].substr(0,2);
  104. DOBDay=DOBParts[1].substr(0,2);
  105. DOBYear=DOBParts[2].substr(0,4);
  106. }
  107. GM_setValue("patientDOBYear",DOBYear);
  108. GM_setValue("patientDOBMonth",DOBMonth);
  109. GM_setValue("patientDOBDay",DOBDay);
  110. }
  111.  
  112. function safeFocus(id)
  113. {
  114. var element = document.getElementById(id);
  115. if (element != null)
  116. {
  117. element.focus();
  118. }
  119. }
  120. function safeClick(id)
  121. {
  122. var element = document.getElementById(id);
  123. if (element != null)
  124. {
  125. element.click();
  126. }
  127.  
  128. }
  129.  
  130. function safeFocusVal(id,value)
  131. {
  132. var element = document.getElementById(id);
  133. if (element !== null)
  134. {
  135. element.focus();
  136. element.value=value;
  137. }
  138. }
  139.  
  140. function patDOB()
  141. {
  142. retVal=GM_getValue("patientDOBMonth");
  143. retVal=retVal.concat("/");
  144. retVal=retVal.concat(GM_getValue("patientDOBDay"));
  145. retVal=retVal.concat("/");
  146. retVal=retVal.concat(GM_getValue("patientDOBYear"));
  147. return retVal;
  148. }
  149.  
  150. function asPopulateAndSearchPatientInfo()
  151. {
  152. // window.alert("Pause");
  153. safeFocusVal(asContID['txtPatLNAME'],GM_getValue("patientLNAME"));
  154.  
  155.  
  156. safeFocusVal(asContID['txtPatFNAME'],GM_getValue("patientFNAME"));
  157. GM_setValue("searchState","searching") ;
  158. safeClick(asContID['btnSearch']);
  159. }
  160.  
  161. function asFindPatientInResults()
  162. {
  163. var myHTML=$(this).html();
  164. var foundPatient=myHTML.indexOf(GM_getValue("patientLNAME")+", "+GM_getValue("patientFNAME"));
  165. if(foundPatient>=0)
  166. {
  167.  
  168. var foundDOB=myHTML.indexOf(patDOB(),foundPatient);
  169. if(foundDOB>=0)
  170. {
  171. rowID=$(this).find("input[id]").attr("id");
  172. safeClick(rowID);
  173. }
  174. }
  175. }
  176.  
  177. function asCheckPatientInfo()
  178. {
  179. var pn=$("#"+asContID['lblPatientName']).text();
  180. var foundPatient=pn.indexOf(GM_getValue("patientLNAME")+", "+GM_getValue("patientFNAME"));
  181. if(foundPatient===0)
  182. {
  183. DOB=$("#"+asContID['lblGenderDOB']).text();
  184. foundDOB=DOB.indexOf(patDOB());
  185. if(foundDOB>=0)
  186. {
  187. GM_setValue("searchState","found");
  188. }
  189.  
  190. }
  191.  
  192. }
  193. function asAddOpenEMRSearch()
  194. {
  195. var addPtButton=$("#ctl00_ContentPlaceHolder1_PatientSearch_AddPanel");
  196. var openSearch=$("<input type='button' id='openemr_search' value='OpenEMR '/>");
  197. openSearch.click(asPopulateAndSearchPatientInfo);
  198. var searchTd=$("<td></td>");
  199. searchTd.append(openSearch);
  200. addPtButton.after(openSearch);
  201. }
  202. function asSearchDispatcher()
  203. {
  204. if($("#txtUserName").length>0)
  205. {
  206. // This is the initial login screen and we should just abort.
  207. return;
  208. }
  209. asAddOpenEMRSearch();
  210. asCheckPatientInfo();
  211. if(GM_getValue("searchState").indexOf("searching")==0)
  212. {
  213. var tblViewPatients=$("#"+asContID['tblViewPatients']);
  214. if(tblViewPatients.length>0)
  215. {
  216. GM_setValue("searchState","results scanning");
  217. rows=tblViewPatients.find("tbody tr");
  218. rows.each(asFindPatientInResults);
  219. }
  220. }
  221. else if(GM_getValue("searchState").indexOf("not found")==0)
  222. {
  223. asPopulateAndSearchPatientInfo();
  224. }
  225. }
  226.  
  227. var asAddPatientControls={
  228. btnAllergy: "ctl00_ContentPlaceHolder1_btnAddAllergy",
  229. txtPatFNAME: "ctl00_ContentPlaceHolder1_txtFName",
  230. txtPatLNAME: "ctl00_ContentPlaceHolder1_txtLName",
  231. txtPatDOB: "ctl00_ContentPlaceHolder1_txtDOB",
  232. txtPatAddr1: "ctl00_ContentPlaceHolder1_txtAddress1",
  233. txtPatPhone: "ctl00_ContentPlaceHolder1_txtPhone",
  234. txtPatMobilePhone: "ctl00_ContentPlaceHolder1_txtMobilePhone",
  235. txtPatCity: "ctl00_ContentPlaceHolder1_txtCity",
  236. txtPatZIP: "ctl00_ContentPlaceHolder1_txtZip",
  237. txtPatMRN: "ctl00_ContentPlaceHolder1_txtMRN",
  238. selGender: "ctl00_ContentPlaceHolder1_DDLGender",
  239. selState:"ctl00_ContentPlaceHolder1_ddlState"
  240. };
  241.  
  242. function chooseSelect(control,option)
  243. {
  244. sel=document.getElementById(control);
  245.  
  246. for(idx=0;idx<sel.options.length;idx++)
  247. {
  248. opt=sel.options[idx];
  249. if(opt.value==option)
  250. {
  251. sel.selectedIndex=idx;
  252. opt.click();
  253. }
  254. }
  255. }
  256. function removeTags(text,tag,endTag)
  257. {
  258. tag="<"+tag;
  259. loc=text.indexOf(tag);
  260. while(loc>=0)
  261. {
  262. endMarker=text.indexOf(endTag,loc+tag.length);
  263. text=text.substr(0,loc)+text.substr(endMarker+endTag.length);
  264.  
  265. loc=text.indexOf(tag);
  266. }
  267. return text;
  268. }
  269. function extractTag(text,tag,endTag)
  270. {
  271. loc=text.indexOf(tag);
  272. end=text.lastIndexOf(endTag);
  273. return text.substr(loc,end+endTag.length-loc);
  274. }
  275.  
  276. // Get the text from the OpenEMR form and populate the appropriate Allscripts control.
  277. function setAddPatientText(asControl,oemrcontrol)
  278. {
  279. val=$("#"+oemrcontrol).val();
  280. $("#"+asAddPatientControls[asControl]).val(val);
  281. }
  282.  
  283. // Use the results of the ajax request to OpenEMR to get the patient's demographics
  284. function processOEMRDemographics(data)
  285. {
  286. $("#demoLoading").hide();
  287. var text=data.responseText;
  288. text=text.substr(text.indexOf("<form"));
  289. text=removeTags(text,"img",">");
  290. text=removeTags(text,"a","</a>");
  291. text=extractTag(text,"<form","</form>");
  292. $("#gmOEMRInfo").append(text);
  293. $("#gmOEMRInfo img").remove();
  294. patID=$("#gmOEMRInfo").find("input[name='form_pubpid']").val();
  295. $("#"+asAddPatientControls['txtPatMRN']).val(patID);
  296. setAddPatientText('txtPatFNAME',"form_fname");
  297. setAddPatientText('txtPatLNAME',"form_lname");
  298. setAddPatientText('txtPatLNAME',"form_lname");
  299. setAddPatientText('txtPatZIP',"form_postal_code");
  300. setAddPatientText('txtPatAddr1',"form_street");
  301. setAddPatientText('txtPatCity',"form_city");
  302. setAddPatientText('txtPatPhone',"form_phone_home");
  303. setAddPatientText('txtPatMobilePhone',"form_phone_cell");
  304.  
  305.  
  306. var sex=$("#form_sex").val();
  307. var state=$("#form_state").val();
  308. chooseSelect(asAddPatientControls['selGender'],sex[0]);
  309. chooseSelect(asAddPatientControls['selState'],state);
  310.  
  311. var dob=$("#form_DOB").val();
  312. setOEMRDOB(dob);
  313. safeFocus(asAddPatientControls['txtPatDOB']);
  314. $("#"+asAddPatientControls['txtPatDOB']).val(patDOB());
  315. // $("#"+asAddPatientControls['txtPatDOB']).blur();
  316. }
  317. function loadDemographicsFromOpenEMR()
  318. {
  319. var demoFullURL=GM_getValue("OpenEMR Server")+pages['oemrDemoFull'];
  320. var loading=$("#demoLoading");
  321. if(loading.length===0)
  322. {
  323. $("#gmOEMRImport").before("<SPAN id='demoLoading' float:right>Loading</SPAN>");
  324. loading=$("#demoLoading");
  325. }
  326. loading.show();
  327. GM_xmlhttpRequest({
  328. method: "GET",
  329. url: demoFullURL,
  330. onload: processOEMRDemographics
  331. });
  332. }
  333.  
  334.  
  335.  
  336. // Put the control to request patient data from OpenEMR on the Allscripts form.
  337. function asAddPatientUpdate()
  338. {
  339.  
  340. btnAll=$("#"+asAddPatientControls['btnAllergy']);
  341. btnAll.after("<DIV id='GMControls' style='float:right;'></DIV>");
  342. $("#GMControls").append("<input type='button' value='Load from OpenEMR' id='gmOEMRImport' >");
  343. $("#GMControls").append("<div id='gmOEMRInfo' style='display:none;' >OpenEMRInfo</DIV");
  344.  
  345. $("#gmOEMRImport").click(loadDemographicsFromOpenEMR);
  346. }
  347.  
  348. function OpenEMRDemographics()
  349. {
  350. resetInfo();
  351. var location = window.location.href;
  352. var server=location.substr(0,location.indexOf(pages['oemrDemo']));
  353. GM_setValue("OpenEMR Server",server);
  354. var whoDIV=$("td.label:contains('DOB:')").parents("div.tab");
  355.  
  356. var DOB=whoDIV.find("td.label:contains('DOB:')").next();
  357. setOEMRDOB(DOB.text());
  358. var Gender=whoDIV.find("td.label:contains('Sex:')").next();
  359. var patName=$("span.title").text();
  360. var splitName=patName.replace(" ","").split(",");
  361. var fname=splitName[1];
  362. var lname=splitName[0];
  363.  
  364. var patIDHREF=$("span:contains('Delete')").parent("a.css_button[href]").attr("href");
  365. var deleterHREFInfo="../deleter.php?patient=";
  366. var loc=patIDHREF.indexOf("deleterHREFInfo")+deleterHREFInfo.length+1;
  367. var patID=parseInt(patIDHREF.substr(loc));
  368.  
  369. GM_setValue("patientPID",patID);
  370. GM_setValue("patientFNAME",fname);
  371. GM_setValue("patientLNAME",lname);
  372. }
  373.  
  374. function OpenEMRAddLink()
  375. {
  376. var allScriptsLink=$("<a id='gmASLink' class='css_button_small' style='float:right;'>"+"<span>Allscripts</span>"+"</a>");
  377. var targetCB=$("<input type='checkbox' id='gmASChoice' title='Open Allscripts in New Window'/>");
  378. $("#current_patient_block").append(allScriptsLink).append(targetCB);
  379. allScriptsLink.click(function()
  380. {
  381. if($("#gmASChoice:checked").length===0)
  382. {
  383. if(window.top.left_nav.document.forms[0].cb_bot.checked)
  384. {
  385. window.top.RBot.location="https://eprescribe.allscripts.com/SearchPatient.aspx";
  386. window.top.left_nav.botName='All2';
  387. }
  388. else
  389. {
  390. window.top.RTop.location="https://eprescribe.allscripts.com/SearchPatient.aspx";
  391. window.top.left_nav.topName='All2';
  392. }
  393. }
  394. else
  395. {
  396. var winAS=window.open("https://eprescribe.allscripts.com/SearchPatient.aspx","Allscripts");
  397. winAS.focus();
  398. }
  399. GM_setValue("searchState","not found");
  400. });
  401. }
  402.  
  403. var loc=window.location.href;
  404. if(loc.indexOf(pages['interstitial'])>=0)
  405. {
  406. var adButton = document.getElementById("adControl_closeButton");
  407. if (adButton != null)
  408. {
  409. adButton.click();
  410. }
  411. }
  412.  
  413. if(loc.indexOf("SelectAccountAndSite.aspx")>=0)
  414. {
  415.  
  416. }
  417. else if((loc.indexOf(pages['Login'])>=0) || (loc.indexOf(pages['search'])>=0) || (loc.indexOf("https://eprescribe.allscripts.com/")>=0) )
  418. {
  419. $(window).load(asSearchDispatcher);
  420. }
  421.  
  422.  
  423.  
  424. handlers=[
  425. {location: pages['oemrDemo'], handler: OpenEMRDemographics },
  426. {location: pages['oemrMain'], handler: OpenEMRAddLink },
  427. {location: pages['addPatient'], handler: asAddPatientUpdate}
  428. ];
  429.  
  430. function dispatch(location)
  431. {
  432. for(var dispatchIdx=0;dispatchIdx<handlers.length;dispatchIdx++)
  433. {
  434. var dispatchEntry=handlers[dispatchIdx];
  435. if(location.indexOf(dispatchEntry.location)>=0)
  436. {
  437. $(document).ready(dispatchEntry.handler);
  438. }
  439. }
  440. }
  441. dispatch(loc);