How to select an element based on a style value? - javascript

I am making a custom progress bar that I want to change color based on it's width value. i.e if it's width is less than 50% the bar is red, if it's greater then the bar is green.
I know I can use the attribute selector like so:
.p-bar[style*="width: 10"] {
background-color: red;
}
But doing it like this would mean I would have to asign a value every step of the way...
P.D. sass solutions acceptable, thanks.
Edit
P.P.D. js solution also acceptable... but I would like to know if there is defenetly no way to accomplish what I want with CSS.

Ok... so as it was said before it seems like it is not possible to to do what I was trying to do using only css.
However it seems pretty easy to change color based on value using javascript.
Here is the code I ended up using (I have a button to add 10% of "progress" AKA width to my bar ):
var progressed = 0; /* Variable to handle the width % */
$('.btnAddProgress').click(function(){
var progressBar = $(this).parent().find('.progress-bar'); /* Get the bar */
progressed += 10;
progressBar.css({
'width': progressed + '%', /* Apply the changed width */
});
var progPrcnt = progressBar.width() / progressBar.parent().width() * 100; /* Wanted to get the actual element width because I figured I would not always have a variable like my "progressed" which value matches the actual width */
if (progPrcnt < 50) {
progressBar.css({
'background-color': '#f00',
});
} else {
progressBar.css({
'background-color': '#0f0',
});
}
});
Anyways... It turns out it was fairly easy to do what I wanted to do using JS and ended up figuring it out quite soon, and then not wanting forgetting to come back to my post and point out how dumb I was.
Anyways as I always say I'ms still learning, thanks a lot for your help an patience.

Related

repeatable marquee that's optional based on text width

I've spent most of my morning trying to resolve how to create a scrolling marquee on an Angular app; my goal is when the dynamic text is longer than its viewport, it will scroll (repeating, meaning you don't have to wait for the entire title to scroll off the page before you see it again) but when it's short enough to display without being cut off in the viewport width, it does not scroll.
I like examples I'm seeing but need to combine them somehow and I am very beginner when it comes to adding any kind of javascript.
One is using jQuery and marquee:
$('.marquee').marquee({
duplicated: true
});
This one is great because it repeats the text and continues without it having to completely leave the screen to start again. But, my trouble comes when trying to figure out a way to add in javascript to figure out how wide that text will be; either to have it be static or scroll.
For some reason, I am unable to understand how to link to codepen or jsfiddle of the examples I've found that hit close to home. Hoping my inquiry above is enough information. I know commenters can be a bit rough—please be patient with me.
You could use text-shadow(to clone text) and animation if it is only about text.
JS will be necessary to get the width(from text lenght) of the piece to scroll and to update/insert css rule's values.
example inspired from your jsfiddle
function isElementOverflowing(element) {
var overflowX = element.offsetWidth < element.scrollWidth,
overflowY = element.offsetHeight < element.scrollHeight;
return (overflowX || overflowY);
}
// below css updated and injected . can be shorten and nicely rewritten
var element = document.getElementById('ov1');
if (isElementOverflowing(element)) {
var toscroll = element.scrollWidth;
element.style.textShadow = toscroll + 'px 0 ';
element.style.animation = 'marqueeme 5s infinite linear';
var csstyle = document.createElement('style');
csstyle.innerText = '#keyframes marqueeme {100%{ text-indent:-' + toscroll + 'px;}}';
element.appendChild(csstyle)
}
#marquee {
max-width: 15em;
overflow: hidden;
}
#ov1 {
white-space: nowrap;
margin: 0;
}
<div id="marquee">
<p id="ov1">
Yadda yadda overflowing text this line is too long oh noes!
</p>
</div>
example here is using text-indent within the animation, but negative margin-left or translateX will do the same visual.
Another example with
a text-shadow of different color
transform to see it working instead text-indent.
It also sets speed according to text length
# https://codepen.io/gc-nomade/pen/owPNZg

What is going on behind the scenes and is this the proper way to do this? (modifying the DOM via Javascript)

Not knowing the proper way, after much research on the web I found so many different ways to do something its confusing. The way I tried, and kinda worked is the following...
My CSS
#Content {
left:0px;
top:1px;
width:988px;
z-index:1;
background-color: #FFFFFE;
}
My JS
function Gradients(id) //<- this id not used during testing, i hard coded it below
{
var getit = document.getElementById("Content");
getit.style.backgroundColor="#CCCCCC";
//alert(origcolor);
//var value = document.getElementById("Content").style.backgroundColor;
//var value = document.styleSheets[0].cssRules[0].style.backgroundColor;
}
My HTML (just a test)
<div onClick="Gradients("Content");">Gradients Test:<span>#XXXXXX</span></div>
Firebug Results - bad?
<div id="Content" style="background-color: rgb(204, 204, 204);">
WHAT I'M TRYING TO ACCOMPLISH
My goal was to read the background of an input field (each has an id) and slowly change it to red FROM the DEFAULT color in the CSS to let them know the field was incorrect.
Right now my website just slams it to red and I thought - how hard can it be to gradient a color. So, my mainpage has less clutter so I thought I would try to gradient the background of something. As with all web stuff it's messier than I thought.
I even spent a couple of hours reading up on jQuery but I don't want to pull in a whole library for this 1 tiny thing I will be doing.
Other Info
It's kinda like how THIS stackoverflow website fades from yellow to white the DIV of my question when I come here. Except mine will be in input fields. I have some commented out stuff in my JS because I was trying different things. I removed some of the things that were ugly. It works as is BUT I don't know if it's a good way to do it because firebug shows it added something to the DIV inline.
I like clean code... and my code up there seems ugly because I added something to the DIV. Can't I change the CSS value or is this the proper way to do it?
A couple of questions...
1) Proper way to do it?
2) If thats the proper way to do it how do I delete that change and have it revert back to the CSS style? Or an ugly method would be to just stick the original value I stored before performing the gradient.
3) YOUR much better clean way of doing it :)
4) Is there an elegant way to READ the value in the CSS style sheet?
The reason I didn't go with the document.stylesheets is to me....it seemed ugly... what if it's not [0]. How do I know it will always be [0]. What if it's different in different browsers? sigh. I don't fully understand the DOM. I understand what child nodes and parent nodes are but when looking through firebug it's a huge mess all over the place and I have no clue where to find things, how to insert things and I don't like modifying the DOM much anyways - i would love a simple thing like this (and yes, I am guessing on the code below - if only it could be that easy) lol...
I wish it was this easy in javascript...
$original_color = getElementById("Content").style.backgroundColor;
// loop through starting AT the original_color and gradient to red somehow
//start loop here
getElementById("Content").style.backgroundColor = newcolor;
// end loop here
Awaiting an infusion of wisdom please :)
WHAT I TRIED RECENTLY AFTER POSTING and Reading examples on here -- My JS
var RGradient = 0;
var GGradient = 0;
var GStop = 0;
var BGradient = 0;
var BStop = 100;
var idGradient;
function Gradients(id)
{
var startcolor = "#FFFFFE";
RGradient = hexToR(startcolor);
GGradient = hexToG(startcolor);
BGradient = hexToB(startcolor);
idGradient = document.getElementById(id);
window.setTimeout("GradientIt()", 10);
}
function GradientIt()
{
if (GGradient == GStop && BGradient == BStop) return;
if (GGradient > GStop) GGradient--;
if (BGradient > BStop) BGradient--;
idGradient.style.backgroundColor="#"+(RGradient).toString(16)+(GGradient).toString(16)+(BGradient).toString(16);
document.getElementById('gtest').innerHTML = "#"+(RGradient).toString(16)+(GGradient).toString(16)+(BGradient).toString(16);
window.setTimeout("GradientIt()", 5);
}
function hexToR(h) { return parseInt((cutHex(h)).substring(0,2),16) }
function hexToG(h) { return parseInt((cutHex(h)).substring(2,4),16) }
function hexToB(h) { return parseInt((cutHex(h)).substring(4,6),16) }
function cutHex(h) { return (h.charAt(0)=="#") ? h.substring(1,7) : h}
ERROR in IE
I'm getting an error in IE AFTER it turns the background to red... - Invalid Property in Line 29 which is the line with all the toString(16)'s in it above.
Can someone explain why it's giving an error in IE please? I am checking if I'm above 0 so the numbers should stay 0 or higher. The other browsers don't give an error that I can see. Once it's working I will be changing it - this is just a "hacked together" test - I'll make it more efficient later on when it's on the page I want.
I spent about an hour trying to pass variables to setTimeout before I realized I can't. UGH! lol. Globals :( Can't wait for CSS3 full compatibility in ALL browsers.
I would suggest achieving this using either css3 or jquery (a javascript library)
To do it with css3 is rather simple, this article should have all the necessary information
http://net.tutsplus.com/tutorials/html-css-techniques/css-fundametals-css-3-transitions/
To do it with jQuery you will need to download jquery and preferably have a little bit of experience with javascript although it is not generally required to pick up jQuery for simple things like this. This is the jQuery function you would want to use:
http://api.jquery.com/animate/
#content {
left:0px;
top:1px;
width:988px;
z-index:1;
background-color: #FFFFFE;
transition: 0.3s;
-moz-transition: 0.3s;
-webkit-transition: 0.3s;
}
#content:focus {
background-color: #f00;
transition: 0.3s;
-moz-transition: 0.3s;
-webkit-transition: 0.3s;
}
The above is CSS3 and works in many browsers. However IE support is (as always) lacking.
via javascript/jquery....
function animate_bg(ele, from, to) {
from += from > to ? -1 : 1;
if(!$.support.opacity){
if(from != to){
var opStr = (Math.round(from * 25.5)).toString(16);
//alert(opStr)
ele.css({background:'transparent',filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#" + opStr + "fffff0, endColorstr=#" + opStr + "f00000)"});
}else{
ele.css({background:'transparent',filter:"none"});
}
}else{
ele.css("backgroundColor", "rgba(255, 0, 0, " + (from) / 10 + ")");
}
if(from != to)
setTimeout(function() { animate_bg(ele, from, to) }, 60);
}
and usage....
animate_bg($('...'), 8, 0);

JQuery Progress Bar Inline Text

I am trying to use the basic progress bar however I am unable to figure out the css/command to actually put some text inside the bar. I am using this progress bar: http://docs.jquery.com/UI/Progressbar however I am open to other ones if they are just as simple to implement.
I want it to display in the left corner some static information and then a percentage of complete somewhere in the right section. All css I attempted to do just made the information display below or to the side of. As well I am unsure how to actually have this CSS change based on a JQuery method (new to JQuery).
below is my actual JQuery. Don't try to understand the url value just assume it returns 0-100.
<script type="text/javascript">
var url = "%%$protocol_url%%/bin/task_status?id=%%$tid%%&cmd=percent_done";
$(function() {
var progress = 0;
//alert("some value" + value, value);
$("#progressbar").progressbar({ progress: 0 });
setTimeout(updateProgress, 500);
});
function updateProgress() {
var progress;
$.get(url, function(data) {
// data contains whatever that page returns
if (data < 100) {
$("#progressbar")
.progressbar("option", "value", data);
setTimeout(updateProgress, 500);
} else {
$("#progressbar")
.progressbar("option", "value", 100);
}
});
}
Thanks
I'm not familiar with the plugin, but with CSS you can just position the div with lettering over the progress bar. I'm not sure if it would work with nested divs,since the inner div may get erased when the content for the progress bar is rendered.
You can play around with the top and left positions to position the text exactly where you want. In face you can dynamically change left, so that the text moves with the bar, though this may be a little trickier.
Z-index should not be a problem, but if you want to change the order of the divs, you might have to make sure that the text has a greater z-index than the bar.
The CSS:
#bardivs {
width:400px; /* or whatever the of the porgress bar is */
/*
The position of #bardivs must be something other than
static (the default) so that its children will be positioned
relative to it.
*/
position:relative;
}
#progresstext {
position:absolute;
top:0;
left:0;
}
The HTML:
<div id="bardivs">
<div id="progressbar"></div>
<div id="progresstext"></div>
</div>
The JS:
$("#progressbar").progressbar("option", "value", data);
$("#progresstext").html("<p>Hard code or string here<p>");
I've improved upon an already developed progressbar concept that is simply jquery and CSS based (but not using jquery-ui).
If you like you can look at the following link for having its details:
http://progressbar-simple.blogspot.com/
Hope that helps.

Fix for background-position in IE

I get this problem in IE7 when running a piece of code that uses jquery and 2 jquery plugins. The code works in FF3 and Chrome.
The full error is:
Line: 33
Char: 6
Error: bg is null or not an object
Code: 0
URL: http://localhost/index2.html
However line 33 is a blank line.
I am using 2 plugins: draggable and zoom. No matter what I do to the code it is always line 33 that is at fault. I check the source has update via view source but I feel this could be lying to me.
<body>
<div id="zoom" class="zoom"></div>
<div id="draggable" class="main_internal"><img src="tiles/mapSpain-smaller.jpg" alt=""></div>
<script type="text/javascript">
$(document).ready(function() {
$('#draggable').drag();
$('#zoom').zoom({target_div:"draggable", zoom_images:new Array('tiles/mapSpain-smaller.jpg', 'tiles/mapSpain.jpg') });
});
</script>
</body>
Essentially what I am trying to do is recreate the Pragmatic Ajax map demo with jQuery.
It would appear that the second line of this snippet is causing the trouble:
bg = $(this).css('background-position');
if(bg.indexOf('%')>1){
It seems to be trying to select the background-position property of #draggable and not finding it? Manually adding a background-position: 0 0; didn't fix it. Any ideas on how to get around this problem?
I tried using the MS Script Debugger but that is nearly useless. Can't inspect variables or anything else.
A bit more digging about on the Interweb has revealed the answer: IE doesn't understand the selector background-position. It understands the non-standard background-position-x and background-position-y.
Currently hacking something together to workaround it.
Nice one, Redmond.
To get around the fact that Internet Explorer does not support the "background-position" CSS attribute, as of jQuery 1.4.3+ you can use the .cssHooks object to normalize this attribute between browsers.
To save yourself some time, there is a background position jQuery plugin available that allows both "background-position" and "background-position-x/y" to work as expected in browsers that don't support one or the other by default.
It is interesting. IE8 doesn't understand getter backgroundPosition, but it understands setter.
$('.promo3').mousewheel(function(e,d){
var promo3 = $(this);
var p = promo3.css('backgroundPosition');
if (p === undefined) {
p = promo3.css('backgroundPositionX') + ' ' + promo3.css('backgroundPositionY');
}
var a = p.split(' ');
var y = parseInt(a[1]);
if (d > 0) {
if (y < -1107) y += 1107;
y -= 40;
}
else {
if (y > 1107) y -= 1107;
y += 40;
}
promo3.css('backgroundPosition', a[0] + ' ' + y + 'px');
return false;
});
It works great in IE8 and IE8 compatible view.
This worked for me:
if (navigator.appName=='Microsoft Internet Explorer')
{
bg = $(drag_div).css('backgroundPositionX') + " " + $(drag_div).css('backgroundPositionY');
}
else
{
bg = $(drag_div).css('background-position');
}
hope it does for you.
You may want to check to make sure that you are loading your js files in the correct order so that any dependencies are taken into account.
A bit of thinking (and a cup of tea) later I came up with:
if(bg == 'undefined' || bg == null){
bg = $(this).css('background-position-x') + " " + $(this).css('background-position-y');
}
Unfortunately it returns center center despite the online resources I can find state it should return 0 0 if the values are undefined.
Beginning to wonder if there is an actual fix/workaround to this. A lot of people have tried and all so far fail to catch all edge cases.
The camelCase version of backgroundPosition seems viable but I don't know enough of jQuery to make an accurate assessment of how to go about it - from what I have read you can only use camelCase as getters if the property has been set previously. Please tell me if I am mistaken.
However line 33 is a blank line.
It'll be line 33 of one of your .js files, not line 33 of the HTML itself. IE fails to report which actual file the error was in. Look at line 33 of each .js for something about ‘bg’; if the worst comes to the worst you can start inserting newlines at the start of each .js and see whether the line number changes.
I check the source has update via view source but I feel this could be lying to me.
View source will always show you what IE got from the server. It won't show any updates to the DOM.
try backgroundPosition istead
Also, make sure that 'this' exists and that your request for an attribute returns a value. IE will throw this kind of errors when you try to call a method on a property that does not exist, therefore bg is null or null an object. if you dont care about IE you can do bg = $(this)... || '' so that theres always something referenced.
Also, unrelated to the error you're getting, but is your index value of 1 correct? Did you mean -1 ?
Yupp, Try background-position instead or just set the background-position with jquery before you call it. Ill guess one often knows the positions through CSS before calling it. It isnt pretty, but somehow it did the trick for me.)
eg:
//set it in with javascript.
$("someid").css("background-position", "10px 0");
...
//do some funky stuff
//call it
$("someid").css("background-position");
//and it would return "10px 0" even in IE7
if nothing helps, it's also possible to make the following trick.
We can replace a background of an element by an inner absolutely positioned element (with the same background). The coordinates will be replaced by left and top properties. This will work in all browsers.
For better understanding, please, check the code:
Before
<div></div>
div {
background: url(mySprite.png);
background-position: -100px 0;
}
After
<div>
<span></span>
</div>
div {
position: relative;
overflow: hidden;
width: 100px; /* required width to show a part of your sprite */
height: 100px; /* required height ... */
}
div span {
position: absolute;
left: -100px; /* bg left position */
top: 0; /* bg top position */
display: block;
width: 500px; /* full sprite width */
height: 500px; /* full sprite height */
background: url(mySprite.png);
}
This solution is not very flexible, but it helped me to show icons hover state properly.
You can't use dashes in the jquery css function. You have to do it in camelCase:
.css('backgroundPosition') or .css('backgroundPositionX') and .css('backgroundPositionY') for IE

