How to count number of lines in javascript html string variable - javascript

I have javascript variable with html string data like below format
var html_string = '<p class="MsoListParagraph" style="margin-left:28.5pt;mso-add-space:auto;text-indent:-28.5pt;mso-list:l0 level2 lfo1;tab-stops:list 28.5pt"><!--[if !supportLists]--><b><span lang="EN-US">1.1<span style="font-weight: normal; font-stretch: normal; font-size: 7pt; line-height:normal; font-family: Times New Roman;"></span></span></b><!--[endif]--><b><span lang="EN-US">Purpose of the Document<o:p></o:p></span></b></p><p class="MsoNormal" style="margin-left:28.5pt;tab-stops:80.25pt"><span lang="EN-US">This document helps to understand the design aspects of the ASSMail web based project. This document details the technical specification for the project.</span></p>';
I tried to count based on the break statement but it not work.
I want to count number of lines found in this html string for browser view. Any one please help how to do this process?

Based on your follow-up comment you can parse the content with a DOMParser, and by that get to know the number of paragraphs :
var parser = new DOMParser(),
doc = parser.parseFromString(html_string, "text/html"),
paragraphs = doc.querySelectorAll('p').length;
alert('there is '+paragraphs+' paragraphs');
demo -> http://jsfiddle.net/nfwy006u/1/

If interpret Question correctly , try creating jQuery object from html_string , using .filter() to select p elements , .length property of returned jQuery object for number of p elements in original string
$(html_string).filter("p").length
var html_string = '<p class="MsoListParagraph" style="margin-left:28.5pt;mso-add-space:auto;text-indent:-28.5pt;mso-list:l0 level2 lfo1;tab-stops:list 28.5pt"><!--[if !supportLists]--><b><span lang="EN-US">1.1<span style="font-weight: normal; font-stretch: normal; font-size: 7pt; line-height:normal; font-family: Times New Roman;"></span></span></b><!--[endif]--><b><span lang="EN-US">Purpose of the Document<o:p></o:p></span></b></p><p class="MsoNormal" style="margin-left:28.5pt;tab-stops:80.25pt"><span lang="EN-US">This document helps to understand the design aspects of the ASSMail web based project. This document details the technical specification for the project.</span></p>';
var html = $(html_string);
html.appendTo("body");
console.log(html.filter("p").length)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Find the height of the element the text is displayed in MDN dimensions of element then divide by the font height.

You can get height of div
jQuery("#id-of-your-div").height()
And then devide it to the height of one line, and it will by number of lines
For example:
jQuery("#id-of-your-div").height()/20

I think it will be hard to get how many lines are there, if your html in the variable is going to change, as some tags are inline, some tags are block. Block elements also start a new line (or can be inline css that set an inline element to be block), not just <br> tag.
So I assume you are getting the height of the div. Here is an idea:
You can insert your html on the page with display none, and get the height of it with some code like:
jQuery("#id-of-your-div").height()

Related

Javascript .replace method doesn't override CSS style

I've read here that when both CSS and JavaScript target the same element, then the JavaScript changes are applied over CSS.
However, I've encountered a different behaviour.
Here, we have legal case name: Johnson V United Care.
I want to convert all words to uppercase, except the "V", which I want to convert to lowercase.
This is what I want: JOHNSON v UNITED CARE.
However, in the below code, CSS uppercase style seems to override the Javascript code.
I've referred the CSS file in the <head> and the JS file just before the closing </body> tag.
What I am doing wrong?
Note: After I've posted the question, I've thought that the JS code only changes the innerHTML, and subsequently CSS style is applied to this new HTML. So, this does not seem like a priority issue. But I still can't figure how to apply JS code after CSS in order to get the correct result.
(function() {
let title = document.querySelector("h1.title>a");
let a = title.innerHTML;
let b = a.match(/\b[v]\b/i);
title.innerHTML = a.replace(b, b.toString().toLowerCase());
})();
h1.title>a {
text-transform: uppercase;
}
<h1 class="title">Johnson V United Care</h1>
I've read here that when both CSS and JavaScript target the same element, then the JavaScript changes are applied over CSS.
That article is very wrong.
Inline style has precedence over rule-sets. It doesn't matter how the two styles are added to the document. It just looks like JS has precedence because JS is used to add inline style.
What I am doing wrong?
CSS changes how the content is presented.
The CSS says it should be presented in uppercase.
It doesn't matter if, in the actual content, a particular character is lower-case because it was written that way in HTML or changed to be that way with JS.
You are changing the content with JS, and then CSS is presenting that content in uppercase.
I'd approach the problem by writing extra markup and styling that.
h1.title>a .name {
text-transform: uppercase;
}
<h1 class="title"><span class="name">Johnson</span> v <span class="name">United Care</a>
</h1>
Actually, it will not be possible to override the CSS property this way, because they are not working on the same property. You're setting the text-transform property in the CSS and in JS code you are just changing the HTML content of the element but not overriding the text-transform property. This way the precedence order will have not effect.
To solve the problem, you should do all text transformations in JS and remove the text-transform property in CSS.
Here is an example:
const title = document.querySelector('h1.title > a');
const polifyText = (str, char) =>
str
.split(' ')
.map(part => (part.includes(char) ? part.toLowerCase() : part.toUpperCase()))
.join(' ');
let newTitle = title.textContent;
let char = newTitle.match(/\b[v]\b/i);
title.textContent = polifyText(newTitle, char);
h1.title > a {
/* Comment this out */
// text-transform: uppercase;
}
<h1 class="title">Johnson v United Care
</h1>

