Dynamically adding and updating style block - javascript

Currently I am doing something like this:
function newFont(newSizeA, newSizeB) {
var elem = document.getElementById('style-1');
if (typeof(elem) != 'undefined' && elem != null) {
removeChildNodes(elem); // function that removes child
nodesremoveNode(elem);
}
var styleText = ".a { font-size:" + newSizeA + "px; } .b { font-size:" + newSizeB + "px; }";
var x = document.createElement('style');
x.setAttribute("type", "text/css");
x.setAttribute("id", "style-1");
if (x.styleSheet) { // for IE
x.styleSheet.cssText = styleText;
}
else { // others
var textnode = document.createTextNode(styleText);
x.appendChild(textnode);
}
}
The point of it is that there is a loop happening and another function is measuring the size of a menu to make sure it fits in a spot when someone is changing the font size.
I am wondering, is there a better way to create and manipulate elements? I need to change padding and font size but right now as you can see I'm just removing it entirely and recreating it.

I think the easiest way is to prepare several css-styles for different font-sizes and then attach them as so:
function newFont(targetElement, fontSize) {
document.getElementById(targetElement).className = fontSize;
}
newFont('myElement','bigFont');
the css-style would then be:
.bigFont {
font-size: 5em;
}
if you want to add the style do:
document.getElementById("MyElement").className += "MyClass";
if you want to remove styles or check if the style is already apllied please refer to this perfect answer:
Change an element's class with JavaScript

Related

Change the CSS value from a file

I have a keyboard.css file and a keyboard.js file, I am trying to change a css rule
.ui-keyboard div { font-size: 1.1em; }
I want to change the font size. is there a way to do this without using
$(".ui-keyboard div").css()?
I want to change the value before the element is rendered, I want to pass the value in the construction of an element
$('.onScreenKeyboard').keyboard({
zoomLevel: 2
});
Edit: to clarify this a bit, the goal is to have a way to change the font-size, without having to go and edit the value on the CSS. I want to create an option in the library that does this:
Inside the constructor I check for options and I change the element,
//set Zoom Level
if(o.zoomLevel){
//Change CSS Here.
}
Maybe you're looking for something like CSSStyleSheet's insertRule and deleteRule.
Here is some code I wrote a while ago to let me modify CSS rules
function CSS(sheet) {
if (sheet.constructor.name === 'CSSStyleSheet') this.sheet = sheet;
else if (sheet.constructor.name === 'HTMLStyleElement') this.sheet = sheet.sheet;
else throw new TypeError(sheet + ' is not a StyleSheet');
}
CSS.prototype = {
constructor : CSS,
add: function (cssText) {
return this.sheet.insertRule(cssText, this.sheet.cssRules.length);
},
del: function (index) {
return this.sheet.deleteRule(index);
},
edit: function (index, cssText) {
var i;
if (index < 0) index = 0;
if (index >= this.sheet.cssRules.length) return this.add( cssText );
i = this.sheet.insertRule(cssText, index);
if (i === index) this.sheet.deleteRule(i + 1);
return i;
}
};
You'd use it by giving the constructor CSS your <style> node, or it's StyleSheet directly, then using .edit with the index of the rule and the new rule you want. e.g.
// get StyleSheet
var mycss = new CSS(document.querySelector('style[src="keyboard.css"]'));
// edit rule 0
mycss.edit(0, '.ui-keyboard div { font-size: 5em; }');
Add the following css to the element, initially you wont display it until you run through your library change the style properties then display it.
.ui-keyboard div {
font-size: 1.1em;
display: none;
}
You can also change the font size without jQuery by doing something like:
[element].style.fontSize = "25px";

How to return a javascript set style property to CSS default

