Learning JS - why do my elements not have any styles - javascript

I'm struggling with my web page
document.getElementById("btn").addEventListener("click", function(){
var g = document.getElementById("guitar");
console.log("Styles:", g.style.left,g.style.top, g.style.width,g.style.height, g.style.background);
});
<html>
<head>
<style>
.stage {
position:relative; width:400px;height:300px;background:brown;
}
.guitar {
position:absolute; left:20px; top:10px; width:150px; height:150px; background:#f63f63;
}
</style>
</head>
<body>
<input type="button" id="btn" value="Do something" />
<div class="stage" id="stage">
<div class="guitar" id="guitar" />
</div>
<body>
</html>
If you note the last line of code, I'm referring to the g for the guitar (I know bad naming etc, I'm just messing about here).
The question I have is, when I put a watch on g and expand the properties and navigate to style, there are none (there are no values in the list of styles). Even the background shows an empty value, yet the HTML is rendering it correctly.
Why can't I see the values in the watch Window?

Your g element doesn't have any style attributes...
You can see all of the style definitions on the 'computed style', as they are regular css declarations, and NOT defined via attributes.

Try window.getComputedStyle(g,null).getPropertyValue("height");
This should do the trick

From https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style:
The HTMLElement.style property returns a CSSStyleDeclaration object that represents only the element's inline style attribute, ignoring any applied style rules.
This means that if you have an element <div style="left: 10px;">, then its style object will contain the left value, but not if you only have a CSS rule div { left: 10px; }.
As already stated you can use getComputedStyle() to get the actual style applied by CSS.

Related

Styling content inserted in the Shadow DOM

I have this example:
http://codepen.io/dbugger/pen/IuDxw
Where I have an insertion point inside the Shadow DOM and I try to apply an style to it, making it disappear. But the image is still visible. I suspect there is some principle I haven't undestood propely from the Web Components.
Can someone explain me what am I doing wrong?
The trick is that the image is not, as kkemple mentioned, part of the Shadow DOM, but rather the Light DOM, which means it's not directly accessible from inside the component. It's user provided content, like the parameters passed into a class constructor in an OOP language. If at all possible, then, the user should provide their own styles to go with it.
That being said, there are definitely valid use cases where the component author wants to style user-provided content. Hiding certain parts of the user-provided markup based on attributes on the host, events (clicks), etc. is definitely one of those. In that case, wrap the <content> element in a Shadow DOM element and hide that:
<template>
<style>
.image {
display: none;
}
</style>
<div class="image">
<content></content>
</div>
</template>
http://codepen.io/anon/pen/rCGqD
On a side note: It is technically possible to apply styles directly to Light DOM elements, but be aware that in many cases this is considered leaking implementation details to the outside world. If the first solution works, use that instead.
It is not working is because your code is not in the shadow DOM, the div and image is still accessible through default styling. I forked your codepen and added the styling so you could see.
var host = document.querySelector(".host");
var template = document.getElementById( 'template' );
var root = host.webkitCreateShadowRoot();
root.appendChild( template.content );
<template id="template">
<style>
.wrapper {
display: none;
}
</style>
<div class="wrapper">
<content selector=".img"></content>
</div>
<h2>In the Shadows</h2>
</template>
<style>
img {
border: 1px solid black;
}
</style>
<div class="host">
<img class="img" src="http://placehold.it/200x275&text=1" alt="" />
</div>
http://codepen.io/kkemple/pen/euBKs
I didn't go in to why it was not creating a shadow DOM element as your JS looked correct to me but here is a great article on shadow DOM web-ponents:
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/

Use of Pseudo-Elements in Polymer.js

I'm taking my first steps with Polymer.js, and I'm struggling with creating a pseudo-element.
This is what I tried:
In my host document:
<style type="text/css">
#host::x-a-cool-test {
color: green;
}
</style>
<div id="host">
<my-custom-element></my-custom-element>
</div>
In my custom element:
<element name="my-custom-element">
<template>
<style>
#host {
* { display: block; color: blue; }
}
</style>
<div id="group" pseudo="x-a-cool-test">
just some text
</div>
</template>
<script>
Polymer.register(this);
</script>
</element>
That will show just my text in blue. That is correct, because according to this, rules wrapped in a #host have higher specificity than any selector in the parent page.
My question:
If I delete color: blue from inside the #host block in my template, the text is shown in black and NOT green as I would expect. Why is that???
I believe this plunker works how you want it to. Basically, the CSS pseudo-element has to be applied directly to the custom element (in this case the my-custom-element). I switched id="host" to it (instead of its parent div) and the code worked.
<div>
<my-custom-element id="host"></my-custom-element>
</div>
Note: The overriding nature of #host may change. Some (myself included) think it should be more for providing default, fallback styles. In this case rules in the host document will override #host rules instead of the other way around.

How do I place a background image above body's background image?

I have set a background image in body and in .wrap. My question is how do I place a background above all them? It is done with CSS however I didn't figure it yet.
I place all my code in http://jsfiddle.net/7sdnU/
Thank you.
<body>
<div class="wrap">
</div>
</body>
With z-index:
http://jsfiddle.net/7sdnU/2/
The html element can also be styled, so you can shift the background layers back one element. Something like this:
html {
background:url(bottom-background.png);
}
body {
background:url(middle-background.png);
}
wrap {
background:url(top-background.png);
}
/* Make sure everything takes up the whole viewport */
html, body, .wrap{
height:100%;
width:100%;
padding:0;
margin:0;
}
Demo: http://jsfiddle.net/7sdnU/15/
You could also just add another wrapper div:
<body>
<div class="wrap">
<div class="inner">
</div>
</div>
</body>
Then apply the "top" background to .inner
However, CSS3 allows multiple backgrounds, so you may want to have a look at that - that's best solution if you can use it, but it's not fully supported.

Why won't click events work on a span but the will work on an a?

Can anyone think of a reason why a click event would work on an a tag, but not on a span? I am making a rich text editor and have a bold button that when clicked is supposed to make the text bold. It only works when I use an anchor element. I tried using a span and nothing happens. The html is the only thing that I am changing so I don't think it is a JavaScript problem.
$(document).ready(function(){
//creates the toolbar~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$('#rte').focus()
var tools = [];
tools.push('underline');
tools.push('italic');
tools.push('bold');
tools.push('justifyCenter');
tools.push('justifyLeft');
tools.push('justifyRight');
var simple_toolbar = function(){
//iterates through each tool and adds its functionality to the editor
$.each(tools, function(index,value){
$('#'+value).click(function(event){
document.execCommand( value, false, null);
$('#rte').focus();
return false;
});
//end of click function
});
//end of each iterator
};
//end of simple toolbar function
//invokes the simple toolbar.
simple_toolbar();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
});
//end of the DOM loader
<!doctype html>
<html>
<head>
<title>An HTML5 page</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</head>
<body>
<div id="wrapper">
<div id="controls">
<!-- The only button working here is the bold because it is an <a> -->
<span id="italic"></span>
<span id="underline"></span>
<span id="justifyLeft"></span>
<span id="justifyCenter"></span>
<span id="justifyRight"></span>
</div><!--end of controlls div-->
<div contenteditable="true" id="rte"></div>
<textarea id="my_form" rows="8" cols="58" ></textarea>
</div><!--end of the wrapper div-->
</body>
</html>
#bold{
display:block;
width:30px;
height:30px;
background-image:url('http://dl.dropbox.com/u/25006518/bold.png');
}
#italic{
display:block;
width:30px;
height:30px;
background-image:url('http://dl.dropbox.com/u/25006518/italic.png');
}
#underline{
display:block;
width:30px;
height:30px;
background-image:url('http://dl.dropbox.com/u/25006518/underline.png');
}
#justifyCenter{
display:block;
width:30px;
height:30px;
background-image:url('http://dl.dropbox.com/u/25006518/underline.png');
}
#justifyRight{
display:block;
width:30px;
height:30px;
background-image:url('http://dl.dropbox.com/u/25006518/underline.png');
}
#justifyRight{
display:block;
width:30px;
height:30px;
background-image:url('http://dl.dropbox.com/u/25006518/underline.png');
}
if you update your jQuery to v1.7.1 you can use the .on() function. This will then allow you to bind the click method to the span using an id.
$(document).ready(function(){
$("#yourContainer").on("click", "#yourSpanID", function(){
// The code to make everything bold
});
});
Any DOM element can listen for a "click" event, and in fact the code as you presented it is working in that sense. If you precede your call to document.execCommand with an alert statement you'll find that the alert occurs anytime you click on any of the buttons and not just the "bold" button.
You are using your span tags the wrong way; span tags are for coloring and styling one word in a sentence.
The best thing to do is use the <ul> tag; you do have to end it. Like this:
<html>
<body>
<ul>
<li>"put your text here"</li>
<li>"put your text here"</li>
<li>"put your text here"</li>
</ul>
</body>
</html>
Now assuming you have a style sheet you can style the or user list in CSS
like this:
html{ }
body{ }
ul{ }
ul li{ float:left; this will define how the tags are displayed }
ul li a{ "from here down define how links act." }
ul li a:visited{ color:put a color here like light blue or something;}
ul li a:hover{ color:same with this; }
ul li a:active{color:same with this; }
Also check your hierarchy it will help you in the long run. Hope I helped.
I think the variable 'value' gets destroyed when the iteration is done. You could make a global function that takes care of the actual click handle and assign this function to the buttons in an iteration.
You could grab the ID of the button clicked in the global function and use that to parse as an argument in the execCommand method.
So it's a scope issue, to be clear.
Try setting the spans to display: inline-block.
This is not the best solution, but the only reason I wanted to use spans is so that the page would not jump to the top when you clicked an anchor tag with an href="#". I decided to just use the anchor tags, but instead of using href="#" I am using href="#bold". apparently when you use an id selector as an href attribute the page will jump to the spot on the page where that element is. Still not sure why it won't work with other elements. I tried just getting rid of the iterator and writing out a separate click event for each button, but it still only worked with an anchor tag.
Still trying to research the 'onclick' event more deeply, but one of two things present:
1) onclick is reserved for 'a' and 'input' tags, only (will set out to verify this); or,
2) a more complex method is required on the event handler. See, W3C: http://www.w3.org/TR/html5/webappapis.html#event-handler-content-attributes
Side Note: Having settled on 'a', one could reduce the style sheet to just background URL on the 'id', and add a descendent selector on the controls:
#controls a {
display: block;
width: 30px;
height: 30px;
}
When you attach a mousedown event to the span, which you cancel, then span also works. Don't know which (if at all) spec defines different behavior on spans and anchors, but it works now.
See the jsFiddle. Changed the following part:
$('#'+value).click(function(event){
document.execCommand( value, false, null);
$('#rte').focus();
return false;
}).mousedown(function(e){
e.preventDefault();
});
Instead of click event you should use either live or on
This will bind the click event to all elements even though they are dynamically created.
First of all, use the Doctype:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
and then, for the CSS of a span, use:
span{
display: block;
display: inline-block;
}

