Last active
August 29, 2015 14:22
-
-
Save shgysk8zer0/62ae410717617049a094 to your computer and use it in GitHub Desktop.
HTML5 WYSIWYG Editor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (! ('forEach' in NodeList.prototype)) { | |
NodeList.prototype.forEach = Array.prototype.forEach; | |
} | |
if (! ('import' in HTMLLinkElement.prototype)) { | |
var script = document.createElement('script'); | |
document.head.appendChild(script); | |
script.asrc = true; | |
script.src = location.pathname + "htmlimport.js"; | |
} | |
window.addEventListener('load', function() { | |
if ('contextMenu' in HTMLElement.prototype) { | |
var imported = document.querySelector('link[rel="import"][name="WYSIWYG"]').import; | |
var content = imported.body.firstElementChild; | |
var menu = document.body.insertBefore(content, document.body.firstElementChild); | |
WYSIWYG(menu); | |
document.querySelector('[contenteditable="true"]').setAttribute('contextmenu', 'wysiwyg_menu'); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (! ('import' in HTMLLinkElement.prototype)) { | |
Object.defineProperty(HTMLLinkElement.prototype, 'import', { | |
get: function() { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', this.href, false); | |
xhr.send(); | |
return new DOMParser().parseFromString(xhr.response, "text/html"); | |
} | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>HTML5 WYSIWYG Editor</title> | |
<!-- <base href="../../"> --> | |
<link rel="stylesheet" href="normalize.css" type="text/css" media="all"> | |
<link rel="stylesheet" href="style.css" type="text/css" media="all"> | |
<!-- <link rel="stylesheet" href="stylesheets/core-css/fonts.css" type="text/css" media="all"> --> | |
<link rel="import" href="menu.html" type="text/html" name="WYSIWYG"> | |
<link rel="icon" type="image/svg+xml" href="code.svg" sizes="any"> | |
<link rel="icon" type="image/png" href="code-16.png" sizes="16x16"> | |
<script type="application/javascript" src="functions.js"></script> | |
<script type="application/javascript" src="wysiwyg.js" async=""></script> | |
</head> | |
<body> | |
<div contenteditable="true"> | |
<h1 align="center">HTML5 WYSIWYG Contextmenu Editor For Firefox</h1><h2 align="center"><i><font color="darkgray">See code in <a href="https://gist.github.com/shgysk8zer0/62ae410717617049a094">Gist</a></font></i><br></h2><figure class="fit-content center shadow"><img alt="WYSIWYG Preview" src="wysiwyg_preview.jpg"><br><figcaption>Screen shot of WYSIWYG context menu</figcaption></figure><p>This demo will only be fully functional in Firefox (<i>it should work in other browsers, but the ability to do more than simply enter text requires support of <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu#Examples">contextmenu</a>, which is currently only supported in Firefox</i>).<br></p><h2 align="center">Functionality & Instructions:</h2><hr><ul><li>Click & type, just like in any text editor</li><li>Right-click to reveal <abbr title="What You See Is What You Get">WYSIWYG</abbr> editor menu<br></li><ul><li>Create from a list of available elements</li><ul><li>Headers <code><h1></code> – <code><h6></code></li><li>Lists (<i>ordered & unordered</i>)</li><li>Images</li><li>Links</li><li>Text style elements (<b>bold</b>, <i>italics</i>, <u>underline</u>, <strike>strike-through</strike>, <sub>subscript</sub>, <sup>superscript</sup>, <mark>highlighted</mark>, <code>code</code>, etc)</li><li>Pre-formatted text<br></li><li><q>Quotes</q> & <br><blockquote>blockquotes<br></blockquote></li></ul><li>Insert raw HTML using <q>Custom HTML</q></li></ul><li>Change font <big><big>size</big></big>, <font color="crimson">color</font>, and <font face="Acme">family</font></li><li>A wide variety of special characters such as:</li><ul><li>Punctuation — <samp>» ¿ †</samp></li><li>Mathematical characters — <samp>± ∫ ≠ ½ ⅝</samp></li><li>Legal & currency characters — <samp>© ™ £ ¥</samp></li><li>A variety of miscellaneous characters — <samp>♣ ♀ ♂ ↑ ♬ ♪</samp></li></ul><li>Horizontal Rules | |
<hr></li><li>Justify & indent text</li><li>Undo & redo</li><li>Clear formatting & links<br></li></ul> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! normalize.css v1.1.2 | MIT License | git.io/normalize */ | |
@-moz-viewport{ | |
width:auto; | |
width:100%; | |
width:device-width; | |
height:auto; | |
height:100%; | |
height:device-height; | |
zoom:1; | |
min-zoom:1; | |
max-zoom:1; | |
user-zoom:fixed; | |
} | |
@-webkit-viewport{ | |
width:auto; | |
width:100%; | |
width:device-width; | |
height:auto; | |
height:100%; | |
height:device-height; | |
zoom:1; | |
min-zoom:1; | |
max-zoom:1; | |
user-zoom:fixed; | |
} | |
@-o-viewport{ | |
width:auto; | |
width:100%; | |
width:device-width; | |
height:auto; | |
height:100%; | |
height:device-height; | |
zoom:1; | |
min-zoom:1; | |
max-zoom:1; | |
user-zoom:fixed; | |
} | |
@-ms-viewport{ | |
width:auto; | |
width:100%; | |
width:device-width; | |
height:auto; | |
height:100%; | |
height:device-height; | |
zoom:1; | |
min-zoom:1; | |
max-zoom:1; | |
user-zoom:fixed; | |
} | |
@viewport{ | |
width:auto; | |
width:100%; | |
width:device-width; | |
height:auto; | |
height:100%; | |
height:device-height; | |
zoom:1; | |
min-zoom:1; | |
max-zoom:1; | |
user-zoom:fixed; | |
} | |
body{ | |
min-height:100%; | |
min-height:100vh; | |
} | |
*, *::after, *::before, *:after, *:before{ | |
margin:0; | |
padding:0; | |
box-sizing:border-box; | |
-webkit-animation-fill-mode:forwards; | |
animation-fill-mode:forwards; | |
max-width: 100%; | |
} | |
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary,picture{ | |
display:block; | |
} | |
audio,canvas,video{ | |
display:inline-block; | |
*display:inline; | |
*zoom:1; | |
} | |
audio:not([controls]){ | |
display:none; | |
height:0; | |
} | |
[hidden], menu[type=context], datalist{ | |
display:none; | |
} | |
html{ | |
-ms-text-size-adjust:100%; | |
-webkit-text-size-adjust:100%; | |
} | |
body{ | |
margin:0; | |
} | |
a:focus{ | |
outline:thin dotted; | |
} | |
a:active,a:hover{ | |
outline:0; | |
} | |
abbr[title]{ | |
border-bottom:1px dotted; | |
} | |
b,strong{ | |
font-weight:bold; | |
} | |
blockquote{ | |
margin:1em 40px; | |
} | |
dfn{ | |
font-style:italic; | |
} | |
hr{ | |
-moz-box-sizing:content-box; | |
box-sizing:content-box; | |
height:0; | |
} | |
mark{ | |
background:#ff0; | |
color:#000; | |
} | |
p,pre{ | |
margin:1em 0; | |
} | |
code,kbd,pre,samp{ | |
font-family:monospace,serif; | |
_font-family:'courier new',monospace; | |
font-size:1em; | |
} | |
pre{ | |
white-space:pre; | |
white-space:pre-wrap; | |
word-wrap:break-word; | |
} | |
small{ | |
font-size:80%; | |
} | |
sub,sup{ | |
font-size:75%; | |
line-height:0; | |
position:relative; | |
vertical-align:baseline; | |
} | |
sup{ | |
top:-0.5em; | |
} | |
sub{ | |
bottom:-0.25em; | |
} | |
dl,ol,ul{ | |
margin:1em 0; | |
} | |
dd{ | |
margin:0 0 0 40px; | |
} | |
menu,ol,ul{ | |
padding:0 0 0 40px; | |
} | |
nav ul,nav ol{ | |
list-style:none; | |
list-style-image:none; | |
} | |
menu[type=list]{ | |
list-style:none; | |
} | |
img{ | |
border:0; | |
-ms-interpolation-mode:bicubic; | |
} | |
svg:not(:root){ | |
overflow:hidden; | |
} | |
figure{ | |
margin:0; | |
} | |
form{ | |
margin:0; | |
} | |
fieldset{ | |
border:1px solid silver; | |
margin:0 2px; | |
padding:.35em .625em .75em; | |
} | |
legend{ | |
border:0; | |
padding:0; | |
white-space:normal; | |
*margin-left:-7px; | |
} | |
button,input,select,textarea{ | |
font-size:100%; | |
margin:0; | |
vertical-align:baseline; | |
*vertical-align:middle; | |
} | |
button,input{ | |
line-height:normal; | |
} | |
button,select{ | |
text-transform:none; | |
} | |
button,html input[type="button"],input[type="reset"],input[type="submit"]{ | |
-webkit-appearance:button; | |
*overflow:visible; | |
} | |
button[disabled],html input[disabled]{ | |
cursor:default; | |
} | |
input[type="checkbox"],input[type="radio"]{ | |
padding:0; | |
*height:13px; | |
*width:13px; | |
} | |
input[type="search"]{ | |
-webkit-appearance:textfield; | |
} | |
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{ | |
-webkit-appearance:none; | |
} | |
button::-moz-focus-inner,input::-moz-focus-inner{ | |
border:0; | |
padding:0; | |
} | |
dialog:not([open]){ | |
display:none; | |
} | |
dialog { | |
position: absolute; | |
left: 0px; | |
right: 0px; | |
width: -moz-fit-content; | |
width: -webkit-fit-content; | |
width: fit-content; | |
height: -moz-fit-content; | |
height: -webkit-fit-content; | |
height: -fit-content; | |
margin: auto; | |
border: solid; | |
border-image-source: initial; | |
border-image-slice: initial; | |
border-image-width: initial; | |
border-image-outset: initial; | |
border-image-repeat: initial; | |
padding: 1em; | |
background: white; | |
color: black; | |
} | |
textarea{ | |
overflow:auto; | |
vertical-align:top; | |
} | |
table{ | |
border-collapse:collapse; | |
border-spacing:0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@charset 'UTF-8'; | |
@import url(//fonts.googleapis.com/css?family=Acme|Alice|Ubuntu|Roboto|Press+Start+2P|Open+Sans); | |
@media screen and (min-width:1000px) { | |
:root{ | |
font-size:1.3vw; | |
} | |
} | |
@media screen and (max-width:999px) and (min-width:500px) { | |
:root{ | |
font-size:2vw; | |
} | |
} | |
@media screen and (max-width: 499px) { | |
:root{ | |
font-size:3vw; | |
} | |
} | |
:root { | |
min-height: 100vh; | |
} | |
body { | |
min-height: 100vh; | |
font-family: 'Ubuntu'; | |
} | |
img { | |
max-width: 100%; | |
height: auto; | |
} | |
figure { | |
margin-bottom: 2em; | |
margin-top: 1em; | |
padding: 1em 3em; | |
border: 0.1em solid dimgray; | |
border: 3px outset dimgray; | |
text-align: center; | |
} | |
figure figcaption { | |
color: dimgray; | |
text-decoration: underline; | |
font-style: italic; | |
} | |
blockquote { | |
color: #777; | |
font-family: 'Libertine'; | |
font-style: italic; | |
padding: 0px 15px; | |
border-left: 4px solid #DDD; | |
} | |
blockquote cite { | |
display: block; | |
} | |
blockquote cite::before { | |
content: ' — '; | |
} | |
code { | |
font-size: 0.9rem; | |
padding: 0.1rem; | |
background-color: hsl(0, 0%, 93%); | |
border-radius: 0.2rem; | |
display: inline-block; | |
white-space: pre; | |
} | |
pre > code { | |
display: block; | |
padding: 1rem; | |
background-color: rgb(51, 51, 51); | |
color: rgb(255, 249, 217); | |
border-radius: 0.3rem; | |
overflow-x: auto; | |
} | |
.shadow { | |
box-shadow: 0.5em 0.5em 1em black; | |
} | |
.center { | |
display: table; | |
margin-left: auto; | |
margin-right: auto; | |
} | |
.fit-content { | |
display: inline-block; | |
} | |
@supports (width: fit-content) or (width: -moz-fit-content) or (-webkit-fit-content) { | |
.fit-content { | |
width: -moz-fit-content; | |
width: webkit-fit-content; | |
width: fit-content; | |
} | |
.center.fit-content { | |
display: block; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function WYSIWYG(menu) | |
{ | |
menu.querySelectorAll('menuitem[data-editor-command]').forEach(function(item) | |
{ | |
item.addEventListener('click', function() | |
{ | |
var arg = null; | |
if (this.dataset.hasOwnProperty('editorValue')) { | |
arg = this.dataset.editorValue; | |
} else if (this.dataset.hasOwnProperty('prompt')) { | |
arg = prompt(this.dataset.prompt.toString()); | |
} else if (this.dataset.hasOwnProperty('selectionTo')) { | |
var createdEl = document.createElement(this.dataset.selectionTo); | |
createdEl.textContent = getSelection().toString(); | |
arg = createdEl.outerHTML; | |
} | |
document.execCommand(this.dataset.editorCommand, null, arg); | |
}); | |
}); | |
menu.querySelectorAll('menuitem[label="Add Class"]').forEach(function(menuitem) { | |
menuitem.addEventListener('click', function() { | |
var addClass = prompt('Enter class name to add'); | |
if (addClass.length !== 0) { | |
getSelection().anchorNode.parentElement.classList.add(addClass); | |
} | |
}); | |
}); | |
menu.querySelectorAll('menuitem[label="Remove Class"]').forEach(function(menuitem) { | |
menuitem.addEventListener('click', function() { | |
var removeClass = prompt('Enter class name to remove'); | |
if (removeClass.length !== 0) { | |
var el = getSelection().anchorNode.parentElement; | |
el.classList.remove(removeClass); | |
if (el.classList.length === 0) { | |
el.removeAttribute('class'); | |
} | |
} | |
}); | |
}); | |
menu.querySelectorAll('menuitem[label="Set Attribute"]').forEach(function(menuitem) { | |
menuitem.addEventListener('click', function() { | |
var name = prompt('Enter attribute name'); | |
if (name.length !== 0) { | |
var value = prompt('Enter attribute value'); | |
getSelection().anchorNode.parentElement.setAttribute(name, value.toString()); | |
} | |
}) | |
}); | |
menu.querySelectorAll('menuitem[label="Remove Attribute"]').forEach(function(menuitem) { | |
menuitem.addEventListener('click', function() { | |
var attr = prompt('Enter name of attribute to remove'); | |
if (attr.length !== 0) { | |
getSelection().anchorNode.parentElement.removeAttribute(attr); | |
} | |
}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment