2 $('div[contenteditable]').on('input', function(event) {
3 if (event.originalEvent.inputType == "insertParagraph") {
4 var sel = document.getSelection();
5 var anchorNode = sel.anchorNode;
6 var prev_p = sel.anchorNode.previousSibling;
8 if (prev_p.tagName != 'P') {
9 prev_p = $(prev_p).parents('p')[0];
11 var title_match = prev_p.innerText.match(/^(h[1-6]). /);
13 var title = document.createElement(title_match[1]);
14 title.innerHTML = prev_p.innerHTML;
15 title.textContent = title.textContent.slice(4);
16 prev_p.replaceWith(title);
21 $('div[contenteditable]').on('keyup', function(event) {
22 var sel = document.getSelection();
23 if ((sel.anchorNode instanceof Element && (
24 (sel.anchorOffset == 0 && sel.isCollapsed) || // first line
25 (sel.anchorNode.tagName === 'PRE'))) ||
26 (sel.anchorNode.parentNode.tagName === 'PRE')) {
28 show_block_style_popup();
30 hide_block_style_popup();
35 $('#save').on('click', function() {
36 var text = $('div[contenteditable]')[0].innerHTML;
37 var csrf = $('[name=csrfmiddlewaretoken]').val();
39 { text: text, csrfmiddlewaretoken: csrf}
41 $('#save').css('background', 'red');
46 var block_style_popup = null;
47 function block_style() {
48 var action = $(this).data('action');
49 var class_name = null;
50 if (action == 'code') {
52 class_name = 'screen';
53 if ($(this).hasClass('on')) { // toggle off
58 document.execCommand('formatBlock', false, action);
59 var sel = window.getSelection();
61 $(sel.anchorNode).addClass(class_name);
63 var range = document.createRange();
64 range.setStart(sel.anchorNode, 0);
65 sel.removeAllRanges();
68 function show_block_style_popup() {
69 if (block_style_popup === null) {
70 block_style_popup = $(
71 '<div class="style-popup">' +
72 '<button data-action="code">code</button>' +
74 block_style_popup.hide();
75 block_style_popup.insertAfter($('.actions'));
76 block_style_popup.find('button').on('click', block_style);
78 block_style_popup.css('position', 'absolute');
79 var sel = window.getSelection();
80 var anchor = sel.anchorNode;
81 if (anchor instanceof Text) {
82 anchor = anchor.parentNode;
84 if (anchor.tagName === "PRE") {
85 block_style_popup.find('[data-action=code]').addClass('on');
87 block_style_popup.find('[data-action=code]').removeClass('on');
89 var pos = $(anchor).offset();
90 block_style_popup.css('top', pos.top - 33);
91 block_style_popup.css('left', pos.left);
92 block_style_popup.show();
94 function hide_block_style_popup() {
95 if (block_style_popup) {
96 $(block_style_popup).hide();
100 var style_popup = null;
101 function update_style() {
102 var action = $(this).data('action');
104 if (action == 'code') {
105 action = 'insertHTML';
106 param = $('<code></code>', {text: window.getSelection().toString()})[0].outerHTML;
108 if (action == 'createLink') {
109 var sel = window.getSelection();
110 var $input = $('input[name=link-target]');
111 $input[0]._range = sel.getRangeAt(0);
112 if (sel.anchorNode instanceof Element) {
113 var elem = sel.anchorNode.childNodes[sel.anchorOffset];
114 if (elem.tagName == 'A') {
115 $input.val(elem.href);
118 $input.addClass('shown');
122 document.execCommand(action, false, param);
124 function validate_link(ev) {
125 var charCode = typeof ev.which == "number" ? ev.which : ev.keyCode;
126 if (ev.key == "Enter") {
127 var $input = $(this);
128 var range = this._range;
129 var url = $input.val();
130 $input.removeClass('shown');
131 var sel = window.getSelection();
132 sel.addRange(this._range);
134 document.execCommand('createLink', false, url);
136 document.execCommand('unlink', false, null);
142 function focusout_link(ev) {
143 var $input = $(this);
144 $input.removeClass('shown');
145 var range = this._range;
146 var sel = window.getSelection();
147 sel.addRange(this._range);
150 function show_style_popup(sel) {
151 if (style_popup === null) {
152 style_popup = $('<div class="style-popup short">' +
153 '<button data-action="italic"><i>i</i></button>' +
154 '<button data-action="bold"><b>b</b></button>' +
155 '<button data-action="code">#</button>' +
156 '<button data-action="removeFormat">×</button>' +
157 '<button data-action="createLink">a</button>' +
158 '<input name="link-target"/>' +
161 style_popup.insertAfter($('.actions'));
162 style_popup.find('button').on('click', update_style);
163 style_popup.find('[name=link-target]').on('keypress', validate_link).on('focusout', focusout_link);
165 style_popup.css('position', 'absolute');
166 var pos = sel.getRangeAt(0).getClientRects()[0];
167 style_popup.css('top', pos.top + window.scrollY - 33);
168 style_popup.css('left', pos.left + window.scrollX);
171 $(document).on('selectionchange', function(event) {
172 if ($('input[name=link-target].shown').length) {
175 var sel = window.getSelection();
176 if ($(sel.anchorNode).parents('div[contenteditable]').length && sel.toString()) {
177 show_style_popup(sel);
178 } else if (style_popup) {
179 $(style_popup).hide();