How can I change cssText in IE? - javascript

In the past I've been able to modify the CSS on a page via an inline style tag.
I know this sounds horrible but it's for custom CSS writing while working on a kind of WYSIWYG (not with text though).
I used to do something like:
tag.styleSheet.cssText = myrules;
I don't know when exactly, but at some point IE started saying "Invalid Argument" when I try this. The real crux is that doing tag.innerHTML = 'body {}' gives Unable to set value of the property 'innerHTML': object is null or undefined which doesn't happen in any other browser.
EDIT
To be clear I am using an inline style tag. I am not trying to use the inline style attribute.
<style type="text/css" id="mytag"></style>
How can I change the inside of that tag?
EDIT 2
Please see this fiddle:
http://jsfiddle.net/tTr5d/
It appears that my solution of tag.styleSheet.cssText is identical to using styleSheets property. You can comment out the last definition of cssText to see it working as proposed by #Teemu. So now I'm real lost why it's not working in my app. If anyone has ideas what could break that functionality that would be great. In the meantime I'll be tinkering around my app.

IE is limited to 32 stylesheets. I like to forget that fact apparently, which seems to include inline style tags, on top of <link>.
I changed my sandbox to turn on minification so it would put the files together.
Then my code worked.
So it appears that when you go over the limit and insert via JS, you don't get a real error until you try what I did.

You can get a reference to a styleSheet object only via styleSheets collection (or imports collection). If you refer direct to the style element, you'll just get a HTML-element. (Check properties in both objects within simple for..in-loop, and see the difference)
This works in all IEs, and results are rendered immediately:
document.styleSheets['mytag'].addRule('BODY', 'background-color:red');
More info in MSDN: styleSheet object

You can use jQuery. If it's the inline style, you can use the .attr() function.
$("#myElement").attr('style')
otherwise, you can see what .css() has to offer. You can use that to get and set various CSS styles.
Other CSS related jQuery methods

I never had much luck with style elements and IE's innerHTML.
The dom methods are surer, even if you need to branch for IE;
without jquery-
function addNewStyle(str, title){
var el= document.createElement('style');
if(title) el.title= title;
if(el.styleSheet) el.styleSheet.cssText= str;
else el.appendChild(document.createTextNode(str));
document.getElementsByTagName('head')[0].appendChild(el);
return el;
}

Related

Change CSS class content from javascript [Firefox/XUL]

