jssz12320 order page optimize

optimize jiangsu suzhou 12320 order page,different color highlight for even and odd rows, hover on doctor row to show related doctor's info

As of 2018-12-17. See the latest version.

// ==UserScript==
// @namespace ATGT
// @name     jssz12320 order page optimize
// @name:zh-CN     苏州市12320预约界面优化
// @description optimize jiangsu suzhou 12320 order page,different color highlight for even and odd rows, hover on doctor row to show related doctor's info
// @description:zh-CN		 苏州市12320预约界面优化,奇偶行用不同颜色显示,鼠标放到对应的医生行即显示医生信息
// @version  1.3
// @match    http://www.jssz12320.cn/*
// @match    https://www.jssz12320.cn/*
// @grant    GM.xmlHttpRequest
// @run-at   document-end
// ==/UserScript==

/*
 * v1.3: 2018 Dec 17
 *		Use unpriviliged XMLHttpRequest instead of GM.xmlHttpRequest for fixing exception when privacy.firstparty.isolate=true.
 * v1.2: 2018 Sep 29
 *		Update URL match.
 * v1.1:
 *		Update Description
 * v1:
 *		colorize even and odd row, show doctor info when hover on doctor row.
 */

//alert("hello");
console.log("!!!!!!!!!!!!!!!!!!!!!!jssz12320!!!!!!!!!!!!!!!!!!!!!!!");

function injectFunction(func) {
  var script = document.createElement('script');
  //script.className = "injectFunction";
  //script.appendChild(document.createTextNode('('+ func +')();'));
  script.appendChild(document.createTextNode('(function (){' + '(' + func + ')();' + '})();'));
  try {
    (document.body || document.head || document.documentElement).appendChild(script);
  } catch(e) {
    console.error("Can not inject function ", func);
  }
}

injectFunction(function () {
  //return;
  if (!document.URL.match(/^https?:\/\/www\.jssz12320\.cn:8080\/hrs\/step03/g)) {
    console.log("URL not match, all functions disabled.");
    return;
  }
  
  console.log("12320 script process start.");

  (function removeHeadDivs() {
    document.querySelector(".step03").remove();
    document.querySelector("#head").remove();
    var r0 = document.querySelector(".right-cont");
    r0.style.borderTop = "1px";
    r0.style.marginTop = "0";
  })();

  (function addStyles(){
    var css = document.createElement("style");
    var styles = 'tr.evenRow { background-color: lightcyan; }\
tr.oddRow  { background-color: antiquewhite; }\
.col-left { padding: 10px; }\
';
    if (css.styleSheet) css.styleSheet.cssText = styles;
    else css.appendChild(document.createTextNode(styles));
    document.getElementsByTagName("head")[0].appendChild(css);
  })();

  var drDetail = (function addDrDetail() {
    var colLeft = document.querySelector(".col-left");
    var drDetail = document.createElement("DIV");
    drDetail.innerHTML = "doctor detail";
    drDetail.id = "doctorInfo2";
    drDetail.style.border = "1px solid";
    drDetail.style.float = "left";
    drDetail.style.position = "sticky";
    //drDetail.style.bottom = "10px";
    drDetail.style.top = "10px";
    drDetail.style.left = "5px";
    drDetail.style.width = colLeft.offsetWidth+"px";
    colLeft.parentNode.insertBefore(drDetail, colLeft);

    document.querySelector("#wrapper").style.width = "100%";
    document.querySelector(".col-right").style.float = "left";
    return drDetail;
  })();

  function objToUrlParam(obj) {
    var str = Object.keys(obj).map(function(key) {
      return key + '=' + encodeURIComponent(obj[key]);
    }).join('&')
    //console.log("objToUrlParam ", str);
    return str;
  }

  var drInfoCache = {};
  var drInfoKeyLast = null;

  function getDoctorInfoEx(node, hospName, depName, docName, docRank, docIntro, docMajor, docPhotoURL, docRate, multipleHosp) {
    //console.log("getDoctorInfoEx", arguments);
    var autoNode = document.querySelector("#doctorInfo2");
    var drInfoKey = [ hospName, depName, docName, docRank, docRate].join('&');
    console.log("request dr info of ", drInfoKey);
    if (drInfoKey in drInfoCache) {
      console.log("++++++ cache hit");
      if (drInfoKey != drInfoKeyLast) {
        autoNode.innerHTML = drInfoCache[drInfoKey];
        drInfoKeyLast = drInfoKey;
      }
      return;
    } else {
      console.log("------ cache miss");
    }
    autoNode.innerHTML = '查询中。。。请稍等。。。';//清除之前的load内容
    var xhr = new XMLHttpRequest();
    var post_data = objToUrlParam({
        'doctorInfo.hospName': hospName,
        'doctorInfo.depName': depName,
        'doctorInfo.docName': docName,
        'doctorInfo.docRank': docRank,
        'doctorInfo.docIntro': docIntro,
        'doctorInfo.docMajor': docMajor,
        'doctorInfo.docPhotoURL': docPhotoURL,
        'doctorInfo.docRate': docRate,
        'doctorInfo.multipleHosp': multipleHosp,
      });
    xhr.addEventListener("load", function (evt) {
        console.log("getDoctorInfoEx done");
        autoNode.innerHTML = this.responseText;
        drInfoKeyLast = drInfoKey;
        drInfoCache[drInfoKey] = this.responseText;
      });
    xhr.addEventListener("error", function (evt) {
        console.error("getDoctorInfoEx fail");
        autoNode.innerHTML = '加载失败!';
      });
    xhr.open("POST", "queryDoctorInfo");
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(post_data);
    console.log("getDoctorInfoEx exit");
  }
  //console.log(getDoctorInfoEx.toString());
  var script = document.createElement("script");
  script.textContent = getDoctorInfoEx.toString();
  document.body.appendChild(script);

  function procSchedTable() {
    var pipeTable = document.querySelector("#pipetable");
    //console.log("pipeTable", pipeTable);
    if (!pipeTable)
      return;

    var drInfo = document.querySelector(".schedule").querySelector("#doctorInfo");
    drInfo.onmouseover = drInfo.onmouseout = null;
    drInfo.remove();

    var drRows = pipeTable.querySelectorAll("TR");
    //console.log(drRows);
    var drInfoHandlers = {};
    for (var i=1; i<drRows.length; i++){
      var drRow = drRows[i];
      var actRowIdx = Math.floor((i+1)/2);
      console.log("row ", i, " actRowIdx ", actRowIdx);
      drRow.className += (actRowIdx%2 == 0) ? " evenRow" : " oddRow";
      var dr = drRow.firstElementChild;
      //console.log(dr);
      //if (!dr.onclick)
      //  continue;
      if (actRowIdx in drInfoHandlers) {
        drRow.onmouseover = drRow.onclick = dr.onclick = drInfoHandlers[actRowIdx];
        //console.log("found drInfoHandlers");
      } else {
        var r0 = dr.onclick.toString();
        r0 = r0.slice(r0.indexOf("getDoctorInfo(") + "getDoctorInfo(".length, r0.lastIndexOf(")"));
        //console.log("r0", r0);
        var r1 = r0.split(/\'\s*,\s*\'/);
        //console.log("r1", r1);
        var r2 = r1.shift().split(/,\'/);
        var r3 = r1.pop().split(/\'/).shift();
        r0 = r2.concat(r1).concat(r3);
        r0[0] = "";
        console.log("r0", r0);
        (function () {
          var r4 = JSON.parse(JSON.stringify(r0)); // make a local deep copy of r0
          dr.onclick = function(event) { getDoctorInfoEx.apply(null, r4); }
          drInfoHandlers[actRowIdx] = drRow.onmouseover = drRow.onclick = dr.onclick;
          //console.log("update drInfoHandlers");
        })();
        //console.log("dr.onclick.toString()", dr.onclick.toString());
      }

      console.log("row ", i, " end");
    }
    console.log("procSchedTable done");
  }

  (function waitForScheduleTable() {
    // Options for the observer (which mutations to observe)
    var config = { /*attributes: true,*/ childList: true };
    // Callback function to execute when mutations are observed
    var callback = function(mutationsList) {
      for(var mutation of mutationsList) {
        if (mutation.type == 'childList' && mutation.addedNodes.length) {
          console.log('A child node has been added.');
          console.log(mutation);
          procSchedTable();
        } else if (mutation.type == 'attributes') {
          console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
      }
    };
    // Create an observer instance linked to the callback function
    var observer = new MutationObserver(callback);
    // Start observing the target node for configured mutations
    observer.observe(document.querySelector(".schedule"), config);

    // Later, you can stop observing
    //observer.disconnect();
  })();

});

console.log("&&&&&&&&&&&&&&&&&&&&&&&&/jssz12320&&&&&&&&&&&&&&&&&&&&&&&&");