flux-reactions
Advanced tools
Comparing version 0.0.1 to 0.0.2
@@ -1,5 +0,5 @@ | ||
/* flux-reactions v0.0.1 (24-2-2015) | ||
/* flux-reactions v0.0.2 (26-3-2015) | ||
* https://github.com/arqex/flux-reactions.git | ||
* By arqex | ||
* License: GNU-v2 | ||
* License: MIT | ||
*/ | ||
@@ -50,2 +50,42 @@ ( function(root, factory) { | ||
/** | ||
* Triggers a DOM event in the given DOM node | ||
* @param {HTMLElement} node The HTML node where the event is triggered. | ||
* @param {String} eventName The event type | ||
* @param {Mixed} detail The detail attribute for the event, to add | ||
* some extra data to the event. | ||
* @return {Event} The event triggered | ||
*/ | ||
var trigger = function( node, eventName, detail ){ | ||
var el = node, | ||
e | ||
; | ||
if( document.createEvent ){ | ||
e = document.createEvent( 'HTMLEvents' ); | ||
e.initEvent( eventName, true, true ); | ||
} | ||
else if( document.createEventObject ){ // IE < 9 | ||
e = document.createEventObject(); | ||
e.eventType = eventName; | ||
} | ||
e.detail = detail; | ||
if( el.dispatchEvent ){ | ||
var result = el.dispatchEvent( e ); | ||
} | ||
else if( el.fireEvent && htmlEvents[ 'on' + eventName ] ){ // IE < 9 | ||
el.fireEvent( 'on' + eventName, e ); // can trigger only real event (e.g. 'click') | ||
} | ||
else if( el[ eventName ] ){ | ||
el[ eventName ](); | ||
} | ||
else if( el[ 'on' + eventName ]) { | ||
el[ 'on' + eventName ](); | ||
} | ||
return e; | ||
}; | ||
// The module that will be plublicly available | ||
@@ -93,2 +133,14 @@ var Reactions = { | ||
/** | ||
* Triggers a DOM event in the hub | ||
* @param {String} eventName The event type | ||
* @param {Mixed} detail The detail attribute for the event, to add | ||
* some extra data to the event. | ||
* @return {this} To chain calls | ||
*/ | ||
trigger: function( eventName, fn ){ | ||
trigger( hub, eventName, fn ); | ||
return this; | ||
}, | ||
/** | ||
* A mixin to be used with react components. | ||
@@ -106,31 +158,3 @@ * @type {Object} | ||
trigger: function( eventName, detail ){ | ||
var el = this.getDOMNode(), | ||
e | ||
; | ||
if( document.createEvent ){ | ||
e = document.createEvent( 'HTMLEvents' ); | ||
e.initEvent( eventName, true, true ); | ||
} | ||
else if( document.createEventObject ){ // IE < 9 | ||
e = document.createEventObject(); | ||
e.eventType = eventName; | ||
} | ||
e.detail = detail; | ||
if( el.dispatchEvent ){ | ||
var result = el.dispatchEvent( e ); | ||
} | ||
else if( el.fireEvent && htmlEvents[ 'on' + eventName ] ){ // IE < 9 | ||
el.fireEvent( 'on' + eventName, e ); // can trigger only real event (e.g. 'click') | ||
} | ||
else if( el[ eventName ] ){ | ||
el[ eventName ](); | ||
} | ||
else if( el[ 'on' + eventName ]) { | ||
el[ 'on' + eventName ](); | ||
} | ||
return e; | ||
return trigger( this.getDOMNode(), eventName, detail ); | ||
}, | ||
@@ -190,3 +214,3 @@ | ||
this.listenTo( eventName, listener ); | ||
this.listenTo( eventName, listener.bind( this ) ); | ||
} | ||
@@ -193,0 +217,0 @@ } |
@@ -1,6 +0,6 @@ | ||
/* flux-reactions v0.0.1 (24-2-2015) | ||
/* flux-reactions v0.0.2 (26-3-2015) | ||
* https://github.com/arqex/flux-reactions.git | ||
* By arqex | ||
* License: GNU-v2 | ||
* License: MIT | ||
*/ | ||
!function(t,e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():t.Reactions=e()}(this,function(){"use strict";var t=window.document,e=function(t,e,n){t.addEventListener?t.addEventListener(e,n,!1):t.attachEvent?t.attachEvent("on"+e,n):t["on"+e]=n},n=function(t,e,n){t.removeEventListener?t.removeEventListener(e,n,!1):t.detachEvent?t.detachEvent("on"+e,n):delete t["on"+e]},i={on:function(n,i){return e(t,n,i),this},once:function(i,o){var r=function c(){o.apply(null,arguments),n(t,i,c)};return e(t,i,r),this},off:function(e,i){return n(t,e,i),this},mixin:{trigger:function(t,e){var n,i=this.getDOMNode();if(document.createEvent?(n=document.createEvent("HTMLEvents"),n.initEvent(t,!0,!0)):document.createEventObject&&(n=document.createEventObject(),n.eventType=t),n.detail=e,i.dispatchEvent){i.dispatchEvent(n)}else i.fireEvent&&htmlEvents["on"+t]?i.fireEvent("on"+t,n):i[t]?i[t]():i["on"+t]&&i["on"+t]();return n},thenTrigger:function(t,e){return this.trigger.bind(this,t,e)},listenTo:function(t,n){e(this.getDOMNode(),t,n)},componentDidMount:function(){if(this.onEvents){{var t,e;this.getDOMNode()}for(t in this.onEvents)e=this.onEvents[t],"function"!=typeof e&&(e=this[e]),this.listenTo(t,e)}}}};return i}); | ||
!function(t,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():t.Reactions=n()}(this,function(){"use strict";var t=window.document,n=function(t,n,e){t.addEventListener?t.addEventListener(n,e,!1):t.attachEvent?t.attachEvent("on"+n,e):t["on"+n]=e},e=function(t,n,e){t.removeEventListener?t.removeEventListener(n,e,!1):t.detachEvent?t.detachEvent("on"+n,e):delete t["on"+n]},i=function(t,n,e){var i,o=t;if(document.createEvent?(i=document.createEvent("HTMLEvents"),i.initEvent(n,!0,!0)):document.createEventObject&&(i=document.createEventObject(),i.eventType=n),i.detail=e,o.dispatchEvent){o.dispatchEvent(i)}else o.fireEvent&&htmlEvents["on"+n]?o.fireEvent("on"+n,i):o[n]?o[n]():o["on"+n]&&o["on"+n]();return i},o={on:function(e,i){return n(t,e,i),this},once:function(i,o){var r=function c(){o.apply(null,arguments),e(t,i,c)};return n(t,i,r),this},off:function(n,i){return e(t,n,i),this},trigger:function(n,e){return i(t,n,e),this},mixin:{trigger:function(t,n){return i(this.getDOMNode(),t,n)},thenTrigger:function(t,n){return this.trigger.bind(this,t,n)},listenTo:function(t,e){n(this.getDOMNode(),t,e)},componentDidMount:function(){if(this.onEvents){{var t,n;this.getDOMNode()}for(t in this.onEvents)n=this.onEvents[t],"function"!=typeof n&&(n=this[n]),this.listenTo(t,n.bind(this))}}}};return o}); |
{ | ||
"name": "flux-reactions", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "An event driven Flux implementation.", | ||
@@ -19,3 +19,3 @@ "main": "flux-reactions.js", | ||
"author": "Javi Marquez", | ||
"license": "GNU-v2", | ||
"license": "MIT", | ||
"bugs": { | ||
@@ -22,0 +22,0 @@ "url": "https://github.com/arqex/flux-reactions/issues" |
150
README.md
@@ -8,2 +8,150 @@ # Flux-Reactions | ||
*Flux-Reactions* is just an utility to reduce the boilerplate of dispatch custom events cross-browser, not a complete Flux implementation. | ||
*Flux-Reactions* is just an utility to reduce the boilerplate of dispatch custom events cross-browser, not a complete Flux implementation. | ||
See [A better Flux with DOM events](http://arqex.com/1028/better-flux-dom-events) to know the benefits of this approach. | ||
## Install | ||
*Flux-reactions* comes in the shape of a UMD module to be used in Node.js and the browser. It is possible to install it using npm | ||
``` | ||
npm install flux-reactions | ||
``` | ||
Using bower | ||
``` | ||
bower install flux-reactions | ||
``` | ||
Or adding it directly to your page code for development [flux-reactions.js](https://raw.githubusercontent.com/arqex/flux-reactions/master/flux-reactions.js)(5KB), and minified [flux-reactions.min.js](https://raw.githubusercontent.com/arqex/flux-reactions/master/flux-reactions.min.js)(1KB). | ||
## Use | ||
*Flux-reactions* comes with a mixin for React.js modules that allows to emit events easily using the `trigger` method. Let's create a counter component that emit an `increment` event whenever its button is clicked. | ||
```js | ||
var Counter = React.createClass({ | ||
// Add the reaction mixin | ||
mixin: [Reactions.mixin], | ||
render: function(){ | ||
return ( | ||
<div className="counter"> | ||
<span>{this.props.count}</span> | ||
<button onClick={ this.onIncrease }>Increase</button> | ||
</div> | ||
); | ||
}, | ||
onIncrease: function(){ | ||
// Emit an increase event with 1 as detail | ||
this.trigger('increase', 1); | ||
} | ||
}); | ||
``` | ||
To create a reaction to the event, we can use the Reaction object as a hub. | ||
``` | ||
Reactions.on( 'increase', function( e ){ | ||
// Add the number passed as detail to the | ||
// counter store ( 1 in this example) | ||
store.counter += e.detail; | ||
}); | ||
``` | ||
The mixin also allow to listen to events emited by children components. Imagine a selectable list: | ||
```js | ||
var List = React.createClass({ | ||
mixin:[Reactions.mixin], | ||
// Events to listen are defined in the onEvents attribute | ||
onEvents: { | ||
// Add a listener to the selected event | ||
selected: function(e){ | ||
// Select the item that emitted the event | ||
this.setState({selected: e.detail}); | ||
} | ||
}, | ||
getInitialState: function(){ | ||
return {selected: -1}; | ||
}, | ||
render: function(){ | ||
// Create a list of 3 items | ||
var items = [0,1,2].map( function( i ){ | ||
return <Item text={ 'Item ' + i} index={ i } selected={ this.state.selected == i} />; | ||
}); | ||
return <div>{ items }</div>; | ||
} | ||
}); | ||
var Item = React.createClass({ | ||
mixin:[Reactions.mixin], | ||
render: function(){ | ||
return ( | ||
// thenTrigger will emit a selected event on click | ||
<div onClick={ this.thenTrigger( 'selected', this.props.index ) }> | ||
{ this.props.text } | ||
</div> | ||
); | ||
} | ||
}) | ||
``` | ||
## API | ||
### Reactions.on( eventName, callback ) | ||
Add a listener to some event, AKA creates a reaction. The reaction will receive the event as the only argument. | ||
```js | ||
// Creates a reaction for the selected event | ||
Reactions.on( 'selected', function( e ){ | ||
console.log( 'Hey I am selected!'); | ||
}); | ||
``` | ||
### Reactions.once( eventName, callback ) | ||
Add a listener to some events that will be called just once. | ||
### Reactions.off( eventName, callback ) | ||
Removes an event listener. | ||
### Reactions.trigger( eventName, detail ) | ||
Flux dispatcher uses the `waitfor` method to synchronize different actions. Using flux-reaction you can trigger a new event whenever a reaction has finished to coordinate several reactions for an event. | ||
### Reactions.mixin | ||
A mixin to be used by react components. The mixin will add the following methods to the component: | ||
#### trigger( eventName, detail ) | ||
Triggers the event in the DOM node of the component. The detail attribute of the event can be customized passing its value as the second argument. | ||
#### thenTrigger( eventName, detail ) | ||
Returns a function than trigger the event with the given detail attribute. This is useful to trigger the event directly from the render method without creating a new function that does so. | ||
```js | ||
var Item = React.createClass({ | ||
mixin:[Reactions.mixin], | ||
render: function(){ | ||
return ( | ||
// thenTrigger will emit a selected event on click | ||
<div onClick={ this.thenTrigger( 'selected', this.props.index ) }> | ||
{ this.props.text } | ||
</div> | ||
); | ||
} | ||
}) | ||
``` | ||
#### listenTo( eventName, callback ) | ||
Listen to children events. | ||
#### onEvents | ||
Event listeners for children can also defined declaratively by using the | ||
component `onEvents` attribute. That attribute must be an object with | ||
the name of the events as keys and functions or name of methods of the | ||
current component as values: | ||
```js | ||
onEvents: { | ||
selected: 'onSelected', | ||
removed: function(){ | ||
console.log( 'removed' ); | ||
} | ||
} | ||
``` | ||
A selected event on a children with trigger component's `onSelected` method. | ||
A removed event will trigger the function defined. | ||
Those listeners will be added in this componentDidMount method. | ||
## Collaborate | ||
This is a quick implementation of a crossbrowser event library to be used with React.js. There are some directions to work to: | ||
* Add support for using EventEmitter make it work in the server. | ||
* Study the alternatives to make it work with the future [React Native](https://code.facebook.com/videos/786462671439502/react-js-conf-2015-keynote-introducing-react-native-/). | ||
* Add support for using it as a [higher order component](https://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775). | ||
Any improvement that you may find is welcome. |
@@ -45,2 +45,42 @@ ( function(root, factory) { | ||
/** | ||
* Triggers a DOM event in the given DOM node | ||
* @param {HTMLElement} node The HTML node where the event is triggered. | ||
* @param {String} eventName The event type | ||
* @param {Mixed} detail The detail attribute for the event, to add | ||
* some extra data to the event. | ||
* @return {Event} The event triggered | ||
*/ | ||
var trigger = function( node, eventName, detail ){ | ||
var el = node, | ||
e | ||
; | ||
if( document.createEvent ){ | ||
e = document.createEvent( 'HTMLEvents' ); | ||
e.initEvent( eventName, true, true ); | ||
} | ||
else if( document.createEventObject ){ // IE < 9 | ||
e = document.createEventObject(); | ||
e.eventType = eventName; | ||
} | ||
e.detail = detail; | ||
if( el.dispatchEvent ){ | ||
var result = el.dispatchEvent( e ); | ||
} | ||
else if( el.fireEvent && htmlEvents[ 'on' + eventName ] ){ // IE < 9 | ||
el.fireEvent( 'on' + eventName, e ); // can trigger only real event (e.g. 'click') | ||
} | ||
else if( el[ eventName ] ){ | ||
el[ eventName ](); | ||
} | ||
else if( el[ 'on' + eventName ]) { | ||
el[ 'on' + eventName ](); | ||
} | ||
return e; | ||
}; | ||
// The module that will be plublicly available | ||
@@ -88,2 +128,14 @@ var Reactions = { | ||
/** | ||
* Triggers a DOM event in the hub | ||
* @param {String} eventName The event type | ||
* @param {Mixed} detail The detail attribute for the event, to add | ||
* some extra data to the event. | ||
* @return {this} To chain calls | ||
*/ | ||
trigger: function( eventName, fn ){ | ||
trigger( hub, eventName, fn ); | ||
return this; | ||
}, | ||
/** | ||
* A mixin to be used with react components. | ||
@@ -101,31 +153,3 @@ * @type {Object} | ||
trigger: function( eventName, detail ){ | ||
var el = this.getDOMNode(), | ||
e | ||
; | ||
if( document.createEvent ){ | ||
e = document.createEvent( 'HTMLEvents' ); | ||
e.initEvent( eventName, true, true ); | ||
} | ||
else if( document.createEventObject ){ // IE < 9 | ||
e = document.createEventObject(); | ||
e.eventType = eventName; | ||
} | ||
e.detail = detail; | ||
if( el.dispatchEvent ){ | ||
var result = el.dispatchEvent( e ); | ||
} | ||
else if( el.fireEvent && htmlEvents[ 'on' + eventName ] ){ // IE < 9 | ||
el.fireEvent( 'on' + eventName, e ); // can trigger only real event (e.g. 'click') | ||
} | ||
else if( el[ eventName ] ){ | ||
el[ eventName ](); | ||
} | ||
else if( el[ 'on' + eventName ]) { | ||
el[ 'on' + eventName ](); | ||
} | ||
return e; | ||
return trigger( this.getDOMNode(), eventName, detail ); | ||
}, | ||
@@ -185,3 +209,3 @@ | ||
this.listenTo( eventName, listener ); | ||
this.listenTo( eventName, listener.bind( this ) ); | ||
} | ||
@@ -188,0 +212,0 @@ } |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
Copyleft License
License(Experimental) Copyleft license information was found.
Found 1 instance in 1 package
Non-permissive License
License(Experimental) A license not known to be considered permissive was found.
Found 1 instance in 1 package
10
0
0
100
442
157
25835