A Pen by Derek Basch on CodePen.
Created
September 18, 2015 13:47
-
-
Save derekbasch/6f860b34cf476378bddb to your computer and use it in GitHub Desktop.
Derek Basch - Word Processor
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
</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> |
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
/** | |
* 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 | |
*/ |
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
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