Single Page App in a Single Page App


#1

I am integrating Ember.js in an HTML SPA which has <a href="#to_section_home">Home</a> navigation.

Just wondering how to do this in Ember if anyone has an idea. Would still like history and URL to work as usual but that seems unlikely.


#2

You can tell Ember to leave the URL alone like this:

App.Router.reopen({
  location: 'none'
});

But yes, this means you’ll lose the ability to navigate the Ember app using the normal browser forward & back controls. It’s not great.

If you can change the existing single page app a little, you could make them coexist by putting each in charge of different URLs.


#3

Well I did a rewrite on the navigation of the App. My take was…

In Navigation HBS file.

<ul class="navigation menu">
    <li><a href="#/" {{action goToLink "home" "to_the_top"}}>Home</a></li>
    <li><a href="#/" {{action goToLink "home" "top_center"}}>Services</a></li>
    <li><a href="#/" {{action goToLink "blog" "main_top"}}>Technology</a></li>

In ApplicationRoute JS file:

var ApplicationRoute = Ember.Route.extend({
    actions: {
        goToLink: function(route, scrollToDiv) {
            var $scrollTo = smoothScroll(scrollToDiv);
            this.transitionTo(route).then($scrollTo);
        }
    }
});

Then I have a smooth scrolling JS function that I am not sure where to put or whether to put this in an Handlebars helper or something else.

var smoothScroll = function(e) {
	var destinationLink = document.getElementById(e);

	// If we didn't find a destination, give up and let the browser do its thing
	if (!destinationLink) return true;

	// Find the destination's position
	var destx = destinationLink.offsetLeft; 
	var desty = destinationLink.offsetTop;
	var thisNode = destinationLink;
	while (thisNode.offsetParent && (thisNode.offsetParent != document.body)) {
  	   thisNode = thisNode.offsetParent;
  	   destx += thisNode.offsetLeft;
  	   desty += thisNode.offsetTop;
	}

	// Stop any current scrolling
	clearInterval(self.INTERVAL);

	var cypos = getCurrentYPos();
	var STEPS = 25;
	var ss_stepsize = parseInt((desty-cypos)/STEPS);

	self.INTERVAL = setInterval(function() {
	    var wascypos = getCurrentYPos();
	    var isAbove = (wascypos < desty);
	    window.scrollTo(0,wascypos + ss_stepsize);
	    var iscypos = getCurrentYPos();
	    var isAboveNow = (iscypos < desty);
	    if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
	      // if we've just scrolled past the destination, or
	      // we haven't moved from the last scroll (i.e., we're at the
	      // bottom of the page) then scroll exactly to the link
	      window.scrollTo(0,desty);
	      // cancel the repeating timer
	      clearInterval(self.INTERVAL);
	      // and jump to the link directly so the URL's right
	      //location.hash = anchor;
	    }
	},10);

	function getCurrentYPos() {
		if (document.body && document.body.scrollTop)
		  return document.body.scrollTop;
		if (document.documentElement && document.documentElement.scrollTop)
		  return document.documentElement.scrollTop;
		if (window.pageYOffset)
		  return window.pageYOffset;
		return 0;
	} 
}

This is based on SmoothScroll.js by kryogenix but a much simpler version. I think this would make a good pure helper or perhaps even an extension to Link-To.


#4

@wycats, @tomdale do you guys think internal linking and some type of smooth scrolling is worthy of a PR on the link-to helper of is this something that is not of enough value to have in the core implementation?