Text editor is coming along nicely. Made an article for eventually recording my exploits.
This commit is contained in:
parent
9b0e75967b
commit
9da9e5c56a
4
articles/text_editors_with_contenteditable.article.html
Normal file
4
articles/text_editors_with_contenteditable.article.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<article>
|
||||||
|
<p>I've been playing with an exciting feature of HTML5 that I hadn't heard of: the <code class="language-html">contentEditable</code> attribute. It's magical! It just makes anything suddenly be editable in-browser! It also finally provides me with the thing I've been wanting ever since growing dissatisfied with text editors: A way to build a <em>new</em> text editor, <em>without</em> having to actually code up the guts of text movement, manipulation, and entry. Oh, happy day!</p>
|
||||||
|
<p>More on this as the situation progresses.</p>
|
||||||
|
</article>
|
9
articles/text_editors_with_contenteditable.template.html
Normal file
9
articles/text_editors_with_contenteditable.template.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "articles/article.template.html" %}
|
||||||
|
|
||||||
|
{% block title -%}
|
||||||
|
contentEditable: Text Editors Made Easy?
|
||||||
|
{%- endblock %}
|
||||||
|
|
||||||
|
{% block body -%}
|
||||||
|
{%- include "articles/text_editors_with_contenteditable.article.html" -%}
|
||||||
|
{%- endblock %}
|
@ -13,7 +13,6 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.block {
|
.block {
|
||||||
white-space: pre-line;
|
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
@ -41,33 +40,7 @@ When I see the text "if (something)", then I should make a new if block.
|
|||||||
["block", "block if"] => ["block", "block if"]
|
["block", "block if"] => ["block", "block if"]
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
finds_if_regex = /(?:^|\s+)(if\s*\([^)]+\)\s*)({[^}]*})/
|
|
||||||
function make_new_if(text_area) {
|
|
||||||
if (text_area.is('.block.base')) {
|
|
||||||
var contents = text_area.html();
|
|
||||||
var split_up = contents.split(finds_if_regex);
|
|
||||||
var new_blocks = [];
|
|
||||||
new_blocks.append($('<div></div>').append(split_up[0]).addClass('block base'));
|
|
||||||
for (var i=1; i<split_up.length; i+=3) {
|
|
||||||
var if_container = $('<div></div>').addClass('block if');
|
|
||||||
var branch_container = $('<div></div>').addClass('branch if');
|
|
||||||
var conditional = $('<div></div>').addClass('condition').html(split_up[i]);
|
|
||||||
var result = $('<div></div>').addClass('block base').html(split_up[i+1]);
|
|
||||||
branch_container.append(conditional);
|
|
||||||
branch_container.append(result);
|
|
||||||
if_container.append(branch_container);
|
|
||||||
|
|
||||||
new_blocks.append(if_container);
|
|
||||||
if (split_up[i+2] != '') {
|
|
||||||
var post_if = $('<div></div>').addClass('block base').html(split_up[i+2]);
|
|
||||||
new_blocks.append(post_if);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function make_new_else(text_area) {
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.block {display: block;}
|
.block {display: block;}
|
||||||
@ -76,8 +49,8 @@ function make_new_else(text_area) {
|
|||||||
</style>
|
</style>
|
||||||
<div class="block" id="editor" contentEditable>
|
<div class="block" id="editor" contentEditable>
|
||||||
<div class="block base" >
|
<div class="block base" >
|
||||||
some kind of preparation code, I guess
|
some kind of preparation code, I guess<br>
|
||||||
or something
|
or something<br>
|
||||||
</div>
|
</div>
|
||||||
<div class="block if">
|
<div class="block if">
|
||||||
<div class="branch if">
|
<div class="branch if">
|
||||||
@ -94,16 +67,16 @@ function make_new_else(text_area) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="block base">
|
<div class="block base">
|
||||||
some code
|
some code<br>
|
||||||
do other thing
|
do other thing<br>
|
||||||
{} | : {} ();
|
{} | : {} ();<br>
|
||||||
</div>
|
</div>
|
||||||
<div class="block while">
|
<div class="block while">
|
||||||
<div class="condition">while (something)</div>
|
<div class="condition">while (something)</div>
|
||||||
<div class="block base">
|
<div class="block base">
|
||||||
update the counters
|
update the counters<br>
|
||||||
hack the gibsons
|
hack the gibsons<br>
|
||||||
do the stuff
|
do the stuff<br>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -121,68 +94,58 @@ function make_new_else(text_area) {
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
// Finds an if block, breaking text up around it into useful subblocks.
|
var finds_if_regex = /(?:^|\s+)(if\s*\([^)]+\)\s*)(\{[^}]*\})/
|
||||||
function separate_if_blocks (text_area) {
|
function make_new_if(c1, c2) {
|
||||||
contents = $(text_area).val();
|
var thingeroo;
|
||||||
search = /([\s\S]*)(if\s*\([^)]+\)\s*)({[^}]*})(\s*else\s*)({[^}]*})([\s\S]*)/.exec(contents);
|
if (c1 == undefined) { thingeroo = $(this); }
|
||||||
if (search) {
|
if (c2 == undefined) { thingeroo = $(c1); }
|
||||||
return {
|
else { thingeroo = $(c2); }
|
||||||
'found': true,
|
|
||||||
'before': search[1],
|
if (!thingeroo.is('.block.base')) {
|
||||||
'the_if': search[2],
|
thingeroo.find('.block.base').each(make_new_if);
|
||||||
'true_block': search[3],
|
} else if (finds_if_regex.exec(thingeroo.html())) {
|
||||||
'the_else': search[4],
|
var contents = thingeroo.html();
|
||||||
'false_block': search[5],
|
var split_up = contents.split(finds_if_regex);
|
||||||
'after': search[6],
|
var new_blocks = [];
|
||||||
};
|
new_blocks.push($('<div></div>').append(split_up[0]).addClass('block base'));
|
||||||
} else {
|
for (var i=1; i<split_up.length; i+=3) {
|
||||||
return {'found': false,};
|
var if_container = $('<div></div>').addClass('block if');
|
||||||
|
var branch_container = $('<div></div>').addClass('branch if');
|
||||||
|
var conditional = $('<div></div>').addClass('condition').html(split_up[i]);
|
||||||
|
var result = $('<div></div>').addClass('block base').html(split_up[i+1]);
|
||||||
|
branch_container.append(conditional);
|
||||||
|
branch_container.append(result);
|
||||||
|
if_container.append(branch_container);
|
||||||
|
|
||||||
|
new_blocks.push(if_container);
|
||||||
|
if (split_up[i+2] != '') {
|
||||||
|
var post_if = $('<div></div>').addClass('block base').html(split_up[i+2]);
|
||||||
|
new_blocks.push(post_if);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thingeroo.after(new_blocks);
|
||||||
|
console.log(new_blocks);
|
||||||
|
thingeroo.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function textarea_change_listener(event) {
|
function make_new_else(container) {
|
||||||
var text_area = $(event.target);
|
|
||||||
|
|
||||||
format_block(text_area.parents('.block'), into=$('#output'));
|
|
||||||
|
|
||||||
var s = separate_if_blocks(text_area);
|
|
||||||
console.log(s);
|
|
||||||
if (s.found) {
|
|
||||||
var block = text_area.parent('.block')
|
|
||||||
var before = $('<textarea>' + s.before + '</textarea>');
|
|
||||||
var true_block = $('<div class="block true" />').append(
|
|
||||||
$('<textarea>' + s.the_if + '</textarea>').addClass('if-condition')
|
|
||||||
).append(
|
|
||||||
$('<textarea>' + s.true_block + '</textarea>').addClass('if-code')
|
|
||||||
);
|
|
||||||
var else_block = $('<div class="block false" />').append(
|
|
||||||
$('<textarea>' + s.the_else + '</textarea>').addClass('else-condition')
|
|
||||||
).append(
|
|
||||||
$('<textarea>' + s.false_block + '</textarea>').addClass('else-code')
|
|
||||||
);
|
|
||||||
var after = $('<textarea>' + s.after + '</textarea>');
|
|
||||||
block.append(before, true_block, else_block, after);
|
|
||||||
text_area.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
var collapsible_block_selector = '.block.base';
|
||||||
function format_block (from, into) {
|
var cbs = collapsible_block_selector;
|
||||||
if (from.length > 1) { return; }
|
function collapse_neighbors(container) {
|
||||||
contents = '';
|
container = $(container);
|
||||||
from.find('textarea,.block').each(function (index, element) {
|
container.find('.block.base + .block.base').each(function () {
|
||||||
if ($(element).is('textarea')) {
|
var base = $(this).prev('.block.base');
|
||||||
contents += $(element).val();
|
var target = $(this);
|
||||||
} else {
|
var new_base_contents = base.html() + '<br>' + target.html();
|
||||||
contents += format_block($(element));
|
base.html(new_base_contents);
|
||||||
}
|
target.remove();
|
||||||
});
|
});
|
||||||
if (into == undefined) {
|
|
||||||
return contents;
|
|
||||||
} else {
|
|
||||||
into.html(contents);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#editor').on('input', '.block.base', make_new_if);
|
$('#editor').on('input', function() { make_new_if($(this)); });
|
||||||
|
$('#editor').on('input', function() { collapse_neighbors($(this)); });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
Loading…
Reference in New Issue
Block a user