Simple markdown tag insertion snippet using shortcut keys [Pure Javascript]
Tags: javascript, webdev, codenewbie, tutorial
Published: 2021-03-19 07:54:46


I needed a tiny, light-weight plug to add markdown syntax in my textboxes, I searched online but all of them were very vast so I decided to create my own with the help of many StackOverflow articles. 

It is a very small Pure JS-based scripts to achieve the same, but before that look at some features of this tiny script as below:

### Features:
1. Define your own markdown enclosures like `++` for underline and `__` for *italic*.
2. If any text is selected then it'll be enclosed with the markdown tag.
3. If no text is selected, then you have an option to give a default text to be inserted with markdown tags.
4. Markdown can be inserted using shortcut keys like `ctrl+b`.
5. If any markdown tag is already added around selected text and the same markdown is applied then the markdown tag gets removed.
6. Multiple markdowns can be added sequentially like as `**++underlined bold text++**`
7. Different beginning and closing markdown tags can be inserted like as in hyperlinks, the opening tag can be `[` and the closing tag can be `](example.com)`.

#### Examples: 

`text` means text is selected.

* a text to `bold` => a text to `**bold**`
* a text to remove `**bold**` => a text to remove `bold`
* a text to remove \*\*`bold`\*\* => a text to remove `bold`

#### Shortcut commands used in snippet:
|Markdown|Command  |Result|
|--|--|--|
| Bold  | ctrl+b |\*\*bold text\*\*|
|Italic |ctrl+i|\_\_italic text\_\_|
|Underline |ctrl+u|++underlined text++|
|Link |ctrl+l|\[link title\]\(http://www.example.com)|


### Code:

**HTML:**
```html
<!doctype html>
<html>
  <head>
    <title>Markdown Tag Insertion</title>
    <script language="javascript" type="text/javascript" src="script.js"></script>
  </head>
  <body>                                                            
    </br>
    <input type="text" id="title" style="width:250px;height:35px;">
    </br>
    </br>
    <textarea id="desc" rows="8" cols="80"></textarea>
    </br></br>
    <a href="https://stackoverflow.com/a/54364217/8494462">Stack Overflow Answer Link</a>
  </body>
</html>
```

**Javascript:**
```js
//Code to bind keyevents 
document.addEventListener("keydown", (function(e) {
        if (e.ctrlKey && !e.shiftKey && [66, 73, 85, 76].indexOf(e.keyCode) > -1) {
                var keyCode = e.keyCode;
                var focused = document.activeElement;
                var id = focused.id;
                if (["title", "desc"].indexOf(id) > -1) { // To apply only on required elemenst
                        e.preventDefault();
                        if (keyCode == 66) { //ctrl+B
                                insertFormating(focused, "**", "bold");
                        } else if (keyCode == 73) { //ctrl+I
                                insertFormating(focused, "__", "italic");
                        } else if (keyCode == 85) { //ctrl+U
                                insertFormating(focused, "++", "underline");
                        } else if (keyCode == 76) { //ctrl+l
                                insertFormating(focused, "[", "link title","](http://www.example.com)");
                        }
                }
        }
}));

/**
* @param     {Object}    txtarea       javascript Element Object to the textarea
* @param     {String}    text          markdown enclosing tag text
* @param     {String}    defaultTxt    Default Text to be inserted when no text is selected
* @param     {String}    text2         markdown enclosing tag text for closing if different from opening
*/
function insertFormating(txtarea, text, defaultTxt = "", text2 = "") {
	var selectStart = txtarea.selectionStart
	var selectEnd = txtarea.selectionEnd
	var scrollPos = txtarea.scrollTop;
	var caretPos = txtarea.selectionStart;
	var mode = 0;
	var front = (txtarea.value).substring(0, caretPos);
	var back = (txtarea.value).substring(selectEnd, txtarea.value.length);
	var middle = (txtarea.value).substring(caretPos, selectEnd);
  
  // Sets ending tag as opening tag if empty
	if (text2 == "") {
		text2 = text;
	}
	var textLen = text.length;
	var text2Len = text2.length;

	if (selectStart === selectEnd) {
		middle = defaultTxt;
		mode = 1;
	} else {
		if (front.substr(-textLen) == text && back.substr(0, text2Len) == text2) {
			front = front.substring(0, front.length - textLen);
			back = back.substring(text2Len, back.length);
			text = "";
			text2 = "";
			mode = 2;
		} else if (middle.substr(0, textLen) == text && middle.substr(-text2Len) == text2) {
			middle = middle.substring(textLen, middle.length - text2Len);
			text = "";
			text2 = "";
			mode = 3;
		}
	}
	txtarea.value = front + text + middle + text2 + back;
	if (selectStart !== selectEnd) {
		if (mode === 0) {
			txtarea.selectionStart = selectStart + textLen;
			txtarea.selectionEnd = selectEnd + textLen;
		} else if (mode === 2) {
			txtarea.selectionStart = selectStart - textLen;
			txtarea.selectionEnd = selectEnd - textLen;
		} else if (mode === 3) {
			txtarea.selectionStart = selectStart;
			txtarea.selectionEnd = selectEnd - textLen - text2Len;
		}
	} else {
		txtarea.selectionStart = selectStart + textLen;
		txtarea.selectionEnd = txtarea.selectionStart + middle.length;
	}
	txtarea.focus();
	txtarea.scrollTop = scrollPos;
}
```

Any suggestion is appreciated.

### Codepen:
{% codepen https://codepen.io/shivams136/pen/NWbEoMB default-tab=result %}