How to get a random character from a span - javascript

Hi i have created a span element with a text in a containing 0s and 1s. Is there a way which i can randomly select any character in that span element. I know how to do this by putting each character inside a separate span element but i'm creating this for a background and there will be over 2500 0s and 1s.
Html
<span class="text" id= "text">0001111011110110101100001</span>
JavaScript
var text = document.getElementById('text');
var x = Math.floor(Math.random() * text.length);

This function will return a random character from your span content
let content = document.querySelector('#text').textContent;
function getRandomChar(str){
return str.charAt(Math.floor(Math.random() * str.length));
}
console.log(getRandomChar(content))
<!-- I added another content just for better demonstration -->
<span class="text" id="text">00ABCDEFGHIJK</span>

Related

I need some help using JavaScript to wrap <span> tags around existing content

Hey appreciate any help I can get with this as I'm still learning JavaScript.
I have some HTML that I'm trying to insert specific span tags into. I've found answers that allow you to just replace inner HTML, however the content I'm trying to wrap around is slightly different on each page I'm trying to achieve this for - but the HTML structure is the same.
Here is the current HTML, vs what I would like it to be:
<div class="list-view__count">
<p>
Showing 1 - 18 of 46 results
</p>
</div>
And what I'd like to add in:
<div class="list-view__count" content="nosnippet">
<p>
<span data-nosnippet>Showing 1 - 18 of 46 results</span>
</p>
</div>
I have tried various codes and successfully added the content="nosnippet" section,
document.querySelector(".list-view__count ").setAttribute("content", "nosnippet")
but the tag I can't seem to figure out how it is done yet.
Any help will be appreciated.
Cheers
try something like
var div = document.getElementById('list-view__count');
var x = document.creatElement('span');
var text = document.createTextNode('text here');
x.appendChild(text)
div.appendChild(x)
You can get the text inside the <p> with textContent, save it in a variable, then create a span tag and set the text to the <span> with the same method.
I don't think you can set a data... attribute without a value like that, but functionally it should be the same.
Wrapped it in another div so it's easier to visualize the output.
const div = document.querySelector(".list-view__count");
const p = document.querySelector(".list-view__count>p");
const pText = p.textContent;
const span = document.createElement("span");
div.setAttribute("content", "nosnippet")
p.textContent = '';
span.textContent = pText;
span.setAttribute("data-nosnippet", '')
p.appendChild(span);
console.log(document.querySelector(".wrap").outerHTML)
<div class="wrap">
<div class="list-view__count">
<p>
Showing 1 - 18 of 46 results
</p>
</div>
</div>
You can select the p element that is the immediate child of your div, pick up its innerHTML (I did this just in case it had some HTML mark up in it so that is preserved), clear the innerHTML of the p element then append a span element which has the data- attribute set and the innerHTML copied from the original p.
const p = document.querySelector('.list-view__count > p');
const pInner = p.innerHTML;
p.innerHTML = '';
const span = document.createElement('span');
span.innerHTML = pInner;
span.setAttribute('data-nosnippet', '');
p.append(span);
<div class="list-view__count">
<p>
Showing 1 - 18 of 46 results
</p>
</div>
Explanations are in the code, for every line.
document.addEventListener('DOMContentLoaded', () => { // make sure DOM is parsed ...
let items = document.querySelectorAll('.list-view__count p'); // ... to find elements
for (const item of items) { // iterate over the node list
let span = document.createElement('span'); // create the span
span.toggleAttribute('data-nosnippet', true); // add the data-nosnippet attribute, with no value
span.append(item.childNodes[0]); // move the text node into the span
item.append(span); // and the span into the paragraph
}
})
/* some css so we see the change works */
span[data-nosnippet] { color: green; }
<div class="list-view__count">
<p>
Showing 1 - 18 of 46 results
</p>
</div>
<div class="list-view__count">
<p>
Showing 1 - 18 of 49 results
</p>
</div>
<div class="list-view__count">
<p>
Showing 1 - 18 of 41 results
</p>
</div>

Changing html of <p> without changing <span>

I have a span inside a paragraph and want to be able to change the paragraph text and the span text from button clicks. Right now when I call the function the paragraph is updated but the span disappears.
<p id = "a">Some text to change <span id = "b" onmouseenter="test()">click!</span></p>
function test() {
$("#a").html("New text here");
$("#b").html("click again!");
}
If you change the HTML of the parent p, it will remove everything inside it. However, you can restructure your html to have two spans inside the p and update the text of those.
Here's an example with #c as the first span and #b as the second:
function test() {
$("#c").text("New text here ");
$("#b").text("click again!");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id = "a"><span id = "c">Some text to change </span><span id = "b" onmouseenter="test()">click!</span></p>

JavaScript - Increase font size of the selection in contenteditable div

I am working on WYSIWYG editor which have button IncreaseFontSize (like in MS Office). I am trying to make this button works but without success. Everytime all selected elements have the same font size. Here is example:
<div contenteditable="true">
<p>
Some
<span style="font-size: 20pt">Text</span>
<span style="font-size: 32pt">Some</span>
Text
</p>
</div>
Below is part of my code
var html = $(rangy.getSelection().toHtml());
var firstValue = html.find('.fontSize').first().css('font-size').replace('px', '');
html.find('.fontSize').each(function () {
$(this).css('font-size', parseInt(firstValue) + 1);
});
When I select all text and click this button all spans have the same font-size (for example 21pt, because my function brings only first span into consideration). So how can I do script which can increase font size of each element separately (using JavaScript or/and JQuery)? Thanks for help.
You are grabbing the value of the first span, storing it in firstValue and then setting the font size of ALL the spans to firstValue + 1. Since your first span is 20px, everything gets set to 21px
So if you are trying to increase each span by 1px when the button is clicked, you would do it this way:
html.find('.fontSize').each(function () {
var oldValue = $(this).css('font-size');
$(this).css('font-size', parseInt(oldValue) + 1);
});

making a JavaScript character selector

I’m trying to make a character selector, which select each character separately every time button pressing. But its not working at all
<!DOCTYPE html>
<html lang="en">
<head>
<title>HELLO WORLD</title>
</head>
<body>
<center>
<br />
<p id="temp">ABCDEFGHIJKLMNOPQRSTUVWXYZ</p>
<br />
<input type="button" onclick="selector()" value="SELECT" />
<script>
var x = document.getElementById("temp").innerHTML;
var i = 0;
function selector() {
x.charAt(i).style.backgroundColor = "red";
i++;
}
</script>
</center>
</body>
</html>
The primary issue is that you can only apply styling to HTML elements, not individual characters that make up the text content of an element.
This is why you are getting the "undefined" error that you are... backgroundColor can't be set on undefined, which refers to the return value of the style property, which doesn't exist on individual characters.
So first, you must wrap the character(s) to be highlighted in another element (a <span> is the best choice here) and then you can have the contents of the <span> be highlighted.
You weren't exactly clear on whether each click of the button should highlight only the next character or if the highlighting should be extended to include the next character, so I have solutions for both of those below. See comments inline for detailed explanations:
Solution #1 (highlight single character at a time)
// Get DOM reference to paragraph (not contents of paragraph)
var x = document.getElementById("temp");
// Get DOM reference to button so we can wire it up to
// an event handler in JS (not via inline event handling attributes).
var btn = document.getElementById("btn");
// Set up event handler:
btn.addEventListener("click", selector);
var i = 0;
function selector() {
// Get the character to be highlighted
var char = x.textContent.charAt(i);
// Set the contents of the paragraph to a new string that has the particular character
// wrapped with a <span> that is set to use a predetermined class that does the actual
// highlighting.
x.innerHTML = x.textContent.replace(char, "<span class='highlight'>" + char + "</span>");
// Increment i until we've hit the 26th value, then reset to 0
i < 25 ? i++ : i = 0;
}
.highlight { background-color:red; }
<p id="temp">ABCDEFGHIJKLMNOPQRSTUVWXYZ</p>
<br>
<!-- There is no closing tag for input elements! -->
<input type="button" id="btn" value="SELECT">
Solution #2 (extend highlighting to include next character)
// Get DOM reference to paragraph (not contents of paragraph)
var x = document.getElementById("temp");
// Get DOM reference to button so we can wire it up to an event handler in JS (not via inline event
// handling attributes).
var btn = document.getElementById("btn");
// Set up event handler:
btn.addEventListener("click", selector);
var i = 0;
function selector() {
// Get the character to be highlighted
var char = x.textContent.charAt(i);
// Set the contents of the paragraph to a new string that encloses all the characters
// up to and including the current one in a <span> that is set to use a predetermined
// class that does the actual highlighting.
x.innerHTML = "<span class='highlight'>" + x.textContent.replace(char, char + "</span>");
// Increment i until we've hit the 26th value, then reset to 0
i < 25 ? i++ : i = 0;
}
.highlight { background-color:red; }
<p id="temp">ABCDEFGHIJKLMNOPQRSTUVWXYZ</p>
<br>
<!-- There is no closing tag for input elements! -->
<input type="button" id="btn" value="SELECT">
Here's one possible implementation
Create a list of characters in the HTML element by using string#split.
Wrap each of these characters inside a span tag. This is easy to do using the map function. We want to check if these are alphabetical characters so we use the test function.
We then need to find the number of characters in the original string. We can do that by stripping the new string of all of it's span tags. Set the initial index to the first character, which in JavaScript is zero.
Call an event listener. This could be for example keydown, which listens for keypresses.
All of our characters have now been wrapped with a char class. To find a particular one, use document.querySelectorAll, and pass in [index]
In the event that we cycle through the string, we will remove the styling for the last character in the list. Otherwise, naturally, the previous character will be converted back to normal.
var chars = document.getElementById("par").innerHTML.split('');
var wrapped = chars.map( c => /[a-z]/i.test(c) ? "<span class='char'>" + c + "</span>" : "").join('');
var numLetters = wrapped.replace(/<span class='char'>/g, '').replace(/<\/span>/g, '').length;
document.getElementById("par").innerHTML = wrapped;
var index = 0;
document.addEventListener("keydown", function() {
document.querySelectorAll(".char")[index].style.color = "red";
if (index == 0) {
document.querySelectorAll(".char")[numLetters - 1].style.color = "black";
}
if (index > 0) {
document.querySelectorAll(".char")[index - 1].style.color = "black";
}
index = index == numLetters - 1 ? 0 : index + 1
});
<p id="par">This is a paragraph</p>
You need to put all character into a span tag, and change the span background color.
var i = 0;
function selector() {
if (document.getElementById("temp_" + i))
document.getElementById("temp_" + i).style.backgroundColor = "red";
i++;
}
<p id="temp">
<span id='temp_0'>A</span>
<span id='temp_1'>B</span>
<span id='temp_2'>C</span>
<span id='temp_3'>D</span>
</p>
<button onclick='selector();'>Test</button>

How to highlight an editable word in dynamically generated text?

Intro
I am creating a content editor in which I want to add the functionality to choose a word which you would like to be highlighted while typing your content.
At this moment I achieved to search any word chosen in the #dynamicWord and then typed in #contentAreaContainer and give it a red border by adding em around the keyword and style the em trough CSS:
Part of the Code:
<div class="word">
Dynamic word to highlight: <input name="dynamic_word" id="dynamicWord" value="Enter word..">
</div>
<div id="contentAreaContainer" oninput="highlighter()">
<textarea id="contentArea"></textarea>
</div>
function highlighter()
{
var contentAreaContainer = document.getElementById('contentAreaContainer');
var dynamicWord = document.getElementById('dynamicWord').value;
wrapWord(contentAreaContainer, dynamicWord);
};
wrapWord() does:
function wrapWord(el, word)
{
var expr = new RegExp(word, "i");
var nodes = [].slice.call(el.childNodes, 0);
for (var i = 0; i < nodes.length; i++)
{
var node = nodes[i];
if (node.nodeType == 3) // textNode
{
var matches = node.nodeValue.match(expr);
if (matches)
{
var parts = node.nodeValue.split(expr);
for (var n = 0; n < parts.length; n++)
{
if (n)
{
var em = el.insertBefore(document.createElement("em"), node);
em.appendChild(document.createTextNode(matches[n - 1]));
}
if (parts[n])
{
el.insertBefore(document.createTextNode(parts[n]), node);
}
}
el.removeChild(node);
}
}
else
{
wrapWord(node, word);
}
}
}
em{border: 1px solid red;}
The problem:
Now at this moment every time on input in #contentAreaContainer the keyword chosen is highlighted a short period in the #contentAreaContainer, because highlighter() is triggered on input. But it should stay highlighted after finding it instead of only oninput.
I need oninput to search for the #dynamicWord value with wrapWord() while some one is typing;
Any time the #dynamicWord value was found it should permanently get an em
So how can I sort of 'save' the found keywords and permanently give them the element until the dynamic keyword gets edited?
Check the DEMO version
Solved:
Using setTimeout() instead of oninput I managed to make the highlight look constant. The change:
function highlighter()
{
var contentAreaContainer = document.getElementById('contentAreaContainer');
var mainKeyword = document.getElementById('main_keyword').value;
wrapWord(contentAreaContainer, mainKeyword);
repeater = setTimeout(highlighter, 0.1);
}
highlighter();
I removed oninput="highlighter()" from #contentAreaContainer.
You are trying to highlight words in a textarea. As far as I know a textarea does not support html elements inside. If you do it would simply display them as text.
Therefore you need to use an editable div. This is a normal div but if you add the attribute:
contentEditable="true"
the div acts like a textarea with the only difference it now process html elements. I also needed to change the onchange event into the onkeyup event. The editable div does not support onchange events so the highlight would not be triggered. The HTML for this div looks like:
<div contentEditable="true" id="contentArea">Test text with a word in it</div>
Here is the working code in a fiddle: http://jsfiddle.net/Q6bGJ/ When you enter a new character in the textarea your keyword gets highlighted.
However there is still a problem left. You surround the keyword with an em element. This results in surrounding it on every keystroke. Now you end up width many em's around the keyword. How to solve this, I leave up to you as a challenge.

Categories

Resources