<!-- Dedicated to God the Father -->
<!-- All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024 -->
<!-- https://github.com/ChristopherTopalian -->
<!-- https://github.com/ChristopherAndrewTopalian -->
<!-- Topalian_JavaScript_Text_Editor_(Online_Version).html -->
<!-- Version 001 - (2024-10-11) -->
<html>
<head>
<title> Topalian JavaScript Text Editor </title>
<style>
/* style001.css */
body
{
background-color: rgb(30, 30, 30);
font-family: Arial;
font-size: 24px;
color: rgb(255, 255, 255);
}
textarea
{
width: 700px;
height: 350px;
margin: 5px;
padding-left: 15px;
padding-right: 15px;
padding-top: 10px;
padding-bottom: 10px;
background-color: rgb(20, 20, 20);
font-family: Arial;
font-size: 24px;
color: rgb(255, 255, 255);
}
hr
{
margin: 0px;
}
button
{
margin: 3px;
padding-left: 8px;
padding-right: 8px;
padding-top: 1px;
padding-bottom: 1px;
background-color: rgb(45, 45, 45);
border: solid 1px rgb(255, 255, 255);
border-radius: 8px;
font-weight: bold;
color: rgb(255, 255, 255);
}
button:hover
{
background-color: rgb(0, 0, 0);
cursor: pointer;
}
button:active
{
color: rgb(255, 0, 255);
}
input:hover
{
cursor: pointer;
}
.textInfoStyle
{
margin : 5px;
padding-left: 10px;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
border : solid 1px rgb(200, 200, 200);
font-family: courier;
font-size: 16px;
font-weight: bold;
}
/* -- */
/* Dedicated to God the Father */
/* All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024 */
/* https://github.com/ChristopherTopalian */
/* https://github.com/ChristopherAndrewTopalian */
</style>
<script>
// shortcuts.js
function ge(whichId)
{
let result = document.getElementById(whichId);
return result;
}
function ce(whichType)
{
let result = document.createElement(whichType);
return result;
}
function ba(whichElement)
{
let result = document.body.append(whichElement);
return result;
}
function ct(whichText)
{
let result = document.createTextNode(whichText);
return result;
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// makeInterface.js
function makeInterface()
{
let mainDiv = ce('div');
mainDiv.id = 'mainDiv';
ba(mainDiv);
//-//
let textInfoContainer = ce('div');
textInfoContainer.id = 'textInfoContainer';
textInfoContainer.style.display = 'flex';
textInfoContainer.style.flexDirection = 'row';
mainDiv.append(textInfoContainer);
//-//
let characterCountText = ce('div');
characterCountText.id = 'characterCountText';
characterCountText.className = 'textInfoStyle';
characterCountText.title = 'Char Count';
characterCountText.textContent = '0 chars';
textInfoContainer.append(characterCountText);
//-//
let wordCountText = ce('div');
wordCountText.id = 'wordCountText';
wordCountText.className = 'textInfoStyle';
wordCountText.title = 'Word Count';
wordCountText.textContent = '0 words';
textInfoContainer.append(wordCountText);
//-//
let newTextFileButton = ce('button');
newTextFileButton.textContent = 'New';
newTextFileButton.onmouseover = function()
{
hoverSound();
};
newTextFileButton.onclick = function()
{
clickSound();
let askFirst = confirm("New File and Clear Text?");
if (askFirst == true)
{
ge('theTextbox').value = '';
ge('characterCountText').textContent = '0 chars';
ge('wordCountText').textContent = '0 words';
}
};
mainDiv.append(newTextFileButton);
//-//
let saveButton = ce('button');
saveButton.textContent = 'Save';
saveButton.onmouseover = function()
{
hoverSound();
};
saveButton.onclick = function()
{
clickSound();
download('theTextbox');
};
mainDiv.append(saveButton);
//-//
let openButton = ce('input');
openButton.type = 'file';
// only accept .txt files
openButton.accept = '.txt, .html, .js, .py, .css, .c, .cpp, .rb, .bat, .md';
// handle file selection
openButton.onchange = function(event)
{
// get the selected file
let file = event.target.files[0];
if (file)
{
let reader = new FileReader();
// when the file is loaded, display content in textarea
reader.onload = function(e)
{
// set file content to the textarea
theTextbox.value = e.target.result;
ge('characterCountText').textContent = getCharCount('theTextbox') + ' chars';
ge('wordCountText').textContent = getWordCount('theTextbox') + ' words';
};
// read the file as text
reader.readAsText(file);
}
};
mainDiv.append(openButton);
//-//
mainDiv.append(ce('hr'));
//-//
let theTextbox = ce('textarea');
theTextbox.id = 'theTextbox';
theTextbox.style.borderRadius = '8px';
theTextbox.onkeyup = function()
{
ge('characterCountText').textContent = getCharCount(theTextbox.id) + ' chars';
ge('wordCountText').textContent = getWordCount(theTextbox.id) + ' words';
};
mainDiv.append(theTextbox);
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// makeTitleOfApp.js
function makeTitleOfApp()
{
// mainDiv
let mainDiv = ce('div');
mainDiv.style.position = 'absolute';
mainDiv.style.right = '20px';
mainDiv.style.top = '2px';
mainDiv.style.zIndex = 1;
ba(mainDiv);
//-//
// titleOfApp
let titleOfApp = ce('a');
titleOfApp.id = 'titleOfApp';
titleOfApp.textContent = 'Topalian JavaScript Text Editor';
titleOfApp.href = 'https://github.com/christophertopalian/';
titleOfApp.target = '_blank';
titleOfApp.style.fontSize = '17px';
titleOfApp.style.fontWeight = 'bold';
titleOfApp.style.textDecoration = 'none';
titleOfApp.style.color = 'gray';
mainDiv.append(titleOfApp);
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// download.js
function download(whichElement)
{
// get data from specified Text Area
let data = ge(whichElement).value;
// create an anchor element
let ourElement = ce("a");
// choose text/plain for .txt .html .js .py
let theType = new Blob([data],
{
type: "text/plain"
});
// creates a temp URL for the object
// the object is a file or a blob
// and assigns it to the href attribute of ourElement
// this allows it to downloaded (accessed)
ourElement.href = window.URL.createObjectURL(theType);
ourElement.download = 'filename.txt';
ourElement.click();
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// sound.js
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function playTone(frequency, duration, waveType, volume, detune, attackTime, releaseTime, panValue)
{
let oscillator = audioCtx.createOscillator();
// 'sine', 'square', 'sawtooth', 'triangle'
oscillator.type = waveType;
oscillator.frequency.setValueAtTime(frequency, audioCtx.currentTime);
oscillator.detune.setValueAtTime(detune, audioCtx.currentTime);
let gainNode = audioCtx.createGain();
let pannerNode = audioCtx.createStereoPanner();
oscillator.connect(gainNode);
gainNode.connect(pannerNode);
pannerNode.connect(audioCtx.destination);
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
// attack
gainNode.gain.linearRampToValueAtTime(volume, audioCtx.currentTime + attackTime);
gainNode.gain.linearRampToValueAtTime(0,
// release
audioCtx.currentTime + duration / 1000 - releaseTime);
pannerNode.pan.setValueAtTime(panValue, audioCtx.currentTime);
oscillator.start();
oscillator.stop(audioCtx.currentTime + duration / 1000);
}
function hoverSound()
{
playTone(
300, // frequency
500, // duration
'sine', // waveType
0.3, // volume
50, // detune
0.2, // attackTime
0.2, // releaseTime
-0.5 // panValue -0.5 is left
);
}
function clickSound()
{
playTone(
400, // frequency
500, // duration
'sine', // waveType
0.3, // volume
50, // detune
0.2, // attackTime
0.2, // releaseTime
-0.5 // panValue -0.5 is left
);
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// getCharCount.js
function getCharCount(whichElement)
{
let data = ge(whichElement).value;
// remove newline characters and spaces from the count
let cleanedData = data.replace(/\n/g, '').replace(/\s/g, '');
// count the length of the cleaned data
let charCount = cleanedData.length;
return charCount;
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// getWordCount.js
function getWordCount(whichElement)
{
let data = ge(whichElement).value;
// remove any leading or trailing whitespace and split the data into words
let wordsArray = data.trim().split(/\s+/);
// count the number of words in the array
let wordCount = wordsArray.length;
return wordCount;
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
// whenLoaded.js
function whenLoaded()
{
makeInterface();
makeTitleOfApp();
}
//--//
// Dedicated to God the Father
// All Rights Reserved Christopher Andrew Topalian Copyright 2000-2024
// https://github.com/ChristopherTopalian
// https://github.com/ChristopherAndrewTopalian
// https://sites.google.com/view/CollegeOfScripting
</script>
</head>
<body onload = 'whenLoaded();'>
</body>
</html>