Paul Ledger Paul Ledger - 7 months ago 12
Javascript Question

Use editable div height change to add and remove classes to other DOM elements

I have and editable div that allow users to enter text. This is part of a chat widget so the design needs the box to be fixed to the bottom.

When a user types I need javascript to catch the resize and append classes to elements where needed.

I managed to get the box to resize upwards but I have had a lot of trouble scaling it back down again.

I have been stuck on this for days now, so any help now would be greatly appreciated.

I have the function and a basic UI version here JSFiddle

Its probably really simple but I am having no luck figuring this out


JSFiddle


var chatBoxSize = {
oldHeight : 0,
scrollHeight : 0,
lastClass : 1,
minClass : 1,
maxClass : 5,
min_height : 0,
last_size : 0,
getClass : function (size){
var sizes = [chatBoxSize.min_height, chatBoxSize.min_height * 2, chatBoxSize.min_height * 3, chatBoxSize.min_height * 4, chatBoxSize.min_height * 5];
switch (size){ case sizes[0] : return 1; break; case sizes[1] : return 2; break; case sizes[2] : return 3; break; case sizes[3] : return 4; break; case sizes[4] : return 5; break; };
//is not exact
var r = null;
console.log(size);
for(var x = 0; x < sizes.length; x++){
if(x < sizes.length){
if(size >= sizes[x] && size < sizes[(x + 1)]){
return (x + 1);
}
}
}
return chatBoxSize.maxClass;
}
};
$(function () {
chatBoxSize.min_height = parseInt($('#msgWriteArea').height());
chatBoxSize.max_height = chatBoxSize.min_height * 4;
chatBoxSize.last_size = chatBoxSize.min_height;
});
function updateChatSize() {
var id = '#msgWriteArea';
var element = document.querySelector(id);
var size = $(id)[0].scrollHeight;
var container = $('.container');
var toRemove = 'size_' + chatBoxSize.lastClass;
console.log(chatBoxSize.getClass(size));
chatBoxSize.lastClass = chatBoxSize.getClass(size);
console.log('Add new class', chatBoxSize.lastClass);
chatBoxSize.last_size = size;
$(id).removeClass(toRemove);
$(id).addClass('size_' + chatBoxSize.lastClass);
container.removeClass(toRemove);
container.addClass('size_' + chatBoxSize.lastClass);
$('#display').val('Removed ' + toRemove + ' Added ' + chatBoxSize.lastClass);
};
$(function (){
$('#msgWriteArea').bind('change keydown input', function () {
if(event.type == 'keydown'){
updateChatSize();
}
});
})


I have thought of just setting the heights to auto but that will not work with the rest of the ui elements.

Answer

Sorry to say but No JS needed at all
flex to the rescue, overflow-y: auto; and max-height to the editable DIV:

Heres a jsBin demo so you can play and resize the browser

*{box-sizing:border-box; -webkit-box-sizing:border-box;}
html, body{height:100%; margin:0;font:16px/1 sans-serif; color:#444;}


#chat{
  display: flex;
  flex-direction: column;
  height:100%;
}
#messages{
  flex:1;
  overflow-y: auto;
}
#messages > div{
  padding: 24px;
  background: #eef;
  margin: 4px 0;
}
#ui{
  background: #eee;
}
#msgWriteArea{
  padding: 24px;
  overflow-y: auto;
  height:100%;
  background:#ddd;
  max-height:100px;    /* if max height is exceeded */
  overflow-y: auto;    /* add scrollbars */
}
<div id="chat">
  <div id="messages">
    <div>Message 1</div>
    <div>Message 2</div>
    <div>Message 3</div>
    <div>Message 4</div>
    <div>Message 5</div>
    <div>Message 6</div>      
  </div>
  <div id="ui">
    <div id="msgWriteArea" contenteditable>Some text message</div>
  </div>
</div>

Now, if you still really need to the the message area height (for some reasons) you could count the number of lines using JS.