Skip to content

Commit

Permalink
Merge branch 'master' into relative-require
Browse files Browse the repository at this point in the history
Conflicts:
	bones.js
	test/assets.test.js
  • Loading branch information
wrynearson committed Jul 18, 2012
2 parents 984b533 + 210048f commit d579e5b
Show file tree
Hide file tree
Showing 69 changed files with 676 additions and 334 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
.DS_Store
node_modules
10 changes: 10 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,10 @@

## Bones 2.x.x

- Upgraded to backbone.js 0.5.1. Most important changes affecting Bones applications:
- `Backbone.Controller` is now `Backbone.Router`
- `Backbone.sync(model, method, success, error)` changed to `Backbone.sync(model, method, options)`
- Removed hashbang #! support.
- Removed 'attach' mechanism, use *.server.bones style overrides instead #18

## Bones 1.3.11
12 changes: 9 additions & 3 deletions README.md
@@ -1,10 +1,17 @@
# Bones

Bones provides conventions for [Backbone](http://documentcloud.github.com/backbone/) applications. It allows most code to be shared on the server and the client. Bones exposes your Backbone controller routes as regular paths on the server so they can be accessed by non-JavaScript agents, while capable clients can enjoy the normal client-side Backbone experience.
Bones provides conventions for [Backbone](http://documentcloud.github.com/backbone/) applications. It allows most code to be shared on the server and the client. Bones exposes your Backbone routes as regular paths on the server so they can be accessed by non-JavaScript agents, while capable clients can enjoy the normal client-side Backbone experience.

## Getting started

The [wiki](https://github.com/developmentseed/bones/wiki) contains more information on [**Getting Started**](https://github.com/developmentseed/bones/wiki/Getting-Started) and on the [concepts](https://github.com/developmentseed/bones/wiki/Plugin-Architecture) in Bones.
The [wiki](https://github.com/developmentseed/bones/wiki) contains more information
on [**Getting Started**](https://github.com/developmentseed/bones/wiki/Getting-Started)
and on the [concepts](https://github.com/developmentseed/bones/wiki/Plugin-Architecture) in Bones.

## Example Application

* The [simple app example](https://github.com/developmentseed/bones/tree/master/examples/simple) is
a good quickstart to making a bones application.

## Testing

Expand All @@ -13,4 +20,3 @@ To run the test suite, type `npm test`. **Note**: bones has to be in a folder na
## License

Bones is [BSD licensed](https://github.com/developmentseed/bones/raw/master/LICENSE).

20 changes: 4 additions & 16 deletions assets/jquery.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bones.js
Expand Up @@ -13,7 +13,7 @@ exports.middleware = require('./server/middleware');
exports.server = true;

exports.Backbone = require('./server/backbone');
exports.Controller = require('./server/controller');
exports.Router = require('./server/router');
exports.Model = require('./server/model');
exports.Collection = require('./server/collection');
exports.View = require('./server/view');
Expand Down
75 changes: 5 additions & 70 deletions client/backbone.js
@@ -1,4 +1,4 @@
Backbone.Controller.prototype.route = function(route, name, callback) {
Backbone.Router.prototype.route = function(route, name, callback) {
Backbone.history || (Backbone.history = new Backbone.History);
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
Backbone.history.route(route, _.bind(function(fragment) {
Expand All @@ -8,71 +8,6 @@ Backbone.Controller.prototype.route = function(route, name, callback) {
}, this));
};

// Client-side `Backbone.View` overrides. Adds an `attach()` method that can be
// triggered after `render()` to allow client-side specific JS event handlers,
// UI libraries to be attached or inited. `template()` and `html()` are mirrors
// of their server-side counterparts for templating and easy generation of a
// View's HTML contents.
Backbone.View.augment({
attach: function() {},
_configure: function(parent, options) {
parent.call(this, options);
this.bind('attach', this.attach);
}
});

// Fix for Backbone.History.start with 0.3.3 and IE7.
// See https://github.com/documentcloud/backbone/issues/228
Backbone.History.prototype.start = function() {
var docMode = document.documentMode;
var oldIE = ($.browser.msie && (!docMode || docMode <= 7));
if (oldIE) {
this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
this.iframe.document.open().close();
this.iframe.location.hash = window.location.hash;
}
if ('onhashchange' in window && !oldIE) {
$(window).bind('hashchange', this.checkUrl);
} else {
setInterval(this.checkUrl, this.interval);
}
return this.loadUrl();
};

Backbone.History.prototype._saveLocation = Backbone.History.prototype.saveLocation;
Backbone.History.prototype.saveLocation = function(fragment) {
// Override: Ensure ! so browser behaves correctly when using back button.
Backbone.History.prototype._saveLocation.call(this, '!' + fragment.replace(/^!*/, ''));
};

Backbone.History.prototype.checkUrl = function() {
var current = this.getFragment();
if (current == this.fragment && this.iframe) {
current = this.getFragment(this.iframe.location);
}
if (current == this.fragment ||
current == decodeURIComponent(this.fragment)) return false;
if (this.iframe) {
// Override: Keep IE happy.
this.iframe.location.hash = current;
window.location.hash = '!' + current;
}
this.loadUrl();
};

Backbone.History.prototype.loadUrl = function() {
this.fragment = this.getFragment();
// Override: Remove ! to look up route.
var fragment = this.fragment.replace(/^!*/, '');
var matched = _.any(this.handlers, function(handler) {
if (handler.route.test(fragment)) {
handler.callback(fragment);
return true;
}
});
return matched;
};

// Generate CSRF protection token that is valid for the specified amount of
// msec. The default is 1 second. Callers should provide the request path to
// ensure the cookie is not pervasive across requests.
Expand All @@ -99,7 +34,7 @@ Backbone.csrf = function(path, timeout) {
// must be used server-side to invalidate requests without this CSRF
// protection. The original `Backbone.sync` cannot be reused because it does
// not send a request body for DELETE requests.
Backbone.sync = function(method, model, success, error) {
Backbone.sync = function(method, model, options) {
function getUrl(object) {
if (!(object && object.url)) throw new Error("A 'url' property or function must be specified");
return _.isFunction(object.url) ? object.url() : object.url;
Expand All @@ -126,10 +61,10 @@ Backbone.sync = function(method, model, success, error) {
data: (modelJSON || null),
dataType: 'json',
processData: false,
success: success,
error: error
success: options.success,
error: options.error
};

// Make the request.
$.ajax(params);
return $.ajax(params);
};
4 changes: 0 additions & 4 deletions client/controller.prefix.js

This file was deleted.

5 changes: 0 additions & 5 deletions client/controller.suffix.js

This file was deleted.

4 changes: 4 additions & 0 deletions client/router.prefix.js
@@ -0,0 +1,4 @@
// ---- start __FILE__ ----

Bones.initialize('router', function(models, views, routers) {
var router;
5 changes: 5 additions & 0 deletions client/router.suffix.js
@@ -0,0 +1,5 @@
if (router && !router.title) router.title = '__NAME__';
return router;
});

// ---- end __FILE__ ----
22 changes: 11 additions & 11 deletions client/utils.js
Expand Up @@ -5,8 +5,8 @@ $(function() {
});

(function() {
// Closure for models/views/controllers.
var models = {}, views = {}, controllers = {}, templates = {};
// Closure for models/views/routers.
var models = {}, views = {}, routers = {}, templates = {};

Bones.server = false;

Expand All @@ -17,29 +17,29 @@ $(function() {
} else if (kind === 'view') {
var view = callback(models, views, templates);
if (view) views[view.title] = view;
} else if (kind === 'controller') {
var controller = callback(models, views, controllers);
if (controller) controllers[controller.title] = controller;
} else if (kind === 'router') {
var router = callback(models, views, routers);
if (router) routers[router.title] = router;
} else if (kind === 'template') {
var template = callback(templates);
if (template) templates[template.title] = template;
} else if (_.isFunction(kind)) {
kind(models, views, controllers, templates);
kind(models, views, routers, templates);
}
};

Bones.start = function() {
for (var k in controllers) {
new controllers[k];
Bones.start = function(options) {
for (var k in routers) {
new routers[k];
}

Backbone.history.start();
Backbone.history.start(options);
};

Bones.DEBUG = {
models: models,
views: views,
controllers: controllers,
routers: routers,
templates: templates
};
})();
Empty file removed examples/simple/assets/app.css
Empty file.
7 changes: 0 additions & 7 deletions examples/simple/assets/app.js

This file was deleted.

32 changes: 32 additions & 0 deletions examples/simple/assets/stylesheets/style.css
@@ -0,0 +1,32 @@
#header {
height: 30px;
background: #666;
}

#header ul {
width: 800px;
margin: 0px auto;
}
#header ul li {
list-style: none;
float: left;
padding-right: 20px;
}
#header ul li a {
color: #eee;
font-size: 16px;
line-height: 30px;
}

#page {
width: 800px;
margin: 0px auto;
}

pre {
border: 1px solid #666;
background: #ffb;
color: #666;
padding: 5px;
overflow: auto;
}
3 changes: 0 additions & 3 deletions examples/simple/controllers/Default.bones

This file was deleted.

16 changes: 0 additions & 16 deletions examples/simple/controllers/Home.bones

This file was deleted.

3 changes: 0 additions & 3 deletions examples/simple/controllers/Other.server.bones

This file was deleted.

11 changes: 9 additions & 2 deletions examples/simple/index.js 100644 → 100755
@@ -1,6 +1,13 @@
#!/usr/bin/env node
require('bones').load(__dirname);

var bones = require('bones')

// Bones load views/models/etc.. in alphabetical order. To explicity load
// certain ones early simply require them here.
require('./views/Main');

bones.load(__dirname);

if (!module.parent) {
require('bones').start();
bones.start();
}
5 changes: 0 additions & 5 deletions examples/simple/models/Foo.bones

This file was deleted.

6 changes: 0 additions & 6 deletions examples/simple/models/Foo.server.bones

This file was deleted.

5 changes: 5 additions & 0 deletions examples/simple/models/Project.bones
@@ -0,0 +1,5 @@
model = Backbone.Model.extend({
url: function() {
return '/api/Project/' + encodeURIComponent(this.get('id'));
}
});
73 changes: 73 additions & 0 deletions examples/simple/models/Project.server.bones
@@ -0,0 +1,73 @@
var fs = require('fs'),
path = require('path');

/**
* The only method we need to override for on the server is `sync` which is
* called to load the resource. By default Backbone models will attempt to
* retrieve their state from a URI returned from their 'URL' method. Clearly
* that won't work on the server, as we're trying to power that very same
* URI. Here we do the hard work!
*/
models.Project.prototype.sync = function(method, model, options) {
// Project data can only be read, so return an error it the client is
// trying to do anything else.
if (method != 'read') return options.error('Unsupported method');

var projectDir = path.dirname(require.resolve('bones')) + '/node_modules/' + model.id,
resp = {id: model.id};

var fetchPackage = function(callback) {
fs.readFile(projectDir +'/package.json', 'utf8', function(err, data) {
if (err) return callback('Could not retrieve project information.');
data = JSON.parse(data);
resp = _.extend(resp, data);
callback();
});
};

var fetchReadme = function(callback) {
// Setup the regex we'll use for detecting README files.
var re = /^readme(|\.\w*)$/i;

// Scan the project directory, and send a readme back to the client.
fs.readdir(projectDir, function(err, files) {
if (err) return callback('Project not found.');

for (var i = 0; i < files.length; i++) {
var match = re.exec(files[i]);
if (match) {
fs.readFile(projectDir +'/'+ match.input, 'utf8', function(err, data) {
if (err) return callback('Could not retrieve project information.');
// 80 chars folks...
data = wrap(data);
resp.readme = data;
callback();
});
break;
}
}
});
}

fetchPackage(function(err) {
if (err) return options.error(err);
fetchReadme(function(err) {
if (err) return options.error(err);
options.success(resp);
});
});
};

var wrap = function(str) {
var lines = [];
_(str.split(/\n/)).each(function(v) {
if (v.length > 80) {
var parts = v.match(/.{80}|.+$/g);
lines.push(parts.join('\n'));
} else {
lines.push(v);
}
});

return lines.join('\n');
};

0 comments on commit d579e5b

Please sign in to comment.