[ 10 posts ]

John Mizliso

  • Username: abxccd
  • Joined: Sun Jan 22, 2012 11:20 pm
  • Posts: 48
  • Offline
  • Profile

App Framework in 3.5.0pr1 and hash-based history

Post Posted: Mon Jan 30, 2012 1:56 am
+0-
I am playing around with app framework in 3.5.0pr1 and so far it looks promising.

However, I seem to have run into a problem with hash-based history in browsers that don't support the html5 history api (all versions of IE).

Here's the code I am using

Code:
<script>
   YUI().use('app', function (Y) {
      // Create a CustomApp instance that inherits the defaults and adds to them.
      var app = new Y.App({
         
      
      });

      app.set('root', '/site/root');

      app.route('/testpage', function (req) {
          alert('hi there!');
      });
      app.dispatch();

      app.save('/testtest/')

   });
   </script>


The code works fine for HTML5 browsers (firefox, chrome etc), I get an alert on http://localhost/site/root/testpage and then I get a new history entry for http://localhost/site/root/testtest.

The problem is that when I try the code in IE, nothing happens. There is no alert, and I don't a new history entry for http://localhost/site/root/#/testtest.

Why is this happening, and how can I fix it?

Cheers :)

Eric Ferraiuolo

YUI Developer

  • Username: ericf
  • Joined: Mon Jan 12, 2009 8:26 pm
  • Posts: 380
  • Location: Boston, MA
  • Twitter: ericf
  • GitHub: ericf
  • Gists: ericf
  • IRC: eric_f
  • YUI Developer
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Mon Jan 30, 2012 8:47 am
+0-
John,

I looks like this is a timing issue preventing the history entry for the hash-based URL change. There is a `ready` event which you can wait for and then make your call to `app.save()`.

Code:
app.on('ready', function () {
    app.save('/testtest/');
});


I would recommend that you also use Y.App's `navigate()` method as it is a higher abstraction over `save()` and `replace()` and will internally call the correct one and also resolve URLs you pass into it. The `navigate()` method will behave just like an <a> being clicked.

http://stage.yuilibrary.com/yui/docs/ap ... d_navigate

Note that the docs for Y.App's `navigate()` method need to be updated to reflect their interaction with the `serverRouting` attribute, they should read more like this:
http://stage.yuilibrary.com/yui/docs/ap ... __navigate

Also, here is more information about the `ready` event:
http://stage.yuilibrary.com/yui/docs/ap ... vent_ready

Hopefully that information will help, but I still think there might be a bug here. Could you please create a ticket on this issue and reference this post in the ticket? Thanks!

http://yuilibrary.com/projects/yui3/newticket/

John Mizliso

  • Username: abxccd
  • Joined: Sun Jan 22, 2012 11:20 pm
  • Posts: 48
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Mon Jan 30, 2012 2:59 pm
+0-
Hi ericf,

Thanks for the very helpful reply. I have switched from using
Code:
save()
to
Code:
navigate()
.

After some more testing, I realized that the document did not have a valid doc-type, so it was rendering in quirks mode in IE. This explained why YUI didn't work at all there. Setting a doctype fixed it, so I don't think there's a bug.

I do however have an additional query. Let's say the site root is http://site.com/site/root and I have
Code:
app.set('root', '/site/root');
. If a user in an HTML4 browser visits
Code:
http://site.com/site/root/somepage
, I would like to have the history entry replaced with
Code:
http://site.com/site/root/#/somepage
. Is this possible? If so, how can I go about doing this?

Currently the code will append the hash after the current url:

Any suggestions for fixing this?

John Mizliso

  • Username: abxccd
  • Joined: Sun Jan 22, 2012 11:20 pm
  • Posts: 48
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Tue Jan 31, 2012 3:06 am
+0-
Thought I would post an update in regards to trying to convert http://site.com/site/root/testtest/ to http://site.com/site/root/#/testtest/ on browsers not supporting the HTML5 history api.

Continuing from the code above, I have written the following:

Code:
//Assume that an App was instantiated previously
app.once('ready', convertToHash);
   
         function convertToHash(e){
            if(app.getPath() != '/'){
               Y.log('path: ' + app.getPath());
               var fullpath = Y.config.win.location.href;
               fullpath = fullpath.replace(app.getPath(), '') + '/#' + app.getPath();
               Y.log('full: ' + fullpath);
               Y.config.win.location(fullpath); //problem here
            }
         }


I am able to get the "fullpath" with out any issues. However, the problem lies with redirecting. If I use navigate() or replace() I end up at http://site.com/site/root/testtest/#/testtest

If I try and use Y.config.win.location, this happens:
1. I get redirected to http://site.com/site/root/#/testtest/
2. From there, I get redirected to http://site.com/site/root/#/#/testtest/.

So, this creates 3 history entries which is less than idea. Is using Y.config.win.location the right apporach?

Eric Ferraiuolo

YUI Developer

  • Username: ericf
  • Joined: Mon Jan 12, 2009 8:26 pm
  • Posts: 380
  • Location: Boston, MA
  • Twitter: ericf
  • GitHub: ericf
  • Gists: ericf
  • IRC: eric_f
  • YUI Developer
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Tue Jan 31, 2012 10:26 am
+0-
John,

This is tricky to deal with, as you are finding it to be.

`Y.App` has a `serverRouting` attribute which will help you configure your app instance on how to route requests and which form of URLs to use. The API docs outline the three acceptable values for `serverRouting`:

http://stage.yuilibrary.com/yui/docs/ap ... verRouting

