diff --git a/app/assets/javascripts/modules/global-bar.js b/app/assets/javascripts/modules/global-bar.js
new file mode 100644
index 000000000..5161afc3d
--- /dev/null
+++ b/app/assets/javascripts/modules/global-bar.js
@@ -0,0 +1,58 @@
+/*
+ Global bar
+
+ Manages count of how many times a global bar has been seen
+ using cookies.
+*/
+(function(Modules) {
+ "use strict";
+
+ Modules.GlobalBar = function() {
+ this.start = function($el) {
+ var GLOBAL_BAR_SEEN_COOKIE = "global_bar_seen",
+ count = viewCount();
+
+ $el.on('click', '.dismiss', hide);
+
+ if ($el.is(':visible')) {
+ incrementViewCount(count);
+ track('Viewed');
+ }
+
+ function hide(evt) {
+ $el.hide();
+ GOVUK.setCookie(GLOBAL_BAR_SEEN_COOKIE, 999, {days: 84});
+ track('Manually dismissed');
+ $('html').removeClass('show-global-bar');
+ evt.preventDefault();
+ }
+
+ function incrementViewCount(count) {
+ count = count + 1;
+ GOVUK.setCookie(GLOBAL_BAR_SEEN_COOKIE, count, {days: 84});
+
+ if (count == 2) {
+ track('Automatically dismissed');
+ }
+ }
+
+ function viewCount() {
+ var viewCountCookie = GOVUK.getCookie(GLOBAL_BAR_SEEN_COOKIE),
+ viewCount = parseInt(viewCountCookie, 10);
+
+ if (isNaN(viewCount)) {
+ viewCount = 0;
+ }
+
+ return viewCount;
+ }
+
+ function track(action) {
+ if (GOVUK.analytics && typeof GOVUK.analytics.trackEvent === "function") {
+ GOVUK.analytics.trackEvent('Global bar', action, {nonInteraction: 1});
+ }
+ }
+ };
+ };
+
+})(window.GOVUK.Modules);
diff --git a/app/assets/javascripts/start-modules.js b/app/assets/javascripts/start-modules.js
index e84262083..7a7f499d9 100644
--- a/app/assets/javascripts/start-modules.js
+++ b/app/assets/javascripts/start-modules.js
@@ -1,4 +1,5 @@
// = require govuk/modules
+// = require modules/global-bar
// = require modules/sticky-element-container
// = require modules/toggle
// = require modules/track-click
diff --git a/app/assets/javascripts/surveys.js b/app/assets/javascripts/surveys.js
index 674c69d8b..bca06e06f 100644
--- a/app/assets/javascripts/surveys.js
+++ b/app/assets/javascripts/surveys.js
@@ -158,6 +158,7 @@
if (userSurveys.canShowAnySurvey()) {
var activeSurvey = userSurveys.getActiveSurvey(userSurveys.defaultSurvey, userSurveys.smallSurveys)
if (activeSurvey !== undefined) {
+ $('#global-bar').hide(); // Hide global bar if one is showing
userSurveys.displaySurvey(activeSurvey)
}
}
diff --git a/app/assets/stylesheets/helpers/_header.scss b/app/assets/stylesheets/helpers/_header.scss
index 508ad60ff..80c987c9f 100644
--- a/app/assets/stylesheets/helpers/_header.scss
+++ b/app/assets/stylesheets/helpers/_header.scss
@@ -341,3 +341,48 @@
margin-right: .5em;
}
}
+
+
+.show-global-bar #global-header-bar {
+ display: none;
+}
+
+.global-bar {
+ background-color: #BFE3E0;
+ display: none;
+ margin-bottom: 15px;
+ padding: 15px 0;
+
+ .show-global-bar & {
+ display: block;
+ }
+
+ .global-bar-message-container {
+ @include core-19;
+ @extend %site-width-container;
+ position: relative;
+
+ @include media(tablet) {
+ .dismiss {
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ }
+ }
+
+ .global-bar-message {
+ margin-bottom: 0;
+ margin-top: 0;
+
+ @include media(tablet) {
+ max-width: 66.67%;
+ }
+
+ .global-bar-title {
+ display: block;
+ font-weight: 700;
+ margin-right: 10px;
+ }
+ }
+}
diff --git a/app/views/notifications/_global_bar.html.erb b/app/views/notifications/_global_bar.html.erb
new file mode 100644
index 000000000..989cc3207
--- /dev/null
+++ b/app/views/notifications/_global_bar.html.erb
@@ -0,0 +1,29 @@
+<%
+ show_global_bar ||= false # Toggles the appearance of the global bar
+ title = "The title"
+ information = "Some information about something"
+ link_href = "https://www.gov.uk/"
+ link_text = %Q(More information about this).html_safe
+-%>
+<% if show_global_bar %>
+ <% content_for :head do %>
+
+
+
+ <% end %>
+
+
+
+
+ <%= title %>
+ <%= information %>
+ <%= link_to(link_text, link_href, rel: "external noreferrer") %>
+
+
Hide message
+
+
+
+<% end %>
diff --git a/app/views/root/_base.html.erb b/app/views/root/_base.html.erb
index ea50754ad..9f1be6750 100644
--- a/app/views/root/_base.html.erb
+++ b/app/views/root/_base.html.erb
@@ -30,6 +30,8 @@
<% end %>
<% content_for :content do %>
+ <%= render "notifications/global_bar" %>
+
<%= yield :wrapper_content %>
diff --git a/doc/global-banner.md b/doc/global-banner.md
new file mode 100644
index 000000000..2ea979fd0
--- /dev/null
+++ b/doc/global-banner.md
@@ -0,0 +1,16 @@
+## Global banner
+
+A site-wide banner can be activated to convey important information on GOV.UK which is not deemed emergency level information.
+The file `app/views/notifications/_global_bar.html.erb` contains the necessary minified JS and markup to activate and render the banner.
+
+### Activating the global banner
+
+In `app/views/notifications/_global_bar.html.erb`
+
+1. Update the variables `title`, `information`, `link_href` and `link_text` with the relevant info.
+2. Update the `show_global_bar` variable to `true`
+3. Deploy static
+
+The usual rules apply with static template caching.
+
+![screenshot](/doc/global-banner.png?raw=true)
diff --git a/doc/global-banner.png b/doc/global-banner.png
new file mode 100644
index 000000000..e3a38b987
Binary files /dev/null and b/doc/global-banner.png differ
diff --git a/spec/javascripts/global-bar-class-toggle.spec.js b/spec/javascripts/global-bar-class-toggle.spec.js
new file mode 100644
index 000000000..7dbe76132
--- /dev/null
+++ b/spec/javascripts/global-bar-class-toggle.spec.js
@@ -0,0 +1,133 @@
+describe("toggling a global bar HTML class based on cookie", function () {
+ var root = window;
+
+ /**
+ * The global bar needs to be activated early in page loading to prevent
+ * a flash of unstyled content, to do this we need to minify and inline
+ * the activation logic into the page head.
+ * This spec runs tests against both the full and minified sources of the
+ * activation JS because minification is not automated.
+ */
+ function globalBarSource(fakeWindow) {
+ var window = fakeWindow || root;
+
+ /* begin minify */
+
+ (function (document) {
+ "use strict"
+ var documentElement = document.documentElement;
+ if (urlPermitsShow() && viewCountPermitsShow()) {
+ documentElement.className = documentElement.className.concat(' show-global-bar');
+ }
+
+ function urlPermitsShow() {
+ return !/^\/register-to-vote|^\/done/.test(window.location.pathname);
+ }
+
+ function viewCountPermitsShow() {
+ var c = document.cookie.match('(?:^|[ ;])global_bar_seen=([0-9]+)');
+ if (!c) {
+ return true;
+ }
+
+ return parseInt(c.pop(), 10) < 3;
+ }
+ })(document);
+
+ /* end minify */
+ }
+
+
+ /**
+ * This is the minified version of the function above 'globalBarSource',
+ * when developing and testing updates and features,
+ * changes should be mirrored here manually.
+ * Only the code between the 'begin/end minify' comments should be copied.
+ */
+ function globalBarMinified(fakeWindow) {
+ var window = fakeWindow || root;
+
+ /* begin minify */
+ !function(t){"use strict";function e(){return!/^\/register-to-vote|^\/done/.test(window.location.pathname)}function n(){var e=t.cookie.match("(?:^|[ ;])global_bar_seen=([0-9]+)");return e?parseInt(e.pop(),10)<3:!0}var o=t.documentElement;e()&&n()&&(o.className=o.className.concat(" show-global-bar"))}(document);
+ /* end minify */
+ }
+
+ afterEach(function() {
+ $('html').removeClass('show-global-bar');
+ deleteAllCookies();
+
+ function deleteAllCookies() {
+ var cookies = document.cookie.split(";");
+
+ for (var i = 0; i < cookies.length; i++) {
+ var cookie = cookies[i];
+ var eqPos = cookie.indexOf("=");
+ var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
+ document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
+ }
+ }
+ });
+
+ describe('when running the full source', function() {
+ runTests(globalBarSource);
+ });
+
+ describe('when running the minified source', function() {
+ runTests(globalBarMinified);
+ });
+
+ function runTests(globalBarFn) {
+ it("shows when no cookie is set", function() {
+ expectGlobalBarToBeHidden();
+ globalBarFn();
+ expectGlobalBarToShow();
+ });
+
+ it("does not show when bar has been seen 3 times", function() {
+ GOVUK.setCookie('global_bar_seen', 3);
+ expectGlobalBarToBeHidden();
+ globalBarFn();
+ expectGlobalBarToBeHidden();
+ });
+
+ it("shows when the bar has been seen 2 times", function() {
+ GOVUK.setCookie('global_bar_seen', '2');
+ globalBarFn();
+ expectGlobalBarToShow();
+ });
+
+ it("shows when the bar has been seen 2 times and there are lots of cookies", function() {
+ GOVUK.setCookie('global_bar_thing', '10');
+ GOVUK.setCookie('seen_cookie_message', 'true');
+ GOVUK.setCookie('global_bar_seen', '2');
+ GOVUK.setCookie('is_global_bar_seen', '8');
+ GOVUK.setCookie('_ua', '1234873487');
+ globalBarFn();
+ expectGlobalBarToShow();
+ });
+
+ it("shows when the cookie value is not a parseable number", function() {
+ GOVUK.setCookie('global_bar_seen', 'foo_bar2');
+ globalBarFn();
+ expectGlobalBarToShow();
+ });
+
+ it("does not show on register to vote pages", function() {
+ globalBarFn({location: {pathname: '/register-to-vote'}});
+ expectGlobalBarToBeHidden();
+ });
+
+ it("does not show on done pages", function() {
+ globalBarFn({location: {pathname: '/done'}});
+ expectGlobalBarToBeHidden();
+ });
+ }
+
+ function expectGlobalBarToShow() {
+ expect($('html').is('.show-global-bar')).toBe(true);
+ }
+
+ function expectGlobalBarToBeHidden() {
+ expect($('html').is('.show-global-bar')).toBe(false);
+ }
+});