Reputation: 5281
I'v a problem with my contenteditable div. I am currently trying to detect any change in my div element. This works quite well so far. But it fails when I change the content via jQuery:
jQuery(document).ready(function($) {
let input = $("#input");
input.on("input", function() {
console.log($(this).html().length);
});
$("button").click(function() {
input.html(input.html() + `<span class="emoji">😅</span>`);
});
});
div {
border: 1px solid #aaaaaa;
padding: 8px;
border-radius: 12px;
margin-bottom: 20px;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
display: block;
color: #aaaaaa;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="input" placeholder="Schreib eine Nachricht..." contenteditable="true" spellcheck="true"></div>
<button>Add element to contenteditable div</button>
How can I solve this problem? I could do this check inside my click event but I need to add a lot of them so I don't want to do this every time. In this case I think it's better to do it in one input check function.
Upvotes: 2
Views: 965
Reputation: 66475
In this case you will need to trigger the event you're listening to yourself:
jQuery(document).ready(function($) {
let input = $("#input");
input.on("input", function() {
console.log($(this).html().length);
// Contenteditable adds a <br> when empty.
// Solutions on SO appear not to work
if (!$(this).text()) {
console.log('cleared editable');
input.html('');
}
});
$("button").click(function() {
input.html(input.html() + `<span class="emoji">😅</span>`);
input.trigger('input');
});
});
[contenteditable=true] {
border: 1px solid #aaaaaa;
padding: 8px;
border-radius: 12px;
margin-bottom: 20px;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
display: block;
color: #aaaaaa;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="input" placeholder="Schreib eine Nachricht..." contenteditable="true" spellcheck="true"></div>
<button>Add element to contenteditable div</button>
Upvotes: 5
Reputation: 1324
If you don't want to add function inside your .click()
listener you could achieve your effect by using MutationObserver API:
jQuery(document).ready(function($) {
let input = $("#input");
input.on("input", function() {
console.log($(this).html().length);
});
$("button").click(function() {
input.html(input.html() + `<span class="emoji">😅</span>`);
});
const targetNode = document.getElementById('input');
const config = { attributes: true, childList: true, subtree: true };
const callback = function(mutationsList, observer) {
// Use traditional 'for loops' for IE 11
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
}
else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
});
div {
border: 1px solid #aaaaaa;
padding: 8px;
border-radius: 12px;
margin-bottom: 20px;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
display: block;
color: #aaaaaa;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="input" placeholder="Schreib eine Nachricht..." contenteditable="true" spellcheck="true"></div>
<button>Add element to contenteditable div</button>
I don't think this is most optimal way, maybe you should rethink your architecture. But I'm sure this one will fit your requirements.
Upvotes: 3