1

I have a to do app and I was requested to add more functionality, such as: add some buttons for Bold and Italic text. In a input, after I press the Bold button, the text that is going to be typed to be bolded, leaving the previous text (the one before I pressed the Bold button) the way it was, regular. I understood that there's no way to bold a section of text in a input, so I simulated a input with a div :

const div = document.querySelector('div');

div.innerHTML = '';

const bold = document.getElementById('boldBtn');
const italic = document.getElementById('italicBtn')

bold.style.backgroundColor = 'white';

let previousText = '';
let boldString = '';

boldBtn.addEventListener('click', () => {
    boldBtn.classList.toggle('bold-selected');
    if (boldBtn.classList.contains('bold-selected')) {
        boldBtn.style.backgroundColor = "gray";
        previousText = div.innerHTML;
        console.log(previousText)
        div.addEventListener('keydown', boldText)
    }
    else {
        bold.style.backgroundColor = "white";
        div.removeEventListener('keydown', boldText);
    }
})

function boldText(e) {
    div.innerHTML = div.innerHTML.substr(1)
    console.log("Previous text: " + previousText);
    const NOT_ALLOWED = ['Backspace', 'Shift', 'Control', 'Alt'];
    if (!NOT_ALLOWED.includes(e.key)) {
        boldString += e.key;
        console.log("Bold text: " + boldString)
        console.log(previousText + boldString)
        div.innerHTML = previousText + "<strong>" + boldString + "</strong>"
    }
}
div {
    border: 1px solid black;
    width: 200px;
    height: 20px;
  }
  
.font-style {
    border: 1px solid blue
  }
<div contenteditable="true"></div>
<button id="boldBtn" class="font-style">Bold</button>
<button id="italicBtn" class="font-style">Italic</button>

Try to write something like "cool" in the div then press the Bold button, then type a letter. You'll see that the div gets this innerHTML: letter+cool+boldletter. And the cursor is set at the beginning of the div content. Please help me or at least give a hint to accomplish the wanted behavior! I spent 3-4 hours already and I am ready to give up...

EDIT: I think I didn't make it clear: I don't want to make the entire content of the div be bold, but just a portion/section/part of it. If no button is pressed, the text that is gonna be written should be regular, if the Bold button is pressed, the text that is gonna be written should be Bold, the same with the Italic button. Maybe if the Bold and Italic are selected at the same time, the future text should be bold and italic. But that's another question... An example of what I want is https://html-online.com/editor/ . Remove the default text and just write words on the left panel, and try to use the bold, italic buttons above. In the left panel there will be the HTML generated code. I need the same functionality...

Kirill
  • 303
  • 3
  • 18

2 Answers2

0

Yes there is a way out for this as you can use jquery for this like

<script>
$(document).ready(function () { 
$("#boldBtn").click( function() { 
$("your input id or class").keyup(function () { 
$("your input id or class").css("fontWeight", "bold");
  });
 });
});
</script>

Where your input id or class mentioned if you have class then put it as .classname or if you have an id write is as #id.

Hope this might help you.

Kunal Raut
  • 2,495
  • 2
  • 9
  • 25
0

In order to make text bold when you select "bold", get range from current selection and insert element "strong" in it.

  let range=window.getSelection.getRangeAt(0);
  let elem=document.createElement('strong');
  elem.innerHTML='&#8203;'
  range.insertNode(elem);

this will make the text bold, same applies for the italic option too. Now the problem comes when you need to disable it, for that i had to clear current ranges in selection and set range to end of "div" and insert new element "span"(i used span for normal text).

Likewise i handled below cases too

  1. when bold and italic are pressed together( You need to store previous Element in this case)
  2. when enter is pressed( div was getting created and was creating problems so i had to set keydown listener and use document.execCommand to not create div instead create br)

If anyone is interested in updating my solution to make it effective you are welcome

var boldButton=document.querySelector('#boldBtn'),
 italicButton=document.querySelector('#italicBtn'),
contentDiv=document.querySelector('#content'),
bold=false,italic=false,range,prevElement,selection;
;
contentDiv.addEventListener('keydown',function(e){
 if (e.keyCode === 13) {
       window.document.execCommand('insertLineBreak', false, null);
       range=window.getSelection().getRangeAt(0);
       range.collapse();
       prevElement=undefined;
       if(bold) addElement('strong');
       if(italic) addElement('i');
       e.preventDefault();
      return false;
    }
    return true;
});
boldButton.addEventListener('click',function(){
    debugger
    bold=!bold;
    boldButton.classList.toggle('border-black');
    if(!bold)
      disable('bold');
    else
      addElement('strong');
});
italicButton.addEventListener('click',function(){
   debugger;
   italic=!italic;
   italicButton.classList.toggle('border-black');
   if(!italic)
       disable('italic');
    else
      addElement('i');
});
function addElement(element){
  if(!selection)selection=window.getSelection()
  range=selection.getRangeAt(0);
  let elem=document.createElement(element);
  elem.innerHTML='&#8203;'
  if(prevElement)
    range.selectNodeContents(prevElement);
  range.collapse();
  range.insertNode(elem);
  elem.focus();
  prevElement=elem;
}
function disable(elem){
 if(italic && bold) return;
setRangeAtEnd();
 let element=document.createElement('span');
 if(italic)
   element=document.createElement('i');
 else if(bold)
   element=document.createElement('strong');
 element.innerHTML='&#8203;'
 range.insertNode(element);
 range.setStart(element,1);
 element.focus();
}
function setRangeAtEnd(){
 let childNodes=contentDiv.childNodes;
 range=document.createRange();
 range.setStartAfter(childNodes[childNodes.length-1]);
 prevElement=undefined;
 if(!selection)selection=window.getSelection();
 selection.removeAllRanges();
 selection.addRange(range);

}
#content{
border:1px solid black;
height:150px;

}
.border-black{
border:2px dotted black;
}
<div id="content" contenteditable="true"></div><br>
<button id="boldBtn"  class="font-style">Bold</button>
<button id="italicBtn"  class="font-style">Italic</button>
M A Salman
  • 3,666
  • 2
  • 12
  • 26
  • Yeah, I solved my problem by myself using a span with contenteditable, but I'll accept your answer! – Kirill Apr 05 '20 at 13:20