7

I searched, but couldn't find anything.

I have a sticky header that shows up on the page after scrolling down on the page. This was working wonderfully on the page. However, I now have to unfortunately have to put it within an iframe.

I have to same exact code, but I believe it's the window.scroll that is causing it to trip up. The content is just sitting at the top of the page behind everything and when inspecting the code it stops at that function and goes no further.

Is there an alternative to window.scroll (or scroll function) or is there a way to make it work within an iframe? All my attempts have failed.

My example is here https://www.bootply.com/edHiY15iJy#

My HTML for the header

<div class="container">
        <header class="header-wrapper">
            <div class="sticky-header">
                <div class="row">
                        <div class="col-md-4">
                        <div class="form-group">
                            <label class="bold">Customer Name: </label>
                            <label>Person!! </label>
                        </div>
                        <div class="form-group">
                            <label class="bold">Address: </label>
                            <label>101 Main Street </label>
                        </div>

                    </div>

                    <div class="col-md-4">
                        <div class="form-group">
                            <label class="bold">Email:</label>
                            <label>something@email.com </label>
                        </div>
                        <div class="form-group">
                            <label class="bold">City, State:</label>
                            <label>Tavierner, FL </label>
                        </div>

                    </div>
                    <div class="col-md-4">
                        <div class="form-group">
                            <label class="bold">Phone:</label>
                            <label>555-555-5555 </label>
                        </div>

                        <div class="form-group">
                            <label class="bold">Club Code:</label>
                            <label>456 </label>
                            <label class="bold">Associate#:</label>
                            <label>45 </label>
                        </div>
                    </div>
                </div>
            </div>
        </header>
  <section>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>
    <p>this</p><p>this</p><p>this</p><p>this</p><p>this</p>

  </section>
</div>

and my jquery

 if ($('.sticky-header').length >= 1) {
        $(window).scroll(function () {
            var header = $(document).scrollTop();
            var headerHeight = $('.header-wrapper').height();
            if (header > headerHeight) {
                $('.sticky-header').addClass('sticky');
                $('.sticky-header').fadeIn();
            } else {
                $('.sticky-header').removeClass('sticky');
            }
        });
    }

A screenshot of what the menu looks like when it's not working:

enter image description here

zazvorniki
  • 3,512
  • 21
  • 74
  • 122
  • your iframe has a defined height and width? – Joe RR Nov 30 '17 at 17:54
  • @LeandroRuel, a height and width of 100%. It fills the whole screen and this is something I cannot change. It's part of the overall application – zazvorniki Nov 30 '17 at 18:21
  • can you post some screenshot of the bug? i need understand your problem – Joe RR Nov 30 '17 at 18:29
  • also, instead of window.scroll you tried document.scroll ? look this question: https://stackoverflow.com/questions/1852518/how-to-get-scrolltop-of-an-iframe – Joe RR Nov 30 '17 at 18:32
  • 1
    @LeandroRuel I put a screenshot of the bug, it's just sitting behind all the elements on the page. I have tried document.scroll. That question is for scrolling to the top, like a 'beam me up' button or you click on an element and the page scrolls. My situation is that I need to detect when the page scrolls and then show the div – zazvorniki Nov 30 '17 at 19:51
  • you checked if have any css inside of iframe breaking your header too? – Joe RR Nov 30 '17 at 19:58
  • @LeandroRuel, yes I have. The code stops at the window or document.scroll. So I am 99% sure this is a javascript issue – zazvorniki Nov 30 '17 at 20:09
  • i think i understand what is happening now... you can't detect scroll event from inside of iframe (because is a parent element), but you can from outside. – Joe RR Nov 30 '17 at 20:37
  • @LeandroRuel Yes...but I need it to work within the iframe. – zazvorniki Nov 30 '17 at 20:41
  • If I put a `console.log` statement in the `$(window).scroll` function of your bootply, I see the trace in the browser console when I scroll. Is that the correct way to test your code (knowing that bootply runs the code in an iframe)? – ConnorsFan Dec 01 '17 at 16:58
  • @ConnorsFan yes, the bootply works perfectly....the problem is when that code is placed inside an iframe it stops working. – zazvorniki Dec 01 '17 at 18:29
  • But bootply runs the code in an iframe (as you can see with the F12 tools), and it works. – ConnorsFan Dec 01 '17 at 19:04
  • This is working fine in jsfiddle as well... – Mrigank Pawagi Dec 04 '17 at 16:53
  • @zazvorniki I have to ask to rule it out, but you are calling your javascript from within the iframe (i.e. binding to the body scroll within the iframe, not the outer page), right? Because, as said above, your working example is running in an iframe. – delinear Dec 05 '17 at 09:46
  • @delinear, I have tried outside the document, before the iframe loads, within the iframe. – zazvorniki Dec 05 '17 at 15:49
  • the only way of solve this is showing a link to your enviroment or production. so we can see what is happening. looks like we can't figure out the problem just seeing your code – Joe RR Dec 05 '17 at 18:16
  • @LeandroRuel I can't do that. I work in a company and it's an internal application. – zazvorniki Dec 05 '17 at 19:33
  • @zazvorniki Can you check if the scolling actually occurs inside the iframe? Chances are it's the document holding the iframe that is actually being scrolled and the iframe's height is > 100vh. – Manuel Otto Dec 07 '17 at 17:32
  • @ManuelOtto yes, the scrolling is actually happening inside the iframe. The height is set to 100% and the overflow is auto allowing it to scroll. This is the first thing I checked. – zazvorniki Dec 08 '17 at 14:57

6 Answers6

4

I would have commented, but I haven't gotten enough reputation, yet. (Sorry) I found this on SO. Since you are trying to detect the scroll event inside the iframe, skyline's answer should be helpful.

Geshode
  • 3,600
  • 6
  • 18
  • 32
  • this is the best aproach since iframe is like another window inside a window. – Joe RR Dec 01 '17 at 13:22
  • I unfortunately couldn't get either of the solutions on that post to work. It's just not recognizing the scroll. – zazvorniki Dec 01 '17 at 13:56
  • Since it is getting stuck at window.scroll, it seems to be a "reference" problem to the iframe, right? Have you tried window.frameElement? I haven't seen in the post or comments, if you tried it or not. Or have you tried to reference it by id? – Geshode Dec 01 '17 at 14:20
  • @Geshode I have tried window.frameElement, calling the iframe id, doing the iframeId.contents(), calling the document, attaching it to the html, just attaching it to the window, calling the parent of the iframe....you name it I've tried calling it. – zazvorniki Dec 01 '17 at 14:42
  • I guess, then you also have tried `getFrameTargetElement( document.getElementById("ID") )`, right? If you tried all these, then maybe it isn't a problem with the calling. Have you tried different variations of .scroll? For example the longhand version `.on("scroll", function(){...})`. I don't think, that will fix it, but who knows. – Geshode Dec 01 '17 at 15:03
  • I just tried getFrameElement with no luck. I've also tried on scroll, or through the html onscroll....is there any others to try? I am so out of ideas haha – zazvorniki Dec 01 '17 at 15:55
0

The question here is where the scroll apply.

If the scroll apply on the document, the JS is in this document, and the iframe have the scroll, then it should work just like the jQuery doc : see the last demo here.

Maybe try to replace the iframe's content with the demo to see if it work.

A straight possible solution is to get the scroll back in the page, to do that just create some parent element in it (or use an existing one), with a width and height of the size of the iframe plus the overflow, and use a

$('#myparent').scroll(function () {

instead of targeting the document. Beware that you'll need for #myparent to exist when the JS will execute this line, so think of using a .ready or putting the JS at the bottom of the page.

At last, if you want solution without scroll, you could try for something like this post here or this one maybe more like it for some css-only solutions (quite a different way of going around it). But it's not certain that the iframe won't cause issues there too.

Edit : since the full css is a no-go, here's two others work-around i can think of.

1- The mousewheel event.

On Chrome, try to replace the .scroll(... by .on('mousewheel',... If it work, you can use this plugin here for a cross browser solution.

2- The Bad and Dirty

Well, my last bullet isn't the nicest. You can detect the scroll event on the iframe page (make the iframe go all the way to the bottom of your document, and detect the scroll of the iframe's window for example). From here, you can then do your work in the iframe page, for example :

$('#myiframe').ready(function () {
  $(window).scroll(function () {      
        var header = $(document).scrollTop();
        var headerHeight = $('#myiframe').contents().find('.header-wrapper').height();
        var sticky = $('#myiframe').contents().find('.sticky-header');
        if (header > headerHeight) {
            sticky.addClass('sticky');
            sticky.fadeIn();
        } else {
            sticky.removeClass('sticky');
        }
  });
});

I tested it, it should work if you juste replace #myiframe. But as i said, it's not that clean (not sure what your team will think of it ^^').

Nomis
  • 854
  • 7
  • 11
  • I have actually tried to attach the scroll to the first div on the page. I have also tried to attach it to the id of the iframe as well as the content of the iframe. I'm at the point of trying to find an alternative to the scroll function as it does not want to work in this case. – zazvorniki Dec 05 '17 at 15:45
  • Did you try to replace your page with the demo from jQuery doc ? If yes and it doesn't work, could you post your full code of this try (iframe+demo), it'll be easier to debug. If yes and it work, could you see in your actual code if by putting alert('1'); before if ($('.sticky-header').length >= 1) { and alert('2'); after you have any result ? – Nomis Dec 05 '17 at 16:38
  • I can't post the entire applications code. I work in a company and cannot post their internal app publicly. Yes, I tried putting in the example from there, but the code ignores the scroll function, just like any other time I have tried. I always test with console.logs to make sure it can get in the function. In this case it cannot. Which is why I'm looking for alternatives to the scroll functions. – zazvorniki Dec 05 '17 at 19:36
  • 1
    Cool, it mean the problem come from the iframe's page. If you replace the .scroll event by a .click one, does it work ? I understand you can't post any company code, but does it happen to have JS inside? Is there any preventdefault ? Or any .contentWindow (that one let the iframe page access the called page) ? And at last, as for alternative i'll edit one in my answer. – Nomis Dec 05 '17 at 23:49
  • clicks, hovers and pretty much every other function works (except for mousemove). Which is what has me so stumped. There are no preventdefaults, but I did add one just to see if it changed anything and it did not. There is quite a bit js, but none of it touches this page directly. – zazvorniki Dec 06 '17 at 14:26
  • The css only scrolls don't work for this solution. I know because I attempted that before falling to jquery. I can't change the actual way of scrolling. I have attempted to and received pushback from other developers. – zazvorniki Dec 06 '17 at 14:28
  • Too bad mousemove doesn't work... added two more to go with what we have. – Nomis Dec 06 '17 at 17:51
  • I've unfortunately tried all of the above :( Apparently mousewheel doesn't want to work either. Seems like an issue with certain events not wanting to fire. Hover seems fine, but that only fired when you first enter the screen. I've tried the bad and the dirty before. For some reason it still will not go in that scroll function even if it's in a ready function. I've even tried a load function or a click function to see if once I clicked on the iframe the scroll would start to work, but that didn't work either. :( – zazvorniki Dec 06 '17 at 20:36
  • Can you confirm then that the scroll event (and the mousemove ?) won't work even in the window containing the iframe (whithout even interacting with the iframe) ? If so, the issue isn't that your code is in a iframe, but with something in the js of your app wich stop those specific event. The best you will be left with is asking the guys who gave you this app why it block some events (just to be sure, you can test a page with juste a simple iframe to your code, but i think there's few places for doubt). – Nomis Dec 06 '17 at 21:35
  • If you can't ask for any reason (or they already said it doesn't), you'll have to debug the JS by removing large chunk of code until you find the block. – Nomis Dec 06 '17 at 21:36
  • Seeing another answer in another post, you already tried clean pages ? Then have you tried to remove chunk of your JS code in those clean test ? Have you tried the demo from the jQuery doc in one of those ? We maybe can try to find a starting, working point from where to go back to the others. – Nomis Dec 06 '17 at 21:43
  • And at last, did you check the encoding of each page ? Sometime when they differ it get messy. – Nomis Dec 06 '17 at 22:05
0

my solution is: use a wrapper to the whole page, you can use body tag too, put the following css:

<style>
 html,
 body {
   height: 100%;
 }
 body {
   overflow-y: scroll;
 }
</style>

and test it in your js:

<script>
  $('body').on('scroll', function() {
  // your code goes here...
  console.log('scroll being made');
  })
</script>
Joe RR
  • 262
  • 3
  • 22
0

Check the code rendered in your example (https://www.bootply.com/edHiY15iJy#) it's in "iFrame". I think what you are missing is the "css code" in your inner iframe code.

John Tribe
  • 1,407
  • 14
  • 26
0

Try this code to get scroll offset inside iframe:

$(document).ready(function()
{   

    $('#yourFrameId').load(function()
    {

        var iframe = $(this).get(0);
        iframe.contentWindow.onscroll = function(evt)
        {
            console.log(evt.pageY);
        };


    });


});
dfionov
  • 314
  • 1
  • 8
-1

I ripped you bootply, loaded all the libraries in order to work and added it in an iframe and it works fine. Try it just to make sure that it is the script that is causing the error and not the page where the iframe is loaded.

itdoesntwork
  • 1,745
  • 16
  • 31
  • There is no error, the script just refuses to go into the scroll function. I have loaded it in several clean environments and cannot get it to work there either...I wish I knew how you got your to work. – zazvorniki Dec 01 '17 at 15:41