I'm working on a firefox addon, and relies heavily on some dynamic changes with javascript. There are some UI elements (hbox/descriptions), which are styled using CSS classes. Now I wish to change the a CSS class defintion from javascript, without having to work element id's. Is it possible ?
Similar questions had been asked before, but most of them are using php to generate a CSS or jquery based changes.
Here's an example for my scenario:
My XUL :
<box id="firefox-addon-box">
<description id="description-1" class="description-text"> Some description </description>
<description id="description-2" class="description-text"> Some description </description>
</box>
My CSS :
.description-text {
font-size: 15px;
color: #fff;
}
So I wish to change the font-size in description-text class to say, 20px dynamically.
Now I know that we can change the style using individual id's, with a getElementById() and changing the style. But here I wish to change a class (which matters to a lot of elements), rather than to work on individual ids.
I also know that we can point to another class definition by setAttribute() and change 'class' - this would again require working on individual id's. In reality, I have plenty of UI elements (all pointing to one CSS class), and many values changed in a CSS class. So my question is, is there a way to directly change a CSS class definition from javascript, without having to work on element ids ?
Thanks for any help.
myVar = document.getElementsByClassName("description-text");
document.getElementsByClassName
I asked a very similar question last night and figured it out this afternoon, which I have just tested as working on Firefox 29.0b1-49.0a1, may work on earlier versions, not sure about newer versions once XUL is removed (SDK or WebExtensions), but as it is pure JS/DOM/CSS, I think it might work ok.
What I learned was that it is easier than I thought. Essentially, you find the specific style sheet, the specific rule, and edit the "style" of that rule using DOM, just like in HTML.
document.styleSheets[ i ].href
document.styleSheets[ i ].cssRules[ j ].selectorText
document.styleSheets[ i ].cssRules[ j ].style.fontSize
It all starts with the document.styleSheets array-like object, where i is the outer document.styleSheet loop index and j is the cssRules inner loop index.
The href is optional to consider, and is the URI of the style sheet. If known, and if the sheet is not dynamically generated, and if you are certain that the selector you want exists only in that one file, then you can use it to limit searching through all selectors in all the ~10 style sheets that Firefox loads by default, before your add-on's first sheet is ever loaded.
Otherwise, you loop through all document.styleSheets, (optionally skip if href doesn't match), then loop through all the cssRules on each style sheet, and see if the .selectorText matches your desired selector, in the case of the OP: .description-text (note that you need the leading . or # etc, exactly as it appears in the CSS file, for classes or IDs, etc).
When you find the selector you want, then you can modify the .style object (well documented at W3Schools DOM Style Object). In the OP example, we want to change the font-size style to 20px, which would be .style.fontSize = '20px'.
Using these fundamentals, a more generic function can be crafted, to more easily reuse. Perhaps a getCSSrule function which takes a required selector and an optional href argument, which will help you by getting the sheet and rule you want. Perhaps a getCSSsheet function if you want to use just the href to get a sheet. Perhaps a setStyle function to set the style and value. Perhaps a set of delCSSsheet and delCSSrule functions if you want to discard these rather than modify. And also an insCSSsheet and insertCSSrule function, maybe a createCSSsheet and createCSSrule as well.
This url (Totally Pwn CSS with Javascript), despite the name, and defunct Web Archive only status, and being 9 years old or more, is actually still relevant.
I will refrain from advising in favour of this method, but it is possible to also directly add css rules (or more complex remove them) doing the following
var css = '.description-text { font-size: 100px; }',
head = document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
head.appendChild(style);
There are rare occasions where this is a possible way to go and many situations where this is not the proper thing to do. You should never do this if you plan on overwriting the same thing multiple times (except if you remove the old rule first) and should only do this if you will use some other feature of CSS which builds upon this (e.g. new elements getting properly styles, 3rd party content getting properly styled, css animations, etc.).
I had to do the same few months ago. I solved it with jQuery with .addClass() and .removeClass() and more http://api.jquery.com/category/css/
Or if you want only Javascript use the HTML DOM from pure Javascript. Official documentation about that with examples: http://www.w3schools.com/js/js_htmldom_css.asp
Using JQuery you could use the css property :
$(".description-text").css({backgroundColor: "#ffe", borderLeft: "5px solid #ccc" });
All your elements that use the description-text class will be affected
Documentation of jquery css property
EDIT
Or with pure javascript
var elements = document.getElementsByClassName('description-text');
for(var i=0; i<elements.length; i++){
elements[i].style.backgroundColor = "#ffe";
elements[i].style.borderLeft = "5px solid #ccc";
//any style you want to apply
}
Documentation of javascript style

which one is given more preference for JavaScript or CSS?

here is my code
<!doctype html>
<html>
<head>
<style>
body {
color:red;
}
</style>
<script>
window.onclick = function(){
document.getElementsByTagName("body").color="blue";
}
</script>
</head>
<body>
here is some text for test
</body>
when i run it in my browser (initially it is red) and click in window it doesn't respond to click i mean it should change the color of text from red to blue but nothing happens. Where am i wrong?
Try this:-
Demo
This will add style attribute to the body element, which will override the css rule.
window.onclick = function(){
document.getElementsByTagName("body")[0].style.color="blue";
}
It should be style.color as color is a property of style property of element and even though it is body .getElementsByTagName returns a collection so you need to use document.getElementsByTagName("body")[0] to get the element and apply style to it.
And yes styles applied the element direclty will override the class css rule
Style property has more precedence over styles applied by class.
document.getElementsByTagName("body").color="blue";
This has more preference
Also color is a property of style attribute.
So your style should have looked something like this as getElementsByTagName returns a node list.
document.getElementsByTagName("body")[0].style.color="blue";
it is a better idea to use classes instead, cause it is lot cleaner.
Inline CSS is more powerful and overrides CSS defined anywhere else.As far as working of your code, I modified it a little bit like this:
window.onclick = function(){
//document.getElementsByTagName("body").color="blue";
document.body.style.color="blue";
}
DEMO here
You have an error in your JS. getElementsByTagName returns a NodeList (which is like an array), not a single element. You need to set the property on an element, not a NodeList. For example:
document.body.color="blue";
Setting the color property of the body element (IIRC, it's been a very long time since I went near that part of HTML) is equivalent to setting the color attribute. This is an obsolete presentational hint attribute.
The CSS specification says:
The UA may choose to honor presentational attributes in an HTML source document. If so, these attributes are translated to the corresponding CSS rules with specificity equal to 0, and are treated as if they were inserted at the start of the author style sheet. They may therefore be overridden by subsequent style sheet rules. In a transition phase, this policy will make it easier for stylistic attributes to coexist with style sheets.
So the style specified in the stylesheet should continue to apply.
On the other hand, setting a style.something property is equivalent to modifying the style attribute on an element.
document.body.style.color="blue";
In the cascade, !important declarations aside, properties set via the style attribute are most specific.
So of those two rules, the blue one would win.
JS inserts the changes inline, giving them pretty much the highest priority, unless you have !important in your css.
Check to see if you code (document.getElementsByTagName("body").color="blue";) works from the dev console (F12 for Chrome). There appears to be a problem with it. I can't help debug, however, as I usually do such actions via jQuery, and vanilla JS color changes are unintuitive for me.
js and css does not compete with each other, what you are doing is essentially javascript applying css to an html element, this means that its still css, that type of css is called inline css, . As others have said inline css has more precendence over normal css except if you use !important in your css rules
As to why your code is not working, because you are doing it wrong.
Change
document.getElementsByTagName("body").color="blue";
To
document.getElementsByTagName("body")[0].style.color = 'blue';
Here's a jsFiddle
http://jsfiddle.net/n2kqd/

css style not loaded when window.onload is triggered

Here is my problem : the css style is not initialised when window.onload is triggered.
<div id="foo"></div>
css file
#foo {
height: 200px
}
js file
window.onload = function(){
console.log(document.getElementById('foo').style.height);
};
the console displays : ""
the style must be in a different file, if the style attribute is used (style="height=200px") it works.
.style.height does not show styles that come from CSS rules. It only returns styles that have been explicitly set on that object, either in the HTML or via javascript, not styles inherited from CSS rules.
Instead, you must use window.getComputedStyle(). See the MDN doc for more details on how to use getComputedStyle() properly. Here's one example:
window.getComputedStyle(document.getElementById('foo'),null).getPropertyValue("height");
Note: for older versions of IE, you have to either install a polyfill for getComputedStyle or use el.currentStyle.
Element.style will only be set for inline styles(<div id="foo" style="height: 200px"></div>), to get the computed style use window.getComputedStyle
window.getComputedStyle(document.getElementById("foo"), null).getPropertyValue('height')
You can also consider working with jquery, a very popular javascript libraray with tons of very nice and powerfull features. And if you use the google cdn you don't need to worry about performance cause most browsers will already have the libray in cache.
To get the height of an element you would just use .height() The full explanation is here http://api.jquery.com/height/
Your code would look something like this:
$(document).ready(function() {
console.log($('#foo).height());
});
It may look a bit confusing at first, but you will quickly get the hang of it, and you will be writing js a lot faster and more compact with jquery. I never go without it!
What you really want is either offsetHeight or clientHeight. Try this:
window.onload = function(){
console.log(document.getElementById('foo').offsetHeight);
};

Can you target classes with jquery?

What I want to do is $('.class.img').css('cellpadding', variable);
It doesn't seem to be working. I tried googling to no avail. Any help would be appreciated. I'm trying to apply it to an image inside the element with the given class.
CSS applies the styling properties inline as in style="..." and does not modify the .class itself.
$('.class').css does not do anything.
$('.class').css('color','red') writes a color style
$('.class').css('color') reads the color style
So to target your img elements within an element with class "cellBox":
var borderx = "1px solid red";
$('.cellbox img').css('border',borderx);
(That sets border, but you can set padding the same way.)
Check working example at http://jsfiddle.net/SBjfp/2/
(Note that the jQuery documentation says that shorthand properties like padding or border are not supported; this mostly applies to getting the properties; setting [as above] usually works because it's supported by the underlying browser's implementation.)
The jQuery selector engine works perfectly well with class selectors.
The only thing clearly wrong with this (there might be other things, but you haven't provided any context (such as what the document looks like or when the statement is run)) is that css is a function, and you aren't calling it (i.e. css('foo')).

CKEditor: Class or ID for editor body

I have an instance of CKEditor on a page. I am trying to give the CKEditor's body a class or ID so it matches some styles I have defined in a stylesheet.
There is a API documentation that should give access to the respective DOM elements, but I can't seem to get it working. All objects I try to query that way turn out undefined.
Does anybody know how to do this, or how to properly address CKEditor's dom elements?
Edit: Thanks folks, nemisj's answer did it for me but for some reason, I don't get to set the "accepted" checkmark in this question.
Although that part of the API wasn't ported from 2.x at the time that this question was placed, now it's easier to use the bodyId and bodyClass config options.
Of course, the explanation by nemisj is good and can be useful for other things, but you must remember that each time that you switch away from design (to source view), the iframe is destroyed, so you'll need to reassign your attributes if you do it manually.
If you are talking about CKEditor( version 3), then there is a possibility to get any DOM instance inside the editor itself. Every CKEditor instance has reference to it's document via "document" property.
var documentWrapper = edit.document;
This reference represent some public wrapper for all CKEditor nodes, but it also has the direct reference to its node. You can retrieve by getting ["$"] property.
var documentNode = documentWrapper.$; // or documentWrapper['$'] ;
documentNode will represent the DOM instance of the document node inside the iframe. After you have the DOM instance, you can do whatever you want to do with DOM structure, Append, remove, replace classes, rebuild, etc. For example
documentNode.body.className = "zork";
I hope this should be enough.
I had the same problem today in trying to set the bodyClass like this:
CKEDITOR.replace( 'editor1',
{
fullPage : true,
bodyClass : 'myClass'
});
What I found is that in this version (3.3.1), if you set fullpage = true, setting the bodyId or bodyClass does not work, but if you set fullPage = false, it does work.
Hope this helps.
From the Manual:
<static> {String|Array} CKEDITOR.config.contentsCss
The CSS file(s) to be used to apply style to the contents. It should reflect the CSS used in the final pages where the contents are to be used.
config.contentsCss = '/css/mysitestyles.css';
config.contentsCss = ['/css/mysitestyles.css', '/css/anotherfile.css'];
Default Value:
<CKEditor folder>/contents.css
Don't know that editor, but as they all work the same way, you probably can't access the DOM elements created by the instance because they are created after the page has finished loading, and the DOM is ready as well. So, any new DOM elements added after that, theorically will not exist.
Still, you can try TinyMCE editor, wich has a "partnership" with jQuery javascript library to manipulate all you want, and the editor itself is pretty easy to change in almost every way.
Your queries may return undefined because the editor instances are placed inside an iFrame and your query is not looking there?
In config.js, write this code
config.bodyId = 'contents_id';
then you see body id in Ckeditor but when you want to access this id please use
$('#parent_id').find('iframe').contents().find('#within_iframe')
there $('#parent_id') means form_id or any parent which is simply way to access iframe. follow this code to access element in iframe

Categories

Resources