Brunch - Handlebars.templates is undefined - handlebars.js

I try to setup a dev environnement using brunch and handlebars. The handlebars-brunch package is stored in my node_modules and handlebars.runtime.js included in my vendor.js file. I've defined this template :
hello.template:
<p>Hello {{name}}</p>
And add these lines to my config.coffee :
templates:
defaultExtension: 'handlebars'
joinTo: 'app.js'
And as a proof that it works, I can see in my app.js the following lines :
;var __templateData = Handlebars.template(function Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression;
buffer += "<p>Hello ";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "</p>\r\n\r\n";
return buffer;
});
if (typeof define === 'function' && define.amd) {
define([], function() {
return __templateData;
});
} else if (typeof module === 'object' && module && module.exports) {
module.exports = __templateData;
} else {
__templateData;
}
But when i invoke Handlebars.templates.hello like this :
var tpl = Handlebars.templates.hello;
var html = tpl ( { name: "ok" } );
console.log ( tpl );
I get this error : Cannot read property 'hello' of undefined. So Handlebars is defined but not templates. My dependencies inclusion seems fine too as my main function is located after everything else, like this:
[...]
if (typeof define === 'function' && define.amd) {
define([], function() {
return __templateData;
});
} else if (typeof module === 'object' && module && module.exports) {
module.exports = __templateData;
} else {
__templateData;
}
;( function ( $, document, window ) {
var tpl = Handlebars.templates.hello;
var html = tpl ( { name: "ok" } );
console.log ( tpl );
} ( jQuery, document, window ) );
Any idea/suggestion?

Brunch uses modules. It doesn't assign global variables or something.
require('name')
if your file was app/name.js

Related

How to get the entire path in Next.js 13 in custom loader function, for server components only?

I have a loader function called getBlogData which is like this:
import { getFromCacheOrApi } from 'Base'
const getBlogData = async () => {
const { pathname } = { pathname: "" }
var url = '/blog/data?'
let matches = /\/blog(\/\d+)?\/?$/.exec(pathname)
if (matches != null) {
const pageNumber = matches[1]
if (pageNumber !== undefined) {
url += `&pageNumber=${pageNumber.replace('/', '')}`
}
}
else {
const secondSegments = ['category', 'tag', 'author', 'search']
if (pathname.split('/').length >= 2 && !secondSegments.includes(pathname.split('/')[2])) {
response.status = 404
return
}
for (let i = 0; i < secondSegments.length; i++) {
const segment = secondSegments[i]
if (pathname.startsWith(`/blog/${segment}`)) {
matches = new RegExp(`(?<=\\/blog\\/${segment}\\/)[^/]+\\/?(\\d+)?\\/?$`).exec(pathname)
if (matches == null) {
response.status = 404
return
}
else {
url += `&${segment}=${encodeURI(matches[0].split('/')[0])}`
const pageNumber = matches[1]
if (pageNumber !== undefined) {
url += `&pageNumber=${pageNumber}`
}
break
}
}
}
}
url = url.replace('?&', '?')
const data = await getFromCacheOrApi(url)
// console.log(params, response.status)
// if (pageNumber && isNaN(pageNumber)) {
// console.log(pageNumber, isNaN(pageNumber))
// response.status = 400
// return
// }
const { seoParameters } = data
return data
}
export default getBlogData
This function is only used in my page which is inside app directory in Next 13, which means that it's a server component, and I don't want to change it to a client component.
However, I need to access request data, in this particular case, the path of the URL.
How can I get that?

Simple pug html form, make it send immediately on change of value rather than wait for submit button

