Aipoのスケジュールツールチップ表示

Aipoのスケジュールではツールチップ表示があります。

ここを表示しているScreenはScheduleDetailJSONScreenになります。

https://github.com/aipocom/aipo/blob/master/portlets/schedule/src/main/java/com/aimluck/eip/modules/screens/ScheduleDetailJSONScreen.java

中身のロジックはScheduleTooltipSelectDataになります。

https://github.com/aipocom/aipo/blob/master/portlets/schedule/src/main/java/com/aimluck/eip/schedule/ScheduleTooltipSelectData.java

ToolTipの内容はJSON形式で返しています。

    JSONObject scheduleJson = new JSONObject();
    if (detailData.doViewDetail(this, rundata, context)) {
      ScheduleDetailResultData schedule =
        (ScheduleDetailResultData) detailData.getDetail();
      scheduleJson.put("id", schedule.getScheduleId().getValue());
      scheduleJson.put("name", ALStringUtil.sanitizing(schedule
        .getName()
        .getValue()));
      scheduleJson.put("date", schedule.getDate2());
      scheduleJson.put("place", ALStringUtil.sanitizing(schedule
        .getPlace()
        .getValue()));
      scheduleJson.put("isSpan", schedule.isSpan());
      scheduleJson.put("memberList", detailData.getMemberList());
      scheduleJson.put("facilityList", detailData.getFacilityList());
    }
    return scheduleJson.toString();

表示する側では

https://github.com/aipocom/aipo/blob/master/portlets/schedule/src/main/webapp/javascript/aipo/calendar/weekly.js#L1061

でJSONからhtmlタグを生成して表示しています。

aipo.calendar.showTooltip = function(url, portlet_id, containerNode) {
    var datehtml = "";
    var mbhtml = "";
    var mbfhtml = "";
    var placehtml = "";

    var escapeHTML = function(value) {
        var replaceChars = function(ch) {
            switch (ch) {
                case "<":
                    return "&lt;";
                case ">":
                    return "&gt;";
                case "&":
                    return "&amp;";
                case "'":
                    return "'";
                case '"':
                    return "&quot;";
            }
            return "?";
         };
         return String(value).replace(/[<>&"']/g, replaceChars);
    };
    dojo.style(containerNode, "display", "block");
    dojo.xhrGet({
        portletId: portlet_id,
        url: url,
        encoding: "utf-8",
        handleAs: "json-comment-filtered",
        load: function(data, event) {
            if (!data.id) {
                dojo.style(containerNode, "display", "none");
                return;
            }

            if (!data.isSpan) {
                datehtml = "<span style=\"font-size: 0.90em;\">" + data.date + "</span><br/>";
            }


            if (data.memberList) {
                var memberSize = data.memberList.length;
                for (var i = 0 ; i < memberSize ; i++) {
                    mbhtml += "<li>" + escapeHTML(data.memberList[i].aliasName.value) + "</li>";
                }
            }

            if (data.facilityList) {
                var facilitySize = data.facilityList.length;
                for (var i = 0 ; i < facilitySize ; i++) {
                    mbfhtml += "<li>" + escapeHTML(data.facilityList[i].facilityName.value) + "</li>";
                }
            }

            if(data.place != ""){
                placehtml = "<span style=\"font-size: 0.90em;\">場所</span><br/><ul><li>" + data.place + "</li></ul>";
            }

            if(mbhtml != ""){
                mbhtml = "<span style=\"font-size: 0.90em;\">参加者</span><br/><ul>" + mbhtml + "</ul>";
            }

            if(mbfhtml != ""){
                mbfhtml = "<span style=\"font-size: 0.90em;\">設備</span><br/><ul>" + mbfhtml + "</ul>";
            }

            var tooltiphtml = "<h4>" + data.name + "</h4>" + datehtml + mbhtml + mbfhtml + placehtml;

            containerNode.innerHTML = tooltiphtml;
        }
    });
};