JSFiddle - React, Tailwind, and code Playground
by waxwing
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<div id="auto" contenteditable="true" data-bind="bidiHtml: test" class="text">
This is a <span class="keyword" contenteditable="false">Keyword</span>. And also here is another <span class="keyword" contenteditable="false">one</span>.
</div>
<select data-bind="options: fields, value: selectedField"></select>
<button data-bind="click: addField">Add</button>
CSS
.text {
border: 1px solid black;
padding: 10px;
}
.keyword {
background-color: #aaaaff;
border: 1px solid #333399;
border-radius: 2px;
}
JavaScript
ko.bindingHandlers.bidiHtml = {
init: function (element, valueAccessor) {
var obs = valueAccessor();
ko.utils.registerEventHandler(element, 'input', function () {
obs(this.innerHTML);
});
},
update: function (element, valueAccessor) {
var obs = valueAccessor();
console.log(obs(), element.innerHTML);
if (obs() !== element.innerHTML) {
ko.utils.setHtml(element, obs);
}
}
}
var model = {
fields: [ "Lead actor", "Production cost", "Record name", "Date published" ],
selectedField: ko.observable(),
addField: function () {
this.test(this.test() +
'<span class="keyword">' +
this.selectedField() +
'</span>');
},
test: ko.observable('')
};
$("#auto").autocomplete({
source: function(request, response) {
var words = request.term.split(/\s+/);
var term = words[words.length];
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});