Backbone Routing with Static HTML files - javascript

I'm working on a website where we are using 3rd Party web services to return dynamic content and using javascript to parse and display that data from to the page. We are already using backbone in a couple places on the site to post data to web services so I had the thought of trying to use Backbone's router to run specific functions based on the page url and grabbing the query because we are hashing the queries to the url of the page.
For example: global-site-search.html#query
This is the router code I have to this point:
var Router = Backbone.Router.extend({
routes : {
'' : 'indexRoute',
'global-site-search.html(:query)' : 'getSearchResults'
},
indexRoute: function(query) {
console.log("indexRoute");
},
getSearchResults: function(query) {
console.log("getSearchResults with query", query);
}
});
var WaRouter = new Router();
Backbone.history.start({
pushState: true,
root: '/'
});
But when I hit the page with a url like global-site-search.html#query the query value returns null. Has anyone tried this before or am I trying to extend Backbone's router to far in handling this?

Is global-site-search.html from your server?, if yes then the config for router should be
':query' : 'getSearchResults'
If no, then you can't do that, because Backbone.Router uses the hash part of the current page URL to track pages. And since global-site-search.html is not containing any backbone code, it can't do anything. It is possible only if you somehow can inject your router code into global-site-search.html which is illegal in this case
Updated: this should allow you to search with this route ':query' : 'getSearchResults'
Backbone.history.start({
pushState: true,
root: window.location.pathname
});
When using router, you need to set the correct root, so using window.location.pathname is the easiest way to do that. Also, according to Backbone documentation
and if a hash URL is visited by a pushState-capable browser, it will be transparently upgraded to the true URL. Note that using real URLs requires your web server to be able to correctly render those pages, so back-end changes are required as well. For example, if you have a route of /documents/100`
Since you are not having any real back-end to handle pushState, I suggest that you turn it off

Related

How to create a custom route in Sails JS

I'm trying to create a custom route in Sails and according to their documentation, if I add the following in config/routes.js:
'post /api/signin': 'AuthController.index',
The request would be dealt with by the index action in the AuthController but that doesn't seems to work at all. When I try the /api/login in Postman, I get nothing back.
Please note that I've added restPrefix: '/api' in my config/blueprints.js. Please note I'm using Sails 0.12.x
What am I missing here?
Since you are pointing to a controller with method index on it, you need to add it to your controllers and send a JSON response from there, (since you are using post). here is a simple example
config/routes.js
'post /api/signin': 'AuthController.index',
api/controllers/AuthController.js
module.exports = {
index: function(req, res) {
var id = req.param('id');
if(!id) {
return res.json(400, { error: 'invalid company name or token'});
}
/* validate login..*/
res.json(200, {data: "success"};
}
}
Update
Since you already have the above its probably caused by the blueprints you have.
Blueprint shortcut routes
Shortcut routes are activated by default in new Sails apps, and can be
turned off by setting sails.config.blueprints.shortcuts to false
typically in /config/blueprints.js.
Sails creates shortcut routes for any controller/model pair with the
same identity. Note that the same action is executed for similar
RESTful/shortcut routes. For example, the POST /user and GET
/user/create routes that Sails creates when it loads
api/controllers/UserController.js and api/models/User.js will
respond by running the same code (even if you override the blueprint
action)
with that being said from sails blueprint documentation, maybe turning off shortcuts and remove the prefix you've added.
possibly the shortcuts are looking elsewhere other than your controllers thus returning 404.
the prefix is being added to your blueprint connected route, hence you need /api/api/signin to access it?
Note
I am unable to replicate your issue on my computer as its working fine over here. but i have all blueprint settings turned off.
module.exports.blueprints = {
actions: false,
rest: false,
shortcuts: false,
// prefix: '',
pluralize: false,
populate: false,
autoWatch: false,
};

Marionette app 2 way navigation with history api

I have node.js server application (rest API service).
I also have Backbone + Marionette(for my serverside RESTful app) multiple page app at the client side.
I currently have Marionette navigation which is work pretty good with links like domain.com/#feedbacks (pages are render on client side with ajax data). But I also want to add serverside navigation e.g. domain.com/feedbacks (for google and other seach engines).
The question is: How can I match serverside and clientside navigations?
Mb I should try to add event handler for all links on page, which is will do something like Backbone.history.navigate("/feedbacks")? But I have a lot different hash links(#feedbacks)... Mb there is a more elegant solution? Thank you.
My current marionette router:
var AppRouter = Backbone.Blazer.Router.extend({
routes: {
'': new HomeRoute(),
'sell': new SellRoute(),
'login': new LoginRoute(),
'feedbacks': new FeedbacksRouter(),
'product/:id': new ProductRoute(),
'profile/:id': new UserRoute()
}
})
I just had to use:
Backbone.history.start({pushState: true})
instead of:
Backbone.history.start();
It make backbone routing work without # symbols

Meteor: Creating URLs for sharing (currently using iron-router)

I have a meteor app that uses iron-router.
How do I make this meteor app create a fixed URL for sharing?
For example in jsfiddle.net, you start of in just jsfiddle.net PLAINLY.
However, after you type in the code, etc...and you decide you wanna share this with the world, you click on save. After you click on save, the link above changes to something like: jsfiddle.net/m9mfLn3p/.
And now you can use jsfiddle.net/m9mfLn3p/ to share that page with that certain setting with the world....
How do I achieve something similar in my meteor app that uses iron-router?
Thank you very much.
I have a similar pattern in my app. To solve this problem I have a collection that contains the data context that will be used by the route. Then I just create a document with the required data and use the _id of the document in that collection to create a url that can be reused.
Ex:
var id = Permalinks.insert(object); // object is the data I'll need later
var url = Meteor.absoluteUrl() + "myPath/" + id;
... share this url however - email, SMS, etc...
Then a route:
Router.route("/myPath/:id",{
data: function(){
return Permalinks.findOne({ _id: this.params.id });
}
});

Backbone router with no hashbangs

I've set up a super simple Backbone app with just a router and two views to try and nail down the correct way to handle routing with no hashbangs.
var Router = Backbone.Router.extend({
routes: {
'': 'index',
'episodes': 'episodes'
},
index: function () {
var view = new IndexView();
view.render();
},
episodes: function () {
var view = new EpisodesView();
view.render();
}
});
var IndexView = Backbone.View.extend({
el: $('#primary'),
render: function () {
console.log('index view');
}
});
var EpisodesView = Backbone.View.extend({
el: $('#primary'),
render: function () {
console.log('episodes view');
}
});
var router = new Router;
Backbone.history.start({pushState: true});
I realize that the history object allows forward and backward navigation between pages, which is great. However, the way it's actually implemented seems a little messed up to me.
For instance, I created a simple MAMP server to serve an index.html file and the JS file. Navigating to http://backbone:8888/, the console logs index view like I'm telling it to. However, navigating to http://backbone:8888/episodes (by typing it into the address bar) returns a 404. BUT, if I navigate to http://backbone:8888/#episodes, the URL redirects to http://backbone:8888/episodes (without the hashbang) and I get episodes view logged to the console, which obviously means it's hitting that EpisodesView view.
From here, I can go back and forth between the index and episodes views. (back hits /, forward hits /episodes). That's all fine and dandy until I hit refresh while on /episodes again. 404...
So my question is this: how can Backbone be set up to handle URLs without relying on hashbangs? Everything I've found on the topic says "oh just pushState!". Well, I'm using pushState and, like I described above, you can't hit a URL like /episodes directly without getting a 404.
When you use push state, pages are served from the back end, which means that you have to define a corresponding route in your back end that corresponds to a front end route.
If the back end doesn't find the requested route, then it will deliver a 404 message, because it won't know what to serve. In your case, the episodes view gets triggered at the front end level, but the browser doesn't have a DOM to render the view when the page gets refreshed because nothing was served.
By default, the route http://backbone:8888/ will serve the index file because this is how the webserver is configured.
I'm not sure what back end technology you are using, but for serving a file from http://backbone:8888/episodes, just make sure that your back end has a router set up that serves the requested route and it should work.

How do I generate a unique link that will load a session with certain docs available to the client?

Sorry for the bad phrasing.
Essentially, I want to be able to generate a link to a page, which will load a session of certain docs.
For example, Links.find() returns to Client A Links.find({clientName:"A"}). Now Client A wants to send this series of elements to his friend, and wants to do so by sending him a link which loads a client instance that can see Links.find({clientName"A"}).
Any input at all would be greatly appreciated.
Add Iron Router to your project. Then create a route that puts the relevant query into the URL, for example (in a client-loaded JavaScript file):
Router.map(function () {
this.route('client', {
path: '/client/:_clientName',
before: function () {
this.subscribe('client', this.params._clientName).wait();
}
}
}
Then a URI like http://yourapp.com/client/A would cause the client template to render (by default it uses the same name as the route name, unless you specify a different name) subscribing to the client subscription using "A" as the subscription parameter. This would be paired on the server side with:
Meteor.publish('client', function (clientName) {
// Clients is a Meteor collection
return Clients.find({clientName: clientName});
});
So that's how to process links after they've been generated. As for creating them, just work backwards: what query parameters are you passing to your subscription (that in turn get put into the find() call to MongoDB)? Identify each of them and write some code that adds them to an appropriate URI—in this case, your function would simply concatenate "http://yourapp.com/client/" with clientName, in this case "A". Obviously much-more-complicated routes/URIs and queries are possible, for example http://yourapp.com/events/2012-01-01/2012-12-31 with an Iron Router route path of /events/:_fromDate/:_toDate and so on.

Categories