This should be a really simple problem, but I can't quite figure out what I am doing wrong. I am trying to access the CSS property 'border-bottom' like this:
var temp = $('#divName').css('border-bottom');
Unfortunately, after this, temp contains the string ""
Does anyone know why this is not working or what I should do differently to make it function? Thanks.
The styles have to be more specific. Since border-bottom is a short-property for other properties (similar to background, to name a common one), the property has to be explicitly given.
var elem = $('#divName');
var border_width = elem.css('border-bottom-width');
var border_color = elem.css('border-bottom-color');
var border_style = elem.css('border-bottom-style');
var border_bottom = border_width + " " + border_color + " " + border_style;
Fiddle: http://jsfiddle.net/6wRj4/
See also: MDN: border-bottom short-hand.
Check to ensure that $('#divName') does select a single element. You can use array syntax on a jquery object to get back the underlying DOM object. You should also check (for example, using Firebug) to make sure that the DOM element you're looking at does have the style that you're looking for.
If both of those things are working correctly, you might try using the more granular border properties... border-bottom-style, border-bottom-width, etc.
Try with document.getElementById("divName").style.borderBottom;.
Related
I generate the numbering of my headers and figures with CSS's counter and content properties:
img.figure:after {
counter-increment: figure;
content: "Fig. " counter(section) "." counter(figure);
}
This (appropriate browser assumed) gives a nice labelling "Fig. 1.1", "Fig. 1.2" and so on following any image.
Question: How can I access this from Javascript? The question is twofold in that I'd like to access either the current value of a certain counter (at a certain DOM node) or the value of the CSS generated content (at a certain DOM node) or, obviously, both information.
Background: I'd like to append to links back-referencing to figures the appropriate number, like this:
<a href="#fig1">see here</h>
------------------------^ " (Fig 1.1)" inserted via JS
As far as I can see, it boils down to this problem:
I could access content or counter-increment via getComputedStyle:
var fig_content = window.getComputedStyle(
document.getElementById('fig-a'),
':after').content;
However, this is not the live value, but the one declared in the stylesheet. I cannot find any interface to access the real live value. In the case of the counter, there isn't even a real CSS property to query.
Edit: Digging deeper and deeper through the DOM specs, I found the DOM Level 2 Style Counter interface. This seems to a) allow access to the current counter value and b) be implemented in Firefox, at least. However, I have no idea on how to use it. My current approach died tragically after this Firebug output:
// should return a DOM 2 Counter interface implementation...
window.getComputedStyle(fig_a_element, ':after')
.getPropertyCSSValue("counter-increment")[0]
.getCounterValue();
[Exception... "Modifications are not allowed for this document" code: "7"
nsresult: "0x80530007 (NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR)"
location: "http://localhost/countertest.html Line: 71"]
Any idea, how this could be brought to life would be highly appreciated.
Edit 2: Apparently I misinterpreted the Counter object of DOM Level 2 Style. It, too, has no property to return the current counter value. This makes the above approach invalid.
New approach: Is there a possibility to read the content of a pseudo-element via the DOM? That is, can I select the pseudo-element (treeWalker comes to mind) and then get its nodeValue? (If you start to type 'jQuery' now, please reconsider to change that term into 'Sizzle'...)
I cannot find any interface to access the real live value. [of the counter]
Yeah. I don't think there is one. Sorry.
The only thing I can think of would be to go through every element (including its :before/:after pseudo-elements) before the element in the document, looking for counters and adding up how many there are.
Obviously that's hideous. If you're going to try to reproduce the browser's own counter mechanism it would probably be easier (and much more compatible, given IE<=7's lack of counter/content support) to just replace it with your own script-based counters. eg. something along the lines of:
this
<div class="counter level=0">...</div>
<img id="prettypicture" class="counter level=1" alt="ooo, pretty"/>
window.onload= function() {
var counters= Node_getElementsByClassName(document.body, 'counter');
var indices= [];
for (var counteri= 0; counteri<counters.length; counteri++) {
var counter= counters[counteri];
var level= Element_getClassArgument(counter, 'level');
while (indices.length<=level)
indices.push(0);
indices[level]++;
indices= indices.slice(level+1);
var text= document.createTextNode('Figure '+indices.join('.'));
counter.parentNode.insertBefore(text, counter.nextSibling);
if (counter.id!=='') {
for (var linki= document.links.length; linki-->0;) {
var link= document.links[i];
if (
link.hostname===location.hostname && link.pathname===location.pathname &&
link.search===location.search && link.hash==='#'+counter.id
) {
var text= document.createTextNode('('+indices.join('.')+')');
link.parentNode.insertBefore(text, link.nextSibling);
}
}
}
}
};
read this:
http://www.w3.org/TR/CSS2/generate.html#propdef-content
Generated content does not alter the
document tree. In particular, it is
not fed back to the document language
processor (e.g., for reparsing).
https://developer.mozilla.org/en/CSS/Getting_Started/Content
Content specified in a stylesheet does not become part of the DOM.
so for this reason the getComputedStyle will not work in this case; i think the only way, is to perform a classic loop through as someone has described below!
I would port your css to Javascript, this enables you to get the figure caption and also you get greater browser coverage. Using jQuery you'd do something like this:
$(function() {
var section = 0;
$(".section").each(function() {
section++;
var figure = 0;
$(this).find("img.figure").each(function() {
figure++;
var s = "Fig. " + section + "." + figure;
$(this).attr({alt:s}).after(s);
});
});
});
Then you could do:
<div class="section">blabla <img id="foo" src="http://www.example.com/foo.jpg"></div>
<p>Lorem ipsum dolor sit amet see here</p>
<script type="text/javascript">
$(function() {
$("a.figurereference").each(function() {
var selector = $(this).attr("href");
var $img = $(selector);
var s = $(this).text() + " (" + $img.attr("alt") + ")";
$(this).text(s);
});
});
</script>
Though I agree that doing this using CSS would be very neat.
I cannot find any interface to access the real live value.
If you can't get the value from window.getComputedStyle, it seems that it would be impossible.
More importantly, while it can do it, I think this might be abusing CSS since you're breaking the barrier between content and presentation at this point.
Check out this related question What are good uses of css “Content” property?
I have dynamically created elements on the page, a picture and three buttons which are created upon clicking the main button.
All of this works, but now I am trying to change the display on the dynamically created div with the pics to "none".
More than one issue arises here for me, first I cannot find out how to make the div "images" the target, or select it.
I am trying to get one function to do this for all the elements, they are all structured equally just the pictures are different.
function hidePic(arrayPos){
var elem = document.getElementsByClassName("closingButton") + "[" + arrayPos + "]",
finalTarget = elem.getElementsByClassName("images")[0];
finalTarget.style.display = "none";
}
document.getElementsByClassName("closingButton")[0].addEventListener("click", function(){
hidePic(0);
});
This is the relevant code, lines 4 to 10. If this is commented out, the rest of the code works, but as it is I get entirely unrelated errors in dev Tools.
Click this link to see Codepen.
So the question is, how can I best implement the above code?
So just working on the code above you can do this in order to make it work for all instances. First let me point out that this:
var elem = document.getElementsByClassName("closingButton") + "[" + arrayPos + "]";
will never work. That line is building a string. What you really want to make that line work is:
var elem = document.getElementsByClassName("closingButton")[arrayPos];
But even that I find unnecessary. Take a look at this code.
function hidePic (elem) {
var finalTarget = elem.getElementsByClassName("images")[0];
finalTarget.style.display = "none";
}
var closingButtons = document.getElementsByClassName("closingButton");
var index = 0, length = closingButtons.length;
for ( ; index < length; index++) {
closingButtons[index].addEventListener("click",
function () {
hidePic(this);
}
);
}
This first finds all elements with the class closingButton. Then for each one we attach a click event listener. Instead of attempting to pass some index to this hidePic function we already have our function context which is what you seem to be trying to find in the function so lets just pass that and use it to find the image inside.
Let me know if you have any questions. I took a look at your codepen as well. I am not sure you should be forcing all that interactive HTML into a button element honestly, which itself is considered an interactive element. Not sure that meets the HTML spec. Perhaps add that HTML below the button. I bet when you click on things inside of that button it will register as clicks on the button as well unless you remove the event upon inserting your elements but then it seems like its getting too complicated for the simple stuff you are trying to do here.
The codepen complains because there is no element with the "closingButton" class, so it's trying to call addEventListener on nothing, but I'm doubting that's the actual error you're seeing.
It's also worth nothing that I think this:
var elem = document.getElementsByClassName("closingButton") + "[" + arrayPos + "]",
is excessive.
var elem = document.getElementsByClassName("closingButton")[arrayPos];
should be sufficient. Also not the syntax error at the end of the same line: it should be ; not ,. If this is the error in your code it could explain why you were getting "unrelated errors" syntax errors can cause misleading problems that are supposedly in other areas of the code!
Lastly, I'd highly recommend using JQuery to do your selection magic - it's exactly what it was designed for. If you're averse to using JS libraries, fair enough, but it would make your code a lot simpler and you can have reasonable confidence that it will perform the tasks about as optimally as is possible.
I am trying to replace the content of a div tag with a certain value every 50sec via polling and jQuery. And I would like to access the value of that updated div, so I can save a request to the backend.
My problem is that once the content has been replaced, the browser displays it correctly, however the HTML stays the same as the beginning. I'm afraid this is a rather basic question, but I'm really curious about this.
Here I prepared an example to illustrate the issue: http://jsfiddle.net/LJgN6/7/
And you can see it out ot JSfiddle's context to check the final HTML here: http://jsfiddle.net/LJgN6/7/show
I would like to achieve a way to have in the final HTML(i.e. right click, view page source):
num 1.1 replaced with num 1.2
num 2.1 replaced with num 2.2
...
The code that you see in the View Source window is the HTML that was sent to the browser before anything client side was allowed to modify the DOM. If you want to see the source as it is modified by your javascript, you need to inspect the DOM (IE F12, Firebug, etc.)
If you need to access this value that was inserted earlier, using javascript to access the contents of your element (ie. $('#number-2').text()) should return its contents as they are currently in the DOM.
EDIT: Corrected typo
It looks like you're already familiar with jQuery so I would go ahead and head over to the extremely helpful API and take a look at AJAX calls. There is plenty of documentation there that will help you.
http://api.jquery.com/jQuery.ajax/
Here's an idea. Take a look at my fiddle of your problem
$(document).ready(function(){
$('#number-1').html("num " + 1.1);
$('#number-2').html("num " + 2.2);
$('#number-3').html("num " + 3.3);
$('#number-4').html("num " + 4.4);
setInterval(function(){newInfo();}, 3000);
});
function newInfo(){
var firstDiv = $('#number-1');
var secDiv = $('#number-2');
var thdDiv = $('#number-3');
var frthDiv = $('#number-4');
var firstDivInfo = firstDiv.text().substr(4);
var secDivNewInfo = firstDiv.text().substr(4);
var thdDivNewInfo = secDiv.text().substr(4);
var frthDivNewInfo = thdDiv.text().substr(4);
var newNumber = (Math.random() + 1).toFixed(1);
secDiv.html("num " + secDivNewInfo);
thdDiv.html("num " + thdDivNewInfo);
frthDiv.html("num " + frthDivNewInfo);
firstDiv.html("num " + newNumber);
}
Here is a simplified example of what i'm working with, working around preexisting code:
Basically I have 2 divs I want to hide/show in multiple places(stage 1, stage 2, stage 3,etc), as so:
var blue_div = "#Blue";
var red_div = "#Red";
var blue_stage = "#Blue" + count;
var red_stage = "#Red" + count;
Adding insult to injury the div's exist elsewhere on page and are hidden. Need to pull the content into another div for each stage. So i'm using .prepend() to grab the content, as so:
var blue_html = $(blue_div).html();
var new_div = "#new_div";
$(new_div).prepend(blue_html);
$(new_div).attr('id', blue_stage); //Changing the id based on the stage
That last part is really whats throwing me...As now I'm trying to use the new_div without first ending the script so it's not yet in the DOM...
if ($(blue_stage).is(':hidden')) {
$(blue_stage).show()
$("#cancel").bind("click",function(){
$(blue_stage).hide()
}
}
I've seen a lot done with Window setTimeout() as well as setinterval and .queue(). But my attempts have all failed. Hopefully my example wasn't confusing, any help at all is appreciated!
I think you can do something like this:
var $new_div = $('<div id="' + blue_stage + '"></div>');
which will allow you to edit the element directly so you can do things like:
$new_div.prepend(blue_html);
to change the id you do:
$new_div.attr('id', blue_stage)
and note when your setting the id like this you don't need the "#" as the other answer mentions
Remember that you use the hash-mark # when selecting, but when setting as an ID on a node, you just use the identifier without this mark. So this line:
$(new_div).attr('id', blue_stage); //Changing the id based on the stage
Equates to this:
$(new_div).attr('id', '#Blue' + count);
But should perhaps be like this:
$(new_div).attr('id', 'Blue' + count);
(without the hashmark).
Hopefully your problem is as easily solved! Good luck!
I generate the numbering of my headers and figures with CSS's counter and content properties:
img.figure:after {
counter-increment: figure;
content: "Fig. " counter(section) "." counter(figure);
}
This (appropriate browser assumed) gives a nice labelling "Fig. 1.1", "Fig. 1.2" and so on following any image.
Question: How can I access this from Javascript? The question is twofold in that I'd like to access either the current value of a certain counter (at a certain DOM node) or the value of the CSS generated content (at a certain DOM node) or, obviously, both information.
Background: I'd like to append to links back-referencing to figures the appropriate number, like this:
<a href="#fig1">see here</h>
------------------------^ " (Fig 1.1)" inserted via JS
As far as I can see, it boils down to this problem:
I could access content or counter-increment via getComputedStyle:
var fig_content = window.getComputedStyle(
document.getElementById('fig-a'),
':after').content;
However, this is not the live value, but the one declared in the stylesheet. I cannot find any interface to access the real live value. In the case of the counter, there isn't even a real CSS property to query.
Edit: Digging deeper and deeper through the DOM specs, I found the DOM Level 2 Style Counter interface. This seems to a) allow access to the current counter value and b) be implemented in Firefox, at least. However, I have no idea on how to use it. My current approach died tragically after this Firebug output:
// should return a DOM 2 Counter interface implementation...
window.getComputedStyle(fig_a_element, ':after')
.getPropertyCSSValue("counter-increment")[0]
.getCounterValue();
[Exception... "Modifications are not allowed for this document" code: "7"
nsresult: "0x80530007 (NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR)"
location: "http://localhost/countertest.html Line: 71"]
Any idea, how this could be brought to life would be highly appreciated.
Edit 2: Apparently I misinterpreted the Counter object of DOM Level 2 Style. It, too, has no property to return the current counter value. This makes the above approach invalid.
New approach: Is there a possibility to read the content of a pseudo-element via the DOM? That is, can I select the pseudo-element (treeWalker comes to mind) and then get its nodeValue? (If you start to type 'jQuery' now, please reconsider to change that term into 'Sizzle'...)
I cannot find any interface to access the real live value. [of the counter]
Yeah. I don't think there is one. Sorry.
The only thing I can think of would be to go through every element (including its :before/:after pseudo-elements) before the element in the document, looking for counters and adding up how many there are.
Obviously that's hideous. If you're going to try to reproduce the browser's own counter mechanism it would probably be easier (and much more compatible, given IE<=7's lack of counter/content support) to just replace it with your own script-based counters. eg. something along the lines of:
this
<div class="counter level=0">...</div>
<img id="prettypicture" class="counter level=1" alt="ooo, pretty"/>
window.onload= function() {
var counters= Node_getElementsByClassName(document.body, 'counter');
var indices= [];
for (var counteri= 0; counteri<counters.length; counteri++) {
var counter= counters[counteri];
var level= Element_getClassArgument(counter, 'level');
while (indices.length<=level)
indices.push(0);
indices[level]++;
indices= indices.slice(level+1);
var text= document.createTextNode('Figure '+indices.join('.'));
counter.parentNode.insertBefore(text, counter.nextSibling);
if (counter.id!=='') {
for (var linki= document.links.length; linki-->0;) {
var link= document.links[i];
if (
link.hostname===location.hostname && link.pathname===location.pathname &&
link.search===location.search && link.hash==='#'+counter.id
) {
var text= document.createTextNode('('+indices.join('.')+')');
link.parentNode.insertBefore(text, link.nextSibling);
}
}
}
}
};
read this:
http://www.w3.org/TR/CSS2/generate.html#propdef-content
Generated content does not alter the
document tree. In particular, it is
not fed back to the document language
processor (e.g., for reparsing).
https://developer.mozilla.org/en/CSS/Getting_Started/Content
Content specified in a stylesheet does not become part of the DOM.
so for this reason the getComputedStyle will not work in this case; i think the only way, is to perform a classic loop through as someone has described below!
I would port your css to Javascript, this enables you to get the figure caption and also you get greater browser coverage. Using jQuery you'd do something like this:
$(function() {
var section = 0;
$(".section").each(function() {
section++;
var figure = 0;
$(this).find("img.figure").each(function() {
figure++;
var s = "Fig. " + section + "." + figure;
$(this).attr({alt:s}).after(s);
});
});
});
Then you could do:
<div class="section">blabla <img id="foo" src="http://www.example.com/foo.jpg"></div>
<p>Lorem ipsum dolor sit amet see here</p>
<script type="text/javascript">
$(function() {
$("a.figurereference").each(function() {
var selector = $(this).attr("href");
var $img = $(selector);
var s = $(this).text() + " (" + $img.attr("alt") + ")";
$(this).text(s);
});
});
</script>
Though I agree that doing this using CSS would be very neat.
I cannot find any interface to access the real live value.
If you can't get the value from window.getComputedStyle, it seems that it would be impossible.
More importantly, while it can do it, I think this might be abusing CSS since you're breaking the barrier between content and presentation at this point.
Check out this related question What are good uses of css “Content” property?