JSFiddle - React, Tailwind, and code Playground
by jcreamer898
HTML
<script src="http://knockoutjs.com/downloads/knockout-3.0.0.debug.js"></script>
<div class="caret-container"><div class="caret"></div></div>
<!--
div.paragraph
div.line
div.line-background
div.line-content
span.line-wrapper
span.bold
span
div.line
-->
<div id="editor" data-bind="template: {
name: 'paragraphTemplate',
foreach: paragraphs }">
</div>
<script id="paragraphTemplate" type="text/html">
<div class="paragraph"
data-bind="template: { foreach: lines, name: 'lineTemplate' }"></div>
</script>
<script id="lineTemplate" type="text/html">
<div class="line"
data-bind="
click: $root.activeLine,
template: { foreach: contents, name: 'contentTemplate'}"></div>
</script>
<script id="contentTemplate" type="text/html">
<span data-bind="text: content, click: $root.activeContent,"></span>
</script>
CSS
.caret-container {
position: absolute;
}
.caret {
border-left: 2px solid black;
opacity: 0;
transition: opacity .13s ease-in;
-webkit-transition: opacity .13s ease-in;
min-height: 15.6px;
}
.caret-animating {
opacity: 1;
}
JavaScript
var keyCodes = {
'65': 'a',
'66': 'b',
'67': 'c',
'68': 'd',
'69': 'e',
'70': 'f',
'71': 'g',
'72': 'h',
'73': 'i',
'74': 'j',
'75': 'k',
'76': 'l',
'77': 'm',
'78': 'n',
'79': 'o',
'80': 'p',
'81': 'q',
'82': 'r',
'83': 's',
'84': 't',
'85': 'u',
'86': 'v',
'87': 'w',
'88': 'x',
'89': 'y',
'90': 'z'
};
var caretContainer = document.getElementsByClassName('caret-container')[0],
caret = caretContainer.firstChild,
editor = document.getElementById('editor');
caretContainer.style.top = 0;
caretContainer.style.left = 0;
var each = function(arr, fn) {
Array.prototype.forEach.call(arr, fn);
};
setInterval(function() {
caret.className = ~caret.className.indexOf('animating') ? 'caret' : 'caret caret-animating';
}, 500);
var EditorViewModel = function(paragraphs) {
this.activeLine = ko.observable();
this.activeContent = ko.observable();
this.paragraphs = ko.observableArray(paragraphs);
};
var ParagraphViewModel = function(lines) {
this.lines = ko.observableArray(lines);
};
var LineViewModel = function(contents) {
this.contents = ko.observableArray(contents);
};
var ContentViewModel = function(content) {
this.content = ko.observable(content);
};
ko.bindingHandlers.editor = {
init: function(el, valueAccessor, allBindings, data, context) {
var value = valueAccessor(),
paragraphs = value();
ko.applyBindingsToNode(el, {
});
}
};
var vm = new EditorViewModel([
new ParagraphViewModel([
new LineViewModel([
new ContentViewModel("hello world"),
new ContentViewModel("wuttup?")
]),
new LineViewModel([
new ContentViewModel("hello"),
new ContentViewModel("world")
]),
new LineViewModel([
new ContentViewModel("hello"),
new...