Add dedicated Title field to WYSIWYG editor
This takes styling from the Classic Editor on Write.as. It adds all application code for auto-saving the title, publishing it with the post body, and including it in the word count.
This commit is contained in:
parent
4b0833435f
commit
f76bfebfde
|
@ -515,7 +515,7 @@ pre, body#post article, #post .alert, #subpage .alert, body#collection article,
|
|||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
textarea, pre, body#post article, body#collection article p {
|
||||
textarea, input#title, pre, body#post article, body#collection article p {
|
||||
&.norm, &.sans, &.wrap {
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap; /* CSS 3 */
|
||||
|
@ -525,7 +525,7 @@ textarea, pre, body#post article, body#collection article p {
|
|||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
}
|
||||
textarea, pre, body#post article, body#collection article, body#subpage article, span, .font {
|
||||
textarea, input#title, pre, body#post article, body#collection article, body#subpage article, span, .font {
|
||||
&.norm {
|
||||
font-family: @serifFont;
|
||||
}
|
||||
|
|
|
@ -188,18 +188,18 @@ body#pad, body#pad-sub {
|
|||
body#pad {
|
||||
.pad-theme-transition;
|
||||
|
||||
textarea {
|
||||
textarea, #title {
|
||||
.pad-theme-transition;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
textarea, #editor {
|
||||
textarea, #title, #editor {
|
||||
background-color: @darkBG;
|
||||
color: @darkTextColor;
|
||||
}
|
||||
}
|
||||
&.light {
|
||||
textarea, #editor {
|
||||
textarea, #title, #editor {
|
||||
background-color: @lightBG;
|
||||
color: @lightTextColor;
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ body#pad {
|
|||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
textarea {
|
||||
textarea, #title {
|
||||
position: fixed !important;
|
||||
top: 3em;
|
||||
right: 0;
|
||||
|
@ -367,6 +367,14 @@ body#pad {
|
|||
top: 2.25em;
|
||||
padding-top: 0.25em;
|
||||
}
|
||||
&.classic {
|
||||
#editor {
|
||||
top: 5.25em;
|
||||
}
|
||||
#title {
|
||||
top: 3.5rem;
|
||||
}
|
||||
}
|
||||
#tools {
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
|
@ -420,40 +428,40 @@ body#pad {
|
|||
}
|
||||
|
||||
@media all and (min-width: 50em) {
|
||||
body#pad {
|
||||
textarea {
|
||||
body#pad, body#pad.classic {
|
||||
textarea, #title {
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 60em) {
|
||||
body#pad {
|
||||
textarea {
|
||||
body#pad, body#pad.classic {
|
||||
textarea, #title {
|
||||
padding-left: 15%;
|
||||
padding-right: 15%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 70em) {
|
||||
body#pad {
|
||||
textarea {
|
||||
body#pad, body#pad.classic {
|
||||
textarea, #title {
|
||||
padding-left: 20%;
|
||||
padding-right: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 85em) {
|
||||
body#pad {
|
||||
textarea {
|
||||
body#pad, body#pad.classic {
|
||||
textarea, #title {
|
||||
padding-left: 25%;
|
||||
padding-right: 25%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 105em) {
|
||||
body#pad {
|
||||
textarea {
|
||||
body#pad, body#pad.classic {
|
||||
textarea, #title {
|
||||
padding-left: 30%;
|
||||
padding-right: 30%;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,36 @@
|
|||
body#pad.classic {
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
#editor {
|
||||
top: 4em;
|
||||
}
|
||||
#title {
|
||||
top: 4.25rem;
|
||||
bottom: unset;
|
||||
height: auto;
|
||||
font-weight: bold;
|
||||
font-size: 2em;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
border: 0;
|
||||
}
|
||||
#tools {
|
||||
#belt {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
#target {
|
||||
ul {
|
||||
a {
|
||||
padding: 0 0.5em !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ProseMirror {
|
||||
position: relative;
|
||||
height: calc(~"100% - 1.6em");
|
||||
|
@ -5,13 +38,13 @@
|
|||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.ProseMirror {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
-webkit-font-variant-ligatures: none;
|
||||
font-variant-ligatures: none;
|
||||
padding: 0.5em 0;
|
||||
line-height: 1.5;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ProseMirror pre {
|
||||
|
@ -344,12 +377,6 @@ li.ProseMirror-selectednode:after {
|
|||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.ProseMirror {
|
||||
padding: 4px 8px 4px 14px;
|
||||
line-height: 1.2;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ProseMirror p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
|
|
@ -119,6 +119,15 @@ var H = {
|
|||
save: function($el, key) {
|
||||
localStorage.setItem(key, $el.el.value);
|
||||
},
|
||||
saveClassic: function($titleEl, $el, key) {
|
||||
var out = "";
|
||||
var title = $titleEl.el.value;
|
||||
if (title !== "") {
|
||||
out = "# "+title+"\n\n";
|
||||
}
|
||||
out += $el.el.value;
|
||||
localStorage.setItem(key, out);
|
||||
},
|
||||
load: function($el, key, onlyLoadPopulated) {
|
||||
var val = localStorage.getItem(key);
|
||||
if (onlyLoadPopulated && val == null) {
|
||||
|
@ -127,6 +136,20 @@ var H = {
|
|||
}
|
||||
$el.el.value = val;
|
||||
},
|
||||
loadClassic: function($titleEl, $el, key, onlyLoadPopulated) {
|
||||
var val = localStorage.getItem(key);
|
||||
if (onlyLoadPopulated && val == null) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
if (val.indexOf("# ") === 0) {
|
||||
var eol = val.indexOf("\n");
|
||||
title = val.substring("# ".length, eol);
|
||||
val = val.substring(eol+"\n\n".length);
|
||||
$titleEl.el.value = title;
|
||||
}
|
||||
$el.el.value = val;
|
||||
},
|
||||
set: function(key, value) {
|
||||
localStorage.setItem(key, value);
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<meta name="google" value="notranslate">
|
||||
</head>
|
||||
<body id="pad" class="light">
|
||||
<body id="pad" class="light classic">
|
||||
|
||||
<div id="overlay"></div>
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
|||
<!-- Markdown <input type=radio name=inputformat value=markdown checked> </label> -->
|
||||
<!-- <label> <input type=radio name=inputformat value=prosemirror> WYSIWYM</label> -->
|
||||
<!-- </div> -->
|
||||
<input type="text" id="title" name="title" placeholder="Title..." {{if .Post.Title}}value="{{.Post.Title}}"{{end}} autofocus />
|
||||
<div id="editor" style="margin-bottom: 0"></div>
|
||||
|
||||
<div style="display: none"><textarea id="content"{{if .Post.Content }} value={{.Post.Content}}>{{.Post.Content}}{{else}}>{{end}}</textarea></div>
|
||||
|
@ -93,6 +94,7 @@
|
|||
if (H.get('padTheme', 'light') != 'light') {
|
||||
toggleTheme();
|
||||
}
|
||||
var $title = H.getEl('title');
|
||||
var $writer = H.getQEl('div.ProseMirror');
|
||||
var $content = H.getEl('content');
|
||||
var $btnPublish = H.getEl('publish');
|
||||
|
@ -103,6 +105,10 @@
|
|||
if (val != '') {
|
||||
words = $content.el.value.trim().replace(/\s+/gi, ' ').split(' ').length;
|
||||
}
|
||||
val = $title.el.value.trim();
|
||||
if (val != '') {
|
||||
words += $title.el.value.trim().replace(/\s+/gi, ' ').split(' ').length;
|
||||
}
|
||||
$wc.el.innerText = words + " word" + (words != 1 ? "s" : "");
|
||||
};
|
||||
var setButtonStates = function() {
|
||||
|
@ -118,7 +124,7 @@
|
|||
};
|
||||
{{if .Post.Id}}var draftDoc = 'draft{{.Post.Id}}';
|
||||
var origDoc = '{{.Post.Content}}';{{else}}var draftDoc = 'lastDoc';{{end}}
|
||||
H.load($content, draftDoc, true);
|
||||
H.loadClassic($title, $writer, draftDoc, true);
|
||||
updateWordCount();
|
||||
|
||||
var typingTimer;
|
||||
|
@ -140,7 +146,7 @@
|
|||
var publishing = false;
|
||||
var justPublished = false;
|
||||
var silenced = {{.Silenced}};
|
||||
var publish = function(content, font) {
|
||||
var publish = function(title, content, font) {
|
||||
if (silenced === true) {
|
||||
alert("Your account is silenced, so you can't publish or update posts.");
|
||||
return;
|
||||
|
@ -165,7 +171,7 @@
|
|||
|
||||
var params = {
|
||||
body: post.content,
|
||||
title: post.title,
|
||||
title: title,
|
||||
font: font,
|
||||
lang: lang
|
||||
};
|
||||
|
@ -248,6 +254,21 @@
|
|||
};
|
||||
|
||||
setButtonStates();
|
||||
$title.on('keyup input', function() {
|
||||
setButtonStates();
|
||||
clearTimeout(typingTimer);
|
||||
typingTimer = setTimeout(doneTyping, doneTypingInterval);
|
||||
}, false);
|
||||
$title.on('keydown', function(e) {
|
||||
if (e.keyCode == 13) {
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
$btnPublish.el.click();
|
||||
} else {
|
||||
e.preventDefault();
|
||||
$writer.el.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
$writer.on('keyup input', function() {
|
||||
setButtonStates();
|
||||
clearTimeout(typingTimer);
|
||||
|
@ -262,8 +283,9 @@
|
|||
$btnPublish.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (!publishing && $content.el.value) {
|
||||
var title = $title.el.value;
|
||||
var content = $content.el.value;
|
||||
publish(content, selectedFont);
|
||||
publish(title, content, selectedFont);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -329,6 +351,7 @@
|
|||
e.preventDefault();
|
||||
selectedFont = this.href.substring(this.href.indexOf('#')+1);
|
||||
// TODO: don't change classes on the editor window
|
||||
//$title.el.className = selectedFont;
|
||||
//$writer.el.className = selectedFont;
|
||||
document.querySelector('nav#font-picker li.selected').classList.remove('selected');
|
||||
this.parentElement.classList.add('selected');
|
||||
|
@ -346,7 +369,7 @@
|
|||
|
||||
var doneTyping = function() {
|
||||
if (draftDoc == 'lastDoc' || $content.el.value != origDoc) {
|
||||
H.save($content, draftDoc);
|
||||
H.saveClassic($title, $content, draftDoc);
|
||||
updateWordCount();
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue