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>
Related
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()
I am trying to create a very low specificity css property using javascript. Just like !unimportant (which doesn't exists)
I don't know whether this is possible or not.
My reason to look for something like !unimportant is that I am writing a small javascript plugin. In which I want to add a default style to a element which should be later easily overriden by the user.
But if I write:
element.style.backgroundColor = "green";
The user will not be able to override the above style easily without using !important. So, I added a dynamic style tag by using the following code:
var style = document.createElement('style');
// WebKit hack :(
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
and then to the above code, I added a dynamic stylesheet using the following code:
var element = document.getElementById('main');
// To use attribute names to apply the styles
element.setAttribute('custom-el', '1');
var sheet = style.sheet;
var properties = "background-color: green;";
var elName = "[custom-el]";
if (sheet.insertRule) {
sheet.insertRule(elName + "{" + properties + "}", 0);
} else if (sheet.addRule) {
sheet.addRule(elName, properties, 0);
}
Now the background-color: green can be overriden by using the following code:
div.main {
background-color: red;
}
But as you can see in css, I used higher specificity to override background-color: green i.e div + .green.
But I want the overriden to happen even when user writes the following css:
.main{ /* Could be simple class name or id name or even tag name */
background-color: red;
}
Fiddle
This might seems to be a small issue. but it is a big problem for me. Please help.
I would simply write like this:
element.style.backgroundColor = element.style.backgroundColor || "green";
Where, if backgroundColor is undefined then it uses green as backgroundColor else it would take the backgroundColor from stylesheet.
Finally I got the answer..
document.head.insertBefore(style, document.head.children[0]);
I should just insert the dynamic stylesheet above already present stylesheets in the head tag.
Working Fiddle
Unfortunately, this is not working in any IE version. I am still looking for answer.
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;
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();
}
I'm making a widget that will be added to external websites, and I have made a page that generates css for them to style it (text color, background color, font size, etc). I end up with a textarea filled with css for them to copy/paste to their website.
Is there a way to add this css to the current page in order to have a live preview?
If you want to add CSS as text
var style = document.createElement('style');
style.innerHTML = 'content';
document.head.appendChild(style);
If you want to add a CSS file
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'css/my.css');
document.head.appendChild(link);
I have traditionally appended a <style> block when doing elements.
var style_rules = [];
style_rules.push("#" + myElemId + " { /* Rules */ } ");
/* ... */
var style = '<style type="text/css">' + style_rules.join("\n") + "</style>";
$("head").append(style);
An important thing to note is that because you don't know what any of the existing styles is, or what id's might conflict on the page, it's very useful to keep track of your id's inside your JavaScript application, then using those to populate the injected <style> block. I also tend to run my names through a prefix function to ensure that the generic names of wrapper, and unit do not conflict (they are turned into something like myunique_wrapper and myunique_unit.
Incorporating a basic CSS reset like #myWrapper {margin: 0; padding: 0} can be a decent starting platform for building your own custom styles.
Addressing your unique case, a live preview so to speak, I would designate a div with standard elements. Then when they click "update" read in the rules and append them to the head. If you want to negate any residual effects from past rules you can remove the last <style> element or better yet give your <style> element an id. I'm not sure if that kind of selection would work, but it should.
var element = document.createElement('style');
element.setAttribute('type', 'text/css');
if ('textContent' in element) {
element.textContent = css;
} else {
element.styleSheet.cssText = css;
}
document.getElementsByTagName('head')[0].appendChild(element);
Can you add a style tag to the DOM, with the contents of the text-area in it? You may want to give it an id so you can change it later.
I recommend you start using a decent framework for your web/JavaScript development, personally I'd go with jQuery.
http://api.jquery.com/css/
There are some code snippets here that show you how to quickly set css properties for elements.