When building the Photos Near Me app I wanted all "requests" to be handled by my Y.App instance, and wanted it to use the best form of URLs depending on the browser's capabilities. This sounds similar to what you're looking for.

For PNM, I left `serverRouting` as its default value of `undefined`, this way HTML5 browsers will get full-path URLs while non HTML5 browsers will get hash-based ones.

This configuration posed the same issue you're running into. To overcome this I implemented some redirect logic on the server so any request that wasn't to "/" would redirect to "/" and tack on the extra path segments to the URL's hash fragment, i.e.:

Code:
Request:     http://example.com/users/1
Redirect to: http://example.com/#/users/1


Here is the specific Node.js server code that does this: https://github.com/ericf/photosnear.me/ ... .js#L21-31

The server is now sending all browsers to a hash-based URL. To get nice full-path URLs in HTML5 browsers, I simply call Y.App's `upgrade()` method which upgrades a hash-based URL to an HTML5 URL if necessary. In non-HTML5 browsers, this method is a noop.

Let me know if this pattern will work for you.

John Mizliso

  • Username: abxccd
  • Joined: Sun Jan 22, 2012 11:20 pm
  • Posts: 48
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Tue Jan 31, 2012 2:52 pm
+0-
Hi Eric,

Thanks for the tips :) I will have a look and get back to you. However, if I use the server to redirect all requests from http://site.com/site/root/testtest/ to http://site.com/site/root/#/testtest/, does this mean that the user must have javascript enabled and people without JS will be left out?

Cheers :)

Eric Ferraiuolo

YUI Developer

  • Username: ericf
  • Joined: Mon Jan 12, 2009 8:26 pm
  • Posts: 380
  • Location: Boston, MA
  • Twitter: ericf
  • GitHub: ericf
  • Gists: ericf
  • IRC: eric_f
  • YUI Developer
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Tue Jan 31, 2012 8:23 pm
+0-
Yes. But like the docs say, if you can, you should set `serverRouting` to `true`. The tradeoff here is a degraded experience for people using non HTML5 browsers, i.e. they will experience full page reloads, but all users will get full-path URLs and search engines can spider it.

I feel this decision is very context specific. It involves understanding the differences between a website and web application, and whether its data is for everyone or specific to users.

If you're building a website and its data is for everyone, like a blog, then the goal of using Y.App (or simply Y.Pjax) is to enhance the experience and performance when possible. In this case, setting `serverRouting` to `true` is advised. All URLs will be full-path, the server loads the initial data, and search engines can spider the site.

If you're building a web application where each user has their own data, like a todo app, then you could use Y.App to contain all of the application logic with the server just providing a data API and persistence. In this case, leaving `serverRouting` `undefined` or explicitly setting it to `false` will cause all page "requests" to be handled by Y.App. All URLs will still be bookmarkable, the back/forward buttons will always work, it will be really performant, and since the user has to login, search engines cannot spider the site anyways.

If you're building something that blurs the lines between site vs. app and data for everyone vs. per user, like Twitter, a balanced approach is probably best, and it is always good to error on the site of `serverRouting` set to `true`.

I will be adding to Y.App's User Guide over the coming weeks to better outline the best practices and tradeoffs for the different ways to configure routing and URLs.

John Mizliso

  • Username: abxccd
  • Joined: Sun Jan 22, 2012 11:20 pm
  • Posts: 48
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Wed Feb 01, 2012 12:47 am
+0-
Hi Eric,

Thanks for the indepth explaination :) I have decided to set "serverRouting" to underfined so that all users would be able to have access to "states" within the application without full page reloads.

I have, however found an issue with the stored history in IE9. This can be replicated in the photosnear.me application. However, this doesn't seem to be a known issue in the documentation for Y.App or Y.Router.

To replicate:

1. Visit photosnear.me and let it look up your location.
2. Visit any random photo (http://photosnear.me/#/photo/5334879584/)
3. Manually access a hashed address link (for example: http://photosnear.me/#/place/2452537/).

Looking at the history menu, the entry for the photo in step 2 is replaced by the entry in step 3. I would expect that step 3 would create a history entry of its own.

Is this something that can't be fixed or worked around?

Cheers :)

Eric Ferraiuolo

YUI Developer

  • Username: ericf
  • Joined: Mon Jan 12, 2009 8:26 pm
  • Posts: 380
  • Location: Boston, MA
  • Twitter: ericf
  • GitHub: ericf
  • Gists: ericf
  • IRC: eric_f
  • YUI Developer
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Wed Feb 01, 2012 9:08 am
+0-
John,

I can confirm the behavior you're seeing in IE9, however I can also reproduce this behavior on any page I visit that uses hashes in the URL. Therefore it appears to be the way IE is handling manual changes to the hash in the URL bar and how those correspond to entries in its history.

Digging into the debugger and watching the `hashchange` events, after updating the hash in the address bar manually, I see the correct new and old values for the hash fragment. But once on the URL in step 3, when I click the back button, I'm sent back to the URL in step 1.

So I'm not sure if there is a work around, but let us know if you find something.

John Mizliso

  • Username: abxccd
  • Joined: Sun Jan 22, 2012 11:20 pm
  • Posts: 48
  • Offline
  • Profile

Re: App Framework in 3.5.0pr1 and hash-based history

Post Posted: Wed Feb 01, 2012 3:40 pm
+0-
Thanks Eric :)

I will let you know if I find a way, but I have a feeling it's something that we can't really work around.
  [ 10 posts ]
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum