Skip to content

Commit

Permalink
Add snTitle service
Browse files Browse the repository at this point in the history
Allows site title to be set in javascript and page title to be set after angular app config
  • Loading branch information
edoparearyee committed Mar 16, 2015
1 parent cfaafa4 commit 7d3ad00
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 21 deletions.
143 changes: 123 additions & 20 deletions app/js/title.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,24 @@
* @author SOON_
*/
angular.module("sn.title", [])

/**
* Title text to display when $routeChangeError
* event occurs.
* @constant
* @property ROUTE_CHANGE_ERROR_TITLE
* @type {String}
* @type {String}
*/
.constant("ROUTE_CHANGE_ERROR_TITLE", "Page Error")

/**
* @constant
* @property EVENTS
* @type {Object}
*/
.constant("EVENTS", {
SET_TITLE: "sn.title:setTitle",
ROUTE_CHANGE_SUCCESS: "$routeChangeSuccess",
ROUTE_CHANGE_ERROR: "$routeChangeError",
})
/**
* Title element directive which updates it's content to
* update the page title. Place the name of you site inside
Expand All @@ -51,50 +59,79 @@ angular.module("sn.title", [])
*/
.directive("title", [
"$rootScope",
"snTitle",
"EVENTS",
"ROUTE_CHANGE_ERROR_TITLE",
/**
* @constructor
* @param {Service} $rootScope
* @param {Service} snTitle
* @param {String} EVENTS
* @param {String} ROUTE_CHANGE_ERROR_TITLE
*/
function ($rootScope, ROUTE_CHANGE_ERROR_TITLE) {
function ($rootScope, snTitle, EVENTS, ROUTE_CHANGE_ERROR_TITLE) {
return {
restrict: "E",
link: function ($scope, $element) {

/**
* The name of the site to use to append
* to all page titles.
* The name of the site. We use this to append to all page titles.
* We use various sources to get the site title, here is the list
* in order of priority:
* 1. First attempt to get the site title from snTitle service
* 2. Fallback to text inside <title> element for site title
* 3. Set title as undefined
* @property siteTitle
* @type {String}
* @type {String}
* @example
* My Site Name
* "My Site Name"
*/
var siteTitle = $element.html().length > 0 ? $element.html() : undefined ;
var siteTitle =
snTitle.getSiteTitle() && snTitle.getSiteTitle().length > 0 ?
snTitle.getSiteTitle() :
($element.html().length > 0 ? $element.html() : undefined) ;

/**
* Update the content of the title element to the value
* of the title key in the object of the current route
* @method onRouteChangeSuccess
* @param {event} $event '$routeChangeSuccess' event from ngRoute service
* @param {Object} current The requested route object
* @method setTitle
* @param {Event} $event Angular event object
* @param {String} pageTitle Value to set the document title to
*/
var onRouteChangeSuccess = function onRouteChangeSuccess($event, current){
var setTitle = function setTitle($event, pageTitle){

// route title & site title
if (current && current.$$route && current.$$route.title && siteTitle){
$element.html(current.$$route.title + " - " + siteTitle);
if (pageTitle && siteTitle){
$element.html(pageTitle + " - " + siteTitle);

// route title only
} else if (current && current.$$route && current.$$route.title){
$element.html(current.$$route.title);
} else if (pageTitle){
$element.html(pageTitle);

// site title only
} else if (siteTitle){
$element.html(siteTitle);
}
};

/**
* Update the content of the title element to the value
* of the title key in the object of the current route
* @method onRouteChangeSuccess
* @param {event} $event '$routeChangeSuccess' event from ngRoute service
* @param {Object} current The requested route object
*/
var onRouteChangeSuccess = function onRouteChangeSuccess($event, current){

var pageTitle = null;

if (current && current.$$route && current.$$route.title){
pageTitle = current.$$route.title;
}

setTitle($event, pageTitle);
};

/**
* Update the content of the title element to the value
* of ROUTE_CHANGE_ERROR_TITLE constant when $routeChangeError
Expand All @@ -109,10 +146,76 @@ angular.module("sn.title", [])
}
};

$rootScope.$on("$routeChangeSuccess", onRouteChangeSuccess);
$rootScope.$on("$routeChangeError", onRouteChangeError);
$rootScope.$on(EVENTS.SET_TITLE, setTitle);

$rootScope.$on(EVENTS.ROUTE_CHANGE_SUCCESS, onRouteChangeSuccess);
$rootScope.$on(EVENTS.ROUTE_CHANGE_ERROR, onRouteChangeError);

}
};
}
]);
])
/**
* Service that sets the title of the document by specifying
* the page title and the site title.
* @example
* angular.module("myApp", ["sn.title"])
* .config([
* "snTitleProvider",
* function(snTitleProvider){
* snTitleProvider.setSiteTitle("My Site Name");
* }
* ])
* .controller("myCtrl",[
* "snTitle",
* function (snTitle){
* snTitle.setPageTitle("My Page");
* }
* ])
* @class snTitle
* @module sn.title
* @author SOON_
*/
.provider("snTitle", function() {
/**
* @property siteTitle
* @type {String}
*/
var siteTitle = null;
/**
* @method setSiteTitle
* @param {String} value Value to set the site title to
*/
this.setSiteTitle = function setSiteTitle(value) {
siteTitle = value;
};
/**
* @property $get
* @param {Array}
*/
this.$get = [
"$rootScope",
"EVENTS",
function ($rootScope, EVENTS) {
return {
/**
* @method getSiteTitle
* @return {String} Value of the site title
*/
getSiteTitle: function getSiteTitle(){
return siteTitle;
},
/**
* Set the page title of title directive.
* Broadcasts an event which is being listen
* to by title directive
* @method setPageTitle
* @param {String} value Value to set the current page title to
*/
setPageTitle: function setPageTitle(value){
$rootScope.$broadcast(EVENTS.SET_TITLE, value);
}
};
}
];
});
60 changes: 59 additions & 1 deletion tests/unit/title.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

describe("sn.title:title", function() {
describe("sn.title:title directive", function() {
var element, $scope, $rootScope, errorText;

beforeEach(module("sn.title"));
Expand Down Expand Up @@ -82,3 +82,61 @@ describe("sn.title:title", function() {
});

});

describe("sn.title:snTitle service", function() {
var element, $scope, $rootScope, errorText, snTitle;

beforeEach(module("sn.title", function (snTitleProvider){
snTitleProvider.setSiteTitle("My Site Name");
}));

beforeEach(inject(function (_$rootScope_, $compile, $injector) {
$rootScope = _$rootScope_;

spyOn($rootScope, "$broadcast").and.callThrough();

$scope = $rootScope.$new();

snTitle = $injector.get("snTitle");

errorText = $injector.get("ROUTE_CHANGE_ERROR_TITLE")

element = "<title></title>";

element = $compile(element)($scope);
$scope.$digest();

}));

describe("site title defined using snTitle service", function() {

it("should render directive with correct title text", function(){
$rootScope.$broadcast("$routeChangeSuccess", {
$$route: {
title: "foo"
}
})
expect(element.html()).toEqual("foo - My Site Name");

$rootScope.$broadcast("$routeChangeSuccess", {
$$route: {
title: undefined
}
})
expect(element.html()).toEqual("My Site Name");
});

it("should render directive with error title text", function(){
$rootScope.$broadcast("$routeChangeError")
expect(element.html()).toEqual(errorText + " - My Site Name");
});

it("should update title element text with page title", function(){
snTitle.setPageTitle("My page");
expect($scope.$broadcast).toHaveBeenCalled();
expect(element.html()).toEqual("My page - My Site Name");
});

});

});

0 comments on commit 7d3ad00

Please sign in to comment.