How google fonts loads fonts dynamically

In Google fonts website (https://fonts.google.com/) they add <li> elements dynamically on scroll. Those <li> elements has <a> tag with href attribute (screenshot bellow) with url value that points to the font page. Then deeper inside <li> there is <gf-content-editable> element which sets font-family CSS value to the actual font family.
Could someone explain how do they do that? Looking for a way to load fonts dynamically, but CSS Font Loading API is still experimental.
Thanks for any insights.
One way to do this would be to create an object using data from a database or any other source, and iterating over it to dynamically create cards. A bare-bones example of this could be:
const data = [
{
fontFamily: 'Open Sans',
href: 'Open+Sans+Condensed',
// Other attributes
},
// Other fonts
]
for(const font of data) {
let li, gridItemTemplate, gfFontPreview, a, section, gfContentEditable /*other elements*/;
li = document.createElement('li')
li.setAttribute('class', 'grid-list-tile is-in-last-column');
// Other attributes
gridItemTemplate = document.createElement('grid-item-template');
gfFontPreview = document.createElement('gf-font-preview')
gfFontPreview.setAttribute('class', 'grid-list-font-preview');
// Other attributes
a = document.createElement('a')
a.setAttribute('class', 'https://fonts.google.com/specimen' + font.href);
// Other attributes
section = document.createElement('section');
section.setAttribute('class', 'font-preview-card-static ...');
gfContentEditable = document.createElement('gf-content-editable')
gfContentEditable.setAttribute('class', 'preview-text-font-card static-font...')
gfContentEditable.setAttribute('style', `font-size: 40px; line-height: 1.10909; font-family: "${font.fontFamily} script=latin rev=1"; weight: 300; font-style: normal;`);
gfContentEditable.innerText = 'Almost before we knew it, we had left the ground.';
document
.body
.appendChild(li)
.appendChild(gridItemTemplate)
.appendChild(gfFontPreview)
.appendChild(a)
.appendChild(section)
.appendChild(gfContentEditable);
}
This is a pretty verbose way of writing this out. If you actually wish to create this as a function for your website, you can abstract a lot of this code out into separate functions, or use a templating engine or library to achieve this. I'm just sharing this to show how I could achieve this with just the information I have from the question.

How to change different language to different font-size at same line without unique each container?

How to change different language to different font-size at same line without unique each container? is it possible? with css or javascript?
div{
font-family: "English", "中文"
font-size: 20px;
// I need to make "中文" font-size 10px.
}
<div>This is English. 這是中文 This is English</div>
<div>This is English. 這是中文這是中文這是中文 This is English</div>
...
If you alter the text using JavaScript (since your question allowed for JavaScript), you can use CSS upon the results changed by JavaScript (which as others have said, requires adding a container).
For example :
window.onload = function () {
// Note that the following might also be used for Japanese or Korean
// Note also that I have not included (deprecated) compatibility characters. As
// per http://www.unicode.org/reports/tr38/#BlockListing , to cover those
// you would need to add:
// 1. \u3358-\u3370\u337B-\u337F\u33E0-\u33FE (e.g., immediately after "\u32CB")
// 2. \uFA2E-\uFA6D\uFA70-\uFAD9 (e.g., immediately after "\uFA29")
// 3. Replace \uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29 with \uF900-\uFA2D OR if you want to keep the compat. listed separately from non-compat. (though there is no need for this), add the following, e.g., before \uFA0E: \uF900-\uFA0D\uFA10\uFA12\uFA15-\uFA1E\uFA20\uFA22\uFA25\uFA26\uFA2A-\uFA2D
// 4. Immediately before ")+\s?)+/g", add |\ud87e[\udc00-\ude1d]
// The portion \u2E80 up to \u32CB is for punctuation and special characters like radicals,
// but this does not support some punctuation characters which might be reused outside of
// CJK as well as in CJK.
var chineseChars = /((?:[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0\u2FFB\u3000-\u303F\u3105-\u312D\u3190-\u31B7\u31C0-\u31E3\u3220-\u3243\u3280-\u32B0\u32C0-\u32CB\u4E00-\u9FCC\u3400-\u4DB5\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\ud840-\ud868][\udc00-\udfff]|\ud869[\udc00-\uded6\udf00-\udfff]|[\ud86a-\ud86c][\udc00-\udfff]|\ud86d[\udc00-\udf34\udf40-\udfff]|\ud86e[\udc00-\udc1d])+\s?)+/g;
document.body.innerHTML = document.body.innerHTML.replace(
chineseChars,
'<span lang="zh">$1</span>'
);
};
with your CSS:
body {font-size: 12px;}
span:lang(zh) {font-size: 10px}
JSFiddle
My use of lang="zh" is based on an assumption that you know these to be used for Chinese as opposed to Japanese or Korean. If you do not know, you can change the span in JS to this:
'<span class="cjk">$1</span>'
and the Chinese part of the CSS to this:
span.cjk {font-size: 10px}
That won't make any assumptions about the language, only the characters.
JSFiddle
http://jsbin.com/qozidepi/1/watch?js,output
JS:
// Get the div
var div = document.getElementById("text");
// Get the value
var value = div.innerHTML;
// Regular expression finds Chinese characters and wraps them
// in a span tag, which have font-size 40px
value = value.replace(/([\u3400-\u9FBF]+)/g, function(match){
return "<span>" + match + "</span>";
});
// Set the div's value
div.innerHTML = value;

Removing automatically added line breaks when combining Javascript + HTML

Just starting off in web development and hoped one of you all could help me out.
I am building a site that displays the weather along with the four-day forecast with the help of SimpleWeather.js. There's a section in my javascript where I want to display a particular day's High & Low with a "|" in the middle to divide them. I also wanted to declare a class for the "|" part so that I can change the color of the divider. However, when I do this, it adds two line breaks, and I don't understand why or how to fix it.
The code is
$("#high-low-one").html(weather.forecasts.one.high+'<p class="high-low-divider">|</p>'+weather.forecasts.one.low);
However it shows up as:
30
|
28
(where the 30 is the high and 28 is the low temperature for any given day.)
I've also tried fixing this in CSS using inline-text, inline-block, block, and nowrap, just to name a few. Any help would be greatly appreciated!
<p> Is a block element by default. You can change this with CSS but use <span> instead as it is by default an inline element
You would end up with:
$("#high-low-one").html(weather.forecasts.one.high+'<span class="high-low-divider">|</span>'+weather.forecasts.one.low);
However I would style the temps in span elements and use the :after pseudo-element to add and style the pipe character.
Something like:
$("#high-low-one").html("<span class='high'>" + weather.forecasts.one.high + "</span><span class='low'>" + weather.forecasts.one.low + "</span>");
With some sample css:
#high-low-one .high
{
color:#F00;
}
#high-low-one .high:after
{
content: "|";
color: #0F0;
padding-left:0.5em;
padding-right:0.5em;
}
#high-low-one .low
{
color:#00F;
}
Which would give you something like: http://jsfiddle.net/D29AH/
For Completeness if you really had to use <p> use the following CSS
.high-low-divider
{
display:inline;
}

How to calculate the width of an input HTML element so that it matches the size of its content?

How to calculate the width of an input HTML element so that it matches the size of its content ?
I already update an input on the fly as the user types :
<input type='text' onkeydown='this.size=this.value.length' />
However, this does not seem completely correct because it does not take into account the fact that some characters are longer than others :
I will get more and more whitespace if I type only some "l" characters
the size will be insufficient if I type only some "w" characters
How to proceed?
PS: Why I want to do this (already answered this in a answer that was deleted)?
I have sentences in which I have to replace the bracket content by inputs (ex: [user] is [years] old). I have no idea what the sentence can be, so I do not know an adequate length for the inputs, and I would like to keep it readable on one line (avoiding too much whitespace).
You could use a (hidden) canvas and the measureText() method of the context to get your string's width.
EDIT:
Looks fast enough.
First, define some CSS...
input,
#input-helper {
display: inline;
font-size: 14px;
font-family: serif;
line-height: 16px;
}
#input-helper {
position: absolute;
top: -10000px;
}
...then use some JavaScript...
var div = document.createElement("div");
div.id = "input-helper";
document.body.appendChild(div);
var input = document.querySelector("input");
input.addEventListener("keyup", function() {
div.textContent = this.value;
input.style.width = div.offsetWidth + "px";
});​
jsFiddle.
You will want to choose a reasonable start width for your input element too.
If using jQuery is not a problem, here is a demo I put together on jsFiddle. It uses an Autoexpand.js file that does what you want. Check out the last example in the fiddle.
Some specifics:
It's based on .keyup and .keypress for the fastest response possible.
It takes into account the HTML markup that's pasted into the box. Things like linebreaks are dealt with.
The source file shows smart processing by taking everything about the font into consideration.
Also included in the jsFiddle are links to download a pastebin version of the fiddle since jsFiddle Sandbox breaks in IE8. That said, it also works in IE7 too!
First : Add this div where you want
<div id="calcsize" style="display:none;"></div>
Second : Use this function
function getWidthof(txt)
{
$('#calcsize').empty().append(txt);
return $('#calcsize').width();
}

Categories