I'm trying to set the style on an HTML element before appending it to the page by passing the style tag through a variable in a JavaScript string literal.
So my code looks like this:
const STYLE = "font-weight: bold; color: crimson; background-color: red;"
const item = `<p class="text" style=${STYLE}>Some Text</p>`
const position = "beforeend";
list.insertAdjacentHTML(position, item);
When I run it though, the HTML on the page looks like this - the quotation mark on the style tag ends after the first colon. Is there any way to get the full string into the style tag?
<p class="text" style="font-weight:" bold; color: crimson; background-color: red;>Some Text</p>
const item = `<p class="text" style=${STYLE}>Some Text</p>
You should wrap ${STYLE} with ":
const item = `<p class="text" style="${STYLE}">Some Text</p>
Browsers for attributes values without " are adding them themselves and closing them before the first space in the string. That's why "font-weight:" was wrapped here:
style="font-weight:" bold; color: crimson; background-color: red;>
Related
I have given text strings which are displayed in containers of varying width. I want to allow linebreaks only after the character "·", which occurs two or three times in each of those text strings.
What I came up with (see below): With jQuery, I wrapped a span around the whole string with a css class that applies white-space: nowrap; to the string, and additionally I added a <br> tag after each "·", both using a replaceAll function: Now line breaks can only happen at the position of the inserted <br> tags.
My problem: This forces line breaks at all <br> tags. But if part one and two of the text string (i.e. the text up to the second "·" character) would fit into the parent container next to each other, I would like the line break only to happen after the second "·"!
var mytext = $('#wrapper2 .string1').text();
var search = " ·";
$('#wrapper2 .string1').each( function(index, element) {
$(element).html( $(element).html().replaceAll(mytext, '<span class="inner_wrapper">' + mytext + '</span>') );
$(element).html( $(element).html().replaceAll(search, search + '<br>') );
})
.wrapper1 {
width: 400px;
border: 1px solid #aaa;
padding: 0.5em;
font-size: 18px;
text-align: center;
}
#wrapper2 .inner_wrapper {
white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>The original text</h3>
<div id="wrapper1" class="wrapper1">
<p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>The width of the above box can change. What I want: Linebreaks should only occur <b>after the "·" characters</b>.</p>
<h3>The text processed by jQuery</h3>
<div id="wrapper2" class="wrapper1">
<p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>This comes close, but if there is enough space (as in the boxes above), the first linebreak should occur after the <b>second</b> "·" character, not after <em>all</em> of them.</p>
You could use the <wbr /> tag to add a word break only when needed, but unfortunately this does not work with a white-space: nowrap; style. The trick is to remove that style, replace all spaces with (non-braking space) entity, and restore spaces (or <wbr /> tags) where needed:
var $el = $('#wrapper2 .string1');
var html = $el.text()
.replace(/ /g, ' ')
.replace(/( ·)/g, '$1 '); // or replace with '$1<wbr />'
$el.html(html);
.wrapper1 {
width: 400px;
border: 1px solid #aaa;
margin: 3px 0;
padding: 0 0.5em;
font-size: 18px;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<b>The original text</b>
<div id="wrapper1" class="wrapper1">
<p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<b>The text processed by jQuery</b>
<div id="wrapper2" class="wrapper1">
<p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
To complete this question/answer set for anyone who's interested, here's the solution I came up with myself after reading #Nikkorian's comment concerning split() and wrapping the split substrings in <span> tags, to which I apply white-space: nowrap via CSS to avoid linebreaks inside them:
I split the text string using split('·') (var "parts", which is an array), looped through that array until the next-to-last part adding span tags around it and a · before span's end tag, then added the last part, also with a span tag around it, but without the · at the end.
$('#wrapper2 .string1').each( function(index, element) {
var parts = $(element).text().split(' · ');
var editedContent = '';
for(var i=0; i < parts.length - 1; i++) {
editedContent += '<span>' + parts[i] + ' ·</span> ';
}
editedContent += '<span>' + parts[i] + '</span>';
$(element).html(editedContent);
});
.wrapper1 {
width: 400px;
border: 1px solid #aaa;
padding: 0.5em;
font-size: 18px;
text-align: center;
}
#wrapper2 > .string1 > span {
white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>The original text</h3>
<div id="wrapper1" class="wrapper1">
<p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>The width of the above box can change. What I want: Linebreaks should only occur <b>after the "·" characters</b>.</p>
<h3>The text processed with javascript/jQuery</h3>
<div id="wrapper2" class="wrapper1">
<p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>This is the desired result: linebreaks can only occur after the "·" characters which appear between the substrings, but if the container is wide enough, two or more substrings can appear in the first line.</p>
I have a input box of type text and the input value have 2 words and I need to strike only the first word not the second one and unfortunately I can't edit html. I should do it using javascript and css only. I have tried using css text-decoration: line-through; but it striking both the words. any help is very much appreciated.
.text-blot { text-decoration: line-through; }
<input type='text' value='two words' class='text-blot'>
The value attribute within an input element can be accessed using JavaScript with HTMLElement.value. Unfortunately, styles will apply to the whole input value. So this is a bit tricky.
Since the value is a single string, which will contain two words. I used some JavaScript to split the string into array of words so then you can strike-through the first word using CSS with text-decoration: line-through and the second word can have text-decoration: none (no strike-through).
I wouldn't recommend this in a production environment, but I made it work by creating two span elements to hold the two words and styled them accordingly. I then gave the original input value a transparent text color with color: transparent and positioned the two span elements on top of the input value to achieve your desired first word strike-through second word without.
const textBlot = document.querySelector(".text-blot");
const demo = document.querySelector(".demo");
const word1 = document.createElement("span");
const word2 = document.createElement("span");
word1.setAttribute("class", "strike");
word2.setAttribute("class", "no-strike");
demo.appendChild(word1);
demo.appendChild(word2);
const arr = textBlot.value.split(" "); // create an array of words
word1.innerHTML = arr[0];
word2.innerHTML = " " + arr[1];
.text-blot {
/* text-decoration: line-through; */
z-index: 1;
color: transparent;
}
.strike {
text-decoration: line-through;
}
.no-strike {
text-decoration: none;
}
.demo span {
position: relative;
left: -9.5rem;
z-index: 99;
}
<div class="demo">
<input type='text' value='two words' class='text-blot'>
</div>
This question already has answers here:
How to get computed background color style inherited from parent element
(3 answers)
Closed 5 years ago.
As I understand the getComputedStyles() method, it should return an object that allows one to access the actual CSS property values of an HTML element node.
I created this simple example with a paragraph containing a span:
let span = document.getElementsByTagName("span")[0];
let style = window.getComputedStyle(span);
span.innerText = "span background-color is " + style.getPropertyValue("background-color");
<p style="background-color: orange">
<span style="color: green">Empty</span>
</p>
The background color of the paragraph is orange, so the span should also have that property value, or am I mistaken? Could it be that inherited values are ignored in getComputedStyles? And if so, how can I get the actually visible background color for the span? Thank you.
It is giving you the correct result.
span background-color is rgba(0, 0, 0, 0)
Note that the a in rgba is 0. There is no opacity at all, the element is completely transparent.
It isn't orange, you can just see through it to the orange element behind it.
EDIT: Updated my answer to use pure JS to find the background color you are looking for:
let span = document.getElementsByTagName("span")[0];
let parent = document.getElementsByTagName("span")[0].parentElement;
let style = window.getComputedStyle(parent);
span.innerText = "span background-color is " + style.getPropertyValue("background-color");
<p style="background-color: orange">
<span style="color: green">Empty</span>
</p>
Another potential option would be updating your style of the span to inherit the background color of the parent, in which case your initial attempt would work:
let span = document.getElementsByTagName("span")[0];
let style = window.getComputedStyle(span);
span.innerText = "span background-color is " + style.getPropertyValue("background-color");
<p style="background-color: orange">
<span style="color: green; background-color: inherit">Empty</span>
</p>
And here is the old version using Jquery:
var color = $('#getThis').closest("p").css("background-color");
$('#getThis').html('Background color is ' + color);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p style="background-color: orange">
<span id="getThis" style="color: green">Empty</span>
</p>
I have wrote this simple snippet to be sure that getComputedStyle returns only the applied style for the element, and not what is actually rendered.
let style1 = window.getComputedStyle(document.getElementById('s1'));
let style2 = window.getComputedStyle(document.getElementById('s2'));
document.getElementById('i1').value = style1.getPropertyValue("background-color");
document.getElementById('i2').value = style2.getPropertyValue("background-color");
<div style='background-color: cyan'>
<span id='s1'>Span without backgound</span>
</div>
<div style='background-color: cyan'>
<span id='s2' style='background-color: yellow'>Span with backgound</span>
</div>
<input id='i1' type='text' />
<input id='i2' type='text' />
But, reading the defination of getComputedStyle from W3Schools, looks confusing, for me:
The computed style is the style actually used in displaying the
element, after "stylings" from multiple sources have been applied.
Reading this, sounds like all "stylings" applied should be returned, and this is not what happens, just my opinion.
let span = document.getElementsByTagName("span")[0];
getBackgroundColor(span);
function getBackgroundColor(ele){
let style = window.getComputedStyle(ele);
if(ele){
if(ele.style.backgroundColor)
span.innerText = "span background-color is " + style.getPropertyValue("background-color");
else
getBackgroundColor(ele.parentNode);
}else
span.innerText = "span background is transparent";
return;
}
<p style="background-color: orange">
<span style="color: green">Empty</span>
</p>
This is done using recursion...may be this is what you want. It will keep checking its parent background-color until it finds one otherwise it will return transparent.
if you use this
span.innerText = "span background-color is " + style.getPropertyValue("color");
then you will get the font color rgb(0, 128, 0) as you use in span. your syntax giving you correct answer.
I want to extract text form the html, which named as text.html, as below
<div class="trans-container">
<ul>
<p class="wordGroup">
<span style="font-weight: bold; color: #959595; margin-right: .5em; width : 36px; display: inline-block;">adj.</span>
<span class="contentTitle"><a class="search-js" href="/w/good/#keyfrom=E2Ctranslation">good</a>
<span style="font-weight: bold; color: #959595;"> ;</span>
</span>
<span class="contentTitle"><a class="search-js" href="/w/fine/#keyfrom=E2Ctranslation">fine</a>
<span style="font-weight: bold; color: #959595;"> ;</span>
</span>
<span class="contentTitle"><a class="search-js" href="/w/ok/#keyfrom=E2Ctranslation">ok</a>
</span>
</p>
<p class="wordGroup">
<span style="font-weight: bold; color: #959595; margin-right: .5em; width : 36px; display: inline-block;">adv.</span>
<span class="contentTitle"><a class="search-js" href="/w/well/#keyfrom=E2Ctranslation">well</a>
</span>
</p>
<p class="wordGroup">
<span style="font-weight: bold; color: #959595; margin-right: .5em; width : 36px; display: inline-block;">misc.</span>
<span class="contentTitle"><a class="search-js" href="/w/all right/#keyfrom=E2Ctranslation">all right</a>
</span>
</p>
</ul>
</div>
and print it out as the following format.
adj. good ; fine ; ok
adv. well
misc. all right
What I've tried is the code below
const cheerio = require('cheerio');
const fs = require('fs');
const $ = cheerio.load(fs.readFileSync('./test.html'));
$('div.trans-container').find('p.wordGroup').each(function(i,elm){
const line = []
$(this).find('span').each(function(i,elm){
line[i] = $(this).text().trim()
})
console.log(line.join(' '))
});
Unfortunenately, the ourput is as below, not exactly as what I want. Can anyone help me to point out where I am wrong? Also, it would be greatly appreciated if you can offer me other decent ways to solve this problem by JavaScript, no matter with or without Cheerio.
adj. good
; ; fine
; ; ok
adv. well
misc. all right
Just use text() on the main group, .wordGroup in this case, it will get all the text of the element without the html elements. Then run a replace() on it removing all whitespace characters with a single space.
$('div.trans-container').find('p.wordGroup').each(function(i,elm){
// regex: /\s+/g matches 1 or more whitespace characters \n\r\f\t
var line = $(this).text().replace(/\s+/g," ");
console.log(line);
});
As for doing it with just native javascript you can't do that with Nodejs as it does not have native DOM support. So you have to use a module like cheerio or jsdom. If you mean javascript in the browser it would be like:
document.querySelectorAll('div.trans-container p.wordGroup')
.forEach(ele=>console.log( ele.innerText.replace(/\s+/g," ") ));
if you give an id to each one of your <p> tags, then you can use this script to get access to your child elements and get the values from them :
var adjElements = document.getElementById("adj").children;
var advElements = document.getElementById("adv").children;
var miscElements = document.getElementById("misc").children;
var adjObject =[];
var advObject =[];
var miscObject =[];
for (var i=0; i<=adjElements.length -1; i++){
adjObject.push(adjElements[i].innerText);
}
for (var i=0; i<=advElements.length -1; i++){
advObject.push(advElements[i].innerText);
}
for (var i=0; i<=miscElements.length -1; i++){
miscObject.push(miscElements[i].innerText);
}
console.log(adjObject); //["adj.", "good ; ", "fine ; ", "ok"]
console.log(advObject); //["adv.", "well"]
console.log(miscObject); // ["misc.", "all right"]
I make an example for you :
https://jsfiddle.net/37g6ture/2/
remember to add adj, adv and misc IDs to your p tag.
This is perhaps the solution you are looking for
line[i] = $(this).children().length > 0 ? $(this).children(":first-child").text().trim() : $(this).text().trim();
This gives the expected output. This checks if this node has child nodes and gets the first node text only. If there are no child nodes then just extract the node text.
The official document about jquery text() function at http://api.jquery.com/text/ says
Get the combined text contents of each element in the set of matched
elements, including their descendants, or set the text contents of the
matched elements.
Another relevant post is this https://stackoverflow.com/a/32170000/578855
Your primary issue is the double loop. The inner one $(this).find('span').each is causing some spans to be iterated over twice. For example:
<span class="contentTitle">
<a class="search-js" href="/w/fine/#keyfrom=E2Ctranslation">fine</a>
<span style="font-weight: bold; color: #959595;"> ;</span>
</span>
calling span.text() on <span class="contentTitle"> will return fine ;
then also, the inner span <span style="font-weight: bold; color: #959595;"> is iterated over as well, adding a second ;.
Secondly, if your goal is to remove all extra white space, but leaving a single, this would work .replace(/\s\s+/g, ' '))
The whole code:
const $ = require('cheerio').load(require('fs').readFileSync('./test.html'));
$('div.trans-container').find('p.wordGroup').each(function(i,elm){
console.log($(this).text().replace(/\s\s+/g, ' '));
});
which results in
adj. good ; fine ; ok
adv. well
misc. all right
I'm using a div for people to enter text and then I tried saving
div.innerText
and
div.innerHTML
to my database but when I bring it back from the database and put it back into the div all of the carriage returns or newlines are gone
innerHTML to database
a
b
c
//in database like this <div>a</div><div></div><div>b</div><div></div><div>c</div>
innerText to database
a
a
a
a
a
a
//how it stored in database aaaaaa
if you could tell me how to handle this situation I would appreciate it greatly thank you for your time
div.innerHTML creates an HTML output of your new lines using <div> containers.
Therefore the line breaks will be "replaced".
div.innerText uses the "invisible" character \n or \r\n to mark new lines and it is possible that they are not shown in your database. You can however replace them by <br> tags to see if they are there.
document.getElementById("output").addEventListener("click", function() {
console.log("HTML:");
console.log(document.getElementById("text").innerHTML);
console.log("Text:");
var text = document.getElementById("text").innerText;
console.log(text.replace(/(?:\r\n|\r|\n)/g, '<br>'));
});
#text {
background-color:#FAFAFA;
border: red solid 1px;
height:150px;
width: 200px;
}
<button id="output">
Show in console
</button>
<div id="text" contenteditable>
</div>
console.log(text.replace(/(?:\r\n|\r|\n)/g, '<br>')); replaces all different kinds of possible new lines into <br> tags.
You can substitute <textarea> element for <div> with contenteditable attribute set. Encode, decode .value of textarea using encodeURIComponent(), decodeURIComponent() or format data as JSON utilizing JSON.stringify(), JSON.parse()
var button = document.querySelector("button")
var textarea = document.querySelector("textarea");
button.onclick = function() {
var value = textarea.value
console.log(encodeURIComponent(value)
, decodeURIComponent(value)
, JSON.stringify(value)
, JSON.parse(JSON.stringify(value))
);
}
textarea {
border: 1px solid navy;
width: 300px;
height: 200px;
}
You can use
<button>click</button><br>
<textarea></textarea>