Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomhodgins/c9fda3535c19802186b8 to your computer and use it in GitHub Desktop.
Save tomhodgins/c9fda3535c19802186b8 to your computer and use it in GitHub Desktop.
Parse-powered web page with editor
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title id="site_title"></title>
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, minimal-ui">
<link href="style.css" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=PT+Serif:400,700,400italic,700italic" rel="stylesheet" type="text/css">
<link href="//code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css">
<style>
* {
box-sizing: border-box;
-moz-box-sizing: border-box;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-kerning: auto;
}
html {
-webkit-text-size-adjust: 100%;
background: #eee;
font-size: 10pt;
font-weight: 400;
}
body {
margin: 0;
font-family: 'Open Sans', 'Source Sans Pro', Roboto, 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', 'Myriad Pro', 'Segoe UI', Myriad, Helvetica, 'Lucida Grande', 'DejaVu Sans Condensed', 'Liberation Sans', 'Nimbus Sans L', Tahoma, Geneva, Arial, sans-serif;
}
main,
header,
footer {
width: 100%;
max-width: 900px;
background: #fff;
margin: 0 auto;
}
footer a {
color: #666;
text-decoration: none;
}
footer a:hover {
color: #f60;
}
/* Content Styles */
#template {
padding: 2em;
position: relative;
}
#template #header #brand_name {
font-size: 200%;
color: #000;
font-weight: 900;
text-decoration: none;
display: inline-block;
padding: .5em;
line-height: 1;
background: #fc0;
position: absolute;
top: 0;
left: 0;
transition: background .1s ease-in-out;
}
#template #header #brand_name:hover {
background: #f60;
}
#template #headline {
text-align: center;
font-size: 200%;
font-family: 'PT Serif', Cambria, 'Hoefler Text', Utopia, 'Liberation Serif', 'Nimbus Roman No9 L Regular', Times, 'Times New Roman', serif;
color: #300;
margin: 2em 0 .5em 0;
line-height: 1;
}
#template #content {
font-size: 125%;
line-height: 1.4;
color: #333;
display: block;
margin: 0;
}
#template #content p {
margin: 0 0 .5em 0;
}
#template #content,
#template #content * {
font-family: 'PT Serif', Cambria, 'Hoefler Text', Utopia, 'Liberation Serif', 'Nimbus Roman No9 L Regular', Times, 'Times New Roman', serif;
}
#template footer {
text-align: center;
}
/* Editor Styles */
#login,
#editor {
display: block;
position: fixed;
width: 100%;
height: 100%;
background: #fafafa;
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZhZmFmYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlYWVhZWEiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
background: -moz-linear-gradient(top, #fafafa 0%, #eaeaea 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fafafa), color-stop(100%,#eaeaea));
background: -webkit-linear-gradient(top, #fafafa 0%,#eaeaea 100%);
background: -o-linear-gradient(top, #fafafa 0%,#eaeaea 100%);
background: -ms-linear-gradient(top, #fafafa 0%,#eaeaea 100%);
background: linear-gradient(to bottom, #fafafa 0%,#eaeaea 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fafafa', endColorstr='#eaeaea',GradientType=0 );
overflow: auto;
}
#login form,
#editor > section {
padding: 1em;
max-width: 700px;
margin: 0;
position: relative;
}
#editor #alert {
overflow: hidden;
display: block;
width: 100%;
height: auto;
max-width: 700px;
max-height: 0;
margin: 0 auto;
transition: max-height .2s ease-in-out;
}
#editor #alert p {
display: block;
background: #99ffaa;
color: #008833;
margin: 0;
padding: 1em;
}
#editor #alert p a {
color: #008833;
font-weight: 600;
}
#login h1,
#editor h1 {
letter-spacing: -.03em;
margin: 0 0 .5em 0;
font-size: 175%;
line-height: 1;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
#editor #preview {
position: absolute;
display: inline-block;
top: 1em;
right: 1.125em;
color: #333;
text-decoration: none;
font-size: 110%;
padding: .125em 0;
outline: none;
}
#editor #preview:hover {
color: #26ba62;
}
#editor section > label {
display: block;
width: 100%;
padding: .5em 0;
color: #333;
font-weight: 700;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
cursor: pointer;
}
#login input ~ input,
#editor section label ~ label,
#editor input[type="submit"] {
margin-top: 1em;
}
#editor input[type="text"],
#editor input[type="url"],
#login input[type="text"],
#login input[type="password"] {
display: block;
width: 100%;
padding: .5em;
color: #333;
appearance: none;
-webkit-appearance: none;
border: 1px solid #999;
border-radius: 2px;
font-size: 120%;
outline: none;
transition: all .2s ease-in-out;
}
#editor input[type="text"]:focus,
#editor input[type="url"]:focus,
#login input[type="text"]:focus,
#login input[type="password"]:focus {
border-color: #26ba62;
box-shadow: rgba(0,200,150,.5) 0 0 10px;
}
#editor input[type="submit"],
#login input[type="submit"] {
box-sizing: border-box;
-moz-box-sizing: border-box;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: block;
width: 100%;
max-width: 350px;
margin-left: auto;
margin-right: auto;
padding: .6em .7em .7em .7em;
-webkit-appearance: none;
appearance: none;
outline: none;
cursor: pointer;
background: #ff8900;
background: -moz-linear-gradient(top, #ff8900 0%, #ff3d00 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ff8900), color-stop(100%,#ff3d00));
background: -webkit-linear-gradient(top, #ff8900 0%,#ff3d00 100%);
background: -o-linear-gradient(top, #ff8900 0%,#ff3d00 100%);
background: -ms-linear-gradient(top, #ff8900 0%,#ff3d00 100%);
background: linear-gradient(to bottom, #ff8900 0%,#ff3d00 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff8900', endColorstr='#ff3d00',GradientType=0 );
font-family: 'Source Sans Pro', 'Myriad Pro', 'Open Sans', Roboto, Myriad, 'Segoe UI', Helvetica, Arial, sans-serif;
font-weight: normal;
font-kerning: auto;
text-decoration: none;
text-align: center;
font-size: 120%;
line-height: 1;
color: #fff;
text-shadow: #e20 1px 1px 0;
border: 1px solid #f60;
border-bottom-color: #e20;
border-radius: 3px;
box-shadow: inset #f20 0 -5px 15px, inset #fc0 0 1px 1px, rgba(0,0,0,.15) 0px 1px 1px;
}
#editor input[type="submit"]:hover,
#editor input[type="submit"]:focus,
#login input[type="submit"]:hover,
#login input[type="submit"]:focus {
background: #fa3;
background: -moz-linear-gradient(top, #fa3 0%, #f30 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fa3), color-stop(100%,##f30));
background: -webkit-linear-gradient(top, #fa3 0%,#f30 100%);
background: -o-linear-gradient(top, #fa3 0%,#f30 100%);
background: -ms-linear-gradient(top, #fa3 0%,#f30 100%);
background: linear-gradient(to bottom, #fa3 0%,#f30 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fa3', endColorstr='#f30',GradientType=0 );
box-shadow: inset #f40 0 -5px 15px, inset #ffd28a 0 1px 1px, rgba(0,0,0,.15) 0px 1px 1px, rgba(255,200,0,.5) 0 0 10px;
}
#editor input[type="submit"]:active,
#login input[type="submit"]:active {
background: #f50;
border: 1px solid #f00;
box-shadow: inset #f40 0 -5px 15px, inset #ffd28a 0 1px 1px;
border-bottom-color: #d10;
}
::-moz-selection {
color: #fff;
text-shadow: #007931 1px 2px 2px;
background-color: #26ba62 !important;
}
::-webkit-selection {
background-color: #26ba62;
}
::selection {
color: #fff;
background-color: #26ba62;
}
@media (min-width: 350px) {
#login form {
max-width: 350px;
margin: 0 auto;
}
}
@media (min-width: 700px) {
#template #headline {
font-size: 350%;
margin: 1em 0 .5em 0;
}
#template {
margin-top: 50px;
}
#login,
#editor {
background:
radial-gradient(black 15%, transparent 16%) 0 0,
radial-gradient(black 15%, transparent 16%) 8px 8px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
background-size:16px 16px;
background-color:#282828;
overflow: auto;
}
#editor #alert p {
margin: 1em auto;
border-radius: 2px;
}
#login form,
#editor > section {
margin: 50px auto;
box-shadow: rgba(0,0,0,.3) 0 15px 50px;
background: #fafafa;
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZhZmFmYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlYWVhZWEiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
background: -moz-linear-gradient(top, #fafafa 0%, #eaeaea 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fafafa), color-stop(100%,#eaeaea));
background: -webkit-linear-gradient(top, #fafafa 0%,#eaeaea 100%);
background: -o-linear-gradient(top, #fafafa 0%,#eaeaea 100%);
background: -ms-linear-gradient(top, #fafafa 0%,#eaeaea 100%);
background: linear-gradient(to bottom, #fafafa 0%,#eaeaea 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fafafa', endColorstr='#eaeaea',GradientType=0 );
border-radius: 2px;
}
}
</style>
</head>
<body>
<section id="login" style="display:none">
<form onsubmit="return false; login()">
<h1>Login</h1>
<input type="text" autocapitalize="off" autocorrect="off" placeholder="username" id="username">
<input type="password" placeholder="password" id="password">
<input type="submit" id="submit" value="Log In" onclick="login()">
</form>
</section>
<main id="template">
<header id="header">
<a href="#" id="brand_name"></a>
</header>
<section id="page">
<h1 id="headline"></h1>
<article id="content"></article>
</section>
<footer id="footer"></footer>
</main>
<section id="editor" style="display:none">
<div id="alert">
<p>Changes saved! Would you like to <a href="/"> view the page?</a></p>
</div>
<section>
<h1>Page Editor</h1>
<a id="preview" href="/"><i class="ion-eye"></i> View Page</a>
<label for="site_title_edit">Site Title</label>
<input id="site_title_edit" type="text">
<label for="brand_name_edit">Brand Name</label>
<input id="brand_name_edit" type="text">
<label for="brand_link_edit">Brand Link</label>
<input id="brand_link_edit" type="url">
<label for="headline_edit">Headline</label>
<input id="headline_edit" type="text">
<label for="content_edit">Content</label>
<textarea id="content_edit"></textarea>
<label for="footer_edit">Footer</label>
<input id="footer_edit" type="text">
<input id="submit" type="submit" value="Save Changes" onclick="saveChanges()">
</section>
</section>
<script src="//tinymce.cachefly.net/4.1/tinymce.min.js"></script>
<script src="//www.parsecdn.com/js/parse-1.3.5.min.js" type="text/javascript"></script>
<script type="text/javascript">
// Log into Parse
Parse.initialize('0NZyLedqRCopy7GOJiBO2XTgI6VoTo1GL4zpruNr', 'pSvUjYUNKC5RRHsfx40nwWU9IfK8mHh7dt2Bm1Wj');
// Populate the page with data from Parse
populatePage();
// Load the template
if (window.location.search === '?edit') {
document.getElementById('template').style.display = 'none';
document.getElementById('login').style.display = 'block';
}
// Login to editor
function login() {
var username = document.getElementById('username').value,
password = document.getElementById('password').value;
Parse.User.logIn(username, password, {
success: function(user) {
document.getElementById('login').style.display = 'none';
document.getElementById('template').style.display = 'none';
populateEditor();
document.getElementById('editor').style.display = 'block';
},
error: function(user, error) {
alert('login failed, try again');
}
})
};
// Poulate Editor with Page content from Parse
function populateEditor() {
var site_title = document.getElementById('site_title_edit'),
brand_name = document.getElementById('brand_name_edit'),
brand_link = document.getElementById('brand_link_edit'),
headline = document.getElementById('headline_edit'),
content = document.getElementById('content_edit'),
footer = document.getElementById('footer_edit');
var Page = Parse.Object.extend('Page'),
query = new Parse.Query(Page);
query.get('w43EYK8njt', {
success: function(page) {
headline.value = page.get('headline');
content.value = page.get('content');
tinymce.init({
selector:'#content_edit',
plugins: 'advlist autolink lists link image media charmap preview hr anchor pagebreak searchreplace wordcount visualchars code visualblocks fullscreen',
menubar: 'edit inset view format tools',
toolbar: 'undo redo | styleselect | bold italic underline | link image media | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | searchreplace | fullscreen code'
});
},
error: function(object, error) {
alert(error + ' ' + object);
}
});
var SiteInfo = Parse.Object.extend('SiteInfo'),
query = new Parse.Query(SiteInfo);
query.get('cp4QNjSC56', {
success: function(info) {
site_title.value = info.get('site_title');
brand_name.value = info.get('brand_name');
brand_link.value = info.get('brand_link');
footer.value = info.get('footer');
},
error: function(object, error) {
alert(error + ' ' + object);
}
})
};
// Save changes to Page content to Parse
function saveChanges() {
var site_title = document.getElementById('site_title_edit'),
brand_name = document.getElementById('brand_name_edit'),
brand_link = document.getElementById('brand_link_edit'),
headline = document.getElementById('headline_edit'),
content = tinyMCE.get('content_edit').getContent(),
footer = document.getElementById('footer_edit');
var Page = Parse.Object.extend('Page'),
query = new Parse.Query(Page);
query.get('w43EYK8njt', {
success: function(page) {
page.save(null, {
success: function() {
page.set('headline', headline.value);
page.set('content', content);
page.save();
}
});
},
error: function(object, error) {
alert(error + ' ' + object);
}
});
var SiteInfo = Parse.Object.extend('SiteInfo'),
query = new Parse.Query(SiteInfo);
query.get('cp4QNjSC56', {
success: function(info) {
info.save(null, {
success: function() {
info.set('site_title', site_title.value);
info.set('brand_name', brand_name.value);
info.set('brand_link', brand_link.value);
info.set('footer', footer.value);
info.save();
}
});
},
error: function(object, error) {
alert(error + ' ' + object);
}
});
document.getElementById('alert').style.maxHeight = '75px';
document.querySelectorAll('#editor > section')[0].style.margin = '0 auto';
window.location.href = '#alert';
};
function populatePage() {
var site_title = document.getElementById('site_title'),
brand_name = document.getElementById('brand_name'),
brand_link = document.getElementById('brand_link'),
headline = document.getElementById('headline'),
content = document.getElementById('content'),
footer = document.getElementById('footer');
var Page = Parse.Object.extend('Page'),
query = new Parse.Query(Page);
query.get('w43EYK8njt', {
success: function(page) {
headline.innerHTML = page.get('headline');
content.innerHTML = page.get('content')
},
error: function(object, error) {
alert(error + ' ' + object);
}
});
var SiteInfo = Parse.Object.extend('SiteInfo'),
query = new Parse.Query(SiteInfo);
query.get('cp4QNjSC56', {
success: function(info) {
site_title.innerHTML = info.get('site_title');
brand_name.innerHTML = info.get('brand_name');
brand_name.href = info.get('brand_link');
footer.innerHTML = info.get('footer');
},
error: function(object, error) {
alert(error + ' ' + object);
}
})
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment