[HTML/JS/CSS] contenteditable을 이용한 editor 만들기

2021. 2. 24. 22:22WEB.DEV

반응형

안녕하세요.

이번 포스팅은 HTML에 있는 contenteditable을 이용해서 editor를 만들기입니다.

만드는 방법은 아주 간단합니다.

input, textarea와 같은 텍스트 입력 태그가 아닌 div와 같은 태그에 contenteditable="true"를 추가해주면 됩니다.

<div id="editor" contenteditable="true"></div>

그렇게 되면 아래와 같이 원래는 텍스트 입력이 불가능한 div 태그에 아래와 같이 텍스트를 입력할 수 있습니다.

그럼 이제 텍스트 입력이 되는 것을 확인했으니 CSS를 적용해보겠습니다.

<style>
	div#editor {
    	padding: 16px 24px;
        border: 1px solid #D6D6D6;
        border-radius: 4px;
    }
</style>

그렇게 하면 아래와 같이 에디터 영역이 보이게 됩니다.

이제 추가로 editor 메뉴를 만들어 보겠습니다.

기본적으로 굵기 적용, 기울임 적용, 밑줄 적용, 취소선 적용, 숫자 목록, 기호 목록 메뉴를 만들어보겠습니다.

먼저 메뉴 버튼을 추가하기 위해서 아래와 같이 버튼들을 추가해주겠습니다.

<div class="editor-menu">
    <button id="btn-bold">
        <b>B</b>
    </button>
    <button id="btn-italic">
        <i>I</i>
    </button>
    <button id="btn-underline">
        <u>U</u>
    </button>
    <button id="btn-strike">
        <s>S</s>
    </button>
    <button id="btn-ordered-list">
        OL
    </button>
    <button id="btn-unordered-list">
        UL
    </button>
    <button id="btn-image">
        IMG
    </button>
</div>
<div id="editor" contenteditable="true"></div>

그러면 아래와 같이 보이게됩니다.

버튼까지 추가를 했으니 버튼들에 이벤트를 등록해보겠습니다. 아래와 같이 스크립트를 추가해줍니다. 그러면 굵기, 기울임, 밑줄, 취소선, 숫자 목록, 기호 목록이 적용되는 것을 확인할 수 있습니다.

<script>
    const editor = document.getElementById('editor');
    const btnBold = document.getElementById('btn-bold');
    const btnItalic = document.getElementById('btn-italic');
    const btnUnderline = document.getElementById('btn-underline');
    const btnStrike = document.getElementById('btn-strike');
    const btnOrderedList = document.getElementById('btn-ordered-list');
    const btnUnorderedList = document.getElementById('btn-unordered-list');

    btnBold.addEventListener('click', function () {
        setStyle('bold');
    });

    btnItalic.addEventListener('click', function () {
        setStyle('italic');
    });

    btnUnderline.addEventListener('click', function () {
        setStyle('underline');
    });

    btnStrike.addEventListener('click', function () {
        setStyle('strikeThrough')
    });

    btnOrderedList.addEventListener('click', function () {
        setStyle('insertOrderedList');
    });

    btnUnorderedList.addEventListener('click', function () {
        setStyle('insertUnorderedList');
    });

    function setStyle(style) {
        document.execCommand(style);
        focusEditor();
    }

    // 버튼 클릭 시 에디터가 포커스를 잃기 때문에 다시 에디터에 포커스를 해줌
    function focusEditor() {
        editor.focus({preventScroll: true});
    }
</script>

아래의 사진은 굵기, 기울임, 밑줄, 취소선, 숫자 목록, 기호 목록을 적용한 모습입니다.

이제 마지막 이미지 메뉴 버튼에 이벤트를 적용해보겠습니다.

먼저 이미지를 선택하기 위한 input을 추가해주겠습니다.

...
<input id="img-selector" type="file" accept="image/*"/>

그 다음 저는 img 버튼을 클릭한 후에 선택을 하도록 할 거라 이 input은 보일 필요가 없어서 style을 추가해서 안 보이도록 하겠습니다.

<style>
	...
    #img-selector {
        display: none;
    }
</style>

이제 마지막으로 스크립트를 추가해서 이미지를 추가하도록 해보겠습니다. 아래와 같이 이벤트를 추가해주면 이미지를 추가할 수 있습니다.

<script>
	...
    
    const btnImage = document.getElementById('btn-image');
    const imageSelector = document.getElementById('img-selector');

	...
    
    btnImage.addEventListener('click', function () {
        imageSelector.click();
    });

    imageSelector.addEventListener('change', function (e) {
        const files = e.target.files;
        if (!!files) {
            insertImageDate(files[0]);
        }
    });
    
    function insertImageDate(file) {
        const reader = new FileReader();
        reader.addEventListener('load', function (e) {
            focusEditor();
            document.execCommand('insertImage', false, `${reader.result}`);
        });
        reader.readAsDataURL(file);
    }
</script>

 

이미지를 추가하면 아래와 같이 보이게 됩니다.

여기서 보면 사진이 너무 커서 에디터 밖으로 빠져나가는 걸 볼수가 있습니다. 스타일을 추가해서 에디터 안에 맞게 해보겠습니다.

<style>
	...
    #editor img {
    	max-width: 100%;
    }
    ...
</style>

그러면 아래와 같이 작은 이미의 경우에는 해당 사진의 크기로 삽입이 되고 에디터보다 큰 사진의 경우에는 에디터에 맞게 삽입이됩니다.

이제 추가로 텍스트 상태에 따라서 버튼에 스타일을 적용을 해보도록 하겠습니다. 아래와 같이 스크립트와 스타일을 추가해주겠습니다.

<style>
	...
    button.active {
        background-color: purple;
        color: #FFF;
    }
</style>
<script>
	...
    
    editor.addEventListener('keydown', function () {
        checkStyle();
    });

    editor.addEventListener('mousedown', function () {
        checkStyle();
    });
    
    ...
    
    function setStyle(style) {
        document.execCommand(style);
        focusEditor();
        checkStyle();
    }
    
    ...
    
    function checkStyle() {
        if (isStyle('bold')) {
            btnBold.classList.add('active');
        } else {
            btnBold.classList.remove('active');
        }
        if (isStyle('italic')) {
            btnItalic.classList.add('active');
        } else {
            btnItalic.classList.remove('active');
        }
        if (isStyle('underline')) {
            btnUnderline.classList.add('active');
        } else {
            btnUnderline.classList.remove('active');
        }
        if (isStyle('strikeThrough')) {
            btnStrike.classList.add('active');
        } else {
            btnStrike.classList.remove('active');
        }
        if (isStyle('insertOrderedList')) {
            btnOrderedList.classList.add('active');
        } else {
            btnOrderedList.classList.remove('active');
        }
        if (isStyle('insertUnorderedList')) {
            btnUnorderedList.classList.add('active');
        } else {
            btnUnorderedList.classList.remove('active');
        }
    }

    function isStyle(style) {
        return document.queryCommandState(style);
    }
</script>

스크립트와 스타일을 적용해주면 아래와 같이 보이게 됩니다.

이 포스팅에서 다루지 않은 내용들은 MDN execCommand에서 추가로 확인할 수 있습니다.

 

Document.execCommand() - Web API | MDN

HTML 문서가 designMode로 전환되면 문서에서 execCommand 메서드를 사용할 수 있게 되는데 이것을 이용해서 문서의 편집 가능한 영역을 변경할 수 있습니다. 대부분의 명령어는 문서의 선택 영역에 영

developer.mozilla.org

contenteditable을 이용해 폰트 변경하는 방법은 다음 포스팅에서 확인 가능합니다.

 

[HTML/JS/CSS] contenteditable을 이용한 에디터 폰트 변경하기

안녕하세요. 이번 포스팅에서는 이전 포스팅에서 폰트 변경에 대해서 여쭤보시는 분이 계셔서 추가로 정보를 드리기 위한 포스팅입니다. [HTML/JS/CSS] contenteditable을 이용한 editor 만들기 안녕하세

dev-bak.tistory.com

추가로 contenteditable을 이용해서 다른 에디터에서 복사한 글의 글자만 붙여넣고 싶다면 다음 포스팅에서 확인 가능합니다.

 

[HTML/JS/CSS] contenteditable에 clipboard 내용 텍스트만 입력하기

이전 포스팅에서 contenteditable을 이용해서 에디터를 만들기를 해보았습니다. [HTML/JS/CSS] contenteditable을 이용한 editor 만들기 안녕하세요. 이번 포스팅은 HTML에 있는 contenteditable을 이용해서 edito..

dev-bak.tistory.com

 

포스팅이 마음에 드셨다면 아래 관심💛과 구독 부탁드리겠습니다.

긴 글 읽어주셔서 감사합니다.

728x90
반응형