I'm trying to work out how, after changing style properties with javascript, I can revert to the value in the stylesheet (including the units).
In the example below, I'd like the output to read 100px (the value in the CSS), rather than 10px, as getComputedStyle gives.
I'd also keep the dummy div at top:25px, so removing the style property won't work.
The best I have is cloning the node and reading the height and storing in a property (http://jsfiddle.net/daneastwell/zHMvh/4/), but this is not really getting the browser's default css value (especially if this is set in ems).
http://jsfiddle.net/daneastwell/zHMvh/1/
<style>
#elem-container{
position: absolute;
left: 100px;
top: 200px;
height: 100px;
}
</style>
<div id="elem-container">dummy</div>
<div id="output"></div>
<script>
function getTheStyle(){
var elem = document.getElementById("elem-container");
elem.style.left = "10px";
elem.style.top = "25px";
var theCSSprop = window.getComputedStyle(elem,null).getPropertyValue("left");
document.getElementById("output").innerHTML = theCSSprop;
}
getTheStyle();
</script>
Just clear the inline style you wish to fallback to original stylesheet on.
elem.style.left = null;
The style object has a built-in removeProperty() method, so you could do something like:
elem.style.removeProperty('left');
As far as I know, this will have exactly the same effect as setting the property to null, as abaelter suggested. I just thought it might be worth including for the sake of completeness.
Combining abaelter's answer and http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/ gives us the below function:
var getCssStyle = function(elementId, cssProperty) {
var elem = document.getElementById(elementId);
var inlineCssValue = elem.style[cssProperty];
// If the inline style exists remove it, so we have access to the original CSS
if (inlineCssValue !== "") {
elem.style[cssProperty] = null;
}
var cssValue = "";
// For most browsers
if (document.defaultView && document.defaultView.getComputedStyle) {
cssValue = document.defaultView.getComputedStyle(elem, "").getPropertyValue(cssProperty);
}
// For IE except 5
else if (elem.currentStyle){
cssProperty = cssProperty.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
cssValue = elem.currentStyle[cssProperty];
}
// Put the inline style back if it had one originally
if (inlineCssValue !== "") {
elem.style[cssProperty] = inlineCssValue;
}
return cssValue;
}
Placing in your example code and testing:
console.log("getCssStyle: " + getCssStyle("elem-container", "left"));
Gives us getCssStyle: 100px allowing you to see the original CSS value. If you just want to revert the value then do as abaelter says and null the CSS value you want to revert.

changing CSS class definition

Suppose I have this class:
.MyClass{background:red;}
This class applies to several divs. I want to change the color of the background to orange by changing the color defined in MyClass.
Now, I know I could do $('.MyDiv').css('background', 'orange');
But my question is really this: how do I change the CSS class definition so that MyClass elements now have background:orange;? I want to be able to change several CSS color properties from one color to another.
Thanks.
Actually altering your stylesheet is pretty challenging. Much more easily, though, you can switch out your stylesheet for a different one, which may be sufficient for your purposes. See How do I switch my CSS stylesheet using jQuery?.
For actually altering the stylesheet content, How to change/remove CSS classes definitions at runtime? will get you started.
It is difficult to find the rule you want because you have to iterate through the document.styleSheets[i].cssRules array. (and compare your class name with the selectorText attribute)
So my solution to this problem is to add a new CSS class, remove the old CSS class from the HTML element and add this class instead of it.
var length = getCssRuleLength();
var newClassName = "css-class-name" + length;
//remove preview css class from html element.
$("#your-html-element").removeClass("css-class-name");
$("#your-html-element").removeClass("css-class-name" + (length-1));
$("#your-html-element").addClass(newClassName);
//insert a css class
insertCssRule("." + newClassName + ' { max-width: 100px; }', length);
function getCssRuleLength() {
var length = 0;
if (document.styleSheets[1].cssRules) {
length = document.styleSheets[1].cssRules.length;
} else if (document.styleSheets[1].rules) { //ie
length = document.styleSheets[1].rules.length;
}
return length;
}
function insertCssRule(rule, index) {
if (document.styleSheets[1].cssRules) {
document.styleSheets[1].insertRule(rule, index);
} else if (document.styleSheets[1].rules) { //ie
document.styleSheets[1].addRule(rule, index);
}
}
Here's my answer in case anyone stumbles upon this. Give your elements a new class name that doesn't already exist, then dynamically add a style segment:
var companyColor = 'orange' //define/fetch the varying color here
var style = '<style>.company-background {background-color: ' + companyColor + '; color: white;}</style>';
$('html > head').append($(style));
//give any element that needs this background color the class "company-background"
You have 2 options
add a new stylesheet that overrides this .MyClass
have a second class with the different property, and change the class Name on these elements
Looking at your question, I think a better approach is to switch MyClass with something else using JavaScript rather than to change the properties of the class dynamically.
But if you are still keen you can switch CSS stylesheets with jQuery http://www.cssnewbie.com/simple-jquery-stylesheet-switcher/
var changeClassProperty = function(sheetName, className, propertyName, newValue, includeDescendents) {
var ending = '$';
setValue = '';
if (includeDescendents === true) {
ending = '';
}
if (typeof(newValue) != 'undefined') {
setValue = newValue;
}
var list = document.styleSheets;
for (var i = 0, len = list.length; i < len; i++) {
var element = list[i];
if (element['href'] && element['href'].match(new RegExp('jquery\.qtip'))) {
var cssRules = element.cssRules;
for (j = 0, len2 = cssRules.length; j < len2; j++) {
var rule = cssRules[j];
if (rule.selectorText.match(new RegExp(className + ending))) {
cssRules[j].style.backgroundColor = setValue;
console.log(cssRules[j].style.backgroundColor);
}
}
}
}
}
changeClassProperty('jquery.qtip', 'tipsy', 'backgroundColor', 'yellow');
You'd be much better off adding and removing classes instead of attempting to change them.
For example
.red {
background: red;
}
.orange {
background: orange;
}
$('#div').click(function(){
$(this).removeClass('red').addClass('orange');
});

