Skip to content

Instantly share code, notes, and snippets.

@derekbasch
Created September 18, 2015 13:47
Show Gist options
  • Save derekbasch/6f860b34cf476378bddb to your computer and use it in GitHub Desktop.
Save derekbasch/6f860b34cf476378bddb to your computer and use it in GitHub Desktop.
Derek Basch - Word Processor
</head>
<body>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Word Processor</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="main">
<div class="left">
<h2>Input</h2>
<textarea id="textTextArea" rows="5" cols="60">Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river named Duden flows by their place and supplies it with the necessary regelialia.</textarea>
<h4>Paragraph</h4>
<div class="holder">
<button onClick="paragraphSentencesButtonOnClick()">Show sentences</button>
</div>
<div class="holder">
<button onClick="paragraphSentencesReversedButtonOnClick()">Show sentences reversed</button>
</div>
<div class="holder">
<button onClick="paragraphWordsButtonOnClick()">Show words</button>
</div>
<div class="holder">
<button onClick="paragraphWordsReversedButtonOnClick()">Show words reversed</button>
</div>
<div class="holder">
<button onClick="paragraphWordsBeginningWithCountButtonOnClick()">Show count of words beginning:</button>
<input id="paragraphWordsBeginningWithInput" type="text" placeHolder="A-Z..."></input>
</div>
<div class="holder">
<button onClick="paragraphWordsSortedByButtonOnClick()">Show words sorted by:</button>
<select id="paragraphWordsSortedBySelect">
<option value="wordLength">Word length</option>
<option value="alphabetization">Alphabetization</option>
<option value="reverseAlphabetization">Reverse alphabetization</option>
</select>
</div>
<div class="holder">
<button onClick="paragraphConvertToPigLatinButtonOnClick()">Show paragraph in Pig Latin</button>
</div>
<h4>Sentence</h4>
<div class="holder">
<label for="sentenceIndexInput">Sentence index:</label>
<input id="sentenceIndexInput" type="text" size="2" placeHolder="0-9..."></input>
</div>
<div class="holder">
<button onClick="sentenceWordsButtonOnClick()">Show words</button>
</div>
<div class="holder">
<button onClick="sentenceWordsReversedButtonOnClick()">Show words reversed</button>
</div>
<div class="holder">
<button onClick="sentenceWordsBeginningWithCountButtonOnClick()">Show count of words beginning:</button>
<input id="sentenceWordsBeginningWithInput" type="text" placeHolder="A-Z..."></input>
</div>
<div class="holder">
<button onClick="sentenceWordsSortedByButtonOnClick()">Show words sorted by:</button>
<select id="sentenceWordsSortedBySelect">
<option value="wordLength">Word length</option>
<option value="alphabetization">Alphabetization</option>
<option value="reverseAlphabetization">Reverse alphabetization</option>
</select>
</div>
</div>
<div class="right">
<h2>Output</h2>
<ul id="outputList">
<li></li>
</ul>
</div>
</div>
</body>
</html>
/**
* VIEW MODEL
*/
/**
* Handle the paragraphSentencesButtonOnClick view action.
* Deconstruced read/process/write one-liner:
* var inputObj = inputRead();
* var processor = wordProcessor(inputObj.text);
* var dataArray = processor.getSentences();
* outputRender(dataArray);
*/
function paragraphSentencesButtonOnClick() {
outputRender(wordProcessor(inputRead().text).getSentences());
}
/**
* Handle the paragraphSentencesReversedButtonOnClick view action.
*/
function paragraphSentencesReversedButtonOnClick() {
outputRender(wordProcessor(inputRead().text).getReversedSentences());
}
/**
* Handle the paragraphWordsButtonOnClick view action.
*/
function paragraphWordsButtonOnClick() {
outputRender(wordProcessor(inputRead().text).getWords());
}
/**
* Handle the paragraphWordsReversedButtonOnClick view action.
*/
function paragraphWordsReversedButtonOnClick() {
outputRender(wordProcessor(inputRead().text).getReverseWords());
}
/**
* Handle the paragraphWordsBeginningWithCountButtonOnClick view action.
*/
function paragraphWordsBeginningWithCountButtonOnClick() {
var inputObj = inputRead();
outputRender([wordProcessor(inputObj.text).countWordsBeginningWith(inputObj.paragraphWordsBeginningWith)]);
}
/**
* Handle the paragraphWordsSortedByButtonOnClick view action.
*/
function paragraphWordsSortedByButtonOnClick() {
var inputObj = inputRead();
outputRender(wordProcessor(inputObj.text).wordsSorted(inputObj.paragraphWordsSortedBy));
}
/**
* Handle the paragraphConvertToPigLatinButtonOnClick view action.
*/
function paragraphConvertToPigLatinButtonOnClick() {
var inputObj = inputRead();
outputRender([wordProcessor(inputObj.text).convertParagraphToPigLatin()]);
}
/**
* Handle the sentenceWordsButtonOnClick view action.
*/
function sentenceWordsButtonOnClick() {
var inputObj = inputRead();
// validate input
if (!inputObj.sentenceIndex || isNaN(inputObj.sentenceIndex)) {
alert("Sentence index must be a number.");
return null;
}
outputRender(wordProcessor(inputObj.text).getWords(inputObj.sentenceIndex));
}
/**
* Handle the sentenceWordsReversedButtonOnClick view action.
*/
function sentenceWordsReversedButtonOnClick() {
var inputObj = inputRead();
// validate input
if (!inputObj.sentenceIndex || isNaN(inputObj.sentenceIndex)) {
alert("Sentence index must be a number.");
return null;
}
outputRender(wordProcessor(inputObj.text).getReverseWords(inputObj.sentenceIndex));
}
/**
* Handle the sentenceWordsBeginningWithCountButtonOnClick view action.
*/
function sentenceWordsBeginningWithCountButtonOnClick() {
var inputObj = inputRead();
// validate input
if (!inputObj.sentenceIndex || isNaN(inputObj.sentenceIndex)) {
alert("Sentence index must be a number.");
return null;
}
outputRender([wordProcessor(inputObj.text).countWordsBeginningWith(inputObj.sentenceWordsBeginningWith, inputObj.sentenceIndex)]);
}
/**
* Handle the sentenceWordsSortedByButtonOnClick view action.
*/
function sentenceWordsSortedByButtonOnClick() {
var inputObj = inputRead();
// validate input
if (!inputObj.sentenceIndex || isNaN(inputObj.sentenceIndex)) {
alert("Sentence index must be a number.");
return null;
}
outputRender(wordProcessor(inputObj.text).wordsSorted(inputObj.sentenceWordsSortedBy, inputObj.sentenceIndex));
}
/**
* Read view data.
* @returns object
*/
function inputRead() {
return {
text: document.getElementById("textTextArea").value,
sentenceIndex: sentenceIndex = document.getElementById("sentenceIndexInput").value,
paragraphWordsBeginningWith: document.getElementById("paragraphWordsBeginningWithInput").value,
paragraphWordsSortedBy: document.getElementById("paragraphWordsSortedBySelect").options[paragraphWordsSortedBySelect.selectedIndex].value,
sentenceWordsBeginningWith: document.getElementById("sentenceWordsBeginningWithInput").value,
sentenceWordsSortedBy: document.getElementById("sentenceWordsSortedBySelect").options[sentenceWordsSortedBySelect.selectedIndex].value
};
}
/**
* Handle render output view action.
* @param array data
*/
function outputRender(data) {
var outputList = document.getElementById("outputList");
// clear output list
while (outputList.firstChild) {
outputList.removeChild(outputList.firstChild);
}
// populate output list
for (var i = 0; i < data.length; i++) {
var node = document.createElement("LI");
var textnode = document.createTextNode(data[i]);
node.appendChild(textnode);
outputList.appendChild(node);
}
}
/**
* BUSINESS LOGIC
*/
/**
* Process a string of text in various ways.
* Not using prototype for private/public properties.
* Pseudo private/public properties.
* @param string initialData
* @returns object _public
*/
var wordProcessor = function(initialData) {
// the object to return
var _public = {};
// an object to hold private data
var _private = {
initialData: initialData
};
/**
* Split input data into sentences.
* @returns array
*/
_public.getSentences = function() {
return _private.initialData.match(/\(?[^\.\?\!]+[\.!\?]\)?/g);
}
/**
* Split input data into sentences.
* Reverse the sort order.
* @returns array
*/
_public.getReversedSentences = function() {
return _public.getSentences().reverse();
}
/**
* Split input data into words.
* Optionally, perform split on only selected sentence.
* @param number [sentenceIndex]
* @returns array
*/
_public.getWords = function(sentenceIndex) {
var text = '';
// validate input
if (typeof sentenceIndex !== 'undefined') {
if (isNaN(sentenceIndex)) {
alert("Sentence index must be a number.");
return null;
}
}
if (!isNaN(sentenceIndex)) {
text = _public.getSentences()[sentenceIndex];
} else {
text = _private.initialData;
}
return text.match(/[\w\d]+/gi);
}
/**
* Split input data into words.
* Optionally, perform split on only selected sentence.
* Reverse the sort order.
* @param number [sentenceIndex]
* @returns array
*/
_public.getReverseWords = function(sentenceIndex) {
return _public.getWords(sentenceIndex).reverse();
}
/**
* Count the words that begin with a certain string
* Optionally, perform count on only selected sentence.
* @param string [needle]
* @param number [sentenceIndex]
* @returns number
*/
_public.countWordsBeginningWith = function(needle, sentenceIndex) {
var words = _public.getWords(sentenceIndex);
var count = 0;
// input validate
if (typeof needle !== 'undefined' && typeof needle !== 'string') {
alert("Search needle must be a string.");
return null;
}
if (typeof sentenceIndex !== 'undefined') {
if (isNaN(sentenceIndex)) {
alert("Sentence index must be a numberaaaa.");
return null;
}
}
for (var i = 0; i < words.length; i++) {
if (words[i].substring(0, needle.length) === needle) {
count++;
};
}
return count;
}
/**
* Sort words
* @param string [sortMethod]
* @param number [sentenceIndex]
* @returns array
*/
_public.wordsSorted = function(sortMethod, sentenceIndex) {
var words = _public.getWords(sentenceIndex);
// input validate
if (typeof sortMethod !== 'undefined' && typeof sortMethod !== 'string') {
alert("Sort method must be a string.");
return null;
}
if (typeof sentenceIndex !== 'undefined') {
if (isNaN(sentenceIndex)) {
alert("Sentence index must be a number.");
return null;
}
}
switch (sortMethod) {
case "wordLength":
words.sort(
function(a, b) {
return b.length - a.length;
}
);
break;
case "alphabetization":
words.sort(function(a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
break;
case "reverseAlphabetization":
words.sort(function(a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
words.reverse();
break;
}
return words;
}
/**
* Convert a word to Pig Latin
* @param string word
* @returns string
*/
_public.convertWordToPigLatin = function(word) {
var isCapitalized = false;
var firstVowelPosition = word.length;
var vowels = new Array("a", "e", "i", "o", "u");
// validate input
if (typeof word === 'undefined' || typeof word !== 'string') {
alert("Word to convert to Pig Latin must be a string.");
return null;
}
for (v in vowels) {
l = vowels[v]
if (word.indexOf(l) < firstVowelPosition && word.indexOf(l) != -1) {
firstVowelPosition = word.indexOf(l);
}
}
if (/^[A-Z]/.test(word)) {
isCapitalized = true;
}
if (firstVowelPosition == 0) {
word = word.substring(firstVowelPosition, word.length) +
word.substring(0, firstVowelPosition) +
"yay";
} else {
word = word.substring(firstVowelPosition, word.length) +
word.substring(0, firstVowelPosition) +
"ay";
}
if (isCapitalized) {
word = word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
return word;
}
/**
* Convert a paragraph to Pig Latin
* @param string paragraph
* @returns string
*/
_public.convertParagraphToPigLatin = function() {
var punctuation = "";
var words, pigLatinWords, convertedSentences = [];
var sentences = _public.getSentences();
for (var i = 0; i < sentences.length; i++) {
punctuation = sentences[i].substr(sentences[i].length - 1);
words = _public.getWords(i);
pigLatinWords = words.map(_public.convertWordToPigLatin).join(' ');
convertedSentences.push(pigLatinWords += punctuation);
}
return convertedSentences.join(" ");
}
/**
* Input validator.
* @returns boolean valid
*/
_private.inputValidate = function() {
if (typeof _private.initialData === 'undefined' || typeof _private.initialData !== 'string') {
alert("Word processor input must be a string.");
return false;
}
return true;
}
// validate input
if (!_private.inputValidate()) {
return null;
} else {
return _public;
};
}
/*
TODO: Improve error handling and reporting
TODO: Create unit tests for business logic
TODO: Improve input validation
TODO: Improve encapsulation of properties for business logic
*/
html, body{
min-height: 100%;
height: 100%;
}
body {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
.main{
width: 100%;
margin: 0 auto;
height: 100%;
}
.left{
width: 48%;
float: left;
margin: 0 2% 0 0;
}
.right{
width: 48%;
float: right;
margin: 0 0 0 2%;
height: 100%;
background-color: #eee;
position: fixed;
top: 0;
right: 0;
overflow-y: auto;
}
h3{
display: block;
}
textarea{
padding: 20px;
line-height: 24px;
font-size: 16px;
border-radius: 3px;
border-color: #cccccc;
width: 98%;
font-family: Arial, Helvetica, sans-serif;
}
.holder{
display: inline-block;
width: 100%;
margin-bottom: 10px;
vertical-align: middle;
}
button{
float: left;
width: 260px;
border: none;
background-color: #4BC6BA;
color: #fff;
padding: 5px 0;
border-radius: 3px;
height: 40px;
font-size: 14px;
margin-right: 10px;
cursor: pointer;
}
input{
float: left;
width: 40%;
margin: 0px;
border: 1px solid #cccccc;
height: 36px;
border-radius: 3px;
}
select{
float: left;
width: 40%;
margin: 0px;
border: 1px solid #cccccc;
height: 40px;
border-radius: 3px;
}
label{
text-align: right;
width: 260px;
display: inline-block;
padding-top: 12px;
padding-right: 10px;
float: left;
}
.right ul{
text-align: left;
font-size: 16px;
line-height: 24px;
}
.right h2{
margin-top: 27px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment