<li> in Medium.js

by András Parditka

HTML

<link rel="stylesheet" href="https://cdn.rawgit.com/jakiestfu/Medium.js/master/medium.css">
<script src="https://cdn.rawgit.com/timdown/rangy/master/lib/rangy-core.js"></script>
<script src="https://cdn.rawgit.com/timdown/rangy/master/lib/rangy-classapplier.js"></script>
<script src="https://cdn.rawgit.com/jzaefferer/undo/master/undo.js"></script>
<script src="https://cdn.rawgit.com/jakiestfu/Medium.js/master/medium.js"></script>
<button type="button" id="liButton">li</button>
<div id="editor">
    <p><b>Highlight text starting with letter ‘C’ here ---&gt; C</b>onsectetur id perspiciatis cum quaerat necessitatibus earum natus – perferendis suscipit alias-repellendus hic ipsum aliquam deserunt, laborum nobis a rerum assumenda eveniet animi modi. Blanditiis iure impedit, dicta sint minus temporibus maiores harum fugit reiciendis rem laboriosam modi deserunt minima harum quasi hic beatae – vel.</p>
    <p>Nesciunt quis quos id eos fuga eaque tempora, ad hic repudiandae labore tempore nostrum sint. Ab minima accusantium pariatur cupiditate tempora, debitis perferendis culpa ullam ipsa beatae repellat, odio sunt-vero esse ea obcaecati. Natus minus saepe. Repudiandae amet, repellendus animi. Veritatis et ipsam alias expedita corporis sapiente sed Magnam – quod illum nemo commodi magni non beatae. Fugiat mollitia impedit dignissimos ratione hic sequi. Fugit repudiandae, neque inventore. Alias temporibus – minus facere ea provident ullam pariatur. Aspernatur alias-impedit itaque provident. Quaerat fuga libero obcaecati saepe corpori<b>s &lt;--- End highlighting with letter ‘s’ here</b></p>
	<p>Now click the ‘li’ button – the two paragraphs should become a single ordered list with two items.</p>
	<p>Now click the ‘li’ button again – the two list items should become paragraphs again.</p>
</div>

JavaScript

// Init editor

var editor = new Medium({
    element: $('#editor')[0],
    tags: {
        'break': 'br',
        horizontalRule: 'hr',
        paragraph: 'p',
        outerLevel: null,
        innerLevel: null
    },
    attributes: null
});

// Bind ‘li’ button functionality

$('#liButton').on('click', function(e) {
    
    editor.focus();
    
    var selection = rangy.getSelection();
    var anchorNode = $(selection.isBackwards() ? selection.focusNode : selection.anchorNode).closest('p,div,li,ul,ol')[0];
    var focusNode = $(selection.isBackwards() ? selection.anchorNode : selection.focusNode).closest('p,div,li,ul,ol')[0];
    
    // Expand selection to the entire element.
    
    var range = rangy.createRange();
    range.setStartBefore(anchorNode);
    range.setEndAfter(focusNode);
    selection.setSingleRange(range);
    
    if ($(anchorNode).closest('li,ul,ol').length) {
        
        // The selection is in a list
        
        editor.invokeElement('p').invokeElement('li').invokeElement('ol');
        
    } else {
        
        // The selection is not in a list
        
        editor.invokeElement('ol').invokeElement('li');
        
        // The structure here is <p><ol><li> x 2
        // We remove the <p>s and move the <li>s into a single <ol>
        
        var ols = $('#editor').find('p>ol');
        var lastOl = null;
        for (var i = 0; i < ols.length; i++) {
            var ol = ols.eq(i);
            var p = ol.parent();
            ol.detach().replaceAll(p);
            if (ol.prev().is(lastOl)) {
                lastOl.append(ol.children());
                ol.remove();
            } else {
                lastOl = ol;
            }
        }
        
        // Correct the selection so that liButton can be used again
        
        if (lastOl) {
            range.setStartBefore(lastOl.children().first()[0]);
            range.setEndAfter(lastOl.children().last()[0]);
            selection.setSingleRange(range);
      ...