how to get value of h2 tag for a div inside other div with id using javascript

I have a div with id, which has some other div's without id.
Some thing like:
<div class="mainDivClass" id="mainDiv">
<div class="subDivClass">
<h2>one</h2>
Hello One!!
</div>
<div class="subDivClass">
<h2>two</h2>
Hello Two!!
</div>
<div class="subDivClass">
<h2>three</h2>
Hello Three!!
</div>
</div>
In my javascript, I am looping through above div like:
var divLists = document.getElementById('mainDiv').firstChild.childNodes;
for (var i = 0; i < tabLists.length; i++) {
var anchor = divLists[i].firstChild;
var iconFile;
if(i==0)
{
iconFile = 'details.png';
}
else
{
iconFile = 'search1.png';
}
anchor.style.backgroundImage = 'url(' + iconFile + ')';
anchor.style.backgroundRepeat = 'no-repeat';
anchor.style.backgroundPosition = '1px 2px';
anchor.className = 'toplevel-tab';
}
As shown, I am setting iconFile variable on value of i. So for i = 0, it would be details.png while for all others, it would be search1.png.
Now, I want to decide the iconFile variable value based on the h2 value of the element.
That is, if h2 is banana, banana.png will go in iconFile but if h2 is orange, orange.png will be selected.
How to get h2 value inside javascript ?
Thanks for reading!!
Nik
Don't use innerHTML, it's an unreliable proprietary Microsoft method; should you get used to using it you will immediately begin having problems if you start coding at an application level and not be able to figure out why. Stick to using DOM specifications instead.
An example that you can obviously throw in to a loop...
document.getElementById('subDivClass').getElementsByTagName('h2').firstChild.nodeValue
.parentNode - The parent element of the currently referenced element.
.parentNode.parentNode.parentNode - You can use this as much as you want to go up or around the DOM.
.childNodes[0] - Index of child elements, does NOT contain reference to text nodes AFTER an element (use treewalker for that).
.nodeValue - The text value of a node, do NOT use innerHTML.
.textContent - Gets or sets the text of an element (but no child elements); a bit easier than nodeValue though it still has reasonable limitations.
.previousSibling - The element BEFORE the reference element, not a child/parent.
.nextSibling - The element AFTER the reference element, not a child/parent.
You can reveal all objects (e.g. methods, properties and other objects) for any object using the in operator to discover what else is available to you...
for (i in document.getElementById('mainDiv')) {alert('i = '+i);}
It should be noted that if you're stuck using the HTML parser .nodeName will be all uppercase (e.g. the old Internet Explorer way) versus using the XML parser (application/xhtml+xml) the .nodeName will properly return the element's name as lowercase (unless you're really in to the 90's style or something).
It should also be noted that when you use previousSibling and nextSibling that line breaks alone will create a textNode and those line breaks will mess with CSS (setting the font-size to 5px will generally eliminate this).
If you want all the H2 elements inside the mainDivClass you can use the getElementsByTagName method:
var outerDiv = document.getElementById("mainDiv");
var h2s = outerDiv.getElementsByTagName("h2");
This returns all the H2 elements as an array of elements.
var answer = function () {
var parent = document.getElementById("mainDiv"),
h2 = parent.getElementsByTagName("h2"),
a = h2.length,
b;
for (b = 0; b < a; b += 1) {
switch (h2[b].innerHTML) {
case "one":
//do something
break;
case "two":
//do something
break;
default:
//do something else
break;
}
}
};
The h2 value will be used as below:
for (var i = 0; i < tabLists.length; i++) {
var anchor = tabLists[i].firstChild;
var iconFile;
if(tabLists[i].firstChild.innerHTML == "Tab 0")
{
iconFile = 'one.png';
}
else if(tabLists[i].firstChild.innerHTML == "apple")
{
iconFile = 'apple.png';
}
else if(tabLists[i].firstChild.innerHTML == "orange")
{
iconFile = 'banana.png';
}
else if(tabLists[i].firstChild.innerHTML == "banana")
{
iconFile = 'orange.png';
}
anchor.style.backgroundImage = 'url(' + iconFile + ')';
anchor.style.backgroundRepeat = 'no-repeat';
anchor.style.backgroundPosition = '1px 2px';
anchor.className = 'toplevel-tab';
}

