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;
|
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 {
|
&.norm, &.sans, &.wrap {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
white-space: pre-wrap; /* CSS 3 */
|
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+ */
|
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 {
|
&.norm {
|
||||||
font-family: @serifFont;
|
font-family: @serifFont;
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,18 +188,18 @@ body#pad, body#pad-sub {
|
||||||
body#pad {
|
body#pad {
|
||||||
.pad-theme-transition;
|
.pad-theme-transition;
|
||||||
|
|
||||||
textarea {
|
textarea, #title {
|
||||||
.pad-theme-transition;
|
.pad-theme-transition;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dark {
|
&.dark {
|
||||||
textarea, #editor {
|
textarea, #title, #editor {
|
||||||
background-color: @darkBG;
|
background-color: @darkBG;
|
||||||
color: @darkTextColor;
|
color: @darkTextColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.light {
|
&.light {
|
||||||
textarea, #editor {
|
textarea, #title, #editor {
|
||||||
background-color: @lightBG;
|
background-color: @lightBG;
|
||||||
color: @lightTextColor;
|
color: @lightTextColor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ body#pad {
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
textarea {
|
textarea, #title {
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
top: 3em;
|
top: 3em;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -367,6 +367,14 @@ body#pad {
|
||||||
top: 2.25em;
|
top: 2.25em;
|
||||||
padding-top: 0.25em;
|
padding-top: 0.25em;
|
||||||
}
|
}
|
||||||
|
&.classic {
|
||||||
|
#editor {
|
||||||
|
top: 5.25em;
|
||||||
|
}
|
||||||
|
#title {
|
||||||
|
top: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
#tools {
|
#tools {
|
||||||
padding-top: 0.5em;
|
padding-top: 0.5em;
|
||||||
padding-bottom: 0.5em;
|
padding-bottom: 0.5em;
|
||||||
|
@ -420,40 +428,40 @@ body#pad {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 50em) {
|
@media all and (min-width: 50em) {
|
||||||
body#pad {
|
body#pad, body#pad.classic {
|
||||||
textarea {
|
textarea, #title {
|
||||||
padding-left: 10%;
|
padding-left: 10%;
|
||||||
padding-right: 10%;
|
padding-right: 10%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media all and (min-width: 60em) {
|
@media all and (min-width: 60em) {
|
||||||
body#pad {
|
body#pad, body#pad.classic {
|
||||||
textarea {
|
textarea, #title {
|
||||||
padding-left: 15%;
|
padding-left: 15%;
|
||||||
padding-right: 15%;
|
padding-right: 15%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media all and (min-width: 70em) {
|
@media all and (min-width: 70em) {
|
||||||
body#pad {
|
body#pad, body#pad.classic {
|
||||||
textarea {
|
textarea, #title {
|
||||||
padding-left: 20%;
|
padding-left: 20%;
|
||||||
padding-right: 20%;
|
padding-right: 20%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media all and (min-width: 85em) {
|
@media all and (min-width: 85em) {
|
||||||
body#pad {
|
body#pad, body#pad.classic {
|
||||||
textarea {
|
textarea, #title {
|
||||||
padding-left: 25%;
|
padding-left: 25%;
|
||||||
padding-right: 25%;
|
padding-right: 25%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media all and (min-width: 105em) {
|
@media all and (min-width: 105em) {
|
||||||
body#pad {
|
body#pad, body#pad.classic {
|
||||||
textarea {
|
textarea, #title {
|
||||||
padding-left: 30%;
|
padding-left: 30%;
|
||||||
padding-right: 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 {
|
.ProseMirror {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: calc(~"100% - 1.6em");
|
height: calc(~"100% - 1.6em");
|
||||||
|
@ -5,13 +38,13 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
|
||||||
|
|
||||||
.ProseMirror {
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
-webkit-font-variant-ligatures: none;
|
-webkit-font-variant-ligatures: none;
|
||||||
font-variant-ligatures: none;
|
font-variant-ligatures: none;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProseMirror pre {
|
.ProseMirror pre {
|
||||||
|
@ -344,12 +377,6 @@ li.ProseMirror-selectednode:after {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProseMirror {
|
|
||||||
padding: 4px 8px 4px 14px;
|
|
||||||
line-height: 1.2;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ProseMirror p {
|
.ProseMirror p {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,15 @@ var H = {
|
||||||
save: function($el, key) {
|
save: function($el, key) {
|
||||||
localStorage.setItem(key, $el.el.value);
|
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) {
|
load: function($el, key, onlyLoadPopulated) {
|
||||||
var val = localStorage.getItem(key);
|
var val = localStorage.getItem(key);
|
||||||
if (onlyLoadPopulated && val == null) {
|
if (onlyLoadPopulated && val == null) {
|
||||||
|
@ -127,6 +136,20 @@ var H = {
|
||||||
}
|
}
|
||||||
$el.el.value = val;
|
$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) {
|
set: function(key, value) {
|
||||||
localStorage.setItem(key, value);
|
localStorage.setItem(key, value);
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<meta name="google" value="notranslate">
|
<meta name="google" value="notranslate">
|
||||||
</head>
|
</head>
|
||||||
<body id="pad" class="light">
|
<body id="pad" class="light classic">
|
||||||
|
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
<!-- Markdown <input type=radio name=inputformat value=markdown checked> </label> -->
|
<!-- Markdown <input type=radio name=inputformat value=markdown checked> </label> -->
|
||||||
<!-- <label> <input type=radio name=inputformat value=prosemirror> WYSIWYM</label> -->
|
<!-- <label> <input type=radio name=inputformat value=prosemirror> WYSIWYM</label> -->
|
||||||
<!-- </div> -->
|
<!-- </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 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>
|
<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') {
|
if (H.get('padTheme', 'light') != 'light') {
|
||||||
toggleTheme();
|
toggleTheme();
|
||||||
}
|
}
|
||||||
|
var $title = H.getEl('title');
|
||||||
var $writer = H.getQEl('div.ProseMirror');
|
var $writer = H.getQEl('div.ProseMirror');
|
||||||
var $content = H.getEl('content');
|
var $content = H.getEl('content');
|
||||||
var $btnPublish = H.getEl('publish');
|
var $btnPublish = H.getEl('publish');
|
||||||
|
@ -103,6 +105,10 @@
|
||||||
if (val != '') {
|
if (val != '') {
|
||||||
words = $content.el.value.trim().replace(/\s+/gi, ' ').split(' ').length;
|
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" : "");
|
$wc.el.innerText = words + " word" + (words != 1 ? "s" : "");
|
||||||
};
|
};
|
||||||
var setButtonStates = function() {
|
var setButtonStates = function() {
|
||||||
|
@ -118,7 +124,7 @@
|
||||||
};
|
};
|
||||||
{{if .Post.Id}}var draftDoc = 'draft{{.Post.Id}}';
|
{{if .Post.Id}}var draftDoc = 'draft{{.Post.Id}}';
|
||||||
var origDoc = '{{.Post.Content}}';{{else}}var draftDoc = 'lastDoc';{{end}}
|
var origDoc = '{{.Post.Content}}';{{else}}var draftDoc = 'lastDoc';{{end}}
|
||||||
H.load($content, draftDoc, true);
|
H.loadClassic($title, $writer, draftDoc, true);
|
||||||
updateWordCount();
|
updateWordCount();
|
||||||
|
|
||||||
var typingTimer;
|
var typingTimer;
|
||||||
|
@ -140,7 +146,7 @@
|
||||||
var publishing = false;
|
var publishing = false;
|
||||||
var justPublished = false;
|
var justPublished = false;
|
||||||
var silenced = {{.Silenced}};
|
var silenced = {{.Silenced}};
|
||||||
var publish = function(content, font) {
|
var publish = function(title, content, font) {
|
||||||
if (silenced === true) {
|
if (silenced === true) {
|
||||||
alert("Your account is silenced, so you can't publish or update posts.");
|
alert("Your account is silenced, so you can't publish or update posts.");
|
||||||
return;
|
return;
|
||||||
|
@ -165,7 +171,7 @@
|
||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
body: post.content,
|
body: post.content,
|
||||||
title: post.title,
|
title: title,
|
||||||
font: font,
|
font: font,
|
||||||
lang: lang
|
lang: lang
|
||||||
};
|
};
|
||||||
|
@ -248,6 +254,21 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
setButtonStates();
|
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() {
|
$writer.on('keyup input', function() {
|
||||||
setButtonStates();
|
setButtonStates();
|
||||||
clearTimeout(typingTimer);
|
clearTimeout(typingTimer);
|
||||||
|
@ -262,8 +283,9 @@
|
||||||
$btnPublish.on('click', function(e) {
|
$btnPublish.on('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!publishing && $content.el.value) {
|
if (!publishing && $content.el.value) {
|
||||||
|
var title = $title.el.value;
|
||||||
var content = $content.el.value;
|
var content = $content.el.value;
|
||||||
publish(content, selectedFont);
|
publish(title, content, selectedFont);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -329,6 +351,7 @@
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
selectedFont = this.href.substring(this.href.indexOf('#')+1);
|
selectedFont = this.href.substring(this.href.indexOf('#')+1);
|
||||||
// TODO: don't change classes on the editor window
|
// TODO: don't change classes on the editor window
|
||||||
|
//$title.el.className = selectedFont;
|
||||||
//$writer.el.className = selectedFont;
|
//$writer.el.className = selectedFont;
|
||||||
document.querySelector('nav#font-picker li.selected').classList.remove('selected');
|
document.querySelector('nav#font-picker li.selected').classList.remove('selected');
|
||||||
this.parentElement.classList.add('selected');
|
this.parentElement.classList.add('selected');
|
||||||
|
@ -346,7 +369,7 @@
|
||||||
|
|
||||||
var doneTyping = function() {
|
var doneTyping = function() {
|
||||||
if (draftDoc == 'lastDoc' || $content.el.value != origDoc) {
|
if (draftDoc == 'lastDoc' || $content.el.value != origDoc) {
|
||||||
H.save($content, draftDoc);
|
H.saveClassic($title, $content, draftDoc);
|
||||||
updateWordCount();
|
updateWordCount();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue