2

My idea is when I click on the button, the div#x will lose 1% of width. Here is my code:

document.querySelector('#a').onclick = function() {
    var
        lost = document.querySelector('#x').style.width,
        lost = lost.slice(0, -1);
    lost = Number(lost);
    lost -= 1;
    document.querySelector('#x').style.width = lost + '%';
}
nav#control {
    display: flex;
    flex-basis: 50px;
    align-items: center;
    justify-content: center;
    background: #FFF;
    padding: 5px;
    width: 100%
}

.knob {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    cursor: pointer
}

#b {
    position: relative;
    flex-grow: 1;
    background: #EFEFEF;
    margin: 0 10px;
    height: 30px
}
#x {
    position: absolute;
    background: #4C8EFA;
    width: 100%; height: 30px;
    border-radius: 1px;
    z-index: 2
}
#c {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 30px;
}
<nav id='control'>
    <section id='a' class='knob'><img src='x.png'/></section>
    <section id='b'>
        <div id='x'></div>
        <div id='c'>background</div>
    </section>
    <section id='d' class='knob'><img src='x.png'/></section>
</nav>

The blue bar (div#x) is supposed to be shorter 1% every time I click on the left button (section#a). I have check so many times but I still don't know what problem with my code. I did change some code and I think that problem is in this line lost = document.querySelector('#x').style.width because it seems like it doesn't return any value which is supposed to gimme 100% width of div#x

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Star Light
  • 154
  • 2
  • 8
  • 19
  • 1
    What is `catchID()`? – Blazemonger Apr 09 '15 at 14:35
  • 1
    Unfortunately, the `style.width` does not give you the percentage that is coming from the CSS. – jwatts1980 Apr 09 '15 at 14:38
  • 1
    The `.style` object only has styles that are applied directly on the element. Styles implied by CSS rules won't be available there. – Pointy Apr 09 '15 at 14:39
  • @Blazemonger My bad, catchID() is just my own function to get ID element. I have fix the right code. – Star Light Apr 09 '15 at 14:41
  • @jwatts1980 I did try on http://www.w3schools.com/jsref/prop_style_width.asp and it working pretty well with other HTML code. – Star Light Apr 09 '15 at 14:44
  • @Pointy I also add it directly on the #x but it won't work. And I think there are no diffirent betwen directly insert or insert in independence file. – Star Light Apr 09 '15 at 14:44
  • `element.style` refers to the `style` attribute of the HTML element. If the width is set in the style attribute like `style="width:100%;"` then `element.style.width` will equal `100%`. But when the element's style is being set in the CSS, `element.style.width` will be empty or null. – jwatts1980 Apr 09 '15 at 14:51
  • @jwatts1980 Thanks, I got it now. – Star Light Apr 09 '15 at 14:54

3 Answers3

5

Give this a shot:

var x = document.querySelector('#x');
var initialWidth = x.clientWidth;

window.onresize = function() {
  //Be careful about calculating too many things in the resize handler!
  //This isn't that intensive, so it shouldn't matter, but look into "debouncing" if you have things like this elsewhere
  initialWidth = x.clientWidth;
};

document.getElementById("a").onclick = function() {
  x.style.width = x.clientWidth - (initialWidth * 0.01) + "px";
};
nav#control {
  display: flex;
  flex-basis: 50px;
  align-items: center;
  justify-content: center;
  background: #FFF;
  padding: 5px;
  width: 100%
}
.knob {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  cursor: pointer
}
#b {
  position: relative;
  flex-grow: 1;
  background: #EFEFEF;
  margin: 0 10px;
  height: 30px
}
#x {
  position: absolute;
  background: #4C8EFA;
  width: 100%;
  height: 30px;
  border-radius: 1px;
  z-index: 2
}
#c {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 30px;
}
<nav id='control'>
  <section id='a' class='knob'>
    <img src='x.png' />
  </section>
  <section id='b'>
    <div id='x'></div>
    <div id='c'>background</div>
  </section>
  <section id='d' class='knob'>
    <img src='x.png' />
  </section>
</nav>

This uses clientWidth to get the real width of the element (in terms of pixels), takes 1% off that number, then reset the number back to pixels again.

Explanation:

In your original code, you were trying to access style.width of #x. Since this is a percentage, and not a static value, this will actually return nothing. Luckily, we can get the rendered width of the element with Javascript's clientWidth property. Using this, we can find the real size of the bar, and calculate the new values from that.

It also might be possible to directly inject the CSS with insertRule - but I don't see any problems with the clientWidth solution.

EDIT: Use @jwatts1980's solution from the comments: http://jsfiddle.net/a9okwLd1/1/

Scott
  • 5,338
  • 5
  • 45
  • 70
  • The only caveat is that by multiplying by 99% every time it will never be fully reduced. – jwatts1980 Apr 09 '15 at 14:43
  • 1
    @jwatts1980 Good point - I've updated my answer, this should fix it. – Scott Apr 09 '15 at 14:46
  • Oh, can you gimme some explanation, plz? – Star Light Apr 09 '15 at 14:46
  • @ScottKaye That is better, but it does not account for the size of the document changing. I think the `var` should hold the current percentage. Then you can multiply that by the `clientWidth`. – jwatts1980 Apr 09 '15 at 14:48
  • @jwatts1980 I tried to implement my CSS `insertRule` suggestion; turns out it's harder than it seems to [find the right selector](http://stackoverflow.com/a/324533/382456) - a `window.resize` handler is clunky, but it seems to work. If you can figure out a better way to do this, I'd love to take a look though! – Scott Apr 09 '15 at 14:57
  • I see, you should post that as an answer then, it's far better than the answers here. – Scott Apr 09 '15 at 15:05
  • 1
    @ScottKaye Heh heh, no that's fine. You have this one. I made that previous comment, then it clicked: I'm so used to updating the size by pixels on HTML elements that I forgot that you can use `%` and even `em` when you're setting the `element.style.width`. – jwatts1980 Apr 09 '15 at 15:19
  • Thank you so much, jwatts and Scott Kaye. I'm very appreciated your help. – Star Light Apr 09 '15 at 15:22
1

This bit is kinda messy:

catchID('a').onclick = function() {
    var
        lost = document.querySelector('#x').style.width,
        lost = lost.slice(0, -1);
    lost = Number(lost);
    lost -= 1;
    document.querySelector('#x').style.width = lost + '%';
}

Also, what is catchID()?

Try this:

document.querySelector('a.knob').addEventListener('click', function() {
    var elem = document.getElementById('x');
    elem.offsetWidth = .99 * elem.offsetWidth;
}, false);
Randy Hunt
  • 435
  • 3
  • 10
0

Try like so:

var w=document.getElementById("x").offsetWidth,
r=parseInt(w*.01);
document.getElementById("a").addEventListener("click",function(){
    w-=r;
    document.getElementById("x").style.width=w+"px";
},0);
Shaggy
  • 6,696
  • 2
  • 25
  • 45