PageSourceSearch

https://medical-tribune.co.jp/js/com_func.js

js medical-tribune.co.jp collected 2026-10-02 05:43:05 UTC 67,439 bytes, 1,904 lines download raw bytes

1function iniArg() {
2    if (window.gl_sfid == "" || window.gl_sfid == undefined) {
3        window.gl_sfid = getCookie("_sfid");
4    }
5
6    if (window.gl_lgtk == "" || window.gl_lgtk == undefined) {
7        window.gl_lgtk = getCookie("_lgtk");
8    }
9
10    // if (window.gl_sfid != "" && window.gl_sfid != null) {
11    //     // GetSiteControlの処理コメントアウト
12    //     com_getGSCParam(window.gl_sfid, 1398);
13    // }
14}
15
16function com_Redirect(st_Url) {
17    window.location.href = st_Url;
18}
19
20function createUserHeader() {
21    const auth = gl_lgtk;
22    let header = {};
23    if ("" != auth) {
24        header = { "UserAuthorization": "Bearer " + auth }
25    }
26    return header;
27}
28
29function createEntryHeader() {
30    const auth = getCookie("_sutk");
31    let header = {};
32    if ("" != auth) {
33        header = { "EntryAuthorization": "Bearer " + auth }
34    }
35    return header;
36}
37function comAjax(st_EndPont, obj_Data, func_Callback, type = 'POST', dataType = 'json', processData = false, contentType = false, auth = 0, withCredentials = true) {
38    let header = {};
39    switch (Number(auth)) {
40        case 1: header = createUserHeader(); break;
41        case 2: header = createEntryHeader(); break;
42    }
43
44    // オブジェクトを送る呼出しは、PHPの$_REQUESTで受け取れる形式へ正規化する。
45    const isObjectPayload = obj_Data !== null
46        && typeof obj_Data === 'object'
47        && !(obj_Data instanceof FormData);
48    const requestData = isObjectPayload && contentType !== 'application/json'
49        ? $.param(obj_Data)
50        : obj_Data;
51    const requestProcessData = isObjectPayload && contentType !== 'application/json'
52        ? false
53        : processData;
54    const requestContentType = isObjectPayload && contentType !== 'application/json'
55        ? 'application/x-www-form-urlencoded; charset=UTF-8'
56        : contentType;
57
58    $.ajax({
59        url: st_EndPont,
60        type: type,
61        dataType: dataType,
62        data: requestData,
63        timeout: 30000,
64        processData: requestProcessData,
65        contentType: requestContentType,
66        xhrFields: { withCredentials: withCredentials },
67        crossDomain: true,
68        headers: header
69    })
70    .done(function (obj_Result) {
71        obj_Result.isNetworkError = false; 
72
73        if (typeof logExecutionTime === 'function') {
74            const result = logExecutionTime(func_Callback);
75            result(obj_Result);
76        } else {
77            func_Callback(obj_Result);
78        }
79    })
80    .fail(function (jqXHR, textStatus, errorThrown) {
81        if (textStatus === "abort") return;
82
83        let failResult = { 
84            result: -1, 
85            isNetworkError: true,
86            status: jqXHR.status,
87            textStatus: textStatus,
88            errorThrown: errorThrown,
89            responseJSON: jqXHR.responseJSON || null,
90            responseText: jqXHR.responseText || ""
91        };
92        if (jqXHR.status === 401 || jqXHR.status === 403) {
93            failResult.isNetworkError = false; 
94        }
95
96        console.error("AJAX Fail (Network Error):", textStatus);
97
98        if (typeof logExecutionTime === 'function') {
99            const result = logExecutionTime(func_Callback);
100            result(failResult);
101        } else {
102            func_Callback(failResult);
103        }
104    });
105}
106
107
108function com_showDialog(st_Name) {
109    obj_Modal = new bootstrap.Modal(document.getElementById(st_Name));
110    obj_Modal.show();
111}
112
113
114function com_closeDialog(st_Name) {
115    obj_Modal = new bootstrap.Modal(document.getElementById(st_Name));
116    obj_Modal.hide();
117}
118
119
120function com_submit(st_Form, st_Dialog) {
121    com_closeDialog(st_Dialog);
122    // 画面更新させるため
123    setTimeout(function () {
124        // submit
125        $('#' + st_Form).submit();
126    }, 500);
127
128}
129
130
131function checkRequestObj(checkList, obj) {
132    let ngList = [];
133    Object.entries(obj).forEach(function ([key, element]) {
134        if (element === '' && checkList.indexOf(key) >= 0) {
135            ngList.push(key);
136        }
137    });
138    return ngList;
139}
140
141
142function checkAlert(msgList, alertObj) {
143    let alertMsg = "";
144    alertObj.forEach(function (value) {
145        alertMsg += "・" + msgList[value] + "\n\r";
146    });
147    alertMsg += "\n\rを設定してください。";
148    alert(alertMsg);
149}
150
151
152function addRow(tableName) {
153    $(function () {
154        $("#" + tableName + " tbody tr:last-child").clone(true).appendTo("#" + tableName + " tbody");
155        // 追加した行の値をクリアする
156        $("#" + tableName + " tbody tr:last-child input").val("");
157    });
158}
159
160
161function delRow(btn, tableBodyName) {
162    if ($("#" + tableBodyName).children('tr').length >= 2) {
163        $(btn).parents('tr').remove();
164    }
165}
166
167
168function setDisplayOrder(tableName) {
169    $('#' + tableName + ' tr').each(function (i) {
170        var tdElement = $(this).find('td:first');
171        var inputElement = tdElement.find('input[name="display_order"]');
172        inputElement.val(i);
173    });
174}
175
176
177function getHeaderInfo() {
178    // 会員ヘッダーがサーバーで正常に生成されたページでは同じAPIを再呼び出ししない。
179    if (document.querySelector('[data-member-header-ssr="1"]')) return;
180
181    let sfid = window.gl_sfid;
182    if (sfid != "" && sfid != null) {
183        let endpoint = BASE_ENDPOINT + "users/" + sfid + "/info/headers";
184        comAjax(
185            endpoint,
186            JSON.stringify([]),
187            getHeaderInfoEndCB,
188            type = 'GET',
189            dataType = 'json',
190            processData = false,
191            contentType = 'application/json',
192            auth = true
193        );
194    }
195}
196
197function getHeaderInfoEndCB(obj_Result) {
198    // 認証エラーと断定できない通信失敗では、Cookieを削除しない
199    if (obj_Result && obj_Result.isNetworkError === true) {
200        console.warn("Temporary network error. Logout canceled.");
201        return;
202    }
203
204    if (obj_Result.result === -1 || obj_Result.result === 10) {
205        // 認証エラー
206        console.warn("Auth Error: Redirecting to login.");
207        dellAllCookie(false);
208        window.location.href = '/login.html';
209        return;
210    } else if (obj_Result.result === 0) {
211        // 正常処理
212        let headerInfo = obj_Result["data"];
213        if (headerInfo && headerInfo.length > 0) {
214            if (obj_Result.result === 0) setBatch(headerInfo[0]);
215            setPoint(headerInfo[0]);
216            setRightName(headerInfo[0]);
217            setEdtlName(headerInfo[0]);
218        }
219    }
220}
221
222function getEdtlTop() {
223    const edetailArea = document.getElementById('top-edetail-area-new');
224    if (!edetailArea || edetailArea.dataset.edetailTopSsr === '1') return;
225    // TOP has already attempted SSR: avoid six automatic retries during API outages.
226    if (edetailArea.dataset.edetailTopSsrAttempted === '1') return;
227
228    const sfid = window.gl_sfid || getCookie('_sfid');
229    if (sfid == "" || sfid == null) return;
230    if (edetailArea.dataset.edetailTopInitialized === '1') return;
231    edetailArea.dataset.edetailTopInitialized = '1';
232
233    // matching 2 に 4・5・6 相当の明細が同梱されるため個別取得しない。
234    const matchingIds = [2, 7, 99];
235    const requests = matchingIds.map((matchingId) => {
236        const endpoint = BASE_ENDPOINT + "users/" + sfid + "/matching/" + matchingId + "/lists?limit=100";
237
238        return $.ajax({
239            url: endpoint,
240            type: 'GET',
241            dataType: 'json',
242            data: JSON.stringify([]),
243            timeout: 30000,
244            processData: false,
245            contentType: 'application/json',
246            xhrFields: { withCredentials: true },
247            crossDomain: true,
248            headers: createUserHeader()
249        }).then(
250            (result) => ({ result, matchingId }),
251            () => ({ result: { result: -1, data: [] }, matchingId })
252        );
253    });
254
255    $.when.apply($, requests).done(function () {
256        getEdtlTopEndCB(Array.from(arguments));
257    });
258}
259
260// 共通right columnのSSR失敗時だけ、既存CSRを1回実行する。
261window.addEventListener('load', getEdtlTop);
262
263
264function getEdtlTopEndCB(responses) {
265    const masterData = {};
266
267    responses.forEach((response) => {
268        const result = response.result;
269        const matchingId = response.matchingId;
270
271        if (!result || result.result < 0) return;
272
273        (result.data || []).forEach((item) => {
274            item.source_matching_id = item.source_matching_id
275                ?? item.matching_id
276                ?? matchingId;
277            masterData[item.id] = item;
278        });
279    });
280
281    const edtlList = Object.values(masterData).sort((a, b) => {
282        const timeA = new Date(a.startDate || '0000-01-01 00:00:00').getTime();
283        const timeB = new Date(b.startDate || '0000-01-01 00:00:00').getTime();
284        return timeB - timeA;
285    });
286
287    createEdetail(edtlList);
288}
289
290function setEdtlName(obj_Results) {
291    let name = [
292        obj_Results.name + obj_Results.job + 'のお知らせ',
293    ];
294    $('.side-edetail-name').append(name.join(""));
295    $('.sp-edetail-name').append(name.join(""));
296}
297
298// 新しい右カラムeディテール
299function handleEdetailTopClick(event, btn, type, blank, readFlg) {
300    if (readFlg === 'no-read') {
301        readEdetailTopNotice(btn);
302    }
303    if (typeof sendClickLog === 'function') {
304        sendClickLog(btn);
305    }
306
307    if (blank === 0) {
308        event.preventDefault();
309        setTimeout(() => {
310            window.location.href = btn.href;
311        }, 100);
312    } else if (blank === 1) {
313        event.preventDefault();
314        window.open(btn.href, '_blank');
315    }
316
317    if (readFlg === 'no-read') {
318        $(btn).remove();
319        if ($('#top-edetail-area-new a').length === 0) {
320            $('#top-edetail-area-new').html(`<div class="no-data">すべてのお知らせを確認しました。</div>`);
321        }
322    }
323}
324
325function readEdetailTopNotice(btn) {
326    const sfid = gl_sfid;
327    const matchingType = btn.dataset.matchingId || MATCHING_CATEGORY["edetail"];
328    const reqData = {
329        "id": btn.id,
330        "readFlg": 1
331    };
332
333    if (sfid != "" && sfid != null) {
334        const endpoint = BASE_ENDPOINT + "users/" + sfid + "/matching/" + matchingType;
335        comAjax(endpoint,
336            JSON.stringify(reqData),
337            readNoticeEndCB,
338            type = 'PATCH',
339            dataType = 'json',
340            processData = false,
341            contentType = 'application/json',
342            auth = true
343        );
344    }
345}
346
347function createEdetail(viewData) {
348    let htmls = [];
349    viewData.forEach((value) => {
350        if (Number(value["read"]) > 0) return;
351        let targetBlank = '';
352        let blank = 0;
353
354        if (value["category"] === 5) {
355            targetBlank = ' target="_blank"';
356            blank = 1;
357        }
358
359        let hrefUrl = value["url"];
360        if (Number(value["source_matching_id"]) === 99) {
361            if (!hrefUrl.includes('/e-detail?blogid=') && !hrefUrl.includes('/e-detail/?blogid=')) {
362                hrefUrl = hrefUrl.replace(/\/?(\?blogid=)/, '/e-detail/$1');
363            }
364        }
365
366        const readStatus = Number(value["read"]) > 0 ? 'read' : 'no-read';
367        const idAttr = readStatus === 'no-read' ? ` id="id_${value.id}"` : '';
368
369        let html = `
370            <a href="${hrefUrl}" onclick="handleEdetailTopClick(event, this, 'edetail', ${blank}, '${readStatus}')"${idAttr} data-matching-id="${value["source_matching_id"]}" ${targetBlank}>
371                <div class="top-edetail-area-new-link">
372                    <div></div>
373                    <i class="bi bi-chevron-right chevron-position"></i>
374                    <p>${value["title"]} <span>NEW</span></p>
375                </div>
376            </a>
377        `;
378        htmls.push(html);
379    });
380
381    if (htmls.length === 0) {
382        htmls.push(`<div class="no-data">すべてのお知らせを確認しました。</div>`);
383    }
384
385    $('#top-edetail-area-new').append(htmls.join(""));
386}
387
388function setBatch(obj_Results) {
389    if (Number(obj_Results.infoCount) > 0) {
390        let info_html = '<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-danger fadeIn-sh p-2 header-badge">' + obj_Results.infoCount + '</span>';
391        //$('#info-badge').prepend(info_html);
392        $('#info-badge-sp').prepend(info_html);
393        $('#sp-menu-badge-edtl').prepend(info_html);
394    }
395
396    if (Number(obj_Results.seminarCount) > 0) {
397        let seminar_html = '<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-danger fadeIn-sh p-2 header-badge">' + obj_Results.seminarCount + '</span>';
398        //$('#seminar-badge').prepend(seminar_html);
399        $('#seminar-badge-sp').prepend(seminar_html);
400        $('#sp-menu-badge-seminar').prepend(seminar_html);
401    }
402
403    if (Number(obj_Results.surveyCount) > 0) {
404        let survey_html = '<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-danger fadeIn-sh p-2 header-badge">' + obj_Results.surveyCount + '</span>';
405        //$('#survey-badge').prepend(survey_html);
406        $('#survey-badge-sp').prepend(survey_html);
407        $('#sp-menu-badge-survey').prepend(survey_html);
408    }
409}
410
411
412function setPoint(obj_Results) {
413    let name_html = '<a id="user_point_name" class="fw-bold article-comment fadeIn-sh" href="/mypage/personal/point-exchange.html">' + obj_Results.name + '<span> ' + obj_Results.job + '</span></a>';
414    let point_html = '<span class="header-point-txt fw-bold fs-xxl-4 fadeIn-sh">' + obj_Results.point + '</span><span class="fw-bold"> pt</span>'
415    // $('#point_name').prepend(name_html)
416    // $('#user_point').prepend(point_html)
417}
418
419
420function setRightName(obj_Results) {
421    let name_html = '<a id="user_name_detail" class="fw-bold text-white fadeIn-sh">' + obj_Results.name + '</a> ';
422    name_html += '<a id="user_clss_detail" class="text-white fadeIn-sh">' + obj_Results.job + '<span> のe-detail</span></a>'
423    $('#e-detail_name').prepend(name_html)
424}
425
426
427// function changeLogin() {
428//     $("#mypage_link").html('<i class="fa fa-user fa-fw" aria-hidden="true"></i>マイページ');
429//     $("#mypage_link").prop("href", "mypage/");
430//     $("#header-signup-btn-pc").addClass("d-none");
431// }
432
433
434function readNotice(btn, type) {
435    let matchingType = MATCHING_CATEGORY[type];
436    let sfid = gl_sfid;
437    let reqData = {
438        "id": btn.id,
439        "readFlg": 1
440    }
441    if (sfid != "" && sfid != null) {
442        let endpoint = BASE_ENDPOINT + "users/" + sfid + "/matching/" + matchingType
443        comAjax(endpoint,
444            JSON.stringify(reqData),
445            readNoticeEndCB,
446            type = 'PATCH',
447            dataType = 'json',
448            processData = false,
449            contentType = 'application/json',
450            auth = true
451        );
452    }
453}
454
455
456function readNoticeEndCB(obj_Result) {
457    result = obj_Result["data"]
458    console.log(result);
459    // $('#' + result.id).off("click");
460    // $('.' + result.id).removeClass("bg-danger");;
461    // $('.' + result.id).removeClass("bg-secondary");;
462}
463
464
465function setCookie_days(name, value, days) {
466    let date = new Date();
467    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
468    let expires = "; expires=" + date.toUTCString();
469    document.cookie = name + "=" + value + expires + "; path=/; SameSite=Lax; Secure";
470}
471
472function setCookie_hours(name, value, hours) {
473    let date = new Date();
474    date.setTime(date.getTime() + (hours * 60 * 60 * 1000));
475    let expires = "; expires=" + date.toUTCString();
476    document.cookie = name + "=" + value + expires + "; path=/; SameSite=Lax; Secure";
477}
478
479function setCookie_minutes(name, value, minutes) {
480    let date = new Date();
481    date.setTime(date.getTime() + (minutes * 60 * 1000));
482    let expires = "; expires=" + date.toUTCString();
483    document.cookie = name + "=" + value + expires + "; path=/; SameSite=Lax; Secure";
484}
485
486function deleteCookie(name) {
487    setCookie_days(name, "", -1);
488}
489
490
491function dellAllCookie(alertFlg = true) {
492    const cookies = document.cookie.split(';');
493    for (let i = 0; i < cookies.length; i++) {
494        let cookie = cookies[i].trim();
495        let eqPos = cookie.indexOf('=');
496        let name = eqPos > -1 ? cookie.substring(0, eqPos) : cookie;
497
498        if (name === "_relogin" || name === "_camentryflg" || name === "_visiontype") {
499            continue;
500        }
501
502        if (name === "mt_user") {
503            document.cookie = "mt_user=; path=/; domain=example.com; expires=Thu, 01 Jan 1970 00:00:00 UTC; Secure";
504        } else {
505            deleteCookie(name);
506        }
507    }
508    if (alertFlg) {
509        alert('cookieを削除しました。\n再度ログインを試みてください。');
510    }
511}
512function updateCookie(name, newValue, newDays = null) {
513    let existingCookieValue = getCookie(name);
514    if (existingCookieValue !== "") {
515        let days = newDays ? newDays : getCookieDays(name);
516        setCookie_days(name, newValue, days);
517    }
518}
519
520function getCookie(name) {
521    let cookie = "";
522    const value = document.cookie.match(
523        new RegExp(name + '\=([^\;]*)\;*')
524    );
525    if (value != null) {
526        cookie = value[1];
527    }
528    return decodeURIComponent(cookie);
529}
530
531function setLoginCookie(obj_Result) {
532    deleteCookie("_lgtk");
533    setCookie_days("_lgtk", encodeURIComponent(obj_Result.token), "30");
534    // deleteCookie("_sfid");
535    // setCookie_days("_sfid", obj_Result.sfid, "30");
536    // deleteCookie("_class");
537    // setCookie_days("_class", obj_Result.job, "30");
538    // deleteCookie("_user");
539    // setCookie_days("_user", obj_Result.userId, "30");
540    // deleteCookie("_cmntflg");
541    // setCookie_days("_cmntflg", obj_Result.cmntFlg, "30");
542    // deleteCookie("_userdep");
543    // setCookie_days("_userdep", obj_Result.department, "30");
544    // deleteCookie("_empname");
545    // setCookie_days("_empname", obj_Result.empName, "30");
546    // deleteCookie("_username");
547    // setCookie_days("_username", obj_Result.name, "30");
548    // deleteCookie("_nickname");
549    // setCookie_days("_nickname", obj_Result.nickname, "30");
550    // deleteCookie("_mail");
551    // setCookie_days("_mail", obj_Result.userId, "30");
552    deleteCookie("_sfid");
553    setCookie_days("_sfid", encodeURIComponent(obj_Result.sfid), "30");
554    deleteCookie("sf_id");
555    setCookie_days("sf_id", encodeURIComponent(obj_Result.sfid), "30");
556    deleteCookie("_class");
557    setCookie_days("_class", encodeURIComponent(obj_Result.job), "30");
558    deleteCookie("_user");
559    setCookie_days("_user", encodeURIComponent(obj_Result.userId), "30");
560    deleteCookie("_cmntflg");
561    setCookie_days("_cmntflg", encodeURIComponent(obj_Result.cmntFlg), "30");
562    deleteCookie("_userdep");
563    setCookie_days("_userdep", encodeURIComponent(obj_Result.department), "30");
564    deleteCookie("_empname");
565    setCookie_days("_empname", encodeURIComponent(obj_Result.empName), "30");
566    deleteCookie("_username");
567    setCookie_days("_username", encodeURIComponent(obj_Result.name), "30");
568    deleteCookie("_nickname");
569    setCookie_days("_nickname", encodeURIComponent(obj_Result.nickname), "30");
570    deleteCookie("_mail");
571    setCookie_days("_mail", encodeURIComponent(obj_Result.userId), "30");
572}
573
574// localStorageに保存されたMTC連携データを復元する
575function getStoredMtcData() {
576    const storedMtc = window.localStorage.getItem('mtc');
577    if (!storedMtc) {
578        return null;
579    }
580
581    try {
582        return JSON.parse(decodeURIComponent(escape(atob(storedMtc))));
583    } catch (error) {
584        window.localStorage.removeItem('mtc');
585        return null;
586    }
587}
588
589// 会員登録入力データをMTC連携データにマージして一時保存する
590function saveMtcCallbackData(data) {
591    const mtc = getStoredMtcData();
592    if (!mtc) {
593        return;
594    }
595
596    const newData = { ...data, ...mtc, expires: new Date().getTime() + 10 * 60 * 1000 };
597    const encoded = btoa(unescape(encodeURIComponent(JSON.stringify(newData))));
598    window.localStorage.setItem('mtc', encoded);
599}
600
601// MTC連携データを復元し、callback URLへフォームPOSTする
602function submitMtcCallback(data) {
603    try{
604        const mtc = getStoredMtcData();
605
606        const currentTime = new Date().getTime();
607        const mtcExpires = mtc && typeof mtc.expires === 'number' && mtc.expires < 1000000000000
608            ? mtc.expires * 1000
609            : mtc.expires;
610        const isValidMtc = mtc
611            && typeof mtc === 'object'
612            && typeof mtc.callback === 'string'
613            && mtc.callback
614            && typeof mtc.expires === 'number'
615            && mtcExpires > currentTime;
616
617        if (!isValidMtc) {
618            window.localStorage.removeItem('mtc');
619            return;
620        }
621
622        if (!document.body) {
623            document.documentElement.appendChild(document.createElement('body'));
624        }
625
626        const form = document.createElement('form');
627        form.method = 'POST';
628        form.action = mtc.callback;
629        form.style.display = 'none';
630
631        const targetData = { ...mtc, ...data };
632        Object.entries(targetData).forEach(([key, value]) => {
633            const input = document.createElement('input');
634            input.type = 'hidden';
635            input.name = key.charAt(0) === '_' ? key : `_${key}`;
636            input.value = value == null ? '' : String(value);
637            form.appendChild(input);
638        });
639
640        // カタカナ名前を設定してPOSTする
641        const input = document.createElement('input');
642        input.type = 'hidden';
643        input.name = '_nameKana';
644        input.value = `${targetData.KanaSei__c} ${targetData.KanaMei__c}`;
645        form.appendChild(input);
646
647        document.body.appendChild(form);
648        window.localStorage.removeItem('mtc');
649        form.submit();
650    }catch(error){
651        console.error(error);
652    }
653}
654
655
656function pageError(type = 0) {
657    switch (type) {
658        case 0:
659            // if (location.href != DOMEIN + "error.html") {
660            //     location.href = DOMEIN + "error.html";
661            // }
662            break;
663        case 21:
664            if (location.href != DOMEIN + "error.html?error=21") {
665                location.href = DOMEIN + "error.html?error=21";
666            }
667            break;
668        case 22:
669            if (location.href != DOMEIN + "error.html?error=22") {
670                location.href = DOMEIN + "error.html?error=22";
671            }
672            break;
673        case 29:
674            if (location.href != DOMEIN + "error.html?error=29") {
675                location.href = DOMEIN + "error.html?error=29";
676            }
677            break;
678    }
679}
680
681
682function hrefError() {
683    if (location.href != DOMEIN + "error.html") {
684        location.href = DOMEIN + "error.html";
685    }
686}
687
688function page404() {
689    if (location.href != DOMEIN + "404.html") {
690        location.href = DOMEIN + "404.html";
691    }
692}
693
694function pageLogin() {
695    if (location.href != DOMEIN + "login.html") {
696        location.href = DOMEIN + "login.html";
697    }
698}
699
700function searchCategory(category) {
701    let req_category = 0;
702    if (category.includes("ドクターズアイ")) {
703        req_category = 1
704    } else if (category.includes("新薬の実力")) {
705        req_category = 2
706    } else if (category.includes("薬剤問題")) {
707        req_category = 3
708    } else if (category.includes("この難病・起床疾患に注目")) {
709        req_category = 4
710    } else if (category.includes("医療の蠢動")) {
711        req_category = 5
712    } else if (category.includes("医療は連携して真価を生む")) {
713        req_category = 6
714    } else if (category.includes("早読み&深掘り")) {
715        req_category = 7
716    } else if (category.includes("Weekly Report")) {
717        req_category = 8
718    } else if (category.includes("肺がん注目論文")) {
719        req_category = 9
720    } else if (category.includes("医師の働き方を考える")) {
721        req_category = 10
722    } else if (category.includes("だから良いのだ")) {
723        req_category = 11
724    } else if (category.includes("診察室の経験")) {
725        req_category = 12
726    } else if (category.includes("最新医療トピック")) {
727        req_category = 13
728    } else if (category.includes("診察室の経験")) {
729        req_category = 14
730    } else if (category.includes("MT Survey")) {
731        req_category = 15
732    } else if (category.includes("学会印象記")) {
733        req_category = 16
734    } else if (category.includes("人・ひと・ヒト")) {
735        req_category = 17
736    } else if (category.includes("Culture Review")) {
737        req_category = 18
738    } else if (category.includes("アウトサイダーの視点")) {
739        req_category = 19
740    } else if (category.includes("皮膚病編")) {
741        req_category = 20
742    } else if (category.includes("症例の森")) {
743        req_category = 21
744    }
745
746    return req_category;
747}
748
749
750function copyText(id) {
751    let html = document.getElementById(id);
752    let text = html.innerText;
753    if (navigator.clipboard == undefined) {
754        window.clipboardData.setData('Text', text);
755    } else {
756        navigator.clipboard.writeText(text)
757        // .then(function() {
758        //     console.log('クリップボードにコピーしました');
759        //   })
760        //   .catch(function(err) {
761        //     console.error('クリップボードにコピーできませんでした: ', err);
762        //   });
763    }
764    alert("コピーしました");
765}
766
767
768function createGlonavi(viewData) {
769    let html = [
770        '<div class="collapse navbar-collapse" id="navbarSupportedContent">',
771        '<ul class="navbar-nav me-auto mb-lg-0">'
772    ];
773    viewData.forEach((parent, i) => {
774        if (parent.hierarchy) {
775            parent['children'].forEach((children, index) => {
776                if (index === 0) {
777                    html.push('     <li class="nav-item dropdown position-static ms-4">');
778                    html.push('         <a class="navbar-brand text-white fs-6 dropdown-toggle" href="' + children.link + '" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">');
779                    html.push(parent.glonav_group_name);
780                    html.push('         </a>');
781                    html.push('         <ul class="dropdown-menu bg-light ms-2 me-2 m-0">');
782                    html.push('         <div class="row d-flex">');
783                }
784                html.push('         <div class="col-md-4 col-12">');
785                html.push('         <div class="card border-2 border border-mt-danger m-2">');
786                if (children.img_path != '') {
787                    html.push('     <img id="entry_img_path" class="img-thumbnail img-fluid" src="' + children.img_path + '" alt="MTWロゴ"/>');
788                }
789                if (children.icon_tag != '') {
790                    html.push(children.icon_tag.replace(/'/g, '"'));
791                }
792                html.push('     <div class="card-body">');
793                html.push('         <a href="' + children.link + '">');
794                html.push('             <h5 class="card-title">' + children.glonav_menu_name + '</h5>');
795                html.push('             <p class="card-text">' + children.glonav_menu_name + '</p>');
796                html.push('         </a>');
797                html.push('     </div></div></div>');
798            });
799            html.push('</div></ul></li>');
800        } else {
801            if (i === 0) {
802                html.push('<li class="nav-item ms-1">')
803            } else {
804                html.push('<li class="nav-item ms-4">')
805            }
806
807            if (parent.img_path != '') {
808                html.push('<img id="entry_img_path" class="img-thumbnail img-fluid" src="' + parent.img_path + '" alt="MTWロゴ"/>');
809            }
810            if (parent.icon_tag != '') {
811                html.push(parent.icon_tag.replace(/'/g, '"'));
812            }
813            html.push('<a class="navbar-brand fs-6 text-white" href="' + parent.link + '">');
814            html.push(parent.glonav_group_name);
815            html.push('</a>');
816            html.push('</li>')
817        }
818    });
819    html.push('</ul></div>');
820    $('#mtw_glonavi').append(html.join(""));
821}
822
823
824$('.table_column_check').change('click', function () {
825    let allCheck = $(this).find('#selectAll').prop("checked")
826    let tableName = $(this).parent().parent().parent().find('tbody').attr('id');
827
828    if (allCheck) {
829        $('#' + tableName + ' tr').each(function () {
830            $(this).find('.form-check-input').each(function () {
831                if (!$(this).prop("checked")) {
832                    $(this).prop("checked", true);
833                }
834            });
835        });
836    } else {
837        $('#' + tableName + ' tr').each(function () {
838            $(this).find('.form-check-input').each(function () {
839                $(this).prop("checked", false);
840            });
841        });
842    }
843});
844
845
846class Fireworks {
847    constructor() {
848        // Canvas要素の取得
849        this.canvas = document.getElementById('canvas');
850        this.ctx = this.canvas.getContext('2d'); // canvasの2Dコンテキストを取得
851
852        // キャンバスの幅と高さをウィンドウのサイズに設定
853        this.canvas.width = window.innerWidth;
854        this.canvas.height = window.innerHeight;
855
856        // パーティクルの配列
857        this.particles = [];
858
859        // アニメーションを開始
860        this.animate();
861    }
862
863    // 花火の作成メソッド
864    createFirework() {
865        for (let i = 0; i < 3; i++) { // 3つの花火を一度に表示
866            const x = Math.random() * this.canvas.width;
867            const y = Math.random() * this.canvas.height / 2; // 上半分に表示するように調整
868            const color = `hsl(${Math.random() * 360}, 100%, 50%)`; // ランダムな色を生成
869            const particleCount = Math.floor(Math.random() * 100) + 50; // パーティクルの数をランダムに設定
870
871            // パーティクルの生成
872            for (let j = 0; j < particleCount; j++) {
873                const particle = new Particle(x, y, color);
874                this.particles.push(particle);
875            }
876        }
877    }
878
879    // アニメーションループ
880    animate() {
881        requestAnimationFrame(this.animate.bind(this));
882        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); // Canvasをクリア
883
884        // パーティクルの更新と描画
885        this.particles.forEach((particle, index) => {
886            particle.update();
887            particle.draw(this.ctx); // ctxを渡す
888
889            // 透明度が0になったら削除
890            if (particle.alpha <= 0) {
891                this.particles.splice(index, 1);
892            }
893        });
894    }
895}
896
897class Particle {
898    constructor(x, y, color) {
899        this.x = x;
900        this.y = y;
901        this.color = color;
902        this.radius = Math.random() * 6 + 1; // より広い範囲のランダムな大きさのパーティクル
903        this.velocity = {
904            x: (Math.random() - 0.5) * 4, // X方向の速度
905            y: (Math.random() - 0.5) * 4 // Y方向の速度
906        };
907        this.alpha = 1; // 初期透明度
908        this.fade = Math.random() * 0.03 + 0.02; // 透明度の減少量
909    }
910
911    // パーティクルを更新するメソッド
912    update() {
913        this.x += this.velocity.x;
914        this.y += this.velocity.y;
915        this.alpha -= this.fade; // 透明度を減少させる
916
917        // 速度を減少させる
918        this.velocity.x *= 0.98;
919        this.velocity.y *= 0.98;
920    }
921
922    // パーティクルを描画するメソッド
923    draw(ctx) { // ctxを引数として受け取る
924        ctx.save();
925        ctx.globalAlpha = this.alpha;
926        ctx.beginPath();
927        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
928        ctx.fillStyle = this.color;
929        ctx.fill();
930        ctx.closePath();
931        ctx.restore();
932    }
933}
934
935
936// ページネーションボタン回り込み
937var buttonsCount = document.querySelectorAll('.page-btn').length;
938if (buttonsCount > 8) {
939    // document.querySelector('#list-pagenation').classList.add('flex-wrap-enabled');
940    addClass('#list-pagenation', 'flex-wrap-enabled');
941}
942if (buttonsCount < 9) {
943    // document.querySelector('.page-btn-first').classList.add('flex-item-first');
944    // document.querySelector('.page-btn-end').classList.add('flex-item-end');
945    addClass('.page-btn-first', 'flex-item-first');
946    addClass('.page-btn-end', 'flex-item-end');
947}
948
949// クラス追加
950function addClass(st_ID, st_Class) {
951    try {
952        var $element = $(st_ID);
953        if ($element.length > 0) {
954            $element.addClass(st_Class);
955        } else {
956            console.warn(st_ID + ' element does not exist.');
957        }
958    } catch (error) {
959        console.error('An error occurred:', error);
960    }
961}
962
963// クリップボタン
964function clipArticle(event) {
965    let sfId = getCookie("_sfid");
966    let mail = getCookie("_user");
967    let clipButton = event.currentTarget;
968    let clipDiv = clipButton.parentElement;
969    let blogId = clipDiv.querySelector('input[name="blogId"]').value;
970    let entryId = clipDiv.querySelector('input[name="entryId"]').value;
971    let clipFlg = "";
972    if (clipButton.classList.contains('clip-checked')) {
973        clipFlg = false;
974    } else {
975        clipFlg = true;
976    };
977    if (window.location.pathname === '/') {
978        clipButton.classList.toggle('clip-checked');
979    };
980
981    if (document.getElementById('article_2312')) {
982        let clipButtons = document.querySelectorAll('.article-clip-btn');
983        clipButtons.forEach(button => {
984            button.classList.toggle('clip-checked');
985        });
986    } else {
987        clipButton.classList.toggle('clip-checked');
988    }
989
990    let postData = {
991        "clipFlg": clipFlg,
992        "mail": mail,
993        "blogId": blogId,
994        "entryId": entryId
995    }
996
997    let endpoint = BASE_ENDPOINT + "users/" + sfId + "/clips"
998    comAjax(
999        endpoint,
1000        JSON.stringify(postData),
1001        clipEndCB,
1002        type = 'POST',
1003        dataType = 'json',
1004        processData = false,
1005        contentType = 'application/json',
1006        auth = 1
1007    );
1008    function clipEndCB() {
1009
1010    }
1011
1012}
1013
1014
1015function showAdjacentMonths(yyyymm, type = "次の月へ") {
1016    console.log(type);
1017    let retunMonth = null;
1018    let [year, month] = yyyymm.split('-').map(Number);
1019    let currentDate = new Date(year, month - 1, 1);
1020
1021    let nextMonth = new Date(currentDate);
1022    nextMonth.setMonth(currentDate.getMonth() + 1);
1023
1024    let prevMonth = new Date(currentDate);
1025    prevMonth.setMonth(currentDate.getMonth() - 1);
1026
1027    console.log(nextMonth);
1028    console.log(prevMonth);
1029
1030    if ("次の月へ" === type) {
1031        retunMonth = formatDate_yyyy_mm(nextMonth);
1032    } else {
1033        retunMonth = formatDate_yyyy_mm(prevMonth);
1034    }
1035
1036    return retunMonth;
1037}
1038
1039function formatDate_yyyy_mm(date) {
1040    let year = date.getFullYear();
1041    let month = (date.getMonth() + 1).toString().padStart(2, '0');
1042    return `${year}-${month}`;
1043}
1044
1045// 記事要約ボタンアニメーション
1046function summaryBtn(button, listBtn) {
1047    if (listBtn) {
1048        let allCollapses = document.querySelectorAll('.accordion-collapse.show');
1049        allCollapses.forEach(collapse => {
1050            collapse.classList.remove('show');
1051        });
1052    }
1053
1054    let isFirstClick = button.getAttribute('data-isFirstClick');
1055
1056    if (isFirstClick === 'true') {
1057        generateTextAnimation(button);
1058        button.setAttribute('data-isFirstClick', 'false');
1059    }
1060}
1061
1062function generateTextAnimation(button) {
1063    let summaryText = "";
1064    let accordionBody = button.closest('.accordion-item').querySelector('.accordion-body');
1065    if (accordionBody) {
1066        summaryText = accordionBody.innerHTML.replace(/,/g, '<br>');
1067        accordionBody.innerHTML = '';
1068    }
1069
1070    let index = 0;
1071    let speed = 30;
1072
1073    function typeWriter() {
1074        if (index < summaryText.length) {
1075            let currentChar = summaryText.charAt(index);
1076            if (currentChar === '<') {
1077                let endTagIndex = summaryText.indexOf('>', index);
1078                if (endTagIndex !== -1) {
1079                    accordionBody.innerHTML += summaryText.substring(index, endTagIndex + 1);
1080                    index = endTagIndex + 1;
1081                }
1082            } else {
1083                accordionBody.innerHTML += currentChar;
1084                index++;
1085            }
1086            setTimeout(typeWriter, speed);
1087        }
1088    }
1089    typeWriter();
1090}
1091
1092
1093// パンくずと上部バナー画像の設定処理(記事・リスト)
1094function getBreadCrumb(blogId, entryId) {
1095
1096    if (entryId !== 0) { // 個別記事の場合API呼ぶ
1097        let endpoint = BASE_ENDPOINT + "articles/metas/" + blogId + "/" + entryId;
1098        comAjax(
1099            endpoint,
1100            JSON.stringify([]),
1101            function (obj_Result) {
1102                getBreadCrumbEndCB(obj_Result, blogId, entryId);
1103            },
1104            type = 'GET',
1105            dataType = 'json',
1106            processData = false,
1107            contentType = 'application/json',
1108            auth = true
1109        );
1110    } else if (entryId === 0) { // リストはAPI呼ばず直行
1111        let viewData = '';
1112        createBreadCrumb(viewData, blogId, entryId);
1113    } else {
1114    }
1115
1116}
1117
1118function getBreadCrumbEndCB(obj_Result, blogId, entryId) {
1119    if (obj_Result.result < 0) {
1120        return;
1121    } if (obj_Result.result === 0) {
1122        let breadCrumbs = obj_Result.data[0];
1123        createBreadCrumb(breadCrumbs, blogId, entryId);
1124    }
1125}
1126
1127function createBreadCrumb(viewData, blogId, entryId) {
1128    let currentYear = new Date().getFullYear();
1129    let currentUrl = window.location.href;
1130    let breadHtmls = [];
1131    let bannerHtmls = [];
1132    let breadLinkTop = '<li><a href="/">医療メディア Medical Tribune</a></li>'; // TOP(固定)
1133    let breadLinkBlog = ''; // ブログ種別(連載とか)
1134    let breadLinkCat = ''; // コンテンツ名
1135    let breadLinkTitle = ''; // 記事タイトル(リンク無し)
1136    let bannerImage = ''; // 上部バナー画像
1137    let bannerText = ''; // 上部バナー画像下の説明文(リストのみ)
1138    let categoryName = '';
1139
1140    // metaからパラメータを取得し、プリセットデータを検索
1141    let metaQuery = document.getElementById('query');
1142    let queryParam = metaQuery.getAttribute('content');
1143    let typeQuery = document.getElementById('typeQuery');
1144    let blogTypeParam = typeQuery.getAttribute('content');
1145    let presetData = {
1146        catName: '',
1147        imgBanner: '',
1148        text: '',
1149        link: '',
1150        blog_1: '',
1151        blog_1Url: '',
1152        blog_2: ''
1153    };
1154
1155    if (queryParam !== "1") {
1156        if (queryParam === "7") {
1157            categoryName = '感染症 早読み&深掘り';
1158        } else {
1159            let url = new URL(currentUrl);
1160            categoryName = url.searchParams.get('category') || viewData?.category || '';
1161        }
1162    } else if (queryParam === "1" && blogTypeParam === "1") {
1163        let catName = viewData['category'];
1164
1165        if (catName.includes('感染症 Hot Topics')) {
1166            let filteredCategories = catName.split(',').filter(category => category.trim() !== '感染症 Hot Topics');
1167            categoryName = filteredCategories.join(', ');
1168        } else {
1169            categoryName = catName;
1170        }
1171    } else if (queryParam === "1" && blogTypeParam === "0") {
1172        let url = new URL(currentUrl);
1173        let params = new URLSearchParams(url.search);
1174        let categoryParam = params.get('category');
1175        categoryName = categoryParam;
1176    }
1177
1178    if (blogTypeParam === "1") { // 記事ページ
1179        if (currentUrl.includes('/news/')) { // ニュース記事のパンくず
1180            let articleDateElement = document.getElementById('article_date');
1181            let articleDateText = articleDateElement.textContent || articleDateElement.innerText;
1182            let firstFourChars = articleDateText.substring(0, 4);
1183            breadLinkBlog = '<li><a href="/all.html?tab=news&year=' + currentYear + '&pointer=1">医学・医療ニュース一覧</a></li>';
1184        } else if (currentUrl.includes('/quiz/')) {
1185            breadLinkBlog = '';
1186            breadLinkCat = '';
1187        } else { // ニュース以外の記事
1188            if (queryParam === "1" && blogTypeParam === "1") { // プリセットにない連載
1189                breadLinkBlog = '<li><a href="/all.html?tab=rensai&year=' + currentYear + '&pointer=1">連載・特集</a></li>';
1190                breadLinkCat = '<li><a href="/rensai/?blogid=' + blogId + '&category=' + categoryName + '">' + categoryName + '</a></li>';
1191            } else if (presetData['blog_2'] === '') { // プリセットデータを各種パンくず変数にセット
1192                if (queryParam === "57") { // 健康百科のパンくず(※今後特設系の新コンテンツで増えるかも)
1193                    breadLinkBlog = '';
1194                    breadLinkCat = '<li><a href="/kenko100/?pointer=1">' + categoryName + '</a></li>';
1195                } else if (queryParam === "7") {
1196                    breadLinkBlog = '<li><a href="' + presetData['blog_1Url'] + '">' + presetData['blog_1'] + '</a></li>';
1197                    breadLinkCat = '<li><a href="/rensai/?blogid=' + blogId + '&category=感染症%20早読み">' + categoryName + '</a></li>';
1198                } else {
1199                    breadLinkBlog = '<li><a href="' + presetData['blog_1Url'] + '">' + presetData['blog_1'] + '</a></li>';
1200                    breadLinkCat = '<li><a href="/rensai/?blogid=' + blogId + '&category=' + categoryName + '">' + categoryName + '</a></li>';
1201                }
1202            } else if (presetData['blog_2'] !== '') { // ドクアイ個別記事
1203                breadLinkBlog = '<li><a href="/all.html?tab=rensai&year=' + currentYear + '&pointer=1">連載・特集</a></li>';
1204                breadLinkCat = '<li><a href="/theme/doctors-eye/?blogid=' + blogId + '&category=' + presetData['link'] + '">' + presetData['blog_2'] + '</a></li>';
1205            }
1206        }
1207
1208        // パンくず最後尾
1209        if (entryId !== 0) { // 個別記事は記事タイトル
1210            breadLinkTitle = '<li>' + viewData['title'] + '</li>';
1211        } else if (entryId === 0) { // リストは種類や連載名
1212            breadLinkTitle = '<li>' + categoryName + '</li>';
1213        }
1214    } else if (blogTypeParam === "0") { // リストページ
1215
1216        if (blogId === 7 || blogId === 34) { // 連載でないものは2つ目のパンくずを空に
1217            breadLinkBlog = '';
1218        } else {
1219            breadLinkBlog = '<li><a href="/all.html?tab=rensai&year=' + currentYear + '&pointer=1">連載・特集</a></li>';
1220        }
1221        breadLinkTitle = '<li>' + categoryName + '</li>';
1222    } else if (blogTypeParam === "2") { // 新着ニュース一覧
1223        breadLinkBlog = '<li>医学・医療ニュース一覧</li>';
1224    } else if (blogTypeParam === "3") { // すべての連載一覧
1225        breadLinkBlog = '<li>連載・特集</li>';
1226    }
1227
1228
1229    if (queryParam === "1") {
1230
1231    } else {
1232        // プリセットにバナーデータがあったら設定
1233        if (presetData['imgBanner'] !== '') {
1234            bannerImage = presetData['imgBanner'];
1235        }
1236        // プリセットにバナー下のテキストデータがあったら設定(リストのみ)
1237        if (blogTypeParam === "0") {
1238            if (presetData['text'] !== '') {
1239                bannerText = presetData['text'];
1240            }
1241        }
1242    }
1243
1244    // パンくずをHTMLに出力
1245    let cleanBreadLinkTitle = formatTitle(breadLinkTitle)
1246    let html = [
1247        breadLinkTop,
1248        breadLinkBlog,
1249        breadLinkCat,
1250        cleanBreadLinkTitle
1251    ];
1252    breadHtmls.push(html.join(""));
1253    $('#breadcrumb').html(breadHtmls.join(""));
1254
1255    // ページ上部のバナー画像をセット
1256    let targetCategory = null;
1257    if (viewData.category) {
1258        let categories = viewData.category.split(',');
1259        categories.forEach(function (category) {
1260            let trimmedCategory = category.trim();
1261            if (trimmedCategory.includes("JDDW2023")) {
1262                targetCategory = trimmedCategory.replace("@", "").trim();
1263                bannerImage = '/assets/images/rensai/special/banners/jddw2023/banner_' + targetCategory + '.png';
1264            } else if (trimmedCategory.includes("JDDW2024_news")) {
1265                let screenWidth = window.innerWidth;
1266
1267                if (screenWidth <= 768) {
1268                    bannerImage = '/special/society_report/2024/jddw/banner_top_sp.png';
1269                } else {
1270                    bannerImage = '/special/society_report/2024/jddw/top_banner_pc.png';
1271                }
1272            } else if (trimmedCategory.includes("JDDW2025")) {
1273                let screenWidth = window.innerWidth;
1274
1275                if (screenWidth <= 768) {
1276                    bannerImage = 'https://asset.mtweb.jp/special/society_report/2025/jddw/top_banner_sp.jpg';
1277                } else {
1278                    bannerImage = 'https://asset.mtweb.jp/special/society_report/2025/jddw/top_banner_pc.jpg';
1279                }
1280            } else if (trimmedCategory.includes("JDDW2026")) {
1281                let screenWidth = window.innerWidth;
1282
1283                if (screenWidth <= 768) {
1284                    bannerImage = 'https://asset.mtweb.jp/media/2026/08/07121539/JDDW2026_top_banner_sp.jpg';
1285                } else {
1286                    bannerImage = 'https://asset.mtweb.jp/media/2026/08/07121538/JDDW2026_top_banner_pc.jpg';
1287                }
1288            }
1289        });
1290    }
1291
1292    let startH1 = '';
1293    let endH1 = '';
1294    if (blogTypeParam === '0') {
1295        startH1 = '<h1 class="p-0">';
1296        endH1 = '</h1>';
1297    }
1298    if (bannerImage !== '') {
1299        headerBanner = startH1 + '<div class="px-0 pt-4 pb-2"><img src="' + bannerImage + '" alt="' + categoryName + '" class="p-0"></div>' + endH1;
1300        if (bannerText !== '') {
1301            headerBanner += '<p>' + bannerText + '</p>';
1302        }
1303        $('#article-image').removeClass('d-none');
1304        $('#article-image').html(headerBanner);
1305        $('#list_image').removeClass('d-none');
1306        $('#list_image').html(headerBanner);
1307    } else {
1308        headerBanner = startH1 + '<div class="fs-3 mt-3 mb-0 mx-0 p-0"><div class="px-0 py-2">' + categoryName + '</div></div>' + endH1;
1309        $('#list_image').removeClass('d-none');
1310        $('#list_image').html(headerBanner);
1311    }
1312    if (queryParam === "50" || queryParam === "51") {
1313        $('#article-image').addClass('d-none');
1314    }
1315
1316}
1317
1318// brタグを半角空きに変換する関数
1319function formatTitle(title) {
1320    if (!title) return "";
1321    let cleanTitle = title.replace(/<br\s*\/?>/gi, ' ');
1322    cleanTitle = cleanTitle.replace(/\s+/g, ' ').trim();
1323    return cleanTitle;
1324}
1325
1326// 右カラムGAMとタグ出し分け
1327$(document).ready(function () {
1328    let metaQueryGam = document.getElementById('query');
1329    let queryParamGam = null;
1330
1331    if (metaQueryGam) {
1332        queryParamGam = parseInt(metaQueryGam.getAttribute('content'), 10);
1333    }
1334
1335    let job = getCookie('_class');
1336    let department = getCookie('_userdep');
1337
1338    // ★追加:特定のアカウント(製薬など)でレクタングルバナーの表示処理をストップさせる処理
1339    // mtw_rightColumn.php側で const notAllowedArr = [...] を定義してなければならない
1340    if (typeof sf_id !== 'undefined' && typeof notAllowedArr !== 'undefined') {
1341        if (notAllowedArr.includes(sf_id)) {
1342            return; // 終了。以下のhtml追加処理などは実行されない
1343        }
1344    }
1345
1346    //レクタングル用
1347    let display_id = '';
1348    const TopRectangle = $('.right-culumn-gam');
1349    function createTopRectangleDiv(adId) {
1350        return `<div id='${adId}' class="mb-3" style='min-width: 300px; min-height: 300px;'></div>`;
1351    }
1352
1353    //マイページ用
1354    let display_id_mypage = '';
1355    const MypageText = $('.mypage-gam-test');
1356    function createMypageTextDiv(adId) {
1357        return `<div id='${adId}' class="text-center my-5 ms-2"></div>`;
1358    }
1359
1360    // if (queryParamGam === 13 || queryParamGam === 53) {
1361    //     // ビジョナリーズ・Hot Topics優先
1362    //     display_id = 'div-gpt-ad-1721891835324-0';
1363    // } else {
1364    switch (job) {
1365        case "MT社員":
1366        case "医師・研修医":
1367            // display_id = 'div-gpt-ad-1760074800000-0';
1368            display_id_mypage = 'div-gpt-ad-1760667600000-0';
1369            display_id = 'div-gpt-ad-1721891444332-0';
1370            break;
1371        case "歯科医師":
1372            display_id = 'div-gpt-ad-dentist-0';
1373            break;
1374        case "看護師":
1375            display_id = 'div-gpt-ad-nurse-0';
1376            break;
1377        case "薬剤師":
1378            display_id = 'div-gpt-ad-pharmacist-0';
1379            break;
1380        case "その他医療関係者":
1381            display_id = 'div-gpt-ad-other-0';
1382            break;
1383        case "製薬医療機器企業関係者":
1384            display_id = 'div-gpt-ad-1723088304593-0';
1385            break;
1386        case "医学生":
1387            display_id = 'div-gpt-ad-student-0';
1388            break;
1389        case "医師以外の医学研究者":
1390            display_id = 'div-gpt-ad-kenkyusha-0';
1391            break;
1392        default:
1393            display_id = 'div-gpt-ad-1717748434986-0';
1394    }
1395    // }
1396
1397    if (display_id) {
1398        TopRectangle.html(createTopRectangleDiv(display_id));
1399        googletag.cmd.push(function () {
1400            googletag.display(display_id);
1401        });
1402    }
1403
1404    if (display_id_mypage) {
1405        MypageText.html(createMypageTextDiv(display_id_mypage));
1406        googletag.cmd.push(function () {
1407            googletag.display(display_id_mypage);
1408        });
1409    }
1410});
1411
1412// 【GAMタグ出し分け】クッキーから職業を取得
1413function getCookie(name) {
1414    let cookieArr = document.cookie.split(";");
1415    for (let i = 0; i < cookieArr.length; i++) {
1416        let cookiePair = cookieArr[i].split("=");
1417
1418        if (name === cookiePair[0].trim()) {
1419            return decodeURIComponent(cookiePair[1]);
1420        }
1421    }
1422
1423    return null;
1424}
1425
1426
1427
1428
1429// 検索ボタン(PC)
1430document.addEventListener('DOMContentLoaded', function () {
1431    let inputSearch = document.getElementById('input-search');
1432    if (inputSearch) {
1433        let isComposing = false;
1434
1435        inputSearch.addEventListener('compositionstart', function () {
1436            isComposing = true; // IME入力開始
1437        });
1438
1439        inputSearch.addEventListener('compositionend', function () {
1440            isComposing = false; // IME入力終了
1441        });
1442
1443        inputSearch.addEventListener('keydown', function (event) {
1444            if (event.key === 'Enter' && !isComposing) {
1445                event.preventDefault();
1446                let inputWord = inputSearch.value;
1447                // window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&year=2025`;
1448                window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&syear=2024&eyear=2026&number=20`;
1449            }
1450        });
1451    }
1452});
1453
1454// document.addEventListener('DOMContentLoaded', function () {
1455//     let inputSearch = document.getElementById('input-search');
1456//     if (inputSearch) {
1457//         inputSearch.addEventListener('keydown', function (event) {
1458//             if (event.key === 'Enter') {
1459//                 event.preventDefault();
1460//                 let inputWord = inputSearch.value;
1461//                 window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&year=2025`;
1462//             }
1463//         });
1464//     }
1465// });
1466
1467
1468// 検索ボタン(SP)
1469document.addEventListener('DOMContentLoaded', function () {
1470    let searchForm = document.getElementById('searchform');
1471    if (searchForm) {
1472        searchForm.addEventListener('submit', function (event) {
1473            event.preventDefault();
1474            let inputWord = document.getElementById('input-search-sp').value;
1475            if (inputWord.trim() !== '') {
1476                // window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&year=2025`;
1477                window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&syear=2024&eyear=2026&number=20`;
1478            }
1479        });
1480    }
1481});
1482
1483document.addEventListener('DOMContentLoaded', function () {
1484    let inputSearchSp = document.getElementById('input-search-sp');
1485    if (inputSearchSp) {
1486        inputSearchSp.addEventListener('keydown', function (event) {
1487            if (event.key === 'Enter') {
1488                event.preventDefault();
1489                let inputWord = inputSearchSp.value;
1490                if (inputWord.trim() !== '') {
1491                    // window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&year=2025`;
1492                    window.location.href = `/navi-search.html?word=${encodeURIComponent(inputWord)}&syear=2024&eyear=2026&number=20`;
1493                }
1494            }
1495        });
1496    }
1497});
1498
1499// 検索リスト作成
1500let currentOffset = 0;
1501let listItemPerPage = 30;
1502let allItems = [];
1503
1504function createSelectOptions(word, selectedYear) {
1505    let startYear = '2008';
1506    let endYear = new Date().getFullYear().toString();
1507    let redirectLink = '';
1508    let select = document.getElementById('search-selectbox');
1509
1510    for (let year = endYear; year >= startYear; year--) {
1511        let option = document.createElement('option');
1512        redirectLink = '/navi-search.html?word=' + word + '&year=' + year;
1513        option.value = redirectLink;
1514        option.textContent = year + 'å¹´';
1515
1516        if (year === parseInt(selectedYear)) {
1517            option.setAttribute('selected', 'selected');
1518        }
1519
1520        select.appendChild(option);
1521    }
1522
1523}
1524
1525// ★ドクアイURLのパス設定
1526// newmtw_list.jsのcreateUrl関数と同様の処理(関数名だけ変更)
1527// 今後は処理をまとめた方が良いかも(2026/02/10)
1528function generateDoctorsEyeURL(urls, categories) {
1529    let newUrl = urls;
1530    if (categories.includes("ドクターズアイ")) {
1531        newUrl = newUrl.replace("rensai", "theme/doctors-eye");
1532        // newUrl = newUrl.replace("news", "theme/doctors-eye");
1533    }
1534    return newUrl;
1535}
1536
1537function renderItems(offset, limit) {
1538    let htmls = [];
1539    let itemsToRender = allItems.slice(offset, offset + limit);
1540
1541    console.log(itemsToRender);
1542
1543    itemsToRender.forEach(value => {
1544        let title = value.title;
1545        let link = generateDoctorsEyeURL(value.url, value.category || []);
1546        let formattedDate = formatDate(value.date);
1547        let text = value.textCommon.length > 70 ? value.textCommon.slice(0, 70) + '…' : value.textCommon;
1548        let html = [
1549            '<li class="my-3 fade-in">',
1550            '           <a href="' + link + '">',
1551            '              <div class="fw-bold my-2">' + title + '</div>',
1552            '              <div class="mb-2">' + text + '</div>',
1553            '        </a>',
1554            '       <div class="mb-2">' + formattedDate + '</div>',
1555            '  </li>',
1556        ];
1557        htmls.push(html.join(""));
1558    });
1559
1560    $('#search-list-item').removeClass('search-list-item');
1561    $('#search-list-item').append(htmls.join(""));
1562}
1563
1564function getSearchList() {
1565    let urlParams = new URLSearchParams(window.location.search);
1566    let paramWord = urlParams.get('word');
1567    let paramYear = urlParams.get('year');
1568    let sfid = getCookie("_sfid");
1569    if (sfid === null || sfid === '') {
1570        sfid = '';
1571    }
1572    let ip = '';
1573
1574    let wordsArray = [];
1575    if (paramWord) {
1576        wordsArray = paramWord.split(/[\s,、]+/);
1577    }
1578
1579    $.getJSON('https://ipinfo.io', function (res) {
1580        ip = res.ip;
1581
1582        // let postData = {
1583        //     "tags": wordsArray,
1584        //     "categories": [],
1585        //     "maxYear": parseInt(paramYear),
1586        //     "minYear": parseInt(paramYear),
1587        //     "limit": 500
1588        // }
1589        let postData = {
1590            "words": wordsArray,
1591            "maxYear": parseInt(paramYear),
1592            "minYear": parseInt(paramYear),
1593            "limit": 500,
1594            "sfid": sfid,
1595            "ip": ip,
1596            "isAnd": true
1597        };
1598
1599        if (parseInt(paramYear) === 2025) {
1600            postData.minYear = 2024;
1601        }
1602
1603        console.log(postData);
1604
1605        let endpoint = BASE_ENDPOINT + "articles/lists/searches"
1606        comAjax(
1607            endpoint,
1608            JSON.stringify(postData),
1609            searchListCB,
1610            type = 'POST',
1611            dataType = 'json',
1612            processData = false,
1613            contentType = 'application/json',
1614            auth = 1
1615        );
1616    });
1617
1618}
1619
1620function searchListCB(response) {
1621    let viewData = response.data[0];
1622
1623
1624    let urlParams = new URLSearchParams(window.location.search);
1625    let paramWord = urlParams.get('word');
1626    let paramYear = urlParams.get('year');
1627    let spanElementCount = document.querySelector('#search-list-count span');
1628    let spanElementTitle = document.querySelector('.search-title span');
1629    spanElementTitle.textContent = paramWord;
1630    if (response.result === 1) {
1631        $('#search-selectbox').addClass('d-none');
1632        $('#load-more-btn-search').addClass('d-none');
1633        $('.spinner-grow').addClass('d-none');
1634        spanElementCount.textContent = '0';
1635    } else if (response.result === 0) {
1636        spanElementCount.textContent = viewData.count;
1637        allItems = viewData.rows;
1638
1639        createSelectOptions(paramWord, paramYear);
1640        renderItems(currentOffset, listItemPerPage);
1641        currentOffset += listItemPerPage;
1642
1643        $('.spinner-grow').addClass('d-none');
1644
1645        if (viewData.count < 31) {
1646            $('#load-more-btn-search').addClass('d-none')
1647        }
1648    }
1649}
1650
1651
1652
1653// 検索リストの作成(改修)
1654
1655function getSearchListNew(sort) {
1656    let urlParams = new URLSearchParams(window.location.search);
1657    let paramWord = urlParams.get('word');
1658    let paramStartYear = urlParams.get('syear');
1659    let paramEndYear = urlParams.get('eyear');
1660    let paramNumber = urlParams.get('number');
1661    let sfid = getCookie("_sfid");
1662    if (sfid === null || sfid === '') {
1663        sfid = '';
1664    }
1665    let ip = '';
1666
1667    console.log(sort);
1668
1669    let wordsArray = [];
1670    if (paramWord) {
1671        wordsArray = paramWord.split(/[\s,、]+/);
1672    }
1673
1674    let searchWordInput = document.querySelector('input[name="search_word"]');
1675    if (paramWord) {
1676        searchWordInput.value = paramWord;
1677    }
1678
1679    let radioButton = document.querySelector(`input[name="search_number"][value="${paramNumber}"]`);
1680    if (radioButton) {
1681        radioButton.checked = true;
1682    }
1683
1684    if (paramStartYear) {
1685        let startSelect = document.getElementById('serch_input_start_number');
1686        if (startSelect) {
1687            let startOption = startSelect.querySelector(`option[value="${paramStartYear}"]`);
1688            if (startOption) {
1689                startOption.selected = true;
1690            }
1691        }
1692    }
1693
1694    if (paramEndYear) {
1695        let endSelect = document.getElementById('serch_input_end_number');
1696        if (endSelect) {
1697            let endOption = endSelect.querySelector(`option[value="${paramEndYear}"]`);
1698            if (endOption) {
1699                endOption.selected = true;
1700            }
1701        }
1702    }
1703
1704    $.getJSON('https://ipinfo.io', function (res) {
1705        ip = res.ip;
1706
1707        let postData = '';
1708
1709        if (parseInt(paramEndYear) < parseInt(paramStartYear)) {
1710            let temp = paramEndYear;
1711            paramEndYear = paramStartYear;
1712            paramStartYear = temp;
1713        }
1714
1715        if (sort === "sortold") {
1716            postData = {
1717                "words": wordsArray,
1718                "maxYear": parseInt(paramEndYear),
1719                "minYear": parseInt(paramStartYear),
1720                "limit": parseInt(paramNumber),
1721                "sfid": sfid,
1722                "ip": ip,
1723                "isAnd": true,
1724                "isOld": true
1725            };
1726        } else {
1727            postData = {
1728                "words": wordsArray,
1729                "maxYear": parseInt(paramEndYear),
1730                "minYear": parseInt(paramStartYear),
1731                "limit": parseInt(paramNumber),
1732                "sfid": sfid,
1733                "ip": ip,
1734                "isAnd": true,
1735                "isOld": false
1736            };
1737        }
1738
1739        // if (parseInt(paramEndYear) === 2025) {
1740        //     postData.minYear = 2024;
1741        // }
1742
1743        console.log(postData);
1744
1745        let endpoint = BASE_ENDPOINT + "articles/lists/searches"
1746        comAjax(
1747            endpoint,
1748            JSON.stringify(postData),
1749            function (response) {
1750                searchListNewCB(response, sort);
1751            },
1752            type = 'POST',
1753            dataType = 'json',
1754            processData = false,
1755            contentType = 'application/json',
1756            auth = 1
1757        );
1758    });
1759}
1760
1761
1762function searchListNewCB(response, sort) {
1763    let viewData = response.data[0];
1764
1765    // let currentOffset = 0;
1766    // let listItemPerPage = 30;
1767    // let allItems = [];
1768
1769    let urlParams = new URLSearchParams(window.location.search);
1770    let paramWord = urlParams.get('word');
1771    let spanElementCount = document.querySelector('.search-title span:nth-child(2)');
1772    let spanElementTitle = document.querySelector('.search-title span:first-child');
1773    spanElementTitle.textContent = paramWord;
1774    console.log(response.result);
1775    if (response.result === 1) {
1776        $('#search-selectbox').addClass('d-none');
1777        $('#load-more-btn-search').addClass('d-none');
1778        $('.spinner-grow').addClass('d-none');
1779        $('#serch_nohit').removeClass('d-none');
1780        spanElementCount.textContent = '0';
1781    } else if (response.result === 0) {
1782        spanElementCount.textContent = viewData.count;
1783
1784        // if (sort === "sortold") {
1785        //     viewData.rows.reverse();
1786        // }
1787
1788        allItems = viewData.rows;
1789
1790        renderItems(currentOffset, listItemPerPage);
1791        currentOffset += listItemPerPage;
1792
1793        $('.spinner-grow').addClass('d-none');
1794
1795        if (viewData.count < 31) {
1796            $('#load-more-btn-search').addClass('d-none')
1797        }
1798    }
1799}
1800
1801function research() {
1802    let baseUrl = "/navi-search.html";
1803    let researchWord = document.querySelector('input[name="search_word"]').value.trim();
1804    let researchSyear = document.getElementById('serch_input_start_number').value;
1805    let researchEyear = document.getElementById('serch_input_end_number').value;
1806    let selectedRadioButton = document.querySelector('input[name="search_number"]:checked');
1807    let researchNumber = selectedRadioButton ? selectedRadioButton.value : '';
1808
1809    let researchParams = new URLSearchParams();
1810
1811    if (researchWord) {
1812        researchParams.append("word", researchWord);
1813    }
1814    if (researchSyear) {
1815        researchParams.append("syear", researchSyear);
1816    }
1817    if (researchEyear) {
1818        researchParams.append("eyear", researchEyear);
1819    }
1820    if (researchNumber) {
1821        researchParams.append("number", researchNumber);
1822    }
1823
1824    let researchFullUrl = `${baseUrl}?${researchParams.toString()}`;
1825    window.location.href = researchFullUrl;
1826}
1827
1828function search_sort_new() {
1829
1830    $('#search-list-item').addClass('search-list-item');
1831    $('#search-list-item').empty();
1832
1833    currentOffset = 0;
1834
1835    document.getElementById("search_sort_new").className = "search_list_sort_active";
1836    document.getElementById("search_sort_old").className = "search_list_sort_notactive";
1837
1838    document.getElementById("search_sort_new").setAttribute("disabled", true);
1839    document.getElementById("search_sort_old").removeAttribute("disabled");
1840
1841
1842    $('.spinner-grow').removeClass('d-none');
1843
1844    getSearchListNew("sortnew");
1845
1846}
1847
1848function search_sort_old() {
1849
1850    $('#search-list-item').addClass('search-list-item');
1851    $('#search-list-item').empty();
1852
1853    currentOffset = 0;
1854
1855    document.getElementById("search_sort_new").className = "search_list_sort_notactive";
1856    document.getElementById("search_sort_old").className = "search_list_sort_active";
1857
1858    document.getElementById("search_sort_new").removeAttribute("disabled");
1859    document.getElementById("search_sort_old").setAttribute("disabled", true);
1860
1861    $('.spinner-grow').removeClass('d-none');
1862
1863    getSearchListNew("sortold");
1864
1865}
1866
1867
1868// 公開日の表記整形
1869function formatDate(dateString) {
1870    let date = new Date(dateString);
1871    let year = date.getFullYear();
1872    let month = date.getMonth() + 1;
1873    let day = date.getDate();
1874    return year + '年' + month + '月' + day + '日 ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
1875}
1876
1877// GetSiteControl
1878function com_getGSCParam(st_sfid, i_DcfId) {
1879    console.log("GSC-id : " + st_sfid + " / " + i_DcfId);
1880    let endpoint = BASE_ENDPOINT + "users/" + st_sfid + "/matching/contents/" + i_DcfId;
1881    comAjax(
1882        endpoint,
1883        JSON.stringify([]),
1884        com_getGSCParamCB,
1885        type = 'GET',
1886        dataType = 'json',
1887        processData = false,
1888        contentType = 'application/json',
1889        auth = true
1890    );
1891}
1892
1893// GetSiteControl(CB)
1894function com_getGSCParamCB(obj_Result) {
1895    if (obj_Result.result === 0) {
1896        for (var i_Pos in obj_Result.data) {
1897            let paramName = 'dcf_' + obj_Result.data[i_Pos].matching_id;
1898            console.log("GSC-ParamName : " + paramName);
1899            gsc('params', {
1900                [paramName]: '1'
1901            })
1902        }   // for end
1903    }
1904}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.