.hasScroll function, checking if a scrollbar is visible in an element












5














I have constructed a function that checks whether an element has a scrollbar or not, and can also check individual axes.



I don't know if this works in all major browsers and am unsure about the performance.



Is there any way to improve upon the code, did I miss anything?

How would a javascript equivalent look like?



Note: I first asked this question on Stack Overflow, but someone suggested I should post it here instead.





Code | Example



$.fn.hasScroll = function(axis){
var sX = this.css("overflow-x"),
sY = this.css("overflow-y");

if(typeof axis == "undefined"){
//Check both x and y declarations
if(
(sX == "hidden" && sY == "hidden") ||
(sX == "visible" && sY == "visible")
){
return false;
}

if(sX == "scroll" || sY == "scroll"){
return true;
}
}else{
//Check individual axis declarations
switch(axis){
case "x":
if(sX == "hidden" || sX == "visible") return false;
if(sX == "scroll") return true;
break;
case "y":
if(sY == "hidden" || sY == "visible") return false;
if(sY == "scroll") return true;
break;
}
}

//Compare client and scroll dimensions to see if a scrollbar is needed
var bVertical = this[0].clientHeight < this[0].scrollHeight,
bHorizontal = this[0].clientWidth < this[0].scrollWidth;

return bVertical || bHorizontal;
};









share|improve this question





























    5














    I have constructed a function that checks whether an element has a scrollbar or not, and can also check individual axes.



    I don't know if this works in all major browsers and am unsure about the performance.



    Is there any way to improve upon the code, did I miss anything?

    How would a javascript equivalent look like?



    Note: I first asked this question on Stack Overflow, but someone suggested I should post it here instead.





    Code | Example



    $.fn.hasScroll = function(axis){
    var sX = this.css("overflow-x"),
    sY = this.css("overflow-y");

    if(typeof axis == "undefined"){
    //Check both x and y declarations
    if(
    (sX == "hidden" && sY == "hidden") ||
    (sX == "visible" && sY == "visible")
    ){
    return false;
    }

    if(sX == "scroll" || sY == "scroll"){
    return true;
    }
    }else{
    //Check individual axis declarations
    switch(axis){
    case "x":
    if(sX == "hidden" || sX == "visible") return false;
    if(sX == "scroll") return true;
    break;
    case "y":
    if(sY == "hidden" || sY == "visible") return false;
    if(sY == "scroll") return true;
    break;
    }
    }

    //Compare client and scroll dimensions to see if a scrollbar is needed
    var bVertical = this[0].clientHeight < this[0].scrollHeight,
    bHorizontal = this[0].clientWidth < this[0].scrollWidth;

    return bVertical || bHorizontal;
    };









    share|improve this question



























      5












      5








      5


      2





      I have constructed a function that checks whether an element has a scrollbar or not, and can also check individual axes.



      I don't know if this works in all major browsers and am unsure about the performance.



      Is there any way to improve upon the code, did I miss anything?

      How would a javascript equivalent look like?



      Note: I first asked this question on Stack Overflow, but someone suggested I should post it here instead.





      Code | Example



      $.fn.hasScroll = function(axis){
      var sX = this.css("overflow-x"),
      sY = this.css("overflow-y");

      if(typeof axis == "undefined"){
      //Check both x and y declarations
      if(
      (sX == "hidden" && sY == "hidden") ||
      (sX == "visible" && sY == "visible")
      ){
      return false;
      }

      if(sX == "scroll" || sY == "scroll"){
      return true;
      }
      }else{
      //Check individual axis declarations
      switch(axis){
      case "x":
      if(sX == "hidden" || sX == "visible") return false;
      if(sX == "scroll") return true;
      break;
      case "y":
      if(sY == "hidden" || sY == "visible") return false;
      if(sY == "scroll") return true;
      break;
      }
      }

      //Compare client and scroll dimensions to see if a scrollbar is needed
      var bVertical = this[0].clientHeight < this[0].scrollHeight,
      bHorizontal = this[0].clientWidth < this[0].scrollWidth;

      return bVertical || bHorizontal;
      };









      share|improve this question















      I have constructed a function that checks whether an element has a scrollbar or not, and can also check individual axes.



      I don't know if this works in all major browsers and am unsure about the performance.



      Is there any way to improve upon the code, did I miss anything?

      How would a javascript equivalent look like?



      Note: I first asked this question on Stack Overflow, but someone suggested I should post it here instead.





      Code | Example



      $.fn.hasScroll = function(axis){
      var sX = this.css("overflow-x"),
      sY = this.css("overflow-y");

      if(typeof axis == "undefined"){
      //Check both x and y declarations
      if(
      (sX == "hidden" && sY == "hidden") ||
      (sX == "visible" && sY == "visible")
      ){
      return false;
      }

      if(sX == "scroll" || sY == "scroll"){
      return true;
      }
      }else{
      //Check individual axis declarations
      switch(axis){
      case "x":
      if(sX == "hidden" || sX == "visible") return false;
      if(sX == "scroll") return true;
      break;
      case "y":
      if(sY == "hidden" || sY == "visible") return false;
      if(sY == "scroll") return true;
      break;
      }
      }

      //Compare client and scroll dimensions to see if a scrollbar is needed
      var bVertical = this[0].clientHeight < this[0].scrollHeight,
      bHorizontal = this[0].clientWidth < this[0].scrollWidth;

      return bVertical || bHorizontal;
      };






      javascript jquery optimization performance






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 23 '17 at 12:41









      Community

      1




      1










      asked Jul 5 '12 at 9:08









      ShadowScripter

      128115




      128115






















          2 Answers
          2






          active

          oldest

          votes


















          8














          I would write this as an extension to the Sizzle engine rather than a jQuery plugin; I've made a few other minor changes as well:



          function hasScroll(el, index, match) {
          var $el = $(el),
          sX = $el.css('overflow-x'),
          sY = $el.css('overflow-y'),
          hidden = 'hidden', // minifiers would like this better
          visible = 'visible',
          scroll = 'scroll',
          axis = match[3]; // regex for filter -> 3 == args to selector

          if (!axis) { // better check than undefined
          //Check both x and y declarations
          if (sX === sY && (sY === hidden || sY === visible)) { //same check but shorter syntax
          return false;
          }
          if (sX === scroll || sY === scroll) { return true; }
          } else if (axis === 'x') { // don't mix ifs and switches on the same variable
          if (sX === hidden || sX === visible) { return false; }
          if (sX === scroll) { return true; }
          } else if (axis === 'y') {
          if (sY === hidden || sY === visible) { return false; }
          if (sY === scroll) { return true };
          }

          //Compare client and scroll dimensions to see if a scrollbar is needed

          return $el.innerHeight() < el.scrollHeight || //make use of potential short circuit
          $el.innerWidth() < el.scrollWidth; //innerHeight is the one you want
          }
          $.expr[':'].hasScroll = hasScroll;


          You can then use this in any jQuery selector, such as:



          $('div:hasScroll') //all divs that have scrollbars
          $('div').filter(':hasScroll') //same but better
          $(this).closest(':hasScroll(y)') //find the parent with the vert scrollbar
          $list.is(':hasScroll(x)') //are there any horizontal scrollbars in the list?


          If you must have an instance method to do this check then you could write this to keep your semantics:



          $.fn.hasScroll = function(axis) {
          var el = this[0];
          if (!el) { return false; }
          return hasScroll(el, 0, [0, 0, 0, axis]);
          };


          Updated JsFiddle






          share|improve this answer

















          • 1




            Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
            – ShadowScripter
            Jul 7 '12 at 9:17





















          8














          === everywhere



          === > == (Not that it really matters in this case, but it's still better.)



          Also, IIRC clientHeight etc are not cross-browser, this is why jQuery provides .position(), .offset(), .scrollTop() and .height() (whichever one best suits your needs).






          share|improve this answer























            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f13338%2fhasscroll-function-checking-if-a-scrollbar-is-visible-in-an-element%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            8














            I would write this as an extension to the Sizzle engine rather than a jQuery plugin; I've made a few other minor changes as well:



            function hasScroll(el, index, match) {
            var $el = $(el),
            sX = $el.css('overflow-x'),
            sY = $el.css('overflow-y'),
            hidden = 'hidden', // minifiers would like this better
            visible = 'visible',
            scroll = 'scroll',
            axis = match[3]; // regex for filter -> 3 == args to selector

            if (!axis) { // better check than undefined
            //Check both x and y declarations
            if (sX === sY && (sY === hidden || sY === visible)) { //same check but shorter syntax
            return false;
            }
            if (sX === scroll || sY === scroll) { return true; }
            } else if (axis === 'x') { // don't mix ifs and switches on the same variable
            if (sX === hidden || sX === visible) { return false; }
            if (sX === scroll) { return true; }
            } else if (axis === 'y') {
            if (sY === hidden || sY === visible) { return false; }
            if (sY === scroll) { return true };
            }

            //Compare client and scroll dimensions to see if a scrollbar is needed

            return $el.innerHeight() < el.scrollHeight || //make use of potential short circuit
            $el.innerWidth() < el.scrollWidth; //innerHeight is the one you want
            }
            $.expr[':'].hasScroll = hasScroll;


            You can then use this in any jQuery selector, such as:



            $('div:hasScroll') //all divs that have scrollbars
            $('div').filter(':hasScroll') //same but better
            $(this).closest(':hasScroll(y)') //find the parent with the vert scrollbar
            $list.is(':hasScroll(x)') //are there any horizontal scrollbars in the list?


            If you must have an instance method to do this check then you could write this to keep your semantics:



            $.fn.hasScroll = function(axis) {
            var el = this[0];
            if (!el) { return false; }
            return hasScroll(el, 0, [0, 0, 0, axis]);
            };


            Updated JsFiddle






            share|improve this answer

















            • 1




              Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
              – ShadowScripter
              Jul 7 '12 at 9:17


















            8














            I would write this as an extension to the Sizzle engine rather than a jQuery plugin; I've made a few other minor changes as well:



            function hasScroll(el, index, match) {
            var $el = $(el),
            sX = $el.css('overflow-x'),
            sY = $el.css('overflow-y'),
            hidden = 'hidden', // minifiers would like this better
            visible = 'visible',
            scroll = 'scroll',
            axis = match[3]; // regex for filter -> 3 == args to selector

            if (!axis) { // better check than undefined
            //Check both x and y declarations
            if (sX === sY && (sY === hidden || sY === visible)) { //same check but shorter syntax
            return false;
            }
            if (sX === scroll || sY === scroll) { return true; }
            } else if (axis === 'x') { // don't mix ifs and switches on the same variable
            if (sX === hidden || sX === visible) { return false; }
            if (sX === scroll) { return true; }
            } else if (axis === 'y') {
            if (sY === hidden || sY === visible) { return false; }
            if (sY === scroll) { return true };
            }

            //Compare client and scroll dimensions to see if a scrollbar is needed

            return $el.innerHeight() < el.scrollHeight || //make use of potential short circuit
            $el.innerWidth() < el.scrollWidth; //innerHeight is the one you want
            }
            $.expr[':'].hasScroll = hasScroll;


            You can then use this in any jQuery selector, such as:



            $('div:hasScroll') //all divs that have scrollbars
            $('div').filter(':hasScroll') //same but better
            $(this).closest(':hasScroll(y)') //find the parent with the vert scrollbar
            $list.is(':hasScroll(x)') //are there any horizontal scrollbars in the list?


            If you must have an instance method to do this check then you could write this to keep your semantics:



            $.fn.hasScroll = function(axis) {
            var el = this[0];
            if (!el) { return false; }
            return hasScroll(el, 0, [0, 0, 0, axis]);
            };


            Updated JsFiddle






            share|improve this answer

















            • 1




              Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
              – ShadowScripter
              Jul 7 '12 at 9:17
















            8












            8








            8






            I would write this as an extension to the Sizzle engine rather than a jQuery plugin; I've made a few other minor changes as well:



            function hasScroll(el, index, match) {
            var $el = $(el),
            sX = $el.css('overflow-x'),
            sY = $el.css('overflow-y'),
            hidden = 'hidden', // minifiers would like this better
            visible = 'visible',
            scroll = 'scroll',
            axis = match[3]; // regex for filter -> 3 == args to selector

            if (!axis) { // better check than undefined
            //Check both x and y declarations
            if (sX === sY && (sY === hidden || sY === visible)) { //same check but shorter syntax
            return false;
            }
            if (sX === scroll || sY === scroll) { return true; }
            } else if (axis === 'x') { // don't mix ifs and switches on the same variable
            if (sX === hidden || sX === visible) { return false; }
            if (sX === scroll) { return true; }
            } else if (axis === 'y') {
            if (sY === hidden || sY === visible) { return false; }
            if (sY === scroll) { return true };
            }

            //Compare client and scroll dimensions to see if a scrollbar is needed

            return $el.innerHeight() < el.scrollHeight || //make use of potential short circuit
            $el.innerWidth() < el.scrollWidth; //innerHeight is the one you want
            }
            $.expr[':'].hasScroll = hasScroll;


            You can then use this in any jQuery selector, such as:



            $('div:hasScroll') //all divs that have scrollbars
            $('div').filter(':hasScroll') //same but better
            $(this).closest(':hasScroll(y)') //find the parent with the vert scrollbar
            $list.is(':hasScroll(x)') //are there any horizontal scrollbars in the list?


            If you must have an instance method to do this check then you could write this to keep your semantics:



            $.fn.hasScroll = function(axis) {
            var el = this[0];
            if (!el) { return false; }
            return hasScroll(el, 0, [0, 0, 0, axis]);
            };


            Updated JsFiddle






            share|improve this answer












            I would write this as an extension to the Sizzle engine rather than a jQuery plugin; I've made a few other minor changes as well:



            function hasScroll(el, index, match) {
            var $el = $(el),
            sX = $el.css('overflow-x'),
            sY = $el.css('overflow-y'),
            hidden = 'hidden', // minifiers would like this better
            visible = 'visible',
            scroll = 'scroll',
            axis = match[3]; // regex for filter -> 3 == args to selector

            if (!axis) { // better check than undefined
            //Check both x and y declarations
            if (sX === sY && (sY === hidden || sY === visible)) { //same check but shorter syntax
            return false;
            }
            if (sX === scroll || sY === scroll) { return true; }
            } else if (axis === 'x') { // don't mix ifs and switches on the same variable
            if (sX === hidden || sX === visible) { return false; }
            if (sX === scroll) { return true; }
            } else if (axis === 'y') {
            if (sY === hidden || sY === visible) { return false; }
            if (sY === scroll) { return true };
            }

            //Compare client and scroll dimensions to see if a scrollbar is needed

            return $el.innerHeight() < el.scrollHeight || //make use of potential short circuit
            $el.innerWidth() < el.scrollWidth; //innerHeight is the one you want
            }
            $.expr[':'].hasScroll = hasScroll;


            You can then use this in any jQuery selector, such as:



            $('div:hasScroll') //all divs that have scrollbars
            $('div').filter(':hasScroll') //same but better
            $(this).closest(':hasScroll(y)') //find the parent with the vert scrollbar
            $list.is(':hasScroll(x)') //are there any horizontal scrollbars in the list?


            If you must have an instance method to do this check then you could write this to keep your semantics:



            $.fn.hasScroll = function(axis) {
            var el = this[0];
            if (!el) { return false; }
            return hasScroll(el, 0, [0, 0, 0, axis]);
            };


            Updated JsFiddle







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 5 '12 at 22:22









            Bill Barry

            2,171818




            2,171818








            • 1




              Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
              – ShadowScripter
              Jul 7 '12 at 9:17
















            • 1




              Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
              – ShadowScripter
              Jul 7 '12 at 9:17










            1




            1




            Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
            – ShadowScripter
            Jul 7 '12 at 9:17






            Most impressive. I didn't consider having it as a selector function. Very nice. You wrote in the comments "don't mix ifs and switches on the same variable", "minifiers would like this better" and "better check than undefined". Could you explain these comments or point to some documentation that does? :)
            – ShadowScripter
            Jul 7 '12 at 9:17















            8














            === everywhere



            === > == (Not that it really matters in this case, but it's still better.)



            Also, IIRC clientHeight etc are not cross-browser, this is why jQuery provides .position(), .offset(), .scrollTop() and .height() (whichever one best suits your needs).






            share|improve this answer




























              8














              === everywhere



              === > == (Not that it really matters in this case, but it's still better.)



              Also, IIRC clientHeight etc are not cross-browser, this is why jQuery provides .position(), .offset(), .scrollTop() and .height() (whichever one best suits your needs).






              share|improve this answer


























                8












                8








                8






                === everywhere



                === > == (Not that it really matters in this case, but it's still better.)



                Also, IIRC clientHeight etc are not cross-browser, this is why jQuery provides .position(), .offset(), .scrollTop() and .height() (whichever one best suits your needs).






                share|improve this answer














                === everywhere



                === > == (Not that it really matters in this case, but it's still better.)



                Also, IIRC clientHeight etc are not cross-browser, this is why jQuery provides .position(), .offset(), .scrollTop() and .height() (whichever one best suits your needs).







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 2 hours ago









                Glorfindel

                2581614




                2581614










                answered Jul 5 '12 at 9:42









                Florian Margaine

                1,012512




                1,012512






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f13338%2fhasscroll-function-checking-if-a-scrollbar-is-visible-in-an-element%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Morgemoulin

                    Scott Moir

                    Souastre