20250315 - 글로벌 변수 Global Variables

G_USER Specifies the currently logged in user.

G_FLOW_ID Specifies the ID of the currently running application.

G_FLOW_STEP_ID Specifies the ID of the currently running page.

G_FLOW_OWNER

Defaults to the application's parsing schema. Use #OWNER# to reference this value in SQL queries and PL/SQL.


Note:Changing G_FLOW_OWNER at runtime does not change the parsing schema.

G_REQUEST Specifies the value of the request variable most recently passed to or set within the show or accept modules.

G_BROWSER_LANGUAGE Refers to the web browser's current language preference.

G_DEBUG Refers to whether debugging is switched on or off. Valid values for the DEBUG flag are Yes or No. Enabling debug shows details about application processing.

G_HOME_LINK Refers to the home page of an application. If no page is given and if no alternative page is dictated by the authentication scheme's logic, the Oracle APEX engine redirects to this location.

G_LOGIN_URL Used to display a link to a login page for users that are not currently logged in.

G_IMAGE_PREFIX Refers to the virtual path the web server uses to point to the images directory distributed with APEX.

G_FLOW_SCHEMA_OWNER Refers to the owner of the APEX schema.

G_PRINTER_FRIENDLY Refers to whether the APEX engine is running in print view mode. This setting can be referenced in conditions to eliminate elements not desired in a printed document from a page.

G_PROXY_SERVER Refers to the application attribute Proxy Server.

G_SYSDATE Refers to the current date on the database server. G_SYSDATE uses the DATE datatype.

G_PUBLIC_USER Refers to the Oracle schema used to connect to the database through the database access descriptor (DAD).

G_GLOBAL_NOTIFICATION Specifies the application's global notification attribute.

G_X01, ... G_X10 Specifies the values of the X01, ... X10 variables most recently passed to or set within the show or accept modules. You typically use these variables in On-Demand AJAX processes. 


=====

APEX_CSP_DISPLAY_NONE

APEX_FILES

APEX$ROW_NUM

APEX$ROW_SELECTOR

APEX$ROW_STATUS

APP_ID

APP_ALIAS

APP_AJAX_X01, ... APP_AJAX_X10

APP_BUILDER_SESSION

APP_DATE_TIME_FORMAT

APP_FILES

APP_NLS_DATE_FORMAT

APP_NLS_TIMESTAMP_FORMAT

APP_NLS_TIMESTAMP_TZ_FORMAT

APP_PAGE_ALIAS

APP_PAGE_ID

APP_REGION_ID

APP_REGION_STATIC_ID

APP_REQUEST_DATA_HASH

APP_SESSION

APP_SESSION_VISIBLE

APP_TITLE

APP_UNIQUE_PAGE_ID

APP_USER

APP_VERSION

AUTHENTICATED_URL_PREFIX

BROWSER_LANGUAGE

CURRENT_PARENT_TAB_TEXT

DEBUG

HOME_LINK

JET_BASE_DIRECTORY

JET_CSS_DIRECTORY

JET_JS_DIRECTORY

LOGIN_URL

LOGOUT_URL

APP_TEXT$Message_Name, APP_TEXT$Message_Name$Lang

OWNER

PRINTER_FRIENDLY

PROXY_SERVER

PUBLIC_URL_PREFIX

REQUEST

Using REQUEST

SCHEMA OWNER

SQLERRM

SYSDATE_YYYYMMDD

THEME_DB_FILES

THEME_FILES

WORKSPACE_FILES

WORKSPACE_ID


참고

https://docs.oracle.com/en/database/oracle/apex/23.2/aeapi/APEX_APPLICATION-Global-Variables.html

https://docs.oracle.com/en/database/oracle/apex/24.1/htmdb/using-available-built-in-substitution-strings.html

20250304 - 버튼 액션 및 포커스 제거

JS :

$("#your-button-id").on("click", function(e) {

  e.preventDefault();

  return false;

});


CSS:

.your-button-class {

  pointer-events: none;

}


Button URL:

javascript:void(0);



20250218 - 여러 종류 메세지 보이기

 // 기본 alert 대신:

apex.message.showPageSuccess('저장되었습니다');  // 성공 메시지 (초록색)

apex.message.showPageError('오류가 발생했습니다');    // 에러 메시지 (빨간색)

apex.message.showPageWarning('주의가 필요합니다');    // 경고 메시지 (노란색)

apex.message.showPageInfo('참고해주세요');      // 정보 메시지 (파란색)


// 타이틀과 함께 표시:

apex.message.alert('메시지 내용', '타이틀');  // 확인 버튼이 있는 모달 창


// 콜백 함수 사용:

apex.message.confirm('저장하시겠습니까?', function(okPressed) {

    if (okPressed) {

        // OK 버튼 눌렀을 때 실행할 코드

    }

});


// 자동으로 사라지는 메시지:

apex.message.clearErrors();

apex.message.showPageSuccess('저장되었습니다', function() {

    // 3초 후 자동으로 사라짐

});


//아이콘 포함


('#SID_BTN_RADMIN').on('click', function(e) {
   e.preventDefault();
   apex.message.clearErrors();
   
   apex.message.confirm("진행을 취소하고 관리 메인 페이지로 이동하시겠습니까?", function(okPressed) {
       if (okPressed) {
           const url = `f?p=${$v('pFlowId')}:200:${$v('pInstance')}::NO:::`;
           
           apex.server.process(
               'AJAX-popup',
               {x01: url},
               {
                   success: function(pData) {
                       pData = pData.replace(",this", ",'#SID_BTN_RADMIN'");
                       apex.navigation.redirect(pData);
                   },
                   error: function() {
                       apex.message.alert("페이지 이동 중 오류가 발생했습니다.");
                   },
                   dataType: "text"
               }
           );
       }
   }, {
        title: "확인 요청",
        style: "warning"
   });
});

20250217 - IG 수정 가능항목에 폰트 색상 Class 넣기

SQL :


     , case
         when delivery_req is null or delivery_req = '' then ''
         when regexp_instr(delivery_req, '/[0-9]|[0-9]일|[0-9].[0-9]|평일|주말|요일|[0-9]월') > 0 then 'css-red'
         else ''
       end as delivery_req_style
     , delivery_req


Column Initialization JavaScript Function :


function(options) {
    options.defaultGridColumnOptions = {
        cellCssClassesColumn: "DELIVERY_REQ_STYLE"
    }
    return options;
}






읽기 전용 항목이면, 간단히 HTML Expression으로.

     , decode(regexp_instr(nvl(delivery_req,''), '/[0-9]|[0-9]일|[0-9].[0-9]|평일|주말|요일|[0-9]월'), 0
              , '<span>'||delivery_req||'</span>'
              , '<span class="css-red">'||delivery_req||'</span>') delivery_req_css




참고

https://apexapps.oracle.com/pls/apex/r/apex_pm/ideas/details?idea=FR-2656&cs=1UuSgWyFNcx0mxFPVL9acva6DYDiz8xoQU3igQfQX24AfPiSBv0TbsWdvNk6cKRXRJnAQd-FirfRIh0qh3XMbQA

20250202 - IG 다운로드 버튼 바로 보이기 및 바로 엑셀 다운로드 실행

JS initialization Code :


function(config) {
    var $ = apex.jQuery,
        toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),
        actionsMenuGroup = toolbarData.toolbarFind("actions1");
    config.initActions = function(actions) {
        actions.add({
            name: "show-download-dialog"
        });
    }

    actionsMenuGroup.controls.push({
        type: "BUTTON",
        action: "show-download-dialog",
        label: "Download",
        icon: "fa fa-download",
        iconBeforeLabel: true

    });

    config.toolbarData = toolbarData;
    return config;
}



최종

Global Variable Declaration :


var firstClickedIG = null;



IG Initialization JavaScript Function :


function(config) {
   var $ = apex.jQuery,
       toolbarData = $.apex.interactiveGrid.copyDefaultToolbar();
   
   config.defaultGridViewOptions = {
       tooltip: {
           content: function(callback, model, recordMeta, colMeta, columnDef ) {
               var text = null;
               if (columnDef && recordMeta) {
                   let value = model.getValue(recordMeta.record, columnDef.property);
                   text = typeof value === 'object' && value.d ? value.d : value;
               }
               return text;
           },
           tooltipClass: "tooltip-custom-style"
       }
   };
   
   config.features.download.formats = ["XLSX"];
   
   var vSID = "myStaticIGPOMST1";
   config.initActions = function(actions) {
       actions.add({
           name: "custom-download1",
           action: function(event, focusElement) {
               var ig$ = apex.region(vSID).widget();
               if(firstClickedIG === null) firstClickedIG = vSID;
               ig$.interactiveGrid("getActions").invoke("show-download-dialog");
               var $hotButton = (firstClickedIG === vSID) ?
                   $('.ui-dialog-buttonpane:first .ui-button--hot') :
                   $('.ui-dialog-buttonpane:last .ui-button--hot');
               if ($hotButton.length > 0) {
                   $hotButton.trigger("click");
               }
           }
       });
   };
   
   var rightActionGroup = toolbarData.toolbarFind("actions4");
   if (!rightActionGroup) {
       rightActionGroup = {
           id: "actions4",
           controls: []
       };
       toolbarData.toolbar.push(rightActionGroup);
   }
   
   var resetButton = rightActionGroup.controls.find(control => control.action === "reset-report");
   var resetIndex = rightActionGroup.controls.indexOf(resetButton);
   
   var downloadButton = {
       type: "BUTTON",
       action: "custom-download1",
       label: "다운로드",
       hot: false
   };
   
   if (resetIndex !== -1) {
       rightActionGroup.controls.splice(resetIndex, 0, downloadButton);
   } else {
       rightActionGroup.controls.unshift(downloadButton);
   }
   
   config.toolbarData = toolbarData;
   return config;
}







참고

20250125 - 메세지 박스 사라짐 처리 fade out

처리


apex.jQuery(function() {
  apex.theme42.util.configAPEXMsgs({
    autoDismiss: true,
    duration: 5000  // duration is optional (Default is 3000 milliseconds)
  });
});


참고

https://apex.oracle.com/pls/apex/apex_pm/r/ut/javascript-apis

20250109 - 각 리전의 높이 Height 맞추기

JS Page Load :


function equalizeHeight() {
    let regionA = apex.jQuery('#SID_MAIN');
    let regionB = apex.jQuery('#SID_SIDE');
    let maxHeightAB = Math.max(regionA.height(), regionB.height());

    regionA.height(maxHeightAB);
    regionB.height(maxHeightAB);

    let region1 = apex.jQuery('#SID_R1');
    let region2 = apex.jQuery('#SID_R2');
    let maxHeight = Math.max(region1.height(), region2.height());
   
    region1.height(maxHeight);
    region2.height(maxHeight);
}

apex.jQuery(window).on('apexwindowresized load', equalizeHeight);






참고

20250107 - 모바일 디자인 참고

1. 하단 Dock 독 메뉴

Navigation Menu - List Template : Top Navigation Tabs




네비게이션 메뉴 숨기기
Appearance - Page Template : Minimal (No Navigation)




2. 상단 GNB
HTML

<div class="c-Alert c-Alert--page c-flex-space" id="c_Alert_Success">
    <div class="t-Alert-wrap col-6">
        <div class="col col-12 apex-col-auto col-start col-end">
            <button class="t-Button t-Button--noLabel t-Button--icon t-Button--large t-Button--noUI lto22518622360929923_0" onclick="OnClickBack()" type="button" id="B22518622360929923Left" title="New" aria-label="New">
                <span class="t-Icon fa fa-arrow-left" aria-hidden="true"></span>
            </button>
        </div>
    </div>
    <div class="t-Alert-wrap col-6 c-flex-end">
        <div class="col col-12 apex-col-auto col-start col-end">
            <button class="t-Button t-Button--noLabel t-Button--icon t-Button--large t-Button--noUI lto22518622360929923_0" onclick="OnClickHome()" type="button" id="B22518622360929923Home" title="New" aria-label="New">
                <span class="t-Icon fa fa-home" aria-hidden="true"></span>
            </button>
            <button class="t-Button t-Button--noLabel t-Button--icon t-Button--large t-Button--noUI lto22518622360929923_0" onclick="OnClickCart()" type="button" id="B22518622360929923Cart" title="New" aria-label="New">
                <span class="t-Icon fa fa-shopping-cart" aria-hidden="true"></span>
            </button>
        </div>
    </div>
</div>


JS :


let selectedMODIDs;

function OnClickBack() {
  window.history.back();
}

function OnClickHome() {
  apex.navigation.redirect ("f?p=&APP_ID.:Home:&APP_SESSION.::NO:RP::");
}

function OnClickCart() {
  apex.navigation.redirect ("f?p=&APP_ID.:ViewCart:&APP_SESSION.::NO:RP::");
}


CSS :


.t-Header-branding {
    display: none;
    visibility: hidden;
}

.t-Form-fieldContainer--floatingLabel {
  --ut-field-fl-label-offset: 0;
}

.c-flex-space {
    display: flex;
    justify-content: space-between;
}
.c-flex-end {
    display: flex;
    justify-content: flex-end;
}
.fa-arrow-left {
    color: white;
}
.fa-home {
    color: white;
}
.fa-shopping-cart {
    color: white;
}
.t-Alert--page {
    transition: none;
    transition-duration: none;
    transition-timing-function: none;
    transition-delay: none;
    transition-property: none;
    left: 0;
    right: 0;
    top: 0;
    padding: 0;
    background-color: transparent;
}

.t-Alert {
    border-style: none;
    border-top-style: none;
    border-right-style: none;
    border-bottom-style: none;
    border-left-style: none;
    box-shadow: none;
}


3. 하단 Sticky 버튼

Appearance - Template : Buttons Container

Appearance - Template Options : Stick to Bottom for Mobile



4. 다음 기능






















참고

20250105 - 에어비앤비와 유사한 기능으로 변경 Date Picker2

처리조건 :

1. 기본 로드될 때 이미 예약되어 선택 불가능한 날짜들 17, 18일, 24,25일 비활성화처리


2. 체크인 날짜 선택시 그 이후 기예약 시작일 찾아서 거기까지만 예약 가능하도록 나머지 일자 비활성화 처리



3. 체크아웃 날짜 선택시 처음에 로드했던 예약 불가능한 날짜들 17, 18일, 24,25일 비활성화처리 (단, 기예약 시작일과 현재 선택하는 체크아웃 날짜는 같을 수 있도록 처리 보완 필요, 추가 이미지 확인)





Page Load


window.checkInCheckOutDateRangePicker = new DateRangePicker({
   picker: {
       name: "P6_CHECKIN_CHECKOUT_PICKER",
       format: "YYYY-MM-DD",
       allowSingleDay: false
   },
   start: {
       name: "P6_CHECKIN",  
       label: "Check In"
   },
   end: {
       name: "P6_CHECKOUT",
       label:"Check Out"
   },
   reset: {
       id:"Reset_CheckIn_CheckOut"
   }
});

const testDates = ['2025-01-17', '2025-01-18', '2025-01-24', '2025-01-25', '2025-01-26'];
window.checkInCheckOutDateRangePicker.setDisabledDates(testDates);


$(document).on('daterangepicker-reset', function(event, data) {
    apex.item('P6_MAX').setValue(null);

    window.checkInCheckOutDateRangePicker.setMaxDate(null);

    const testDates = ['2025-01-17', '2025-01-18', '2025-01-24', '2025-01-25', '2025-01-26'];
    window.checkInCheckOutDateRangePicker.setDisabledDates(testDates);
});

// 참고 : 예약된 날짜 데이터 가져오기
/*
apex.server.process(
   'GET_RESERVED_DATES',
   {},
   {
       success: function(data) {
           // data는 ['2024-01-01', '2024-01-02', '2024-01-03'] 형식으로 받음
           window.checkInCheckOutDateRangePicker.setDisabledDates(data);
           window.eventStartEndDateRangePicker.setDisabledDates(data);  // 두 번째 데이트피커에도 적용
       },
       error: function(jqXHR, textStatus, errorThrown) {
           apex.message.showErrors([{
               type: "error",
               location: ["page"],
               message: "Failed to load reserved dates",
               unsafe: false
           }]);
       }
   }
);
*/


P6_CHECKIN 선택시(변경시), Max 예약일 구한 후 :

PL/SQL


:P6_MAX := '2025-01-17'; --to_date('2025-01-17', 'YYYY-MM-DD');


JS 


const maxDate = apex.item('P6_MAX').getValue();
window.checkInCheckOutDateRangePicker.setDisabledDates(null);
window.checkInCheckOutDateRangePicker.setMaxDate(maxDate);


P6_CHECKOUT 선택시(변경시)


window.checkInCheckOutDateRangePicker.setMaxDate(null);

//나중에 종료일 선택 날짜와 P6_MAX와 같으면 비활성화 날짜 리스트에서 제외, 예를 들어 '2025-01-17' 종료일 선택일 경우
const testDates = ['2025-01-18', '2025-01-24', '2025-01-25', '2025-01-26'];
window.checkInCheckOutDateRangePicker.setDisabledDates(testDates);


P6_CHECKIN_CHECKOUT_PICKER :



Reset_CheckIn_CheckOut 버튼 (SID 및 DA 로 셋팅) :




CSS : 


a-date-picker.date-range-picker .a-DatePicker-calendar td.is-current {
    --a-datepicker-calendar-day-current-background-color: var(--a-datepicker-calendar-background-color);
    --a-datepicker-calendar-day-current-text-color: var(--a-datepicker-calendar-day-text-color);
    --a-datepicker-calendar-day-current-border-color: var(--a-datepicker-calendar-background-color);
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.is-current > span,
a-date-picker.date-range-picker .a-DatePicker-calendar td.is-selected > span {
    font-weight: var(--a-datepicker-calendar-day-font-weight, var(--a-base-font-weight-semibold,500));
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.is-current.dateRangeStart > span,
a-date-picker.date-range-picker .a-DatePicker-calendar td.is-current.dateRangeEnd > span {
     border-radius: var(--a-datepicker-calendar-day-border-radius);
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeStart,
a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeEnd,
a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeSingleDay {
     --a-datepicker-calendar-day-border-radius: calc(var(--a-datepicker-calendar-day-font-size, 1rem) * 2);
     --a-datepicker-calendar-day-text-color: var(--a-palette-primary-contrast);                        
}

a-date-picker.date-range-picker .a-DatePicker-calendar td {
    height: 44px !important;
    position: relative;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td > span {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 44px !important;
    height: 44px !important;
    margin: auto !important;
    border-radius: 50% !important;
    position: relative;
    z-index: 2;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeStart {
    background: none;
    position: relative;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeStart:not(.dateRangeSingleDay)::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    right: 0;
    height: 44px;
    transform: translateY(-22px);
    background-color: #F7F7F7;
    z-index: 1;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeStart > span {
    background-color: #222222 !important;
    color: #FFFFFF !important;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeMiddle {
    background: none;
    position: relative;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeMiddle::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 44px;
    transform: translateY(-22px);
    background-color: #F7F7F7;
    z-index: 1;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeEnd {
    background: none;
    position: relative;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeEnd::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 50%;
    height: 44px;
    transform: translateY(-22px);
    background-color: #F7F7F7;
    z-index: 1;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeEnd > span {
    background-color: #222222 !important;
    color: #FFFFFF !important;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.dateRangeSingleDay > span {
    background-color: #222222 !important;
    color: #FFFFFF !important;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.is-disabled > span {
    text-decoration: line-through;
}

a-date-picker.date-range-picker .a-DatePicker-calendar td.is-selected > span {
    background-color: #222222 !important;
    color: #FFFFFF !important;
}


JS :


window.DateRangePicker = class DateRangePicker {
    constructor(pConfig) {
        this.#config = pConfig;
        this.#disabledDates = new Set();
        this.#maxDate = null;
        this.#pickerItem().element.addClass("date-range-picker");
        this.#assignInitialValueFromStartDate();
        this.#assignDayFormatter();
        this.#pickerItem().element.on("change", () => {
            this.#onChanged();
        });
        document.getElementById(this.#resetId()).addEventListener("click", () => {
            this.#reset();
        });
    }

    #config;
    #disabledDates;
    #maxDate;

    setDisabledDates(dates) {
        this.#disabledDates = new Set(dates);
        this.#pickerItem().refresh();
    }

    setMaxDate(date) {
        this.#maxDate = date;
        this.#pickerItem().refresh();
    }

    #pickerItem() {
        return apex.items[this.#config.picker.name];
    }

    #pickerFormat() {
        return this.#config.picker.format;
    }

    #pickerSingleDay() {
        return this.#config.picker.allowSingleDay;
    }

    #startItem() {
        return apex.items[this.#config.start.name];
    }

    #startItemLabel() {
        return this.#config.start.label;
    }

    #endItem() {
        return apex.items[this.#config.end.name];
    }

    #resetId() {
        return this.#config.reset.id;
    }

    #endItemLabel() {
        return this.#config.end.label;
    }

    #assignInitialValueFromStartDate() {
        const startItemValue = this.#startItem().getValue();
        if (startItemValue) {
            this.#pickerItem().setValue(startItemValue,null,true);
        }
    }

    #assignDayFormatter() {
        const pickerItem = this.#pickerItem();
        const startItemLabel = this.#startItemLabel();
        const endItemLabel = this.#endItemLabel();
        const pickerFormat = this.#pickerFormat();
        const startItem = this.#startItem();
        const endItem = this.#endItem();
        const getDisabledDates = () => this.#disabledDates;
        const getMaxDate = () => this.#maxDate;

        pickerItem.dayFormatter = function(iso8860DateString) {
            const disabledDates = getDisabledDates();
            const maxDate = getMaxDate();
            const currentDate = apex.date.parse(iso8860DateString, "YYYY-MM-DD");
            const isDisabledByDate = disabledDates.has(iso8860DateString);
            const isAfterMax = maxDate ?
                apex.date.isAfter(currentDate, apex.date.parse(maxDate, pickerFormat)) :
                false;
            const isDisabled = isDisabledByDate || isAfterMax;
            const startDateValue = startItem.getValue();
            const startDate = startDateValue ? apex.date.parse(startDateValue, pickerFormat) : null;
            const endDateValue = endItem.getValue();
            const endDate = endDateValue ? apex.date.parse(endDateValue, pickerFormat) : null;
            var tooltipText = "";
            var dateRangeClass = "";

            if (!startDateValue) {
                tooltipText = "Choose " + (startItemLabel ? startItemLabel : "Start") + " Date";
            } else {
                if (apex.date.isSame(startDate, currentDate)) {
                    tooltipText = startItemLabel;
                } else {
                    if (!endDateValue) {
                        tooltipText = "Choose " + (endItemLabel ? endItemLabel : "End") + " Date";
                    } else {
                        if (apex.date.isSame(endDate, currentDate)) {
                            tooltipText = endItemLabel;
                        }
                    }
                }
            }

            if (startDateValue) {
                if (apex.date.isSame(currentDate, startDate)) {
                    if (endDateValue && apex.date.isSame(currentDate, endDate)) {
                        dateRangeClass = "dateRangeSingleDay";
                    } else if (endDateValue) {
                        dateRangeClass = "dateRangeStart";
                    } else {
                        dateRangeClass = "dateRangeSingleDay";
                    }
                } else if (endDateValue) {
                    if (apex.date.isSame(currentDate, endDate)) {
                        dateRangeClass = "dateRangeEnd";
                    } else if (apex.date.isBetween(currentDate, startDate, endDate)) {
                        dateRangeClass = "dateRangeMiddle";
                    }
                }
            }

            return {
                disabled: isDisabled,
                class: dateRangeClass,
                tooltip: isDisabled ? 'Not Available' : tooltipText
            };
        };

        pickerItem.refresh();
    }

    #onChanged() {
        const startItem = this.#startItem();
        const endItem = this.#endItem();
        const pickerItem = this.#pickerItem();
        const pickerFormat = this.#pickerFormat();

        if (!pickerItem.getValue()) {
            this.#reset();
            return;
        }

        const datepicked = pickerItem.getNativeValue();
        const startDateValue = startItem.getValue();
        const endDateValue = endItem.getValue();

        if (startDateValue === "" || (endDateValue !== "")) {
            startItem.setValue(pickerItem.getValue());
            endItem.setValue(null);
        } else {
            const startDate = apex.date.parse(startDateValue, pickerFormat);
            if (apex.date.isBefore(datepicked, startDate)) {
                startItem.setValue(pickerItem.getValue());
                endItem.setValue(null);
            } else if (!apex.date.isSame(datepicked, startDate)) {
                endItem.setValue(pickerItem.getValue());
            }
        }

        pickerItem.refresh();
    }

    #reset() {
        const startItem = this.#startItem();
        const endItem = this.#endItem();
        const pickerItem = this.#pickerItem();
       
        startItem.setValue(null,null,true);
        endItem.setValue(null,null,true);
        pickerItem.setValue(null,null,true);
       
        pickerItem.element.find('.dateRangeStart, .dateRangeEnd, .dateRangeSingleDay').removeClass('dateRangeStart dateRangeEnd dateRangeSingleDay');
        pickerItem.element.find('.is-selected').removeClass('is-selected');
       
        pickerItem.refresh();
       
        $(document).trigger('daterangepicker-reset', {
            picker: this.#config.picker.name,
            start: this.#config.start.name,
            end: this.#config.end.name
        });
    }
};



참고




20250315 - 글로벌 변수 Global Variables

G_USER Specifies the currently logged in user. G_FLOW_ID Specifies the ID of the currently running application. G_FLOW_STEP_ID Specifi...