Dynamically resize text to fill div [duplicate]

This question already has answers here:
Auto-size dynamic text to fill fixed size container
(21 answers)
Closed 8 years ago.
I have been searching for a solution to resize the text size in a div to make the text fill out the entire div height and width, with no avail.
I have made some images to help understand this problem:
So this is a simple div with a height and width set. This height and width does not change, the text in the box does! So what I want to do is to make that text fill the whole width and height of the div just like in the image below.
I have been working on the simple example below and I simply cannot find out how to do this. I have tried setting relative font-sizes with percentage, doing things with overflow,
text-aligning all not giving me the result I want.
<html>
<head>
<title>Test</title>
<style type="text/css">
#box1, #box2{
width: 400px;
height: 300px;
color: white;
margin: 10;
font-size:larger;
text-align:justify;
letter-spacing: 100%;
}
#box1 { background-color: green;}
#box2 { background-color: blue;}
</style>
</head>
<body>
<div id="box1">
Llorem ipsum foo bar baz
</div>
<div id="box2">
Foobar
</div>
</body>
</html>
Is this problem even solvable with simple CSS or will I have to do some javascript/jQuery?
As I said this may be a dupe of
Auto-size dynamic text to fill fixed size container.
The OP did a jQuery plugin for that means, you can download it here
It doesn't seem to up to date though!
Good luck!
You can use FitText.js (github page) to solve this problem. Is really small and efficient compared to TextFill. TextFill uses an expensive while loop and FitText don't.
Also FitText is more flexible (I use it in a proyect with very special requirements and works like a champ!).
HTML:
<div class="container">
<h1 id="responsive_headline">Your fancy title</h1>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jquery.fittext.js"></script>
<script>
jQuery("#responsive_headline").fitText();
</script>
You also can set options to it:
<script>
jQuery("#responsive_headline").fitText(1, { minFontSize: '30px', maxFontSize: '90px'});
</script>
CSS:
#responsive_headline {
width: 100%;
display: block;
}
And if you need it, FitText also has a no-jQuery version.
My guess is, this is not the kind of thing you can do with CSS. There isn't any kind of notion of percentage in fonts (as far as I know). You'll probably need to use Javascript.

Categories