How to remove default document style from an element using Javascript

I am trying to create a div element which shows some text as popup. But the problem is when i create the element using javascript, the div already contains the default style which is defined in document style sheet or external css. Like for example:
popup = document.createElement("div");
popup.setAttribute("id","myElement");
popup.style.left = "100px";
popup.style.top = "100px";
popup.style.width = "100px";
popup.style.height = "100px";
document.body.appendChild(popup);
and now when it shows up, it already has colors, borders etc because in css there is this div style which is being applied on this element. I want it to not inherit anything which is defined for the document itself, how can i do that, or may be overwrite the original style??
A way to achieve this is to override all of the available properties set with the css in this document. But with JavaScript is a lot of work.
Better way is to add an id or class to the newly created element. The style should have all of the properties that are applicable for the type of element you are creating. If you miss a property it will be set from the present css.
I would give these new divs a specific class name and link a custom stylesheet that resets all properties for that class to the desired defaults (ensuring that the linked styles have the necessary precedence in the cascade). Moving this reset into your JavaScript sounds like a bad idea.
So I made something like this. It may not be ideal solution but it atleast does what i wanted:
function displayMenu(){
var popup;
//see if there is already default style defined in the document
var styleSheets = document.styleSheets;
var size = styleSheets.length;
var cssRules = new Array();
var rules = "";
var css, len, st, sp;
for (i=0;i<size;i++){
cssRules[i] = styleSheets[i].rules || styleSheets[i].cssRules;
for (j=0;j<cssRules[i].length;j++){
if(cssRules[i][j].cssText.search(/div/i) != -1){
css = cssRules[i][j].cssText;
css = css.substr(((css.search("{"))+1),((css.search("}"))-(((css.search("{"))+1))));
if((css.search("{") == -1) && (css.search("}") == -1)) {
//no of css-properties in this specific rule
len = css.split(";").length - 1;
for (k=0;k<len;k++){
st = css.search(";") + 1;
rules += css.substr(0,(css.substr(0,st).search(":")+1)) + "0\n";
css = css.substr(st);
}
} else {} //ignore this rule
}
}
}
var reset = '.myStyle { '+ rules +' }\n';
//now create a css Class which overwrite default document properties for this <div> element
var myStyle = document.createElement('style');
myStyle.type = 'text/css';
//TODO: should be replaced with style from arguments
myStyle.innerHTML = reset;
document.getElementsByTagName('head')[0].appendChild(myStyle);
//start creating the popup menu:
var popup;
popup = document.createElement("div");
popup.setAttribute("id","guide_popup");
popup.setAttribute("class","myStyle");
//now define own style rules: (All basic properties need to be defined as there is none by defualt now)
popup.style.top = top;
popup.style.left = left;
popup.style.width = width;
popup.style.height = height;
popup.style.zIndex = index;
//TODO: should be replaced with str in aruguments
var popup_text = document.createTextNode("This is my sample text");
popup.appendChild(popup_text);
//finally process the DOM
document.body.appendChild(popup);
}

Categories

Resources