iTracker Reading App
Lass dir einfach die texte vorlesen.
Lesegeschwindigkeit ist einstellbar
Der hier verwendete Code
<!DOCTYPE html>
<html>
<head>
<title>iTracker Reading App | Remarkable Mark</title>
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" />
<style>
textarea,
.text {
width: 100%;
}
textarea {
font-size: 1em;
font-size: 1.5rem;
height: 18em;
line-height: 1.5;
}
.text {
color: #ddd;
font-size: 1.35em;
font-size: 2rem;
letter-spacing: 0.05px;
line-height: 1.5;
margin-bottom: 8em; /* give some space so reading controls does not cover */
}
.text > .active {
color: #000;
}
.formatted-section {
display: none;
}
/* make controls into a sticky footer */
.reading-controls {
background: #fff;
border-top: 1px solid #eee;
bottom: 0;
left: 0;
padding-top: 1em;
position: fixed;
text-align: center;
width: 100%;
}
/* read button */
.read:hover {
border: 1px solid #33C3F0;
}
/* format button */
.format:hover {
border: 1px solid #33C3F0;
color: #22aeda;
}
/* reformat button */
.reformat {
opacity: 0.5;
}
.reformat:hover {
border: 1px solid #ffaeae;
color: #df5e5e;
opacity: 1;
}
/* disabled buttons */
.button[disabled],
.button[disabeld]:hover {
border: 1px solid #bbb;
opacity: 0.5;
}
</style>
</head>
<body>
<div class="container">
<h1>iTracker Reading App</h1>
<section class="editable-section">
<textarea onclick="this.focus(); this.select();">The artist is the creator of beautiful things. To reveal art and conceal the artist is art's aim. The critic is he who can translate into another manner or a new material his impression of beautiful things.
The highest as the lowest form of criticism is a mode of autobiography. Those who find ugly meanings in beautiful things are corrupt without being charming. This is a fault.
Those who find beautiful meanings in beautiful things are the cultivated. For these there is hope. They are the elect to whom beautiful things mean only beauty.
There is no such thing as a moral or an immoral book. Books are well written, or badly written. That is all.
The nineteenth century dislike of realism is the rage of Caliban seeing his own face in a glass.
The nineteenth century dislike of romanticism is the rage of Caliban not seeing his own face in a glass. The moral life of man forms part of the subject-matter of the artist, but the morality of art consists in the perfect use of an imperfect medium. No artist desires to prove anything. Even things that are true can be proved. No artist has ethical sympathies. An ethical sympathy in an artist is an unpardonable mannerism of style. No artist is ever morbid. The artist can express everything. Thought and language are to the artist instruments of an art. Vice and virtue are to the artist materials for an art. From the point of view of form, the type of all the arts is the art of the musician. From the point of view of feeling, the actor's craft is the type. All art is at once surface and symbol. Those who go beneath the surface do so at their peril. Those who read the symbol do so at their peril. It is the spectator, and not life, that art really mirrors. Diversity of opinion about a work of art shows that the work is new, complex, and vital. When critics disagree, the artist is in accord with himself. We can forgive a man for making a useful thing as long as he does not admire it. The only excuse for making a useless thing is that one admires it intensely.</textarea>
<button class="format">Format</button>
</section>
<section class="formatted-section">
<hr />
<div class="text"></div>
<div class="reading-controls">
<button class="read button">Read</button>
<button class="pause button">Pause</button>
<button class="reset button">Reset</button>
<input class="delay" type="number" value="250" placeholder="Reading Speed" />
<input class="chunk" type="number" value="3" placeholder="Chunk Size" />
<button class="reformat button">Reformat</button>
</div>
</section>
</div>
<script>
// The MIT License (MIT)
// iTracker Reading App | Copyright (c) 2015 Menglin "Mark" Xu | mark@remarkablemark.org
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
(function(){
// Cache all the DOM elements
var textareaNode = document.getElementsByTagName("textarea")[0];
var formatButton = document.getElementsByClassName("format")[0];
var textNode = document.getElementsByClassName("text")[0];
var readButton = document.getElementsByClassName("read")[0];
var pauseButton = document.getElementsByClassName("pause")[0];
var resetButton = document.getElementsByClassName("reset")[0];
var editableSection = document.getElementsByClassName("editable-section")[0];
var formattedSection = document.getElementsByClassName("formatted-section")[0];
var reformatButton = document.getElementsByClassName("reformat")[0];
// Splits text based on pattern
function splitText(text, pattern) {
// Do not continue if text is invalid
if (typeof text !== "string" && text) {
return [];
}
// Split text based on pattern
var splitText = text.split(pattern);
// Return array if no instance of pattern was found
if (splitText.length === 1) {
return splitText;
}
// Clean if at least one instance of pattern was found
for (var i = splitText.length - 1; i > -1; i--) {
// Remove empty arrays
if (!splitText[i]) {
splitText.splice(i, 1);
}
}
return splitText;
}
// Formats the text in the textarea when button is clicked
formatButton.onclick = function() {
var raw, paragraphs, words, output = [], i, j, n = 0;
// Extract raw text from textarea
raw = textareaNode.value;
paragraphs = splitText(raw, "\n");
// Iterate over the paragraphs
for (i = 0; i < paragraphs.length; i++) {
output[i] = [];
words = splitText(paragraphs[i], " ");
// Iterate over the words
for (j = 0; j < words.length; j++) {
output[i][j] = "<span class=" + n + ">" + words[j] + "</span>";
n++;
}
// Join the words array
output[i] = output[i].join(" ");
}
// Join the paragraphs array
textNode.innerHTML = output.join("<br /><br />");
// Show formatted section and hide editable section
formattedSection.style.display = "block";
editableSection.style.display = "none";
return;
};
// Declare and initialize globals
var spanNodes = [], index = 0, operation;
// Executes the reading app's main operation
readButton.onclick = function() {
// Disable read button and enable pause button
readButton.disabled = true;
pauseButton.disabled = false;
// Cache input values
var delay = Number(document.getElementsByClassName("delay")[0].value);
var chunk = Number(document.getElementsByClassName("chunk")[0].value);
spanNodes = textNode.getElementsByTagName("span");
// Clear any highlighted words before the current index
for (var i = 0; i < index - chunk; i++) {
spanNodes[i].className = "";
}
operation = setInterval(function() {
// Ensure the unhighlighted words are within range
for (var i = 0; i < chunk; i++) {
if (index - i - 1 >= 0) {
spanNodes[index - i - 1].className = "";
}
}
// Ensure the highlighted words are within range
for (var i = 0; i < chunk; i++) {
if (index + i < spanNodes.length) {
spanNodes[index + i].className = "active";
}
// If beyond scope, clear the timed interval operation
else {
clearInterval(operation);
}
}
index += chunk;
return;
}, delay);
return;
};
// Pauses the reading app
pauseButton.onclick = function() {
// Disable pause button and enable read button
readButton.disabled = false;
pauseButton.disabled = true;
clearInterval(operation);
return;
};
// Resets the reading app
resetButton.onclick = function() {
// Enable both read button and pause button
readButton.disabled = false;
pauseButton.disabled = false;
// Clear any operation
clearInterval(operation);
if (typeof spanNodes === "object") {
for (var i = 0; i < spanNodes.length; i++) {
spanNodes[i].className = "";
}
}
index = 0;
return;
};
// Allow the text to be editable again
reformatButton.onclick = function() {
// Show editable section and hide formatted section
editableSection.style.display = "block";
formattedSection.style.display = "none";
return;
};
})();
</script>
</body>
</html>