How can I cloze some text in an HTML document? Some marked text is hidden, replaced with an underline of exactly the same length as the original text and all of the words in the sentence should appear in precisely the same places they would appear had there not been a cloze. E.g.:
Once upon a time there ______ a cat.
The word to be clozed might be marked like this:
Once upon a time there <div class="cloze">lived</div> a cat.
Is there some way to hide the text and create an underline of exactly the same length?
Use some CSS:
.clozed {
border-bottom:1px solid black;
color:transparent;
}
This is <span class=clozed>text</span>.
Fiddle
Adding to #HoboSapiens answer (sorry, I can't comment due to score), you may also want to use the ::selection selector to ensure users can't drag across the area to uncover the text.
http://jsfiddle.net/Delorian/mm8tp1xb/
.clozed::selection {
color: transparent;
}
Note that users will always be able to see the text in the source, so if you want something more effective, you will need to use JavaScript on the client or server-side script to replace the text. However you will lose the benefit of having the underline at an accurate width.
You should do it via PHP, because if user would look into source code, he'll see the original text.
But if you need it in JS, you can implement it like this:
var spans = document.querySelectorAll('.clozed');
var words = [];
function repeat (str, count) {
var text = '';
var i;
for (i = 0; i < count; i++) {
text += str;
}
return text;
}
var i, c = spans.length;
for (i = 0; i < c; i++) {
var span = spans[i];
var text = span.innerText = span.textContent;
words.push(text);
span.innerText = span.textContent = repeat('_', text.length);
}
http://jsfiddle.net/0e7hw2a9/
Note: you may use words array to validate the input later.
Update: undo function: http://jsfiddle.net/0e7hw2a9/2/
Related
We are currently learning how to use the DOM and some javascript commands to make dynamic websites. My main and only problem so far is that my CSS won't apply to the HTML I have added to my <p> tag with the id="paragraph":
1.What am i doing wrong?
2.What can i do differently?
3.What can help clean up my code?
function Music() {
var string = document.getElementById('text').value.match( /[^\.!\?]+
[\.!\?]+/g ); // This searches through our text, puts results into an
array
for (var i = 0; i < string.length; i++) { // This goes through our "string array"
var space = string[i].match(/\s/g ); // Counts the amount of
spaces in each string.
var wrapEl = document.createElement("span"); // Create a span tag
wrapEl.innerHTML = string[i]; // place strings into span tag
// This clears the paragraph element and refills it with the new text output.
if (string.length > 0) {
document.getElementById("paragraph").innerHTML = "You didn't
write anything!";
} else {
console.log("You Didn't write anything!");
}
switch (space.length) {
case space <=2: //Tiny (0-2 words) - Yellow Highlight
span.addClass("style1");
break;
case space <=5: //Short (3-5 words) - Red Highlight
span.addClass("style2");
break;
case space <=14: //Medium (6-14 words) - Green Highlight
wrapEl.addClass("style3");
break;
case space >15: //Long (15+ words) - Blue Highlight
wrapEl.addClass("style4");
break;}
var paragraph = document.getElementById("paragraph");
paragraph.appendChild(wrapEl); // append span tag to paragraph tag via id
}
}
!!!For reference, Im using a tag in my HTML as the place to type your text. And i put all my CSS classes in the with the tag.!!!
You are currently trying to add a class to the DOM elements using .addClass(). This is actually a jQuery method, not vanilla JavaScript. I would rather suggest you add a class using classList.add().
Note: classList is not supported in Internet Explorer 9 and below. If you need to support older versions of IE, go with className += "style1" as described in this answer
You also have a few instances of span.addClass("style1"). From the code posted in your question, there is no span variable. Should this be wrapEl?
The following should do it:
var wrapEl = document.querySelector('span');
wrapEl.classList.add('style1')
.style1 {
color: red
}
<p>This is unaffected. Should be black.</p>
<span>This has .style1 applied. Should be red</span>
One web page includes 3 different language words such as:
Language / 한국어 / ภาษาไทย
I'd like to enlarge Thai words(ภาษาไทย) in order to highlight it.
<span class="thai">ภาษาไทย</span>
Of course, it's possible if I specifiy 'class' property to all Thai sections, but it's too many to put them all.
If possible, I would like to change font-family & font-size according to unicode range with jquery.
Thank you.
You can use string.replace() to automatically tag every Thai word.
document.body.innerHTML = document.body.innerHTML.replace(
/([\u0E00-\u0E7F]+)/g,
function (x){return '<span class="thai">'+x+'</span>'}
);
See JSFiddle.
Although no JQuery, I would do something like this:
(In the case of Thai characters, they are in the Unicode range: 0E00-0E7F)
function StyleThaiInTag(tagName) {
var allTags = document.getElementsByTagName(tagName);
for (var i = 0; i < allTags.length; i++) {
var element = allTags[i];
var code = element.innerHTML.charCodeAt(0)
if (0x0E00 <= code && code <= 0x0E7F) {
// style element the way you want
element.style.fontSize = "2em";
//...
}
}
}
// example usage:
StyleThaiInTag('span');
StyleThaiInTag('div');
Here's a JSFiddle.
Say I have something like this:
<p>Here are several words in a sentence.</p>
I'm trying to figure out how to display each word, one by one, via keypress or mouseclick, till it reaches the end.
So for example:
Here (click)
Here are (click)
Here are several , etc.
This may be basic, but I'm not very good and I'd love some help!
Thanks!
I just want to make some interventions on #Dean.DePue answer and make the code so you paste it in your project and does the trick:
Your html should look like this:
<div id="adiv"></div>
And you should add this javascript code too:
var index, newsentence, sentence, words;
sentence = "Here are several words in a sentence";
words = sentence.split(" ");
index = 0;
newsentence = "";
$(document).click(function(e) {
if (e.button === 0 && index < words.length) {
newsentence += words[index];
newsentence += " ";
$("#adiv").html(newsentence);
index = index + 1;
}
});
If you've got any doubt of the code just ask!
This has been turned into a jQuery Plugin: word-reveal.
While the other two answers will work (sort of), they aren't very reusable. What happens when you have more than one container you'd like to reveal with more than one sentence? I created a jQuery plugin that can easily be reused throughout the page.
The Setup
Include jQuery on the page
Download the plugin from GitHub, and include it on the page
You're set and ready to go!
The HTML
Set an id for each div or p tag. An example of multiple uses:
<p id="firstRevealer"></p>
<p id="secondRevealer"></p>
<p id="thirdRevealer"></p>
The jQuery
$(document).ready(function() {
$("#firstRevealer").wordReveal({text:"This reveals one word at a time."});
$("#secondRevealer").wordReveal({text:"Adding more text is easy!"});
$("#thirdRevealer").wordReveal({text:"It <b>also</b> works on <em>some</em> tags, since it splits on <b>spaces</b>!"});
});
The CSS
I added CSS on the example, to make clear where you're clicking to reveal the next word. A different answer registered clicks on the document, but any clicks (for a expandable menu, for example) would add a word.
p {
padding: 10px;
margin:10px;
min-height:25px;
background-color:#BADA55
}
The fiddle.
Note
This can easily be extended to act on other events (keypress).
<script type="text/javascript">
var sentence = "Here are several words in a sentence";
var words = sentence.split(" ");
var index = 0;
var newsentence = "";
function clickit() {
newsentence += sentence[index];
index = index + 1;
}
i'm trying to make my own markdown-able textarea like Stackoverflow has done. The goal is to allow people to type **blah blah** in a textarea and have the output in a div be <span style="font-weight:bold;">blah blah</span>.
I'm having trouble with the javascript to find and replace to the **asterisks with the HTML.
here's a jsfiddle which has gotten the party started: http://jsfiddle.net/trpeters1/2LAL4/14/
here's the JS on that just to show you where I'm at:
$(document.body).on('click', 'button', function() {
var val=$('textarea').val();
var bolded=val.replace(/\**[A-z][0-9]**/gi, '<span style="font-weight:bold;">"'+val+'" </span>');
$('div').html(bolded);
});
and the HTML...
<textarea></textarea>
<div></div><button type="button">Markdownify</button>
any thoughts would be greatly appreciated!
thanks,
tim
The other answers fail when a char is immediately before or after the asterisks.
This works like markdown should:
function bold(text){
var bold = /\*\*(.*?)\*\*/gm;
var html = text.replace(bold, '<strong>$1</strong>');
return html;
}
var result = bold('normal**bold**normal **b** n.');
document.getElementById("output").innerHTML = result;
div { color: #aaa; }
strong { color: #000; }
<div id="output"></div>
None of the provided answers works in all cases. For example, the other solutions wont work if we have a space next to the double star, ie:
This will ** not ** be bold
So I wrote this:
function markuptext(text,identifier,htmltag)
{
var array = text.split(identifier);
var previous = "";
var previous_i;
for (i = 0; i < array.length; i++) {
if (i % 2)
{
//odd number
}
else if (i!=0)
{
previous_i = eval(i-1);
array[previous_i] = "<"+htmltag+">"+previous+"</"+htmltag+">";
}
previous = array[i];
}
var newtext = "";
for (i = 0; i < array.length; i++) {
newtext += array[i];
}
return newtext;
}
Just call it like this:
thetext = markuptext(thetext,"**","strong");
and it will work in all cases. Of course, you can also use it with other identifiers/html-tags as you like
(the stackoverflow preview should have this too).
Choose the perfect regex that will fit your needs.
If you don't want styling to span through new line and also using ([^*<\n]+) makes sure at least one character is in between styles or else ** without a character in-between will result will become invisible.
function format_text(text){
return text.replace(/(?:\*)([^*<\n]+)(?:\*)/g, "<strong>$1</strong>")
.replace(/(?:_)([^_<\n]+)(?:_)/g, "<i>$1</i>")
.replace(/(?:~)([^~<\n]+)(?:~)/g, "<s>$1</s>")
.replace(/(?:```)([^```<\n]+)(?:```)/g, "<tt>$1</tt>")
}
•The downside to the above code is that, you can't nest styles i.e *_Bold and italic_*
To allow nested styles use this 👇
format_text(text){
return text.replace(/(?:\*)(?:(?!\s))((?:(?!\*|\n).)+)(?:\*)/g,'<b>$1</b>')
.replace(/(?:_)(?:(?!\s))((?:(?!\n|_).)+)(?:_)/g,'<i>$1</i>')
.replace(/(?:~)(?:(?!\s))((?:(?!\n|~).)+)(?:~)/g,'<s>$1</s>')
.replace(/(?:--)(?:(?!\s))((?:(?!\n|--).)+)(?:--)/g,'<u>$1</u>')
.replace(/(?:```)(?:(?!\s))((?:(?!\n|```).)+)(?:```)/g,'<tt>$1</tt>');
// extra:
// --For underlined text--
// ```Monospace font```
}
👆 If you want your style to span through new line, then remove \n from the regex. Also if your new line is html break tag, you can replace \n with <br>
Thank me later!
Why create from scratch? With so many open source editors out there, you should pick a code base you like & go from there.
http://oscargodson.github.com/EpicEditor/
http://markitup.jaysalvat.com/home/
custom component in react who receives bold like boolean
{(() => {
const splitText = theText.split('**');
return (
<TextByScale>
{splitText.map((text, i) => (
<TextByScale bold={!!(i % 2)}>{text}</TextByScale>
))}
</TextByScale>
);
})()}
If you are using jQuery, replace this:
$(document.body).on('click', 'button', function() {
with this:
$("button").click(function () {
The following regular expression will find your asterisk-wrapped text:
/\x2a\x2a[A-z0-9]+\x2a\x2a/
I updated your fiddle as an example: http://jsfiddle.net/2LAL4/30/
Your regex is broken, for one thing. You probably want something more like:
/\*\*[A-z0-9]+\*\*/gi
The * is a special character in regular expressions. If you want to match against a literal *, then you need to escape it with \.
For instance: http://jsfiddle.net/2LAL4/22/
However, even with this change there's still a fair ways to go before you get to where you really want to be. For instance, your example will not work if the text area contains a mix of bold and non-bold text.
I'm trying to change the name of a link, however, I have some restrictions. The link is placed in code that looks like this:
<li class='time'>
Review Time
<img alt="Styled" src="blah" />
</li>
Basically, I have a class name to work with. I'm not allowed to edit anything in these lines, and I only have a header/footer to write Javascript / CSS in. I'm trying to get Review Time to show up as Time Review, for example.
I know that I can hide it by using .time{ display: hide} in CSS, but I can't figure out a way to replace the text. The text is also a link, as shown. I've tried a variety of replace functions and such in JS, but I'm either doing it wrong, or it doesn't work.
Any help would be appreciated.
You could get the child elements of the li that has the class name you are looking for, and then change the innerHTML of the anchor tags that you find.
For example:
var elements = document.getElementsByClassName("time")[0].getElementsByTagName("a");
for(var i = 0, j = elements.length; i<j; i++){
elements[i].innerHTML = "Time Review";
}
Of course, this assumes that there is one element named "time" on the page. You would also need to be careful about checking for nulls.
Split the words on space, reverse the order, put back together.
var j = $('li.time > a');
var t = j.text();
var a = t.split(' ');
var r = a.reverse();
j.text(r.join(' '));
This could have some nasty consequences in a multilingual situation.
Old school JavaScript:
function replaceLinkText(className, newContents) {
var items = document.getElementsByTagName('LI');
for (var i=0; i<items.length; i++) {
if (items[i].className == className) {
var a = items[i].getElementsByTagName('A');
if (a[0]) a[0].innerHTML = newContents;
}
}
}
replaceLinkText("time", "Review Time");
Note that modern browsers support getElementsByClassName(), which could simplify things a bit.
You can traverse the DOM and modify the Text with the following JavaScript:
var li = document.getElementsByClassName('time');
for (var i = 0; i < li.length; i++) {
li[i].getElementsByTagName('a')[0].innerText = 'new text';
}
Demo: http://jsfiddle.net/KFA58/