I would like to know, if there is a way to hide certain characters in string, but not replace.
So, for example
let a = 'Hallo';
let b = a.replace('a', ' ');
alert(b);
this code will alert H llo instead Hallo.
Is there any function that really hide (don't display character, but don't replace it (so, we can't see this character, but it exists still there)) ?
Extending on ibrahim mahrir's comment, you could create a hidden class as follows:
<p>Such a nifty string, wi<span class="hidden">th</span>
some l<span class="hidden">e</span>tters missing</p>
Then some javascript could do this:
<script>
var targets = document.querySelectorAll(".hidden");
function hideLetters() {
targets.style.visibility = "hidden";
}
hideLetters();
</script>
By putting it in a function like this, you could dynamically hide them. Say a user clicks a button:
<button id="hider">Hide letters</button>
<script>
var hider = document.querySelector("#hider");
hider.addEventListener("click", hideLetters);
</script>
And then a function to show them, if you like.
<script>
function showLetters() {
targets.style.visibility = "visible";
}
</script>
let div = document.getElementById("div");
let str = "Ibrahim Mahrir plays Hallo!";
div.innerHTML = str.replace(/a/g, "<span class='hidden'>$&</span>");
#div {
margin-top: 30px;
padding: 10px;
background: #fffbec;
border-bottom: 2px solid #d89d9d;
}
.hidden {
visibility: hidden;
}
#div:hover .hidden {
visibility: visible;
}
Hover over the div to see the missing characters:
<div id="div"></div>
Related
I am spliting the value from textarea by line break and add text indent to each of them.
Here is my code:
function splits() {
let textarea = document.getElementsByTagName("textarea")[0]
let arrays = textarea.value.split(/\r?\n/)
for (let i = 0; i < arrays.length; i++) {
textarea.style.textIndent = "10px"
textarea.value = "<p>" + arrays[i] + "</p>"
//not working return "<p>(The content I entered)</p>
}
}
<textarea></textarea>
<button onclick=splits()>Splits</button>
I want to make each of the elements from the arrays be in a new <p>.
However, my code above is obviously not working.
Do anyone know anyone to do this?
Thanks for any helps and responds.
This is not possible to do with a textarea. What you are looking for is an content editable div
function splits(){
const div = document.getElementById("test");
let values = div.innerText.split(/\r?\n/)
div.innerHTML = values.map(sentence => `<p>${sentence}</p>`).join("");
div.style.textIndent = "10px";
}
div#test {
width: 300px;
height: 200px;
border: 1px solid #ccc;
}
<div contenteditable="true" id="test"></div>
<button onclick=splits()>Splits</button>
You're replacing the textarea value each time through the loop, rather than appending to it.
You also don't need to set the style each time through the loop, you can do that just once.
function splits() {
let textarea = document.getElementsByTagName("textarea")[0]
let arrays = textarea.value.split(/\r?\n/)
textarea.style.textIndent = "10px"
textarea.value = arrays.map(s => `<p>${s}</p>`).join("");
}
<textarea></textarea>
<button onclick=splits()>Splits</button>
I've been trying to create a list of tags and separate them using commas. I'm using Webflow and sadly it's not possible in their cms.
I thought of a workaround where I would replace the commas with code using JavaScript.
Here's the code:
function tags() {
var tag = document.getElementById("tag__wrap").innerHTML;
str = tag.replace(/,/g, '</p><p class="tag__wrap">');
}
tags();
console.log(str);
For some reason the code works fine when I look it up in the console, but doesn't actually show anything on the actual website.
Any thoughts?
If your goal is to create multiple elements in place of the single element (that has the comma separated tags), then you need to manipulate the DOM. It is not enough to assign HTML to a string variable.
There are many ways to do this. Here is one:
function tags() {
var elem = document.getElementById("tag__wrap");
var tags = elem.textContent.match(/[^,\s]+/g) || [];
elem.textContent = tags.shift();
for (let text of tags) {
var newElem = elem.cloneNode();
newElem.textContent = text;
elem.insertAdjacentElement("afterend", newElem);
elem = newElem;
}
}
// Delay the change, so you can see before & after in the snippet
setTimeout(tags, 1000);
#tag__wrap {
background: lightblue;
display: inline-block;
margin: 5px;
padding: 3px 8px;
border-radius: 4px;
}
<p id="tag__wrap">algorithm,javascript,html,css</p>
So this is a bit of a mix-up.
I want to highlight certain words and add a help-text to them when you hover them. My current code searches for keywords, let's say the word "Mammal". When it finds the word "Mammal" it adds a span element around the word with a class that styles it so that you get an underline on the word. It also adds a child span element on the word that is hidden and contains the help-text I want to show.
The child's position is set to position:absolute and placed directly underneath the underlined word.
I have no control over the parent elements of the word or where on the page the word is, so the words parent/grandparent/etc might have overflow:hidden (and/or position:relative) which will partially hide the word. I want it to always show up (without taking any space on the page) when you hover the marked word, but I just can't think of a good way to solve this.
I've thought about putting the hover display text, not as a child of the hover element, but to have it further up above the overflow:hidden container, but I can't think of a good way how I would get that to work and how the child element would then target a grandparent sibling element to be displayed, etc.
Here's an element that shows how it looks and behaves:
.tooltip {
border-bottom: 1px solid orange;
}
.tooltip .tooltipText {
visibility: hidden;
width: 100px;
background-color: green;
position: absolute;
margin: 20px 0px 0px -80px;
}
.tooltip:hover .tooltipText {
visibility: visible;
}
<html>
<body>
<div style="overflow: hidden; width:100px;">
<div style="position:relative;">
<div>text <span class="tooltip">containing<span class="tooltipText">Hover text here</span></span> the word i'm looking for</div>
</div>
</div>
</body>
First i get all the nodes, then i go through them updating the words and adding the required elements:
nodes.forEach(function(node){
let nextNode = node.nextSibling,
parent = node.parentNode,
content = node.textContent,
newNodes = [];
node.parentNode.removeChild(node);
content.split(wordToHighlight).forEach(function(part, i, arr){
newNodes.push(document.createTextNode(part));
if(i < arr.length - 1){
let highlight = document.createElement("span");
highlight.innerHTML = wordToHighlight;
highlight.classList.add('tooltip');
let label = document.createElement('span');
label.classList.add('tooltipText');
label.innerHTML = "Hover text here";
highlight.appendChild(label);
newNodes.push(highlight);
}
});
newNodes.forEach(function(n){
if(nextNode)
parent.insertBefore(n, nextNode);
else
parent.appendChild(n);
});
});
This logic works for the most part, but when a parent/grandparent/etc contains either position:relative or overflow:hidden then the text gets cut and I've tried fiddling with CSS for hours now to see if I could find a way to make it work without much success. I would also like a better way to center it directly underneath the word it highlights, but move it so that it won't go out of the viewport to the right/left/top/bottom depending on where the word appears if that's possible.
I can add more details/code or such if needed, thanks for any help!
just insert the tooltip outside the element which has overflow: hidden;.
That is the only solution here, though you will need to position accordingly in that case.
The comment from #pilchard about using the library Popper worked perfectly for this use case and it was easy and fast to set up.
function show(selector, popperInstance) {
const tooltip = document.querySelector(selector);
tooltip.setAttribute('data-show', '');
popperInstance.setOptions({
modifiers: [{ name: 'eventListeners', enabled: true }],
});
popperInstance.update();
}
function hide(selector, popperInstance) {
const tooltip = document.querySelector(selector);
tooltip.removeAttribute('data-show');
popperInstance.setOptions({
modifiers: [{ name: 'eventListeners', enabled: false }],
});
}
function underlineWords()
{
const showEvents = ['mouseenter', 'focus'];
const hideEvents = ['mouseleave', 'blur'];
let nodeNumber = 1;
nodes.forEach(function(node){
let nextNode = node.nextSibling,
parent = node.parentNode,
content = node.textContent,
newNodes = [],
selectorIds = [],
poppers = [],
textIds = [];
node.parentNode.removeChild(node);
content.split(itemName).forEach(function(part, i, arr){
newNodes.push(document.createTextNode(part));
if(i < arr.length - 1){
let highlight = document.createElement('span');
highlight.innerHTML = itemName;
highlight.classList.add('tooltipHover');
highlight.id = itemName + nodeNumber + '-' + i + 'Hover';
highlight.setAttribute('aria-describedby', 'tooltip');
selectorIds.push('#' + highlight.id);
let tooltipText = document.createElement('span');
tooltipText.innerHTML = "Hover text here";
tooltipText.classList.add('tooltip');
tooltipText.id = nodeNumber + '-' + i + 'Show';
textIds.push('#' + tooltipText.id);
highlight.appendChild(tooltipText);
newNodes.push(highlight);
const popper = Popper.createPopper(highlight, tooltipText, {
modifiers: [
{
name: 'offset',
options: {
offset: [0, 8],
},
},
],
});
poppers.push(popper);
}
});
newNodes.forEach(function(n){
if(nextNode)
parent.insertBefore(n, nextNode);
else
parent.appendChild(n);
});
for(let i = 0; i < selectorIds.length; i++){
const popper = poppers[i];
const selectorId = selectorIds[i];
const textId = textIds[i];
const selector = document.querySelector(selectorId);
showEvents.forEach(event => {
selector.addEventListener(event, function(){ show(textId, popper) });
});
hideEvents.forEach(event => {
selector.addEventListener(event, function(){ hide(textId, popper) });
});
}
nodeNumber += 1;
});
}
I've created a sample file that has adding and removing children elements in a mother element. The adding was successful, but I'm having a problem in removing children elements. The goal is every single click of remove button removes a child element.
var adds = document.querySelector('#add');
var remove = document.querySelector('#remove');
var section = document.querySelector('section');
var div;
adds.onclick = function() {
div = document.createElement('div');
section.appendChild(div);
div.classList.add('style');
};
// THE PROBLEM
remove.onclick = function() {
while(section.children.length !== 0) {
for(var c in section.children) {
section.removeChild(div[c]);
}
}
};
section {
display: flex;
background: #0ff;
height: 100px;
padding: 8px;
}
section > div {margin: 0 1px;}
.style {
width: 100px;
height: 100px;
background: lightgreen;
}
<button id="add">Add</button>
<button id="remove">Remove</button>
<section class="container"></section>
<br>
What's wrong with my code?
What's wrong with my code?
This line
section.removeChild(div[c]);
div could be undefined here and anyways, sections's children are not necessarily div's children
so change it to
section.removeChild(section.children [c]);
Also, while is not necessary
remove.onclick = function() {
for(var c in section.children) {
section.removeChild(section.children[c]);
}
};
EDIT
The goal is every single click of remove button removes a child
element.
remove.onclick = function() {
if(section.children length ) {
section.removeChild(section.children[0]);
}
};
changed for with if
I am wondering it there is a way to detect if text-overflow:ellipsis is active on an input field so i can show a tooltip with the full text.
Css:
input[type='text']
{
text-overflow:ellipsis;
}
Html:
<input type="text" onmouseover="Tooltip.Show(this)" value="some long text" />
Javascript:
Tooltip.Show = function (input)
{
// This is where i need the see if the current input show ellipsis.
if ($(input).isEllipsisActive())
{
// Show the tooltip
}
}
BR
Andreas
Please note, this question is about input element. A normal HTML element (e.g., div) also has to have
white-space: nowrap;
overflow: hidden;
for text-overflow: ellipsis; to apply. (Overflow can also be scroll or auto.) See this link for more information.
If you want to know when the input text is too long and hidden ... there is no native support for checking thinks like this. You can hack it. You can make a tmp container with the same text, look the width of that container/text and compare it with the length of the input. If the tmp container is longer ... you have too long text and.
something like this:
function isEllipsisActive() {
return_val = false;
var text = $('input_selector').val();
var html = "<span id="tmpsmp">" + text + "</span>";
$(body).append(html);
if($('input_selector').width() < $('#tmpsmp').width()) {
return_val = true;
}
return return_val;
}
Thanks Aleksandrenko.
Just edited a little your solution:
function isEllipsisActive(el) {
return_val = false;
var text = el.val();
var html = "<span id='tmpsmp'>" + text + "</span>";
$("body").append(html);
if(el.width() < $('#tmpsmp').width()) {
return_val = true;
}
$('#tmpsmp').remove();
return return_val;
}