diff --git a/README.md b/README.md index 8ed4789..517685e 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ The following command installs reflux as a bower component that can be used in t bower install reflux +### ES5 + +Like React, Reflux depends on an es5-shim for older browsers. The es5-shim.js from [kriskowal's es5-shim](https://github.com/kriskowal/es5-shim) provides everything required. + ## Usage For a full example check the [`test/index.js`](test/index.js) file. diff --git a/karma.conf.js b/karma.conf.js index 77b8acb..88dc869 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -13,6 +13,7 @@ module.exports = function(config) { ], files: [ + 'test/shims/phantomjs-shims.js', 'test/*.spec.js' ], diff --git a/src/bindMethods.js b/src/bindMethods.js new file mode 100644 index 0000000..b438498 --- /dev/null +++ b/src/bindMethods.js @@ -0,0 +1,13 @@ +module.exports = function(store, definition) { + for (var name in definition) { + var property = definition[name]; + + if (typeof property !== 'function' || !definition.hasOwnProperty(name)) { + continue; + } + + store[name] = property.bind(store); + } + + return store; +}; diff --git a/src/createStore.js b/src/createStore.js index 7bd0889..7c2b95c 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -1,7 +1,8 @@ var _ = require('./utils'), Reflux = require('../src'), Keep = require('./Keep'), - allowed = {preEmit:1,shouldEmit:1}; + allowed = {preEmit:1,shouldEmit:1}, + bindMethods = require('./bindMethods'); /** * Creates an event emitting Data Store. It is mixed in with functions @@ -42,6 +43,7 @@ module.exports = function(definition) { _.extend(Store.prototype, Reflux.ListenerMethods, Reflux.PublisherMethods, definition); var store = new Store(); + bindMethods(store, definition); Keep.createdStores.push(store); return store; diff --git a/src/index.js b/src/index.js index 7ffd104..e684c2d 100644 --- a/src/index.js +++ b/src/index.js @@ -60,3 +60,14 @@ exports.nextTick = function(nextTick) { * Provides the set of created actions and stores for introspection */ exports.__keep = require('./Keep'); + +/** + * Warn if Function.prototype.bind not available + */ +if (!Function.prototype.bind) { + console.error( + 'Function.prototype.bind not available. ' + + 'ES5 shim required. ' + + 'https://github.com/spoike/refluxjs#es5' + ); +} diff --git a/test/creatingStores.spec.js b/test/creatingStores.spec.js index 73dc21f..d2bc0fa 100644 --- a/test/creatingStores.spec.js +++ b/test/creatingStores.spec.js @@ -303,4 +303,20 @@ describe('Creating stores', function() { assert.isUndefined(Reflux.ListenerMethods.trigger); }); + describe('store methods', function() { + var store; + + beforeEach(function() { + store = Reflux.createStore({ + reflect: function() { + return this; + } + }); + }); + + it('should be bound to store instance', function() { + var reflect = store.reflect; + return assert.equal(store, reflect()); + }); + }); }); diff --git a/test/shims/phantomjs-shims.js b/test/shims/phantomjs-shims.js new file mode 100644 index 0000000..0e81ccb --- /dev/null +++ b/test/shims/phantomjs-shims.js @@ -0,0 +1,36 @@ +// From https://github.com/facebook/react/blob/master/src/test/phantomjs-shims.js +(function() { + +var Ap = Array.prototype; +var slice = Ap.slice; +var Fp = Function.prototype; + +if (!Fp.bind) { + // PhantomJS doesn't support Function.prototype.bind natively, so + // polyfill it whenever this module is required. + Fp.bind = function(context) { + var func = this; + var args = slice.call(arguments, 1); + + function bound() { + var invokedAsConstructor = func.prototype && (this instanceof func); + return func.apply( + // Ignore the context parameter when invoking the bound function + // as a constructor. Note that this includes not only constructor + // invocations using the new keyword but also calls to base class + // constructors such as BaseClass.call(this, ...) or super(...). + !invokedAsConstructor && context || this, + args.concat(slice.call(arguments)) + ); + } + + // The bound function must share the .prototype of the unbound + // function so that any object created by one constructor will count + // as an instance of both constructors. + bound.prototype = func.prototype; + + return bound; + }; +} + +})();