davidjbradshaw / iframe-resizer

Keep iFrames sized to their content.

Home Page:https://iframe-resizer.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

anchor links in page

beardedgeek opened this issue · comments

Thanks for such a great script. It's working great apart from one tiny issue that I'm hoping is my config rather than it not working.

I'm embedding a mediawiki application within a page which creates a table of contents at the top. The TOC has a load of in page anchor links to content lower down the page, however when I click on one of the links it doesn't scroll down to focus it.

The problem is that you need to scroll the parent frame, not the child.

So you have to write script to to workout the position and send a message
to the host page and then have that scroll.

I have been working on a parentIFrame.scrollTo() function to help with
this, currently it is undocumented as I need to find some time to add some
tests for it, but give it a go and let me know how you get on with it.

On Monday, June 30, 2014, Huw Davies notifications@github.com wrote:

Thanks for such a great script. It's working great apart from one tiny
issue that I'm hoping is my config rather than it not working.

I'm embedding a mediawiki application within a page which creates a table
of contents at the top. The TOC has a load of in page anchor links to
content lower down the page, however when I click on one of the links it
doesn't scroll down to focus it.


Reply to this email directly or view it on GitHub
#68.

David J. Bradshaw )'( dave@bradshaw.net

'The people we think are a little weird are the ones who change the world'

  • Simon Sinek

Just for future readers, below is basically one way to get anchor links working (only tested, so far, on mac/Firefox).

Put on iframe page:

$(function() {

    $('a').click(function($e) {

        var $this = $(this);
        var href;

        if ('parentIFrame' in window) { // I only want to do this on parent pages that have enablePublicMethods turned on; this will allow me to use iframe on target and external pages.

            $e.preventDefault();
            $e.stopPropagation();

            $this.blur();

            href = $this.attr('href');

            //console.log(href.substring(href.indexOf('#') + 1));

            window.parentIFrame.sendMessage(href.substring(href.indexOf('#')));

        }

    });

});

On the parent:

(function() {

    var $attn = $('#attn').iFrameResize({
        enablePublicMethods: true,
        messageCallback: function (obj) {

            //console.log(obj.message);

            $.smoothScroll({
                scrollTarget: obj.message
            });

        }
    });

})();

The above uses Smooth Scroll Plugin.

@davidjbradshaw Shouldn't there be some kind of check in the iframe page part whether if its really an anchor on the same page and not a regular link?

@neothemachine anchor links are a real edge case and it's not clear how you would tell if an anchor referenced the parent page.

I think that @mhulse has the best solution for this, although as a simple example I'd cut it down to this.

$('a=[href^=#]').click(function(e) {
    if ('parentIFrame' in window) {
        var href = $(this).blur().attr('href');
        e.preventDefault();
        window.parentIFrame.sendMessage(href.substring(href.indexOf('#')));
    }
});

and

iFrameResize({
    enablePublicMethods: true,
    messageCallback: function (obj) {
        location.href = obj.message;
    }
});

Will add this to the docs when I get time to test.

@davidjbradshaw Thanks for this. Are you sure your expression is right? It says Syntax error, unrecognized expression: a=[href=^=#].

EDIT: I think it should be a[href^=#].

Yep. Have fixed above.

Hm, actually it doesn't even work manually for me. So when I append #anchor to the address in the browser and hit enter nothing happens. Maybe that's why @mhulse used the smooth scroll plugin.

Like I said, not tested it. Not sure how you move to an anchor in JS, I'd suggest looking at the location object on MDN. Let me know what you find out.

I think it doesn't work that way because at least Chrome separates the anchors for both pages and you cannot use the iframe anchors from the parent page (maybe Firefox as tested by @mhulse has less restrictions on that). So I guess for this to work you have to determine the scroll position within the iframe page and send this number as a message to the parent, and the parent then scrolls to that position plus the iframe offset.

Ok, this is my current working approach:

On the iframe:

    $(function() {
        $('a[href^=#]').click(function(e) {
            if ('parentIFrame' in window) {
                var href = $(this).blur().attr('href');
                var anchor = $('a[name=' + href.substring(1) + ']');
                var offset = Math.round(anchor.offset().top);
                e.preventDefault();
                window.parentIFrame.sendMessage(offset);
            }
        });
    });

On the parent page:

iFrameResize({
        enablePublicMethods: true,
        messageCallback: function (obj) {
            window.scrollTo(0, obj.message);
        }
    });

I didn't add the iframe offset yet as this is not an issue for me (offset is quite small) but that should be trivial.

It's great to see other examples. Thanks for sharing codes!

Btw, this is an awesome plugin. I can't wait to use it for other projects. 👍 :octocat:

I've started work on a more complete solution to this problem. Aim is to support the following.

Scroll to anchor in iFrame
If not found in iframe, scroll to anchor in host page
Scroll to anchor on page load in iFrame
Automatic support for <a href="#name">
JS call parentIFrame.scrollToId()
Observe window.onhashchange event.
scrollCallback() method to allow callout to fancy scrolling functions

Can you think of anything else that might be needed?

Work in progress can found here.
https://github.com/davidjbradshaw/iframe-resizer/tree/anchorLinks

I think this covers most use cases. Can't think of anything else. One (unrelated) thing that annoys me though is when I navigate within the iframe and then press the browser back button I'm back at the top of the page and not where I was.

Might be able to fix that via window.onhashchange. It's on my list.

On Saturday, December 6, 2014, Maik Riechert notifications@github.com
wrote:

I think this covers most use cases. Can't think of anything else. One
(unrelated) thing that annoys me though is when I navigate within the
iframe and then press the browser back button I'm back at the top of the
page and not where I was.


Reply to this email directly or view it on GitHub
#68 (comment)
.

Sent from my iPhone.

Just released version v2.8.0 with support for In Page Anchor links. The code now intercepts these in the iFrame and reposition the parent page. Both html links and JS calls to the location object are intercepted.

It will first look for an anchor in the iframe and if it is not found it will bubble up through nested parent pages until it finds the correct link.

I've also added a new scrollCallback function that allows you to hook in your own code for animated scrolling.

This works with in page links and also the parentIFrame.scrollTo() and parentIFrame.scrollToOffset() methods.

Hey guys.

Anchor scrolling is not working for me, is this still valid today?

I'm using angular and the html anchors are created dynamically, could this be it?

Yep take a look at the example. If it is an Angular issue you would be better asking on StackOverflow.

Just pointing out that there are major accessibility problems with the approaches in this issue.

Simply using javascript to scroll the viewport to a new place on the page is not an inclusive solution.

@LukeLeber that is a fair point. Would you like to raise a PR? Or create an accessibility issue