1

I found a JQuery solution to disable scrolling on body when modal view is opened but I am looking for a Javascript solution, can anyone tell me the conversion to JS how it will be :

$(function () {
var $body = $(window.document.body);

function bodyFreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('overflow', 'hidden');
    $body.css('marginRight', ($body.css('marginRight') ? '+=' : '') + ($body.innerWidth() - bodyWidth))
}

function bodyUnfreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('marginRight', '-=' + (bodyWidth - $body.innerWidth()))
    $body.css('overflow', 'auto');
}

$('.modal').hide()

$('.longcontent.main button').click(function () {
    $('.modal').show()
    bodyFreezeScroll()
})
$('.modal button').click(function () {
    $('.modal').hide()
    bodyUnfreezeScroll()
})})

http://jsfiddle.net/ngwhk/

iOSGeek
  • 5,115
  • 9
  • 46
  • 74
  • what part do you want to have translated to vanilla js? The trick is to have a "background" container which is as big as the current viewport (top:0; right:0; bottom:0; left:0;) This container has the css property `overflow: auto` (or scroll) so content bigger the viewport can be scrolled. Then you can apply this to the body, as long as the dialg is open: `document.body.style.overflow = "hidden";` – Nico O Mar 02 '14 at 12:28
  • Yeah, disabling the scrolling and enabling it back works great, but there is a but animation of the hidding and showing back the scrollbar, the width will change I want to get the aquivalent of this line : ` $body.css('marginRight', ($body.css('marginRight') ? '+=' : '') + ($body.innerWidth() - bodyWidth))` – iOSGeek Mar 02 '14 at 12:33
  • i don't see an animation in your jsfiddle. This will just add a margin to the body. – Nico O Mar 02 '14 at 12:41
  • Here is where I want to implement the solution : http://jsfiddle.net/3xv6A/424/ – iOSGeek Mar 02 '14 at 12:51
  • The problem is that when the modal view opens the body shift to the right since the scroll bar will be hidden and it shifts to the left when the scroll bar back again, so I don't want to have this issue – iOSGeek Mar 02 '14 at 13:18
  • I ended up with this solution, it works but it's not perfect `function bodyFreezeScroll() { var c = bodyTag.style; c.marginRight = getScrollBarWidth() +"px"; c.overflow = "hidden"; } function bodyUnfreezeScroll() { var c = bodyTag.style; c.marginRight = "0px"; c.overflow = "auto"; }` – iOSGeek Mar 02 '14 at 13:28

1 Answers1

1

The best i can come up with vanilla js is this:

http://jsfiddle.net/ngwhk/23/

var $body = window.document.body;
var $modal = document.getElementsByClassName("modal")[0];
var aOpenButtons = document.getElementsByClassName("open-modal");
var aCloseButtons = document.getElementsByClassName("close-modal");


function bodyFreezeScroll($obj) {
    $body.style.overflow = "hidden";
    $body.style.marginRight = getScrollBarWidth()+"px";
}

function bodyUnfreezeScroll() {
    $body.style.overflow = "auto";
    $body.style.marginRight = "auto";
}


function showModal(){
    $modal.classList.add("visible");
    $modal.classList.remove("hide");
}

function hideModal(){
    $modal.classList.add("hide");
    $modal.classList.remove("visible");
}


for(var i = 0, a=aOpenButtons.length; i<a; i++){
   aOpenButtons[i].addEventListener("click", function(){
    showModal();
    bodyFreezeScroll();
    }, false); 
}

for(var i = 0, a=aCloseButtons.length; i<a; i++){
   aCloseButtons[i].addEventListener("click", function(){
    hideModal();
    bodyUnfreezeScroll();
    }, false);
}

function getScrollBarWidth() {
    /* found here: https://stackoverflow.com/questions/986937/how-can-i-get-the-browsers-scrollbar-sizes */
  var inner = document.createElement('p');
  inner.style.width = "100%";
  inner.style.height = "200px";

  var outer = document.createElement('div');
  outer.style.position = "absolute";
  outer.style.top = "0px";
  outer.style.left = "0px";
  outer.style.visibility = "hidden";
  outer.style.width = "200px";
  outer.style.height = "150px";
  outer.style.overflow = "hidden";
  outer.appendChild (inner);

  document.body.appendChild (outer);
  var w1 = inner.offsetWidth;
  outer.style.overflow = 'scroll';
  var w2 = inner.offsetWidth;
  if (w1 == w2) w2 = outer.clientWidth;

  document.body.removeChild (outer);

  return (w1 - w2);
};

Update
I found a method to measure the scrollbar width from the answer here: How can I get the browser's scrollbar sizes?

Since the transitions seems not to be triggered, when i change the style or add classes (please correct this, if you know a way) I added keyframes animations for that.

@keyframes show {
  0%   { top: -100%; }
  100% { top: 0; }
}

@keyframes hide {
  0%   { top: 0%; }
  100% { top: -100%; }
}
Community
  • 1
  • 1
Nico O
  • 13,762
  • 9
  • 54
  • 69
  • thank you for the effort, but can we prevent the two scroll bars to displayed together in the transition animation – iOSGeek Mar 02 '14 at 13:34
  • Found a method to get the correct size of the current scrollbars, and udated the fiddle + answer. See references. – Nico O Mar 02 '14 at 14:23