미디어위키:CategoryPillar.js: 두 판 사이의 차이

(Install package: clbiwiki-frame-geometry-normalized-20260717 / js/CategoryPillar.js)
(Install package: clbiwiki-portal-frame-canvas-atomic-v3-20260717 / js/CategoryPillar.js)
1번째 줄: 1번째 줄:
/* portal-frame canvas v3 — 2026-07-17 */
/* =========================================
/* =========================================
CategoryPillar
CategoryPillar
대문 상단 카테고리의 중앙 「프로젝트」 기둥
canvas CategoryNav 내부 프로젝트 기둥 호환 모듈
========================================= */
========================================= */


7번째 줄: 8번째 줄:
     'use strict';
     'use strict';


     var VERSION = '20260717-shared-frame-geometry-001';
     var BUILD_TAG = 'portal-frame-canvas-v3-20260717';
     var renderTimer = 0;
     window.PortalFrameModules = window.PortalFrameModules || {};
    window.PortalFrameModules.CategoryPillar = BUILD_TAG;


     function api() {
     var REQUIRED_CATEGORY_VERSION = BUILD_TAG;
        return window.CLBI && window.CLBI.frame;
    var warned = false;
    }
 
    function renderSvg(svg, seams) {
        var frame = api();
        var source;
        var previous;
        var points;
        var group;
        var label;
        var centerY;
        var leftCenter;
        var rightCenter;
 
        if (!frame || !svg || !seams || Number(svg.getAttribute('data-frame-width')) !== seams.width) return false;
        source = svg.querySelector('.portal-cat-anchor[data-category-key="project"]');
        if (!source) return false;
 
        previous = svg.querySelector('.portal-category-pillar');
        if (previous) previous.remove();
 
        points = frame.segmentAt(
            seams.projectLeftTopX,
            seams.projectRightTopX,
            0,
            seams.rowHeight,
            seams.projectLeftDir,
            seams.projectRightDir,
            0,
            0,
            0
        );
        group = frame.create('g', 'portal-category-pillar');
        group.setAttribute('data-category-key', 'project');
        group.setAttribute('aria-label', '프로젝트');
        group.setAttribute('pointer-events', 'none');
        group.appendChild(frame.polygon('portal-category-pillar-surface', points));
        group.appendChild(frame.line('portal-category-pillar-line portal-category-pillar-shadow', points[3], points[0]));
        group.appendChild(frame.line('portal-category-pillar-line portal-category-pillar-highlight', points[1], points[2]));
 
        centerY = Math.round((seams.buttonTop + seams.buttonBottom) / 2);
        leftCenter = frame.slantX(seams.projectLeftTopX, centerY, seams.projectLeftDir, 0);
        rightCenter = frame.slantX(seams.projectRightTopX, centerY, seams.projectRightDir, 0);
        label = frame.create('text', 'portal-cat-label portal-category-pillar-label');
        label.setAttribute('x', Math.round((leftCenter + rightCenter) / 2));
        label.setAttribute('y', centerY + 1);
        label.setAttribute('font-size', '12');
        label.setAttribute('font-weight', '700');
        label.setAttribute('text-anchor', 'middle');
        label.setAttribute('dominant-baseline', 'middle');
        label.textContent = '프로젝트';
        group.appendChild(label);


         source.setAttribute('aria-hidden', 'true');
    function categoryReady() {
         source.setAttribute('tabindex', '-1');
         var ready = window.CategoryNav &&
        source.classList.add('portal-category-pillar-source');
            window.CategoryNav.version === REQUIRED_CATEGORY_VERSION &&
         svg.appendChild(group);
            typeof window.CategoryNav.renderAll === 'function';
         svg.classList.add('has-category-pillar');
         if (!ready && !warned && window.console && typeof window.console.error === 'function') {
         return true;
            warned = true;
            window.console.error(
                '[CategoryNav 구버전 감지: CategoryPillar.js와 MediaWiki:CategoryNav.js를 같은 배포 세트로 업데이트하세요] ' +
                '필요 버전=' + REQUIRED_CATEGORY_VERSION
            );
         }
         if (ready) warned = false;
         return ready;
     }
     }


     function renderAll(root, seams) {
     function renderAll(root) {
         var scope = root && root.querySelectorAll ? root : document;
         var scope = root && root.querySelectorAll ? root : document;
         var current = seams || (api() && api().seams);
         if (!categoryReady()) return 0;
        var rendered = 0;
         return scope.querySelectorAll(
 
             '.main-portal [data-component="category-nav"] .portal-category-canvas'
         if (!current || !current.width) return 0;
         ).length;
        Array.prototype.forEach.call(
             scope.querySelectorAll('.main-portal [data-component="category-nav"] .portal-category-svg'),
            function (svg) {
                if (renderSvg(svg, current)) rendered += 1;
            }
         );
        return rendered;
     }
     }


     function schedule(root, seams) {
     window.CategoryPillar = {
         window.clearTimeout(renderTimer);
        version:BUILD_TAG,
         renderTimer = window.setTimeout(function () {
        buildTag:BUILD_TAG,
            renderTimer = 0;
        init:renderAll,
            renderAll(root || document, seams);
         renderAll:renderAll,
        }, 0);
         render:function () { return renderAll(document) > 0; }
     }
     };


    if (api()) api().onSeams(function (seams) { schedule(document, seams); });
     if (mw && mw.hook) {
     if (mw && mw.hook) {
         mw.hook('wikipage.content').add(function (content) {
         mw.hook('wikipage.content').add(function (content) {
             schedule(content && content[0] ? content[0] : document);
             renderAll(content && content[0] ? content[0] : document);
         });
         });
     }
     }
    window.CategoryPillar = {
        version:VERSION,
        init:renderAll,
        render:renderSvg,
        renderAll:renderAll
    };
}(window, document, window.mw));
}(window, document, window.mw));

2026년 7월 17일 (금) 17:42 판

/* portal-frame canvas v3 — 2026-07-17 */
/* =========================================
CategoryPillar
canvas CategoryNav 내부 프로젝트 기둥 호환 모듈
========================================= */

(function (window, document, mw) {
    'use strict';

    var BUILD_TAG = 'portal-frame-canvas-v3-20260717';
    window.PortalFrameModules = window.PortalFrameModules || {};
    window.PortalFrameModules.CategoryPillar = BUILD_TAG;

    var REQUIRED_CATEGORY_VERSION = BUILD_TAG;
    var warned = false;

    function categoryReady() {
        var ready = window.CategoryNav &&
            window.CategoryNav.version === REQUIRED_CATEGORY_VERSION &&
            typeof window.CategoryNav.renderAll === 'function';
        if (!ready && !warned && window.console && typeof window.console.error === 'function') {
            warned = true;
            window.console.error(
                '[CategoryNav 구버전 감지: CategoryPillar.js와 MediaWiki:CategoryNav.js를 같은 배포 세트로 업데이트하세요] ' +
                '필요 버전=' + REQUIRED_CATEGORY_VERSION
            );
        }
        if (ready) warned = false;
        return ready;
    }

    function renderAll(root) {
        var scope = root && root.querySelectorAll ? root : document;
        if (!categoryReady()) return 0;
        return scope.querySelectorAll(
            '.main-portal [data-component="category-nav"] .portal-category-canvas'
        ).length;
    }

    window.CategoryPillar = {
        version:BUILD_TAG,
        buildTag:BUILD_TAG,
        init:renderAll,
        renderAll:renderAll,
        render:function () { return renderAll(document) > 0; }
    };

    if (mw && mw.hook) {
        mw.hook('wikipage.content').add(function (content) {
            renderAll(content && content[0] ? content[0] : document);
        });
    }
}(window, document, window.mw));