From 50d1936b8b4654c3a8ea0d607232b2ed670a4f15 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 6 Jun 2020 11:09:59 +0200 Subject: [PATCH] reorg quickedit block styles, to support

in

s and declarative styles --- chloro/phyll/static/css/style.scss | 23 +++++- chloro/phyll/static/js/chloro.js | 118 +++++++++++++++++------------ 2 files changed, 91 insertions(+), 50 deletions(-) diff --git a/chloro/phyll/static/css/style.scss b/chloro/phyll/static/css/style.scss index 473c22f..27d211c 100644 --- a/chloro/phyll/static/css/style.scss +++ b/chloro/phyll/static/css/style.scss @@ -134,6 +134,13 @@ main { margin-top: 3em; color: lighten($text-color, 40%); } + div.note { + background: #fbf7c1;; + padding: 0.2em 0.5em 0.2em 2em; + p { + margin: 0.5em 0; + } + } } .post-list { @@ -191,7 +198,8 @@ div[contenteditable=true]:focus-within { } } -.style-popup { +.inline-style-popup, +.block-style-popup { background: white; box-shadow: 0 0 5px #666; input { @@ -207,7 +215,7 @@ div[contenteditable=true]:focus-within { } } button { - padding: 0; + padding: 0 0.5em; height: 2em; text-align: center; background: #eee; @@ -224,8 +232,17 @@ div[contenteditable=true]:focus-within { color: white; } } - &.short button { + &.inline-style-popup button { width: 2em; + padding: 0; + } + &.block-style-popup { + &.selected button { + display: none; + &.on { + display: block; + } + } } } diff --git a/chloro/phyll/static/js/chloro.js b/chloro/phyll/static/js/chloro.js index c47bb0a..4b0ffea 100644 --- a/chloro/phyll/static/js/chloro.js +++ b/chloro/phyll/static/js/chloro.js @@ -1,4 +1,24 @@ $(function() { + var BLOCKS = [ + {name: 'code', tag: 'PRE', klass: 'screen'}, + {name: 'figure', tag: 'DIV', subtag: true, klass: 'figure'}, + {name: 'note', tag: 'DIV', subtag: true, klass: 'note'}, + ]; + function get_contenteditable_subnode(node) { + if (node === null) return null; + if (node.parentNode.contentEditable === 'true') return node; + return get_contenteditable_subnode(node.parentNode); + } + function get_active_block(node) { + var main_node = get_contenteditable_subnode(node); + if (main_node === null) return null; + for (const block of BLOCKS) { + if (main_node.tagName === block.tag && main_node.classList.contains(block.klass)) + return block; + } + return null; + } + $('div[contenteditable]').on('input', function(event) { if (event.originalEvent.inputType == "insertParagraph") { var sel = document.getSelection(); @@ -18,19 +38,7 @@ $(function() { } return true; }); - $('div[contenteditable]').on('keyup', function(event) { - var sel = document.getSelection(); - if ((sel.anchorNode instanceof Element && ( - (sel.anchorOffset == 0 && sel.isCollapsed) || // first line - (sel.anchorNode.tagName === 'PRE'))) || - (sel.anchorNode.parentNode.tagName === 'PRE')) { - // start of line - show_block_style_popup(); - } else { - hide_block_style_popup(); - } - return true; - }); + $('div[contenteditable]').on('keyup click', update_block_style_popup); $('#save').on('click', function() { var text = $('div[contenteditable]')[0].innerHTML; @@ -45,56 +53,72 @@ $(function() { var block_style_popup = null; function block_style() { - var action = $(this).data('action'); - var class_name = null; - if (action == 'code') { - action = 'pre'; - class_name = 'screen'; - if ($(this).hasClass('on')) { // toggle off - action = 'p'; - class_name = null; - } - } - document.execCommand('formatBlock', false, action); var sel = window.getSelection(); - if (class_name) { - $(sel.anchorNode).addClass(class_name); + var current_anchor = sel.anchorNode; + if (this.classList.contains('on')) { // toggle off + if (this.action_block.subtag) { + // unwrap + var main_node = get_contenteditable_subnode(current_anchor); + $(current_anchor).detach().insertAfter(main_node); + } else { + document.execCommand('formatBlock', false, 'p'); + current_anchor = sel.anchorNode; + } + } else { + action = this.action_block.subtag || this.action_block.tag; + if (this.action_block.subtag) { + // enclose current tag into a new parent; + var new_parent = document.createElement(this.action_block.tag); + new_parent.className = this.action_block.klass; + $(current_anchor).wrap(new_parent); + } else { + document.execCommand('formatBlock', false, this.action_block.tag); + sel.anchorNode.className = this.action_block.klass; + current_anchor = sel.anchorNode; + } } var range = document.createRange(); - range.setStart(sel.anchorNode, 0); + range.setStart(current_anchor, 0); sel.removeAllRanges(); sel.addRange(range); + update_block_style_popup(); } - function show_block_style_popup() { + function update_block_style_popup() { + var sel = window.getSelection(); + if (! ((sel.anchorNode instanceof Element && (sel.anchorOffset == 0 && sel.isCollapsed)) || get_active_block(sel.anchorNode))) { + if (block_style_popup) { + $(block_style_popup).hide(); + } + return true; + } if (block_style_popup === null) { - block_style_popup = $( - '
' + - '' + - '
'); + block_style_popup = $('
'); + for (const block of BLOCKS) { + var button = document.createElement('button'); + button.action_block = block; + button.dataset.action = block.name; + button.textContent = block.name; + block_style_popup.append(button); + } block_style_popup.hide(); - block_style_popup.insertAfter($('.actions')); + block_style_popup.insertAfter(document.body); block_style_popup.find('button').on('click', block_style); } block_style_popup.css('position', 'absolute'); - var sel = window.getSelection(); - var anchor = sel.anchorNode; - if (anchor instanceof Text) { - anchor = anchor.parentNode; - } - if (anchor.tagName === "PRE") { - block_style_popup.find('[data-action=code]').addClass('on'); + var block = get_active_block(sel.anchorNode); + block_style_popup.find('button').removeClass('on'); + if (block) { + block_style_popup.find('[data-action=' + block.name + ']').addClass('on'); + block_style_popup.addClass('selected'); } else { - block_style_popup.find('[data-action=code]').removeClass('on'); + block_style_popup.removeClass('selected'); } + var anchor = get_contenteditable_subnode(sel.anchorNode); var pos = $(anchor).offset(); block_style_popup.css('top', pos.top - 33); block_style_popup.css('left', pos.left); block_style_popup.show(); - } - function hide_block_style_popup() { - if (block_style_popup) { - $(block_style_popup).hide(); - } + return true; } var style_popup = null; @@ -149,7 +173,7 @@ $(function() { function show_style_popup(sel) { if (style_popup === null) { - style_popup = $('
' + + style_popup = $('
' + '' + '' + '' + -- 2.39.2