1

Say there's a surface declared using Famo.us containing markup content:

this.mySurface = new Surface({
    size : this.options.targetSize,
    content : '<a href="http://famo.us">This is a link</a>',
});

Is there an (easy) way to intercept the click event?

Bonus: In addition to intercepting the click, how to pass the click event through so that the default handler also does its job?

pmont
  • 2,083
  • 22
  • 43
  • 1
    What are you trying to do with this? What do you mean by the bonus. If you put a this.mySurface.on('click', function() {}); it will capture the click event letting you act on it and the link is still followed as well. Little more detail as to what your trying to do and I'm sure I can help you. – aintnorest Aug 11 '14 at 22:09
  • The surface contains standard markup with links. I'd like to be able to open a link in a new surface on the page instead of having the browser handle it by opening in a new window/tab. – pmont Aug 12 '14 at 02:22

2 Answers2

1

You can't open a new link directly in a surface but you could add something like an IFrameSurface: Famo.us IframeSurface

As aintnorest implied, you most likely want to add an event handler to the click of the surface:

this.mySurface.on('click', function(e) {
    // Bonus: on click do the standard redirect on main window
    // or redirect of iFrame control
    window.location = "http://famo.us";
});

and then instead of an href in the content you just need the text 'This is a link' as the handler provides the typically expected logic but via an intercept.

If you need to leave them as 'links' for some reason you can try adding a hash to the href to avoid actually navigating via the default behavior.

As an alternative, because we're working in javascript anyways, you can try something like:

use javascript to intercept all document link clicks

Community
  • 1
  • 1
Perry
  • 528
  • 2
  • 12
  • Thanks. That works for a single link, but it won't work if the markup content contains multiple (different) links. +1 for the intercept thread. – pmont Aug 12 '14 at 23:54
1

There are a few ways to handle event stopping. Here is a solution I think will work best in your case. Of course, loading pages or links this way has its own caveats that we will not go too deep into here.

Here is the full code: Example on jsFiddle

First we track the clicks within our target surface and call the function to check if it is a link. If we clicked on a link we will emit an event passing the target href.

this.mySurface.clickNullifier = function (e) {
    if (e.target && e.target.nodeName == 'A' && e.target.href) {
        this.mySurface.emit('href-clicked', { data: { href: e.target.href } })
        return false;
    }
}.bind(this);

this.mySurface.on('deploy', function () {
    // sets up the click function on the surface DOM object
    this._currentTarget.onclick = this.clickNullifier;
});

Now that the surface clicks are tracked we will capture any intercepted clicks and load them into an iFrame or if local links load them in using the loadURL utility in famous.

this.mySurface.on('href-clicked', function (event) {
    console.log(event.data);
    // handle your code for the iframe
    // not always doable in the case of 'X-Frame-Options' to 'SAMEORIGIN'
    loadIframe.call(this, event.data.href);

    // or loadURL like here. Needs CORS open on the href server if cross origin
    //Utility.loadURL(event.data.href, loadLink.bind(this));
}.bind(this));

function loadIframe(content) {
    this.backSurface.setContent('<iframe src="' + content + '" frameborder="0" height="100%" width="100%"></iframe>');
};

Bonus: In the example link above, you will see that the click event still fires on the surface. You can see by watching the console log.

talves
  • 13,993
  • 5
  • 40
  • 63