javascript - How to scrollLock body when a modal/lightbox is open -


i using lightbox jquery plugin open lightbox when user clicks on product. lightbox content stretches below fold, , @ moment right scrollbar moves entire page when scroll down.

i'd work pinterest lightbox, whereby right scrollbar scrolls lightbox, , rest of page stays fixed. i've seen few posts on this, nothing seems work me.

problem want lightbox scroll if content bigger viewport of browser not background.

css:

#lightbox{  position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;} #lightbox img{ width: auto; height: auto;} #lightbox img{ border: none; }  #outerimagecontainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; } #imagecontainer{ padding: 10px; }  #loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; } #hovernav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; } #imagecontainer>#hovernav{ left: 0;} #hovernav a{ outline: none;}  #prevlink, #nextlink{ width: 49%; height: 100%; background-image: url(data:image2/gif;base64,aaaa); /* trick ie showing hover */ display: block; } #prevlink { left: 0; float: left;} #nextlink { right: 0; float: right;} #prevlink:hover, #prevlink:visited:hover { background: url(../images2/prevlabel.gif) left 15% no-repeat; } #nextlink:hover, #nextlink:visited:hover { background: url(../images2/nextlabel.gif) right 15% no-repeat; }  #imagedatacontainer{ font: 10px verdana, helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }  #imagedata{ padding:0 10px; color: #666; } #imagedata #imagedetails{ width: 70%; float: left; text-align: left; }   #imagedata #caption{ font-weight: bold; } #imagedata #numberdisplay{ display: block; clear: left; padding-bottom: 1.0em;  }            #imagedata #bottomnavclose{ width: 66px; float: right;  padding-bottom: 0.7em; outline: none;}        #overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; } 

js:

// ----------------------------------------------------------------------------------- // //  lightbox v2.04 //  lokesh dhakar - http://www.lokeshdhakar.com //  last modification: 2/9/08 // //  more information, visit: //  http://lokeshdhakar.com/projects/lightbox2/ // //  licensed under creative commons attribution 2.5 license - http://creativecommons.org/licenses/by/2.5/ //      - free use in both personal , commercial projects //      - attribution requires leaving author name, author link, , license info intact. //   //  thanks: scott upton(uptonic.com), peter-paul koch(quirksmode.com), , thomas fuchs(mir.aculo.us) ideas, libs, , snippets. //          artemy tregubenko (arty.name) cleanup , in updating latest ver of proto-aculous. // // ----------------------------------------------------------------------------------- /*      table of contents     -----------------     configuration      lightbox class declaration     - initialize()     - updateimagelist()     - start()     - changeimage()     - resizeimagecontainer()     - showimage()     - updatedetails()     - updatenav()     - enablekeyboardnav()     - disablekeyboardnav()     - keyboardaction()     - preloadneighborimages()     - end()      function calls     - document.observe()  */ // -----------------------------------------------------------------------------------  // //  configurationl // lightboxoptions = object.extend({     fileloadingimage:        'images2/loading.gif',          filebottomnavcloseimage: 'images2/closelabel.gif',      overlayopacity: 0.8,   // controls transparency of shadow overlay      animate: true,         // toggles resizing animations     resizespeed: 7,        // controls speed of image resizing animations (1=slowest , 10=fastest)      bordersize: 10,         //if adjust padding in css, need update variable      // when grouping images used write: image # of #.     // change non-english localization     labelimage: "image",     labelof: "of" }, window.lightboxoptions || {});  // -----------------------------------------------------------------------------------  var lightbox = class.create();  lightbox.prototype = {     imagearray: [],     activeimage: undefined,      // initialize()     // constructor runs on completion of dom loading. calls updateimagelist ,     // function inserts html @ bottom of page used display shadow      // overlay , image container.     //     initialize: function() {              this.updateimagelist();          this.keyboardaction = this.keyboardaction.bindaseventlistener(this);          if (lightboxoptions.resizespeed > 10) lightboxoptions.resizespeed = 10;         if (lightboxoptions.resizespeed < 1)  lightboxoptions.resizespeed = 1;          this.resizeduration = lightboxoptions.animate ? ((11 - lightboxoptions.resizespeed) * 0.15) : 0;         this.overlayduration = lightboxoptions.animate ? 0.2 : 0;  // shadow fade in/out duration          // when lightbox starts resize 250 250 current image dimension.         // if animations turned off, hidden prevent flicker of         // white 250 250 box.         var size = (lightboxoptions.animate ? 250 : 1) + 'px';           // code inserts html @ bottom of page looks similar this:         //         //  <div id="overlay"></div>         //  <div id="lightbox">         //      <div id="outerimagecontainer">         //          <div id="imagecontainer">         //              <img id="lightboximage">         //              <div style="" id="hovernav">         //                  <a href="#" id="prevlink"></a>         //                  <a href="#" id="nextlink"></a>         //              </div>         //              <div id="loading">         //                  <a href="#" id="loadinglink">         //                      <img src="images/loading.gif">         //                  </a>         //              </div>         //          </div>         //      </div>         //      <div id="imagedatacontainer">         //          <div id="imagedata">         //              <div id="imagedetails">         //                  <span id="caption"></span>         //                  <span id="numberdisplay"></span>         //              </div>         //              <div id="bottomnav">         //                  <a href="#" id="bottomnavclose">         //                      <img src="images/close.gif">         //                  </a>         //              </div>         //          </div>         //      </div>         //  </div>           var objbody = $$('body')[0];          objbody.appendchild(builder.node('div',{id:'overlay'}));          objbody.appendchild(builder.node('div',{id:'lightbox'}, [             builder.node('div',{id:'outerimagecontainer'},                  builder.node('div',{id:'imagecontainer'}, [                     builder.node('img',{id:'lightboximage'}),                      builder.node('div',{id:'hovernav'}, [                         builder.node('a',{id:'prevlink', href: '#' }),                         builder.node('a',{id:'nextlink', href: '#' })                     ]),                     builder.node('div',{id:'loading'},                          builder.node('a',{id:'loadinglink', href: '#' },                              builder.node('img', {src: lightboxoptions.fileloadingimage})                         )                     )                 ])             ),             builder.node('div', {id:'imagedatacontainer'},                 builder.node('div',{id:'imagedata'}, [                     builder.node('div',{id:'imagedetails'}, [                         builder.node('span',{id:'caption'}),                         builder.node('span',{id:'numberdisplay'})                     ]),                     builder.node('div',{id:'bottomnav'},                         builder.node('a',{id:'bottomnavclose', href: '#' },                             builder.node('img', { src: lightboxoptions.filebottomnavcloseimage })                         )                     )                 ])             )         ]));           $('overlay').hide().observe('click', (function() { this.end(); }).bind(this));         $('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));         $('outerimagecontainer').setstyle({ width: size, height: size });         $('prevlink').observe('click', (function(event) { event.stop(); this.changeimage(this.activeimage - 1); }).bindaseventlistener(this));         $('nextlink').observe('click', (function(event) { event.stop(); this.changeimage(this.activeimage + 1); }).bindaseventlistener(this));         $('loadinglink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));         $('bottomnavclose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));          var th = this;         (function(){             var ids =                  'overlay lightbox outerimagecontainer imagecontainer lightboximage hovernav prevlink nextlink loading loadinglink ' +                  'imagedatacontainer imagedata imagedetails caption numberdisplay bottomnav bottomnavclose';                $w(ids).each(function(id){ th[id] = $(id); });         }).defer();     },      //     // updateimagelist()     // loops through anchor tags looking 'lightbox' references , applies onclick     // events appropriate links. can rerun after dynamically adding images w/ajax.     //     updateimagelist: function() {            this.updateimagelist = prototype.emptyfunction;          document.observe('click', (function(event){             var target = event.findelement('a[rel^=lightbox]') || event.findelement('area[rel^=lightbox]');             if (target) {                 event.stop();                 this.start(target);             }         }).bind(this));     },      //     //  start()     //  display overlay , lightbox. if image part of set, add siblings imagearray.     //     start: function(imagelink) {              $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });          // stretch overlay fill page , fade in         var arraypagesize = this.getpagesize();         $('overlay').setstyle({ width: arraypagesize[0] + 'px', height: arraypagesize[1] + 'px' });          new effect.appear(this.overlay, { duration: this.overlayduration, from: 0.0, to: lightboxoptions.overlayopacity });          this.imagearray = [];         var imagenum = 0;                 if ((imagelink.rel == 'lightbox')){             // if image not part of set, add single image imagearray             this.imagearray.push([imagelink.href, imagelink.title]);                  } else {             // if image part of set..             this.imagearray =                  $$(imagelink.tagname + '[href][rel="' + imagelink.rel + '"]').                 collect(function(anchor){ return [anchor.href, anchor.title]; }).                 uniq();              while (this.imagearray[imagenum][0] != imagelink.href) { imagenum++; }         }          // calculate top , left offset lightbox          var arraypagescroll = document.viewport.getscrolloffsets();         var lightboxtop = arraypagescroll[1] + (document.viewport.getheight() / 10);         var lightboxleft = arraypagescroll[0];         this.lightbox.setstyle({ top: lightboxtop + 'px', left: lightboxleft + 'px' }).show();          this.changeimage(imagenum);     },      //     //  changeimage()     //  hide elements , preload image in preparation resizing image container.     //     changeimage: function(imagenum) {             this.activeimage = imagenum; // update global var          // hide elements during transition         if (lightboxoptions.animate) this.loading.show();         this.lightboximage.hide();         this.hovernav.hide();         this.prevlink.hide();         this.nextlink.hide();         // hack: opera9 not support scriptaculous opacity , appear fx         this.imagedatacontainer.setstyle({opacity: .0001});         this.numberdisplay.hide();                var imgpreloader = new image();          // once image preloaded, resize image container           imgpreloader.onload = (function(){             this.lightboximage.src = this.imagearray[this.activeimage][0];             this.resizeimagecontainer(imgpreloader.width, imgpreloader.height);         }).bind(this);         imgpreloader.src = this.imagearray[this.activeimage][0];     },      //     //  resizeimagecontainer()     //     resizeimagecontainer: function(imgwidth, imgheight) {          // current width , height         var widthcurrent  = this.outerimagecontainer.getwidth();         var heightcurrent = this.outerimagecontainer.getheight();          // new width , height         var widthnew  = (imgwidth  + lightboxoptions.bordersize * 2);         var heightnew = (imgheight + lightboxoptions.bordersize * 2);          // scalars based on change old new         var xscale = (widthnew  / widthcurrent)  * 100;         var yscale = (heightnew / heightcurrent) * 100;          // calculate size difference between new , old image, , resize if necessary         var wdiff = widthcurrent - widthnew;         var hdiff = heightcurrent - heightnew;          if (hdiff != 0) new effect.scale(this.outerimagecontainer, yscale, {scalex: false, duration: this.resizeduration, queue: 'front'});          if (wdiff != 0) new effect.scale(this.outerimagecontainer, xscale, {scaley: false, duration: this.resizeduration, delay: this.resizeduration});           // if new , old image same size , no scaling transition necessary,          // quick pause prevent image flicker.         var timeout = 0;         if ((hdiff == 0) && (wdiff == 0)){             timeout = 100;             if (prototype.browser.ie) timeout = 250;            }          (function(){             this.prevlink.setstyle({ height: imgheight + 'px' });             this.nextlink.setstyle({ height: imgheight + 'px' });             this.imagedatacontainer.setstyle({ width: widthnew + 'px' });              this.showimage();         }).bind(this).delay(timeout / 1000);     },      //     //  showimage()     //  display image , begin preloading neighbors.     //     showimage: function(){         this.loading.hide();         new effect.appear(this.lightboximage, {              duration: this.resizeduration,              queue: 'end',              afterfinish: (function(){ this.updatedetails(); }).bind(this)          });         this.preloadneighborimages();     },      //     //  updatedetails()     //  display caption, image number, , bottom nav.     //     updatedetails: function() {          // if caption not null         if (this.imagearray[this.activeimage][1] != ""){             this.caption.update(this.imagearray[this.activeimage][1]).show();         }          // if image part of set display 'image x of x'          if (this.imagearray.length > 1){             this.numberdisplay.update( lightboxoptions.labelimage + ' ' + (this.activeimage + 1) + ' ' + lightboxoptions.labelof + '  ' + this.imagearray.length).show();         }          new effect.parallel(             [                  new effect.slidedown(this.imagedatacontainer, { sync: true, duration: this.resizeduration, from: 0.0, to: 1.0 }),                  new effect.appear(this.imagedatacontainer, { sync: true, duration: this.resizeduration })              ],              {                  duration: this.resizeduration,                  afterfinish: (function() {                     // update overlay size , update nav                     var arraypagesize = this.getpagesize();                     this.overlay.setstyle({ height: arraypagesize[1] + 'px' });                     this.updatenav();                 }).bind(this)             }          );     },      //     //  updatenav()     //  display appropriate previous , next hover navigation.     //     updatenav: function() {          this.hovernav.show();                         // if not first image in set, display prev image button         if (this.activeimage > 0) this.prevlink.show();          // if not last image in set, display next image button         if (this.activeimage < (this.imagearray.length - 1)) this.nextlink.show();          this.enablekeyboardnav();     },      //     //  enablekeyboardnav()     //     enablekeyboardnav: function() {         document.observe('keydown', this.keyboardaction);      },      //     //  disablekeyboardnav()     //     disablekeyboardnav: function() {         document.stopobserving('keydown', this.keyboardaction);      },      //     //  keyboardaction()     //     keyboardaction: function(event) {         var keycode = event.keycode;          var escapekey;         if (event.dom_vk_escape) {  // mozilla             escapekey = event.dom_vk_escape;         } else { // ie             escapekey = 27;         }          var key = string.fromcharcode(keycode).tolowercase();          if (key.match(/x|o|c/) || (keycode == escapekey)){ // close lightbox             this.end();         } else if ((key == 'p') || (keycode == 37)){ // display previous image             if (this.activeimage != 0){                 this.disablekeyboardnav();                 this.changeimage(this.activeimage - 1);             }         } else if ((key == 'n') || (keycode == 39)){ // display next image             if (this.activeimage != (this.imagearray.length - 1)){                 this.disablekeyboardnav();                 this.changeimage(this.activeimage + 1);             }         }     },      //     //  preloadneighborimages()     //  preload previous , next images.     //     preloadneighborimages: function(){         var preloadnextimage, preloadprevimage;         if (this.imagearray.length > this.activeimage + 1){             preloadnextimage = new image();             preloadnextimage.src = this.imagearray[this.activeimage + 1][0];         }         if (this.activeimage > 0){             preloadprevimage = new image();             preloadprevimage.src = this.imagearray[this.activeimage - 1][0];         }      },      //     //  end()     //     end: function() {         this.disablekeyboardnav();         this.lightbox.hide();         new effect.fade(this.overlay, { duration: this.overlayduration });         $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });     },      //     //  getpagesize()     //     getpagesize: function() {           var xscroll, yscroll;          if (window.innerheight && window.scrollmaxy) {               xscroll = window.innerwidth + window.scrollmaxx;             yscroll = window.innerheight + window.scrollmaxy;         } else if (document.body.scrollheight > document.body.offsetheight){ // explorer mac             xscroll = document.body.scrollwidth;             yscroll = document.body.scrollheight;         } else { // explorer mac...would work in explorer 6 strict, mozilla , safari             xscroll = document.body.offsetwidth;             yscroll = document.body.offsetheight;         }          var windowwidth, windowheight;          if (self.innerheight) { // except explorer             if(document.documentelement.clientwidth){                 windowwidth = document.documentelement.clientwidth;              } else {                 windowwidth = self.innerwidth;             }             windowheight = self.innerheight;         } else if (document.documentelement && document.documentelement.clientheight) { // explorer 6 strict mode             windowwidth = document.documentelement.clientwidth;             windowheight = document.documentelement.clientheight;         } else if (document.body) { // other explorers             windowwidth = document.body.clientwidth;             windowheight = document.body.clientheight;         }             // small pages total height less height of viewport         if(yscroll < windowheight){             pageheight = windowheight;         } else {              pageheight = yscroll;         }          // small pages total width less width of viewport         if(xscroll < windowwidth){               pagewidth = xscroll;                 } else {             pagewidth = windowwidth;         }          return [pagewidth,pageheight];     } }  document.observe('dom:loaded', function () { new lightbox(); }); 

here's class that'll allow that:

class scrolllock {   constructor () {     this.pagebody = document.queryselector('body');     this.scrolly = 0;   }    savescrolly = (num) => {     this.scrolly = num;   }    setscrolly = (num) => {     window.scroll(0, num);   }    setscrolloffset = (voffset) => {     this.pagebody.style.top = `-${voffset}px`;   }    freezebodyscroll = () => {     this.savescrolly(window.scrolly);     this.setscrolloffset(this.scrolly);     this.pagebody.classlist.add('is-fixed');   }    unfreezebodyscroll = () => {     this.pagebody.classlist.remove('is-fixed');      // don't reset scroll position if lock hasn't occurred     if (this.scrolly === 0) return;     this.setscrolloffset(0);     this.setscrolly(this.scrolly);     this.savescrolly(0);   } } 

include following style declaration:

// in css body.is-fixed {   position: fixed;   max-width: 100%; } 

use:

const { freezebodyscroll, unfreezebodyscroll } = new scrolllock();  // call when open modal freezebodyscroll();  // call when close modal unfreezebodyscroll(); 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -