Skip to content

Instantly share code, notes, and snippets.

@hungrymedia
Created August 5, 2010 12:12
Show Gist options
  • Save hungrymedia/509634 to your computer and use it in GitHub Desktop.
Save hungrymedia/509634 to your computer and use it in GitHub Desktop.
<?php
// Simple tool to create customizable letter/web page.
// Think mail-merge or mad libs
// Requires a web server-writable directory called data in the same directory is this file
ob_start();
if( !empty( $_POST['cmd'] ) ){
// use name field to save data
$xmlData = new SimpleXMLElement('<data/>');
foreach( $_POST as $field => $val ){
if( strstr( $field, 'data-' ) ){
$xmlData->addChild( $field, htmlspecialchars( $val ) );
if( $field == 'data-name' ){
// make saveAs filename safe
$saveAsName = makeFilenameSafe( $val );
}
}
}
$saveAsPath = 'data/' . $saveAsName . '.xml';
if( file_exists( $saveAsPath ) ){
$appender = time();
$saveAsPath = str_replace( '.xml', '.' . $appender . '.xml', $saveAsPath );
$saveAsName .= "." . $appender;
}
$scriptPath = explode( '/', $_SERVER['PHP_SELF'] );
array_pop( $scriptPath );
$viewURL = 'http://' . $_SERVER['HTTP_HOST'] . implode( '/', $scriptPath ) ."?$saveAsName";
$xmlData->asXML( $saveAsPath );
echo $viewURL;
exit();
}
function makeFilenameSafe( $str ){
$safeChars = str_split( '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-' );
$cleaned = str_replace( ' ', '-', $str );
$buffer = '';
foreach( str_split( $cleaned ) as $char ){
if( in_array( $char, $safeChars ) ){
$buffer .= $char;
}
}
return $buffer;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>jQuery-driven Letter Making Thingy</title>
<style>
body{
font-family: Arial, Helvetica, sans-serif;
font-size: small;
position: relative;
margin: 0;
padding: 0;
height: 100%;
}
a{
color: #646464;
text-decoration: underline;
}
a:hover{
background: #FED100;
text-decoration: none;
}
#content{
padding: 75px 30px 0 30px;
width: 900px;
}
#footer{
border-top: 1px solid #CCC;
margin-top: 200px;
padding: 10px 30px 0 30px;
font-size: 0.8em;
color: #646464;
width: 900px;
}
.tag{
background: #FF0;
cursor: pointer;
}
#letter{
display: none;
}
h1, h2, h3{
font-weight: normal;
}
#input-form{
position: absolute;
background: #FF9;
padding: 50px;
font-size: xx-large;
border: 1px solid #999;
display: none;
border: 1px solid #FFF;
}
input{
font-size: xx-large;
}
#message{
position: absolute;
width: 100%;
font-size: xx-large;
padding: 1em;
background: #FF9;
display: none;
top: 0;
text-align: center;
}
#overlay{
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.7);
display: none;
position: absolute;
top: 0;
left: 0;
}
#help{
background: #FFC;
padding: 30px 20px 20px 20px;
position: absolute;
top: -10px;
right: 0;
border-radius: 10px;
-moz-border-radius: 10px;
border: 2px solid #CCC;
display: none;
}
#btnSaveLetter{
display: none;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
var formData = new Array();
$(document).ready( function(){
$('body').height( $(window).height() );
// check for passed name
var urlParts = window.location.toString().split('?');
if( urlParts.length == 2 ){
var dataFile = 'data/' + urlParts[1] + '.xml';
$.ajax({
url: dataFile,
dataType: 'xml',
success: function( data ){
$( data ).find('data').children().each( function(){
var tagName = this.tagName.replace( 'data-', '' );
$('#' + tagName).html( $(this).text().replace( '\\', '' ) ).removeClass('tag');
});
$('#letter').show();
}
});
}else{
$('#letter').show();
$('#btnSaveLetter').show();
$('#help').show();
}
$('.tag').live( 'click', function(){
var popupTop = $(window).height() / 2 - $('#input-form').height(); var popupLeft = $(window).width() / 2 - $('#input-form').width() / 2;
$('#overlay').show();
$('#input-form').css({ 'top' : popupTop + 'px', 'left' : popupLeft + 'px' }).show();
$('#input-form #text-entry').attr( 'dataField', $(this).attr('id') );
$('#input-form #text-entry').val( $(this).html() ).focus().select();
$('#input-form label').html( $(this).attr('id') );
});
// close the popup if user clicks outside the popup window
$('#overlay').click( function(){
$(this).hide();
$('#input-form').hide();
});
$('#btnSave').click( function(){
if( $('#input-form #text-entry').val() != '' ){ var dataField = $('#input-form #text-entry').attr('dataField');
if( $('#data-' + dataField).length < 1 ){
$('#form-data form').append( '<input type="hidden" name="data-' + dataField + '" id="data-' + dataFi
eld + '" value="' + $('#input-form #text-entry').val() + '" />' );
}else{
$('#data-' + dataField).val( $('#input-form #text-entry').val() );
}
$('#' + dataField).html( $('#input-form #text-entry').val() );
$('#input-form').hide();
$('#overlay').hide();
}
});
$('#btnSaveLetter').click( function(){
$.ajax({
type: 'POST',
url: 'index.php', data: $('#form-data form').serialize() + '&cmd=save',
success: function( data ){
$('#message').html( 'Letter saved to the following address:<br /><a target="_blank" href="' + data +
'">' + data + '</a>' ).slideDown(100);
}
});
});
});
</script>
</head>
<body>
<div id="help">
<h2>Help</h2>
<p>Click each of the highlighted pieces of text to customize the letter.<br />
When finished, click the &ldquo;Save Letter&rdquo; button.</p>
</div>
<div id="content">
<div id="letter">
<h1>Hello there <span class="tag" id="name">recipient name</span>!</h1>
<p>Please stop on by our offices on <span class="tag" id="date">insert date</span> at <span class="tag" id="time">insert time</span> to chat about the <span class="tag" id="position">insert position</span> role with our <span class="tag" id="department">insert department</span>.</p>
<p>You may ask for <span class="tag" id="interviewer">insert name</span> upon your arrival.</p>
<p>Note how the dynamic pieces of text are simply wrapped with a &lt;span&gt; tag with a class of "tag". The ID assigned to any such fields is used as the input form label in the popup, as well as to save the XML data to the server</p>
<p>Here is some additional text just to fill out this dummy letter. The idea of this simple app is to allow a non-technical person to generate customized letters that will have their own unique URL. It's kind of a very simple wiki or mad-libs. While the value of such an app may be minimal, it was a lot of fun to create and allowed me to show off some jQuery goodness. There is a little PHP under the hood to save the data files associated with each customized letter.</p>
<p>Feel free to view-source or download below and use whatever you find useful from this page.</p>
<p>Download a <a href="hmLetterMaker.zip">zipped copy</a> of this single-file solution here to see how very simple it is.</p>
<input type="button" id="btnSaveLetter" value="Save Letter" />
</div>
</div>
<div id="footer">
&copy; <?php echo date( 'Y', time() ); ?>, <a href="http://hungry-media.com">Hungry Media/Warren Harrison</a>. Some rights reserved. Feel free to view-source and copy the code if you find it useful. Just give me a little credit, cool?
</div>
<div id="overlay"></div>
<div id="input-form-container">
<div id="input-form">
<label for="text-entry">Input Label</label><br />
<input type="text" id="text-entry" /><br />
<input type="button" id="btnSave" value="Save" />
</div>
</div>
<div id="form-data"><form></form></div>
<div id="message"></div>
</body>
</html>
<?php ob_end_flush(); ?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment