[]
        
(Showing Draft Content)

사용자 정의 셀

SpreadJS는 사용자 지정 셀 타입을 생성할 수 있는 기능을 제공합니다. 이는 Base 클래스를 사용하여 구현할 수 있습니다.

디스플레이 모드에서는 셀을 직접 그릴 수 있고, 편집 모드에서는 에디터를 사용자 정의할 수 있으며, 마우스 및 키보드 상호작용도 셀 타입 자체에서 처리할 수 있습니다. 다양한 속성과 함수를 재정의하여 특정 셀에 맞는 동작을 구현할 수 있습니다.

사용 시나리오

사용자가 좋아하는 농구 선수가 시즌 중 5득점을 달성했는지를 추적하는 인터랙티브한 셀을 만들고자 하는 경우가 있습니다.

  • 첫 번째 열에는 별 모양이 있으며, 마우스 클릭에 따라 켜지거나 꺼지는 토글 형태로 표시됩니다. 이는 Boolean 값에 따라 결정됩니다.

  • 두 번째 열에는 선수 이름이 표시되며, 각 셀은 편집 가능하고 이름과 성을 입력할 수 있습니다.

SpreadJS custom cell usage scenario


아래 코드 샘플은 각각 A열과 B열에 두 개의 사용자 지정 셀 범위를 생성합니다.

window.onload = function () {

    // Workbook과 Worksheet 구성
    var spread = new GC.Spread.Sheets.Workbook("ss");
    var sheet = spread.getActiveSheet();
    sheet.suspendPaint();

    sheet.getRange("A1:A5", GC.Spread.Sheets.SheetArea.viewport).cellType(new FivePointedStarCellType());
    sheet.getRange("A1:A5", GC.Spread.Sheets.SheetArea.viewport).value(false);

    sheet.getRange("B1:B5", GC.Spread.Sheets.SheetArea.viewport).cellType(new FullNameCellType());

    sheet.setValue(0, 1, { firstName: "Lebron", lastName: "James" });
    sheet.setValue(1, 1, { firstName: "Kevin", lastName: "Durant" });
    sheet.setValue(2, 1, { firstName: "Stephen", lastName: "Curry" });
    sheet.setValue(3, 1, { firstName: "James", lastName: "Harden" });
    sheet.setValue(4, 1, { firstName: "Joel", lastName: "Embiid" });

    sheet.setColumnWidth(0, 100);
    sheet.setColumnWidth(1, 180);
    sheet.setRowHeight(0, 100);
    sheet.setRowHeight(1, 100);
    sheet.setRowHeight(2, 100);
    sheet.setRowHeight(3, 100);
    sheet.setRowHeight(4, 100);
    sheet.resumePaint();
}

function FivePointedStarCellType() {
    this.fillStyle = "orange";
    this.size = 10;
}

FivePointedStarCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();

FivePointedStarCellType.prototype.paint = function (ctx, value, x, y, w, h, style, context) {
    if (!ctx) {
        return;
    }
    ctx.save();
    // 셀의 경계 내부에 그림을 그립니다.
    ctx.rect(x, y, w, h);
    ctx.clip();
    ctx.beginPath();
    if (value) {
        ctx.fillStyle = this.fillStyle;
    } else {
        ctx.fillStyle = "gray";
    }
    var size = this.size;
    var dx = x + w / 2;
    var dy = y + h / 2;
    ctx.beginPath();
    var dig = Math.PI / 5 * 4;
    for (var i = 0; i < 5; i++) {
        ctx.lineTo(dx + Math.sin(i * dig) * size, dy + Math.cos(i * dig) * size);
    }
    ctx.closePath();
    ctx.fill();
    ctx.restore();
};

FivePointedStarCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
    var xm = cellRect.x + cellRect.width / 2,
        ym = cellRect.y + cellRect.height / 2,
        size = 10;
    var info = { x: x, y: y, row: context.row, col: context.col, cellRect: cellRect, sheetArea: context.sheetArea };
    if (xm - size <= x && x <= xm + size && ym - size <= y && y <= ym + size) {
        info.isReservedLocation = true;
    }
    return info;
};

FivePointedStarCellType.prototype.processMouseUp = function (hitInfo) {
    var sheet = hitInfo.sheet;
    if (sheet && hitInfo.isReservedLocation) {
        var row = hitInfo.row, col = hitInfo.col, sheetArea = hitInfo.sheetArea;
        var newValue = !sheet.getValue(row, col, sheetArea);
        var cellEditInfo = { row: row, col: col, newValue: newValue };
        var spread = sheet.getParent();
        spread.commandManager().execute({ cmd: "editCell", sheetName: sheet.name(), row: row, col: col, newValue: newValue });
        return true;
    }
    return false;
};

function FullNameCellType() {
}
FullNameCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
FullNameCellType.prototype.paint = function (ctx, value, x, y, w, h, style, context) {
    if (value) {
        GC.Spread.Sheets.CellTypes.Base.prototype.paint.apply(this, [ctx, value.firstName + "." + value.lastName, x, y, w, h, style, context]);
    }
};

FullNameCellType.prototype.updateEditor = function (editorContext, cellStyle, cellRect, context) {
    if (editorContext) {
        $(editorContext).width(cellRect.width);
        $(editorContext).height(100);
    }
};

FullNameCellType.prototype.createEditorElement = function (context) {
    var div = document.createElement("div");
    var $div = $(div);
    $div.attr("gcUIElement", "gcEditingInput");
    $div.css("background-color", "white");
    $div.css("position", "absolute");
    $div.css("overflow", "hidden");
    $div.css("border", "2px #5292f7 solid");
    var $span1 = $("<span></span>");
    $span1.css("display", "block");
    var $span2 = $("<span></span>");
    $span2.css("display", "block");
    var $input1 = $("<input type='text'/>");
    var $input2 = $("<input type='text'/>");
    $div.append($span1);
    $div.append($input1);
    $div.append($span2);
    $div.append($input2);
    return div;
};

FullNameCellType.prototype.getEditorValue = function (editorContext) {
    if (editorContext && editorContext.children.length === 4) {
        var input1 = editorContext.children[1];
        var firstName = $(input1).val();
        var input2 = editorContext.children[3];
        var lastName = $(input2).val();
        return { firstName: firstName, lastName: lastName };
    }
};

FullNameCellType.prototype.setEditorValue = function (editorContext, value) {
    if (editorContext && editorContext.children.length === 4) {
        var span1 = editorContext.children[0];
        $(span1).text("First Name:");
        var span2 = editorContext.children[2];
        $(span2).text("Last Name:");
        if (value) {
            var input1 = editorContext.children[1];
            $(input1).val(value.firstName);
            var input2 = editorContext.children[3];
            $(input2).val(value.lastName);
        }
    }
};

FullNameCellType.prototype.isReservedKey = function (e, context) {
    // 셀 타입이 Tab 키 입력을 자체적으로 처리합니다.
    return (e.keyCode === GC.Spread.Commands.Key.tab && !e.ctrlKey && !e.shiftKey && !e.altKey);
};

FullNameCellType.prototype.isEditingValueChanged = function (oldValue, newValue, context) {
    if (newValue.firstName != oldValue.firstName || newValue.lastName != oldValue.lastName) {
        return true;
    }
    return false;
};