Turning numbers into colored bars automatically in HTML/Javascript

I want to auto-generate a HTML table from some custom data. One of the columns in my data is a number in the range 0-100, and I'd like to show it in a more graphical way, most desirably a colored horizontal bar. The length of the bar would represent the value, and the color would also change (i.e. below 20 it's red, etc.)
Something like this (created with paint.net):
(source: thegreenplace.net)
One way this can be achieved is by generating an appropriate .PNG and placing it there as an image. But I think that it can probably be done with some concoction of HTML/CSS/Javascript in an automatic way (i.e. the values thrown into the table are numeric, and JS converts them to bars before showing).
Perhaps someone has done something like this already and can share?
Thanks in advance
P.S: If it can work in IE6, that would be best (don't ask...)
P.P.S: It should work offline, so existing webservices (like Google charts) won't help
AListApart has a great article on how to generate charts using purely CSS. It's nice because it is accessible, meaning even without CSS it will provide meaningful data.
http://www.alistapart.com/articles/accessibledatavisualization
Update: According to one of the commenters on this answer, this solution will also work in IE6.
This is doable.
2 options:
1) put an image in every cell using the img tag and resize the image using the width attribute
2) put a div with a pre-set height and change the width according to the value you want it to display. Use the background color of the div as your color - no images needed.
example:
<table style="border: 1px solid black">
<tr><th>name</th><th>value</th></tr>
<tr><td>hi</td><td><div style="height: 10px; width: 35px; background-color: #236611">35</div></td></tr>
<tr><td>yes</td><td><div style="height: 10px; width: 15px; background-color: #236611">15</div></td></tr>
<tr><td>see?</td><td><div style="height: 10px; width: 75px; background-color: #2366aa">75</div></td></tr>
</table>
... you could/should tweak the sizes to look nicer of course :-)
The best way is the second part of simon's post. Place a div wherever you need it and change the width with javascript or PHP (depending on if you want it to dynamically change or not) using percentages. Use an if statement for the color. For ex, in javascript:
function displayGraph(barID, number)
{
var color;
if (number <= 20)
{
color = "red";
}
elseif (number > 20 && number <= 60)
{
color = "yellow";
}
else
{
color = "green";
}
var bar = document.getElementById(barID);
bar.style.width = number + "%";
bar.style.backgroundColor = color;
}
I didn't test this exactly, but something like it should work.
Check out the jQuery Sparkline which provides inline charts, similar to what you are looking for. If you use a bullet graph, you can display the good/normal/bad ranges associated with your data which provides a huge amount of data in a very small space.
Since you already have your data in a table, you might check out the jQuery Visualize Plugin. Once you include it, you'd just call something like:
$('table').visualize();
and it builds a graph from your table.
If you want it to work offline as well, maybe flot can be used.
It is based on canvas and jquery.
I haven't used it yet but it's on my todo list.
The sample code seems simple enough:
$(function () {
var d1 = [[0, 3], [4, 8], [8, 5], [9, 13]];
$.plot($("#placeholder"), [ d1 ]);
});
It's not HTML, but have you looked into Google Charts? It's really quite amazing.
http://code.google.com/apis/chart/

Categories

Resources