I have a very simple pug file:
for item in itemList
form(method='post', action='/change')
table
tr
td(width=100)
td(width=200)
| #{item.name}
input(type='hidden', name='field' value=item.name)
input(type='hidden', name='style' value='doublevalue')
td(width=100)
input(type='number', name='value' min=-20.0 max=80.00 step=0.01 value=+item.value)
td(width=100)
input(type='submit', value='Update')
p end
As you can see it produces a few trivial forms like this:
(Each form is one 'line' which is a simple table.)
(On the script side, it just reads each 'line' from a MySQL table, there are 10 or so of them.)
So on the www page, the user either
types in new number (say "8")
or clicks the small arrows (say Up, changing it to 7.2 in the example)
then the user must
click submit
and it sends the post.
Quite simply, I would like it to be that when the user
clicks a small arrows (say Up, changing it to 7.2 in the example)
it immediately sends a submit-post.
How do I achieve this?
(It would be fine if the send happens, any time the user types something in the field, and/or, when the user clicks the Small Up And Down Buttons. Either/both is fine.)
May be relevant:
My pug file (and all my pug files) have this sophisticated line of code as line 1:
include TOP.pug
And I have a marvellous file called TOP.pug:
html
head
style.
html {
font-family: sans-serif
}
td {
font-family: monospace
}
body
I have a solution with javascript.
// check if there are input[type="number"] to prevent errors
if (document.querySelector('input[type="number"]')) {
// add event for each of them
document.querySelectorAll('input[type="number"]').forEach(function(el) {
el.addEventListener('change', function (e) {
// on change submit the parent (closest) form
e.currentTarget.closest('form').submit()
});
});
}
Actually it is short but if you want to support Internet Explorer you have to add the polyfill script too. Internet Explorer does not support closest() with this snippet below we teach it.
// polyfills for matches() and closest()
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest) {
Element.prototype.closest = function(s) {
var el = this;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
Ajax form submit to node.js
If you are interested in an ajax solution I put some code below just to blow your mind ;-) It should work instantly, I use it on one of my sites. You could use jQuery and save lines of code but I like it pure. (The ajax function and polyfills are utils so paste it anywhere)
HTML (example)
<form>
<input type="hidden" name="field" value="field1">
<input type="hidden" name="style" value="style1">
<input type="number" name="value">
<input type="submit" value="update">
</form>
<form>
<input type="hidden" name="field" value="field2">
<input type="hidden" name="style" value="style2">
<input type="number" name="value">
<input type="submit" value="update">
</form>
Javascript: event listener and prepare ajax call (note the callbacks).
// check if there are forms to prevent errors
if (document.querySelector('form')) {
// add submit event for each form
document.querySelectorAll('form').forEach(function (el) {
el.addEventListener('submit', function (e) {
e.currentTarget.preventDefault();
submitData(e.currentTarget);
});
});
}
// check if there are input[type="number"] to prevent errors
if (document.querySelector('input[type="number"]')) {
// add change event for each of them
document.querySelectorAll('input[type="number"]').forEach(function (el) {
el.addEventListener('change', function (e) {
submitData(e.currentTarget.closest('form'));
});
});
}
// collect form data and send it
function submitData(form) {
// send data through (global) ajax function
ajax({
url: '/change',
method: 'POST',
data: {
field: form.querySelector('input[name="field"]').value,
style: form.querySelector('input[name="style"]').value,
value: form.querySelector('input[name="value"]').value,
},
// callback on success
success: function (response) {
// HERE COMES THE RESPONSE
console.log(response);
// error is defined in (node.js res.json({error: ...}))
if (response.error) {
// make something red
form.style.border = '1px solid red';
}
if (!response.error) {
// everything ok, make it green
form.style.border = '1px solid green';
}
// remove above styling
setTimeout(function () {
form.style.border = 'none';
}, 1000);
},
// callback on error
error: function (error) {
console.log('server error occurred: ' + error)
}
});
}
As told javascript utils (paste it anywhere like a library)
// reusable ajax function
function ajax(obj) {
let a = {};
a.url = '';
a.method = 'GET';
a.data = null;
a.dataString = '';
a.async = true;
a.postHeaders = [
['Content-type', 'application/x-www-form-urlencoded'],
['X-Requested-With', 'XMLHttpRequest']
];
a.getHeaders = [
['X-Requested-With', 'XMLHttpRequest']
];
a = Object.assign(a, obj);
a.method = a.method.toUpperCase();
if (typeof a.data === 'string')
a.dataString = encodeURIComponent(a.data);
else
for (let item in a.data) a.dataString += item + '=' + encodeURIComponent(a.data[item]) + '&';
let xhReq = new XMLHttpRequest();
if (window.ActiveXObject) xhReq = new ActiveXObject('Microsoft.XMLHTTP');
if (a.method == 'GET') {
if (typeof a.data !== 'undefined' && a.data !== null) a.url = a.url + '?' + a.dataString;
xhReq.open(a.method, a.url, a.async);
for (let x = 0; x < a.getHeaders.length; x++) xhReq.setRequestHeader(a.getHeaders[x][0], a.getHeaders[x][1]);
xhReq.send(null);
}
else {
xhReq.open(a.method, a.url, a.async);
for (let x = 0; x < a.postHeaders.length; x++) xhReq.setRequestHeader(a.postHeaders[x][0], a.postHeaders[x][1]);
xhReq.send(a.dataString);
}
xhReq.onreadystatechange = function () {
if (xhReq.readyState == 4) {
let response;
try {
response = JSON.parse(xhReq.responseText)
} catch (e) {
response = xhReq.responseText;
}
//console.log(response);
if (xhReq.status == 200) {
obj.success(response);
}
else {
obj.error(response);
}
}
}
}
// (one more) polyfill for Object.assign
if (typeof Object.assign !== 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, 'assign', {
value: function assign(target, varArgs) {
// .length of function is 2
if (target === null || target === undefined) {
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource !== null && nextSource !== undefined) {
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}
// polyfills for matches() and closest()
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
In node.js (e.g. express route)
// the route in node.js
app.post('/change', (req, res) => {
// your logic here
let field = req.body.field;
let style = req.body.style;
let value = req.body.value;
// ...
// response result
res.json({
databaseError: false, // or true
additionalStuff: 'message, markup and other things ...',
});
});

How to Get Array Data in HTML Using Meteor JS?

I need to know about to get array data of collections using Meteor JS. I did a simple example with insert data to collections in Meteor JS as shown below :
if (Hcare_Fileds.find().count() === 0) {
var fieldData = [
{fieldName: "Hcare1",
fieldOptions: [ "Bike","Car","TV","Radio","etc"]
},
{fieldName: "Hcare2",
fieldOptions: [ "Bike1","Car1","TV1","Radio1","etc"]
},
{fieldName: "Hcare3",
fieldOptions: [ "Bike2","Car2","TV2","Radio2","etc"]
}
];
for (var i = 0; i < fieldData.length; i++)
{
var list_id = Hcare_Fileds.insert({fieldname: fieldData[i].fieldName,fieldoptions: fieldData[i].fieldOptions}
, function( error, result)
{
if ( error ) console.log ( "Error :"+error.reason ); //info about what went wrong
if ( result )
{
console.log ( "Success="+result );//the _id of new object if successful
}
});
}
}
And Access the above collection fieldoption array data sa shown below :
{{#each fieldName}}
<div class="fmenu {{isselected}}"> {{ fieldname }} </div>
<div class="foptions">
{{#if isselected}}
{{ fieldoptions }}
// Here get fieldoptions data when selected filedname as Bike,Car,Tv,Radio,etc but i need to return like as array but it returns string
{{/if}}
</div>
{{/each}}
JS Code :
if (Meteor.isClient)
{
Session.set('currentFieldName', '');
Template.main.fieldName = function ()
{
return Hcare_Fileds.find().fetch();
};
//TODO ::
Template.main.events
({
'click .fmenu': function (e,t)
{
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button"+this.fieldname);
e.preventDefault();
Session.set('currentFieldName', this.fieldname);
}
});
Template.main.isselected = function ()
{
console.log("currentFieldName");
return Session.equals("currentFieldName", this.fieldname) ? "selected" : '';
};
}
I need to get data as array not string like Bike,Car,Tv,Radio,etc. I didn't get any idea about this.So Can you please suggest me what to do?

Improving FrontEnd Uploads in Wordpress

I want to improve the process of uploading pictures in a Real Estate Website. This website is running WordPress 3.8. The theme offers front end submission with a very simple interface. The user selects the images (one by one) and then clicks to add. Finally when the user submit the listing all the images are uploaded at once. This is the screenshot of how it looks: Original Option: Listing Images.
This is the JQuery Plugin I am currently using,
/*!
* jQuery imagesLoaded plugin v2.1.1
* http://github.com/desandro/imagesloaded
*
* MIT License. by Paul Irish et al.
*/
/*jshint curly: true, eqeqeq: true, noempty: true, strict: true, undef: true, browser: true */
/*global jQuery: false */
;(function($, undefined) {
'use strict';
// blank image data-uri bypasses webkit log warning (thx doug jones)
var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
$.fn.imagesLoaded = function( callback ) {
var $this = this,
deferred = $.isFunction($.Deferred) ? $.Deferred() : 0,
hasNotify = $.isFunction(deferred.notify),
$images = $this.find('img').add( $this.filter('img') ),
loaded = [],
proper = [],
broken = [];
// Register deferred callbacks
if ($.isPlainObject(callback)) {
$.each(callback, function (key, value) {
if (key === 'callback') {
callback = value;
} else if (deferred) {
deferred[key](value);
}
});
}
function doneLoading() {
var $proper = $(proper),
$broken = $(broken);
if ( deferred ) {
if ( broken.length ) {
deferred.reject( $images, $proper, $broken );
} else {
deferred.resolve( $images );
}
}
if ( $.isFunction( callback ) ) {
callback.call( $this, $images, $proper, $broken );
}
}
function imgLoadedHandler( event ) {
imgLoaded( event.target, event.type === 'error' );
}
function imgLoaded( img, isBroken ) {
// don't proceed if BLANK image, or image is already loaded
if ( img.src === BLANK || $.inArray( img, loaded ) !== -1 ) {
return;
}
// store element in loaded images array
loaded.push( img );
// keep track of broken and properly loaded images
if ( isBroken ) {
broken.push( img );
} else {
proper.push( img );
}
// cache image and its state for future calls
$.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } );
// trigger deferred progress method if present
if ( hasNotify ) {
deferred.notifyWith( $(img), [ isBroken, $images, $(proper), $(broken) ] );
}
// call doneLoading and clean listeners if all images are loaded
if ( $images.length === loaded.length ) {
setTimeout( doneLoading );
$images.unbind( '.imagesLoaded', imgLoadedHandler );
}
}
// if no images, trigger immediately
if ( !$images.length ) {
doneLoading();
} else {
$images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoadedHandler )
.each( function( i, el ) {
var src = el.src;
// find out if this image has been already checked for status
// if it was, and src has not changed, call imgLoaded on it
var cached = $.data( el, 'imagesLoaded' );
if ( cached && cached.src === src ) {
imgLoaded( el, cached.isBroken );
return;
}
// if complete is true and browser supports natural sizes, try
// to check for image status manually
if ( el.complete && el.naturalWidth !== undefined ) {
imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 );
return;
}
// cached images don't fire load sometimes, so we reset src, but only when
// dealing with IE, or image is complete (loaded) and failed manual check
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
if ( el.readyState || el.complete ) {
el.src = BLANK;
el.src = src;
}
});
}
return deferred ? deferred.promise( $this ) : $this;
};
})(jQuery);
My goal is to have a more flexible system, where all the images can be selected at the same time and it starts loading right away. This will speed up the process and improve user experience. Also to arrange them in any order by moving them around. This is an example I found on another website. See screenshot: New Option: Multiple Image Upload
What programing language is good for this development? Any recommendations of where I can find code snippets for this application? Thanks in advance for your help!!
rough draft.....you need jquery and wordpress media js..just watch the js variable names below if there are errors it will be with these...
php in functions file:
if(function_exists( 'wp_enqueue_media' )){
wp_enqueue_media();
}
javascript...add to the page header..wp_enqueue_scripts or to your template (do this first to make sure its working!) you'll need your element called upload_image_button or change accordinely
// Uploading files
var media_uploader;
jQuery('.upload_image_button').live('click', function( event ){
var button = jQuery( this );
// If the media uploader already exists, reopen it.
if ( media_uploader ) {
media_uploader.open();
return;
}
// Create the media uploader.
media_uploader = wp.media.frames.media_uploader = wp.media({
title: button.data( 'uploader-title' ),
// Tell the modal to show only images.
library: {
type: 'image',
query: false
},
button: {
text: button.data( 'uploader-button-text' ),
},
multiple: button.data( 'uploader-allow-multiple' )
});
// Create a callback when the uploader is called
media_uploader.on( 'select', function() {
var selection = media_uploader.state().get('selection'),
input_name = button.data( 'input-name' ),
bucket = $( '#' + input_name + '-thumbnails');
selection.map( function( attachment ) {
attachment = attachment.toJSON();
// console.log(attachment);
bucket.append(function() {
return '<img src="'+attachment.sizes.thumbnail.url+'" width="'+attachment.sizes.thumbnail.width+'" height="'+attachment.sizes.thumbnail.height+'" class="submission_thumb thumbnail" /><input name="'+input_name+'[]" type="hidden" value="'+attachment.id+'" />'
});
});
});
// Open the uploader
media_uploader.open();
});
template file:
<span class="upload_image_button alt_button" data-input-name="images" data-uploader- title="Upload Images" data-uploader-button-text="Add to Submission" data-uploader-allow-multiple="true">Upload</span>
php $_POST return
if ( !empty( $_POST['submission_images'] ) ) {
// do something with the files, set featured img, add to content or save post_meta
}
or..............i came across a plugin that does this a lot better........sorry its in OOP and designed on back end but you can modify for front end! The problem with multi file uploader from WP is it required users to hit "CTRL" + click with no guidance....massive problem on front-end forms...this one you can add more guidance to easily...sorry i havent a frontend sample yet, i have yet to create :)
"Multi File Upload"
e.g.
public function render_meta_box_content($post)
{
// Add an nonce field so we can check for it later.
wp_nonce_field('miu_inner_custom_box', 'miu_inner_custom_box_nonce');
// Use get_post_meta to retrieve an existing value from the database.
$value = get_post_meta($post->ID, '_ad_images', true);
$metabox_content = '<div id="miu_images"></div><input type="button" onClick="addRow()" value="Add Image" class="button" />';
echo $metabox_content;
$images = unserialize($value);
$script = "<script>
itemsCount= 0;";
if (!empty($images))
{
foreach ($images as $image)
{
$script.="addRow('{$image}');";
}
}
$script .="</script>";
echo $script;
}
save function
public function save_image($post_id)
{
/*
* We need to verify this came from the our screen and with proper authorization,
* because save_post can be triggered at other times.
*/
// Check if our nonce is set.
if (!isset($_POST['miu_inner_custom_box_nonce']))
return $post_id;
$nonce = $_POST['miu_inner_custom_box_nonce'];
// Verify that the nonce is valid.
if (!wp_verify_nonce($nonce, 'miu_inner_custom_box'))
return $post_id;
// If this is an autosave, our form has not been submitted,
// so we don't want to do anything.
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $post_id;
// Check the user's permissions.
if ('page' == $_POST['post_type'])
{
if (!current_user_can('edit_page', $post_id))
return $post_id;
} else
{
if (!current_user_can('edit_post', $post_id))
return $post_id;
}
/* OK, its safe for us to save the data now. */
// Validate user input.
$posted_images = $_POST['miu_images'];
$miu_images = array();
foreach ($posted_images as $image_url)
{
if(!empty ($image_url))
$miu_images[] = esc_url_raw($image_url);
}
// Update the miu_images meta field.
update_post_meta($post_id, '_ad_images', serialize($miu_images));
}
js file
jQuery(document).ready(function(){
jQuery('.miu-remove').live( "click", function(e) {
e.preventDefault();
var id = jQuery(this).attr("id")
var btn = id.split("-");
var img_id = btn[1];
jQuery("#row-"+img_id ).remove();
});
var formfield;
var img_id;
jQuery('.Image_button').live( "click", function(e) {
e.preventDefault();
var id = jQuery(this).attr("id")
var btn = id.split("-");
img_id = btn[1];
jQuery('html').addClass('Image');
formfield = jQuery('#img-'+img_id).attr('name');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
window.original_send_to_editor = window.send_to_editor;
window.send_to_editor = function(html){
if (formfield) {
fileurl = jQuery('img',html).attr('src');
jQuery('#img-'+img_id).val(fileurl);
tb_remove();
jQuery('html').removeClass('Image');
} else {
window.original_send_to_editor(html);
}
};
});
function addRow(image_url){
if(typeof(image_url)==='undefined') image_url = "";
itemsCount+=1;
var emptyRowTemplate = '<div id=row-'+itemsCount+'> <input style=\'width:70%\' id=img- '+itemsCount+' type=\'text\' name=\'miu_images['+itemsCount+']\' value=\''+image_url+'\' />'
+'<input type=\'button\' href=\'#\' class=\'Image_button button\' id=\'Image_button- '+itemsCount+'\' value=\'Upload\'>'
+'<input class="miu-remove button" type=\'button\' value=\'Remove\' id=\'remove-'+itemsCount+'\' /></div>';
jQuery('#miu_images').append(emptyRowTemplate);
}

How to secure a route in AngularFire 0.6.0 (authRequired)?

In previous versions of angularFire, it was possible to secure selected routes by using "authRequired" and "pathTo" with Angular's $routeProvider. These no longer appear to work with AngularFire 0.6.0. What is the equivalent parameter/technique in Angular 0.6.0?
Routing was moved out of angularFire for the same reasons it was moved out of the core of Angular--to be less opinionated in how routing is conducted and which lib you should use.
You can still include routing by grabbing the module from angularFire-seed, which is plug-and-play ready.
The steps are:
add ngRoute and routeSecurity to your app dependencies
declare the loginRedirectPath constant
add authRequired where appropriate
Example:
// add routeSecurity to your dependency libs
angular.module('myApp', [..., 'ngRoute', 'firebase', 'routeSecurity']);
// declare the loginRedirectPath variable
angular.module('myApp').constant('loginRedirectPath', '/login')
// put authRequired in your routes
$routeProvider.when('/account', {
authRequired: true, // must authenticate before viewing this page
templateUrl: 'partials/account.html',
controller: 'AccountCtrl'
});
// live long and prosper
Here's a hard copy of the module as of 0.6.0 for compliance with SO policy; refer directly to the source for a current version:
(function(angular) {
angular.module('routeSecurity', [])
.run(['$injector', '$location', '$rootScope', 'loginRedirectPath', function($injector, $location, $rootScope, loginRedirectPath) {
if( $injector.has('$route') ) {
new RouteSecurityManager($location, $rootScope, $injector.get('$route'), loginRedirectPath);
}
}]);
function RouteSecurityManager($location, $rootScope, $route, path) {
this._route = $route;
this._location = $location;
this._rootScope = $rootScope;
this._loginPath = path;
this._redirectTo = null;
this._authenticated = !!($rootScope.auth && $rootScope.auth.user);
this._init();
}
RouteSecurityManager.prototype = {
_init: function() {
var self = this;
this._checkCurrent();
// Set up a handler for all future route changes, so we can check
// if authentication is required.
self._rootScope.$on("$routeChangeStart", function(e, next) {
self._authRequiredRedirect(next, self._loginPath);
});
self._rootScope.$on('$firebaseSimpleLogin:login', angular.bind(this, this._login));
self._rootScope.$on('$firebaseSimpleLogin:logout', angular.bind(this, this._logout));
self._rootScope.$on('$firebaseSimpleLogin:error', angular.bind(this, this._error));
},
_checkCurrent: function() {
// Check if the current page requires authentication.
if (this._route.current) {
this._authRequiredRedirect(this._route.current, this._loginPath);
}
},
_login: function() {
this._authenticated = true;
if( this._redirectTo ) {
this._redirect(this._redirectTo);
this._redirectTo = null;
}
else if( this._location.path() === this._loginPath ) {
this._location.replace();
this._location.path('/');
}
},
_logout: function() {
this._authenticated = false;
this._checkCurrent();
},
_error: function() {
if( !this._rootScope.auth || !this._rootScope.auth.user ) {
this._authenticated = false;
}
this._checkCurrent();
},
_redirect: function(path) {
this._location.replace();
this._location.path(path);
},
// A function to check whether the current path requires authentication,
// and if so, whether a redirect to a login page is needed.
_authRequiredRedirect: function(route, path) {
if (route.authRequired && !this._authenticated){
if (route.pathTo === undefined) {
this._redirectTo = this._location.path();
} else {
this._redirectTo = route.pathTo === path ? "/" : route.pathTo;
}
this._redirect(path);
}
else if( this._authenticated && this._location.path() === this._loginPath ) {
this._redirect('/');
}
}
};
})(angular);

Resources