Notes Library Mock

HTML

<link rel="stylesheet" href="http://yui.yahooapis.com/3.9.0/build/cssbase/cssbase-min.css">
<script src="https://pagedown.googlecode.com/hg/Markdown.Converter.js"></script>
<script src="https://pagedown.googlecode.com/hg/Markdown.Sanitizer.js"></script>
<script src="https://raw.github.com/SimonChong/jQuery-Text-Selection-Plug-in/master/js/jquery.textselect.js"></script>
<div class="notes-library">    
    <div class="note-list-panel">
        <ul class="note-list">
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
    <div class="tag-chooser-panel">
        <ul class="tag-list">
            <li style="background-color: red">1a</li>
            <li style="background-color: red">1b</li>
            <li style="background-color: blue">2a</li>
        </ul>
    </div>
    <div class="note-editor-panel">
This is a **test**.

This data can be markdown-formatted, and it will appear as HTML.
    </div>
</div>

CSS

.notes-library {position: relative; padding-left: 100px;}
.note-list-panel {float:left; overflow: none; width: 100px; margin-left: -100px; border:1px solid black; }
.note-editor-panel {overflow: auto; border: 1px solid black; }
.note-list {margin: 0; padding: 0}
.note-list>li {height:25px; border: 1px solid grey; list-style: none;}
.tag-list {margin: 0; padding: 0}
.tag-list>li {display: inline-block; height: 20px; width: 80px; color: white; cursor: pointer;}
.active-tag {border: 1px solid black;}
.tag {color: red;/*letter-spacing: -5px;margin-left: -2px; margin-right: 2px;*/ cursor: default; font-weight: normal;}
.tag.tag-highlight { font-weight: bold; }

JavaScript

var $editorPanel = $('.note-editor-panel');
var mdContents = $editorPanel.html();

var currentTag;

function redrawContents() {
    var converter = new Markdown.Converter();
    var htmlContents = converter.makeHtml(mdContents);
    $editorPanel.html(htmlContents);
    insertTags();
    alert('foo');
};


$editorPanel.on('mouseup', handlePossibleSelection);

function handlePossibleSelection() {
    if(!currentTag) {
        return;
    }
    var range;
    try {
        range = $editorPanel.textSelect('getRange');
    } catch (er){}
    if(range && 
       (range.startElement != range.endElement || 
        range.start < range.end) &&
       isWithinEditor(range.startElement) &&
       isWithinEditor(range.endElement)) {
        addTags(range);
        $editorPanel.textSelect('clear');
    }
};

var tags = [
/*    // Test data
    makeTag("[", 28, 1),
    makeTag("]", 39, 1)*/
];

function getOverallIndex(el, idx) {
    // Recursively add up the number of text characters
    // until we reach the given element.
    var result = getElementIndex($editorPanel, el);
    return result.index + idx;
}
    
function findElementWithIndex($toSearch, index) {
    // If the element is a tag, ignore it.
    if($toSearch.is('.tag')) {
        return {element: null, index: 0};
    }
    var childNodes = $toSearch.contents();
    var count = 0;
    for(var i = 0; i < childNodes.length; i++) {
        var el = childNodes[i];
        if(el.nodeType == 3) { // text nodes
            if(index - count < el.textContent.length) {
                return {
                    element: el, 
                    index: index - count
                };
            }
            count += el.textContent.length;
        } else {
            var result = findElementWithIndex($(el), index - count);
            if(result.element) {
                return result;
            }
            count += result.index;
        }
    }
    return {
        // A null element represents that the given index...