Socket
Socket
Sign inDemoInstall

express-flash-notification

Package Overview
Dependencies
1
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.0 to 0.3.0

255

index.js

@@ -0,1 +1,6 @@

/**
* Provides Flash Notification Middleware
*
* @module Express Flash Notification
*/
var format = require('util').format

@@ -5,18 +10,91 @@ var isArray = require('util').isArray

var REDIRECT = true
var SESSION_NAME = 'flash'
var UTILITY_NAME = 'flash'
var LOCALS_NAME = 'flash'
var VIEW_NAME = 'flash'
var BEFORE_SINGLE_RENDER = function(item, callback){callback(null, item)}
var AFTER_ALL_RENDER = function(htmlFragments, callback){callback(null, htmlFragments.join('\n'))}
/**
* Default value for when calling the `req.flash` method withouth specifying
* the redirect argument.
*
* @property REDIRECT
* @type Boolean|String
* @final
*/
var REDIRECT = true
/**
* Default name of property stored in req.session that holds an array of notifications
* to display.
*
* @property SESSION_NAME
* @type String
* @final
*/
var SESSION_NAME = 'flash'
/**
* Default name of method stored in `req` object used to trigger a request notification.
*
* @property UTILITY_NAME
* @type String
* @final
*/
var UTILITY_NAME = 'flash'
/**
* Default locals property name used to render the flash notification markup.
*
* @property LOCALS_NAME
* @type String
* @final
*/
var LOCALS_NAME = 'flash'
/**
* Default view template filename (extension) that will be passed to tthe express
* template engine to generate the flash notification markup.
*
* @property VIEW_NAME
* @type String
* @final
*/
var VIEW_NAME = 'flash'
/**
* Default callback that is called before each notification is rendered using the
* express template engine.
*
* @method BEFORE_SINGLE_RENDER
* @final
*/
var BEFORE_SINGLE_RENDER = function(item, callback){callback(null, item)}
/**
* Default callback that is called after all notifications have been rendered by the
* express template engine.
*
* @method BEFORE_SINGLE_RENDER
* @param htmlFragments {Array}
* @final
*/
var AFTER_ALL_RENDER = function(htmlFragments, callback){callback(null, htmlFragments.join('\n'))}
/**
* Utility used to check whether an argument is a Native Object
*
* @method isObject
* @return Boolean
* @private
*/
function isObject(sample)
{
return (typeof sample === 'object' && !isArray(sample))
return (sample && typeof sample === 'object' && !isArray(sample))
}
function ConnectMiddleware (app, options)
/**
* Function used to expose express instance and configuration options.
* The actual middleware is returned.
*
* @method Module
* @param app {Express}
* @param options {Object}
*/
function Module (app, options)
{
// Are we configuring the middleware?
if (isObject(options))

@@ -28,18 +106,84 @@ {

VIEW_NAME = options.view_name || VIEW_NAME
BEFORE_SINGLE_RENDER = options.beforeSingleRender || BEFORE_SINGLE_RENDER
AFTER_ALL_RENDER = options.afterAllRender || AFTER_ALL_RENDER
BEFORE_SINGLE_RENDER = (typeof options.beforeSingleRender === 'function')
? options.beforeSingleRender
: BEFORE_SINGLE_RENDER
AFTER_ALL_RENDER = (typeof options.afterAllRender === 'function')
? options.afterAllRender
: AFTER_ALL_RENDER
}
function Middleware(req, res, next)
/**
* Render Notifications on queue
*
* @method render
* @private
*/
function render (req, res, next)
{
if (!req.session) throw new Error('express-session is required')
if (!isArray(req.session[SESSION_NAME])) req.session[SESSION_NAME] = []
if (req.session[SESSION_NAME].length === 0)
{
next()
}
else
{
var resultHTML = []
async.each(
req.session[SESSION_NAME],
function(item, callback)
{
BEFORE_SINGLE_RENDER(item, function(err, item){
if (err) return callback(err)
app.render(VIEW_NAME, item, function(err, html) {
if (err) return callback(err)
resultHTML.push(html)
callback(null)
})
})
},
function(err)
{
if (err) return next(err)
req.session[SESSION_NAME].length = 0
AFTER_ALL_RENDER(resultHTML, function(err, html){
if (err) return next(err)
res.locals[LOCALS_NAME] = html
next()
})
}
)
}
}
// Flash utility
/**
* Adds flash method to req object and renders all notifications found in
* req.session
*
* @method FlashMiddleware
*/
function FlashMiddleware(req, res, next)
{
if (!isObject(req.session))
{
throw new Error('express-session is required')
}
else
{
if (!isArray(req.session[SESSION_NAME]))
{
req.session[SESSION_NAME] = []
}
}
/**
* Utility used to programmatically add flash notifications
*
* @method Flash Utility
*/
req[UTILITY_NAME] = function()
{
var notification
var redirect = REDIRECT
var argc = arguments.length
var redirect = REDIRECT
var argc = arguments.length
// Parse arguments
if (argc === 1)

@@ -50,10 +194,7 @@ {

{
notification = arg
redirect = (arg.redirect === undefined) ? redirect : arg.redirect
notification = arg, redirect = (arg.redirect === undefined) ? redirect : arg.redirect
}
else
{
notification = {
message: arg + '',
}
notification = { message: arg + ''}
}

@@ -63,6 +204,3 @@ }

{
notification = {
type: arguments[0] + '',
message: arguments[1] + '',
}
notification = { type: arguments[0] + '', message: arguments[1] + '' }
redirect = (arguments[2] === undefined) ? redirect : arguments[2]

@@ -75,4 +213,10 @@ }

if (notification) req.session[SESSION_NAME].push(notification)
// Queue Notification
if (notification)
{
req.session[SESSION_NAME].push(notification)
}
// If redirect is set, refresh or redirect, accordingly. Otherwise, render the
// notifications now since it's on this request where they will be displayed.
if (redirect)

@@ -83,42 +227,25 @@ {

}
}
// Check if there are any messages in session to render
if (req.session[SESSION_NAME].length)
{
var resultHTML = []
async.each(
req.session[SESSION_NAME],
function(item, callback)
else
{
/**
* When there is no redirect, notifications must be rendered now and since
* rendering is async (and this method is sync), a *promise* like function is returned.
* The function can be called with a callback that will be called after all notifcations
* are rendered, otherwise, rendering will be done during the next request.
*/
return function ManualRender(callback)
{
BEFORE_SINGLE_RENDER(item, function(err, item){
if (err) return callback(err)
app.render(VIEW_NAME, item, function(err, html) {
if (err) return callback(err)
resultHTML.push(html)
callback(null)
})
})
},
function(err)
{
if (err) throw err
req.session[SESSION_NAME].length = 0
AFTER_ALL_RENDER(resultHTML, function(err, html){
if (err) throw err
res.locals[LOCALS_NAME] = html
next()
})
render(req, res, callback)
}
)
}
}
else
{
next()
}
}
return Middleware
/**
* Process Queued Notifications
*/
render(req, res, next)
}
return FlashMiddleware
}
module.exports = ConnectMiddleware
module.exports = Module
{
"name": "express-flash-notification",
"version": "0.2.0",
"description": "Express.js flash notifications that work with any template engine",
"version": "0.3.0",
"description": "Express.js flash notifications that works with any template engine",
"main": "index.js",

@@ -6,0 +6,0 @@ "scripts": {

# express-flash-notification
This module provides a way to set one-time notifications to be displayed after processing a request. Notifications are stored in session and are removed once they have been displayed.
This module provides a way to set one-time notifications to be displayed during or after processing a request. Notifications are stored in session and are removed once they have been rendered.
**Key Points**
* Template Engine Agnostic, works with any engine you are using logic/logicless
* Supports for Multiple notifications to be sent
* Auto refreshes the page to display the notification
* Allows you to manipulate the notification output before and after it has been created
- **Template Engine Agnostic**, works with any engine you are using logic/logicless.
- Supports for **Multiple notifications** to be sent.
- **Auto refreshes or redirects** the page to display the notification.
- Allows you to manipulate the notification output **before and after** it has been created.
- **No need to refresh or redirect**, notifications can be rendered on the same request.

@@ -18,18 +19,21 @@ ### Why?

`req.flash('info', 'my message')` in my controller/middleware and
`{{{flash}}}` in my layout
`req.flash('info', 'my message')`
in my controller/middleware and
`{{{flash}}}`
in my layout
Then the HTML for each alert gets placed in `{{{flash}}}` including some client side javascript so it doesn't just appear `$(elm).slideDown()` **FTW**
While at the same time, adding the markup nessary to display the alert depending on its **type** (so info is blue, error is red, etc)
While at the same time, adding the markup nessary to display the alert depending on its **type** (so *info* is blue, *error* is red, etc).
## Install
$ npm install express-flash-notification --save
```
npm install express-flash-notification --save
```
## Usage
Flash notifications are stored in the session. You will need the `cookieParser` middleware and the `session` middleware. Depending on your express version it may be bundled in express or for the newer releases you'll have to npm install them as seperate modules. I'm using express 4.x
Flash notifications are stored in the session. You will need the `cookieParser` middleware and the `session` middleware. Depending on your express version it may be bundled in express or for the newer releases you'll have to npm install them as seperate modules. I'm using express 4.x in the following examples.
You must pass the express application instance as the first argument in the `flash()` middleware so `app.render` can be used to create your notification using your template engine and views directory
You must pass the express application instance as the first argument in the `flash()` middleware so `app.render` can be used to create your notification using your chosen template engine and views directory.

@@ -50,4 +54,81 @@ ```javascript

With the `flash` middleware in place, all requests will have a `req.flash()` function that can be used for flash notifications.
##### In your Layout
Wherever you place the local variable `flash`, it will be populated with the notifications if there are any. Make sure it does not escape, as the output *may* be HTML.
```html
<<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
{{{flash}}}
</body>
</html>
```
##### In your Views
By default, a view called `flash` in your `views` directory will be retrieved and used as the default template for your notifications.
The local variables `type` and `message` will be set, depending on the type and message passed when calling **req.render**
**flash.html** (I'm using mustache in this example)
```html
<div class="alert flash">
<button type="button" class="close">×</button>
<i class="fa sign"></i><strong>{{type}}</strong>
<span>{{message}}</span>
</div>
```
### req.flash API
**Note** A `notification` is an object where its properties become the local variables when rendering the it using the express rendering engine of your choice.
- **req.flash**(*String*)
Sets local variable `message` to the string provided, `type` will become an empty string. Will refresh the current page.
- **req.flash**(*String*, *String*)
First string is the `type` local variable, the second is the `message` local variable. Will refresh the current page.
- **req.flash**(*String*, *String*, *String*)
Similar to to above, except last argument as a string defines which page to redirect to.
- **req.flash**(*String*, *String*, *Boolean*)
Same as above. Third variable as a boolean decides whether or not to refresh the page.
**NOTE** If set to false, notification will not be rendered until the next request. If you want the notification to be rendered on the current request, you can use a function that is returned by `req.flash`, simply call the function with a callback, the callback will be executed once rendering is complete.
**example**
```
app.all(function SampleExpressRoute(req, res){
var manualRender = req.flash('warn', 'tell them now!', false)
manualRender(function(err){
if (err) throw err
res.render('layouts/internal')
})
})
```
- **req.flash**(*object*)
You can pass an object as the first argument, the object's properties will be exposed as local variables when rendering the notification template.
The property `redirect` is reserved and functions just as you'd expect; a *Boolean* determines if it will refresh, or as a *String* you specify where to redirect to.
```javascript
req.flash('info', 'if cats ruled the world', false)
```
is treated exactly the same as:
```javascript
req.flash({
type: 'info',
message: 'if cats rules the world',
redirect: false
})
```
### Usage Example
With the `flash` middleware in place, all requests will have a `req.flash()` method to send out flash notifications.
```javascript

@@ -99,3 +180,6 @@ app.use('/login', function loginProcessor(req, res, next){

By default, req.flash will redirect to the current url, effectively refreshing the page so to display the flash notification. It's important that your logic uses `return` when using flash or contraints so you don't get the *headers have already been sent* error.
###### Pitfalls
By default, **req.flash** will redirect to the current url, effectively refreshing the page so to display the flash notification. It is important that your logic uses `return` when using flash or conditioning so you don't get the *headers have already been sent* error.
For example below, if 2 + 2 ever equals 'fish' the `req.flash` method will send out the redirect headers, and execution will continue until the `next` function is called, `next` will also try to set the response headers

@@ -116,3 +200,2 @@

In the case above, and in case you want to send multiple notifications you can disable the redirect by setting the third parameter to `false`
You can also set a string and that will become the destination for the redirect

@@ -132,49 +215,2 @@ ```javascript

##### Using req.flash
A notification is basically an object where its properties become the local variables when rendering the notification
- req.flash(*String*)
Sets local variable `message` to the string provided, `type` will become an empty string. Will refresh page
- req.flash(*String*, *String*)
First string is the `type` local variable, the second is the `message` local variable. Will refresh page.
- req.flash(*String*, *String*, *Boolean*)
Same as above. Third variable as a boolean decides whether or not to refresh the page.
- req.flash(*String*, *String*, *String*)
Similar to to above, except last argument as a string defines which page to redirect to
- req.flash(*object*)
You can pass an object as the first argument, the object's properties will be exposed as local variables when rendering the notification template.
The property `redirect` is reserved and functions just as you'd expect; a Boolean determines if it will refresh, or as a String you specify where to redirect to.
`req.flash('info', 'if cats ruled the world', false)` is treated exactly the same as
`req.flash({
type: 'info',
message: 'if cats rules the world',
redirect: false
})`
##### In your Layout
Wherever you place the local variable `flash`, it will be populated with the notifications if there are any. Make sure it does not escape, as the output will be HTML
##### In your Views
By default, a view called `flash` in your `views` directory will be retrieved and used as the default template for your notifications.
The local variables `type` and `message` will be set.
**flash.html** (I'm using mustache in this example)
```html
<div class="alert flash">
<button type="button" class="close">×</button>
<i class="fa sign"></i><strong>{{type}}</strong>
<span>{{message}}</span>
</div>
```
----------------

@@ -184,3 +220,3 @@

When setting the flash middleware, the second parameter accepts an object for configuration
When setting the flash middleware, the second parameter accepts an object for configuration.
Below is an example with all the options set to their defaults

@@ -213,13 +249,13 @@

-----------------
## Advance Usage
Heres an example where custom notifications will be rendered, `beforeSingleRender` is used to add class names depending on the `type` of notification
so the resulting notification looks different depending on its type. Also, `afterAllRender` will be used to append some javascript so notification
don't just appear, they slide into view.
Heres an example where custom notifications will be rendered, `beforeSingleRender` is used to add class names depending on the `type` of notification so the resulting notification looks different depending on its type. Also, `afterAllRender` will be used to append some javascript so notification don't just appear, they slide into view.
**NOTE** `{{{flash}}}` is placed in my layout template, not shown here
**NOTE** `{{{flash}}}` is placed in my layout, not shown here
This is my `flash.html` view template.
`alert_class` and `icon_class` will be populated inside of `beforeSingleRender`
`style="display: none"` is set so the appended javascript uses jQuery's slideDown method to animate its presentation
`style="display: none"` is set so the appended javascript uses jQuery's `slideDown` method to animate its presentation

@@ -230,3 +266,3 @@ ```html

<i class="fa {{icon_class}} sign"></i><strong>{{type}}</strong>
<span>{{message}}</span>
<span>{{{message}}}</span>
</div>

@@ -241,52 +277,52 @@ ```

view_name: 'elements/flash',
beforeSingleRender: function(item, callback)
beforeSingleRender: function(notification, callback)
{
if (item.type)
if (notification.type)
{
switch(item.type)
switch(notification.type)
{
case 'error':
item.alert_class = 'alert-danger'
item.icon_class = 'fa-times-circle'
notification.alert_class = 'alert-danger'
notification.icon_class = 'fa-times-circle'
break;
case 'alert':
item.alert_class = 'alert-warning'
item.icon_class = 'fa-times-circle'
notification.alert_class = 'alert-warning'
notification.icon_class = 'fa-times-circle'
break;
case 'info':
item.alert_class = 'alert-info'
item.icon_class = 'fa-times-circle'
notification.alert_class = 'alert-info'
notification.icon_class = 'fa-times-circle'
break;
case 'success':
item.alert_class = 'alert-success'
item.icon_class = 'fa-check'
notification.alert_class = 'alert-success'
notification.icon_class = 'fa-check'
break;
case 'ok':
item.alert_class = 'alert-primary'
item.icon_class = 'fa-check'
notification.alert_class = 'alert-primary'
notification.icon_class = 'fa-check'
break;
}
}
callback(null, item)
callback(null, notification)
},
afterAllRender: function(htmlFragments, callback)
{
// Naive JS is appened, waits a while expecting for the DOM to finish loading in 200ms,
// The timeout can be removed if jOuery is loaded before this is called
// Naive JS is appened, waits a while expecting for the DOM to finish loading,
// The timeout can be removed if jOuery is loaded before this is called, or if you're using vanilla js.
htmlFragments.push([
'<script type="text/javascript">',
' setTimeout(function(){',
' $(".alert.flash").slideDown().find(".close").on("click", function(){$(this).parent().hide()})',
' var timer = setInterval(function(){',
' if (window.jOuery){',
' clearInterval(timer)',
' $(".alert.flash").slideDown().find(".close").on("click", function(){$(this).parent().slideUp()})',
' }',
' }, 200)',
'</script>',
].join(''))
callback(null, htmlFragments.join(''))
},
}))
```
And this is how I use it
**And this is how you'd use it**

@@ -293,0 +329,0 @@ ```javascript

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc