Created
July 17, 2017 15:10
-
-
Save andysellick/90d68e33e8cf5056ad9ce5d86b0b3269 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<% | |
appearance_class ||= "on-light-background" | |
layout_class ||= "" | |
search_term ||= "" | |
input_id ||= SecureRandom.hex(4) | |
label_text ||= "Search GOV.UK" | |
label_text = "#{label_text}".html_safe | |
%> | |
<div class="govuk-search <%= appearance_class %> <%= layout_class %>" | |
data-module="toggle-class" | |
data-toggle-class="focus" | |
data-toggle-onload="onloadCheckInputValue" | |
data-toggle-onexit="checkValueAndRemoveClassFromElement" | |
> | |
<label for="search-main-<%= input_id %>" class="search-label"> | |
<%= label_text %> | |
</label> | |
<div class="search-wrapper"> | |
<input type="search" value="<%= search_term %>" id="search-main-<%= input_id %>" name="q" title="Search" class="search-element search-input js-toggle-action js-toggle-target"> | |
<div class="search-element search-submit-wrapper"> | |
<button type="submit" class="search-submit">Search</button> | |
</div> | |
</div> | |
</div> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-env jasmine */ | |
/* eslint-disable no-multi-str */ | |
describe('A toggle class module applied to a search box', function () { | |
'use strict'; | |
var toggle; | |
//base element for all tests, requires some additions for the JS to work correctly | |
//created as a string and then converted into HTML (rather than as an element) as tests modify it | |
var element = '\ | |
<div id="toggle-class-test" class="govuk-search" data-module="toggle-class">\ | |
<label for="search-main-12345" class="search-label">\ | |
Search GOV.UK\ | |
</label>\ | |
<div class="search-wrapper">\ | |
<input type="search" value="" id="search-main-12345" name="q" title="Search" class="search-element search-input">\ | |
<div class="search-element search-submit-wrapper">\ | |
<button type="submit" class="search-submit">Search</button>\ | |
</div>\ | |
</div>\ | |
</div>'; | |
var elementid = '#toggle-class-test'; | |
afterEach(function(){ | |
$('body').find(elementid).remove(); | |
}); | |
describe('when the needed js-toggle-action element is not present', function () { | |
beforeEach(function () { | |
$('body').append($('<div/>').html(element)); | |
toggle = new GOVUK.Modules.ToggleClass(); | |
toggle.start($(elementid)); | |
}); | |
it('does nothing', function () { | |
var searchInput = $('body').find('.search-input'); | |
expect(searchInput.is('.active')).toBe(false); | |
searchInput.trigger('focus'); | |
expect(searchInput.is('.active')).toBe(false); | |
searchInput.trigger('blur'); | |
expect(searchInput.is('.active')).toBe(false); | |
}); | |
}); | |
describe('when the search box is interacted with', function () { | |
beforeEach(function () { | |
$('body').append($('<div/>').html(element)); | |
$('body').find('#search-main-12345').addClass('js-toggle-action'); //class needed to module to operate | |
toggle = new GOVUK.Modules.ToggleClass(); | |
toggle.start($(elementid)); | |
}); | |
it('applies the focus style on focus and removes it on blur', function () { | |
var searchInput = $('body').find('.search-input'); | |
expect($(elementid).is('.active')).toBe(false); | |
searchInput.trigger('focus'); | |
expect($(elementid).is('.active')).toBe(true); | |
searchInput.trigger('blur'); | |
expect($(elementid).is('.active')).toBe(false); | |
}); | |
}); | |
describe('when different options are passed to the module', function () { | |
beforeEach(function () { | |
$('body').append($('<div/>').html(element)); | |
$('body').find('#search-main-12345').addClass('js-toggle-action'); //class needed to module to operate | |
$('body').find('#search-main-12345').addClass('js-toggle-target'); //element to toggle the class on | |
$('body').find('#toggle-class-test').attr('data-toggle-class','custom-focus-class'); //set a custom focus class | |
$('body').find('#toggle-class-test').attr('data-toggle-on-action','keydown'); //set a custom event for adding the class | |
$('body').find('#toggle-class-test').attr('data-toggle-off-action','keyup'); //set a custom event for removing the class | |
toggle = new GOVUK.Modules.ToggleClass(); | |
toggle.start($(elementid)); | |
}); | |
it('works with a custom focus class and custom events', function() { | |
var searchInput = $('body').find('.js-toggle-action'); | |
var targetElement = $('body').find('.js-toggle-target'); | |
expect(targetElement.is('.custom-focus-class')).toBe(false); | |
searchInput.trigger('keydown'); | |
expect(targetElement.is('.custom-focus-class')).toBe(true); | |
searchInput.trigger('keyup'); | |
expect(targetElement.is('.custom-focus-class')).toBe(false); | |
}); | |
}); | |
describe('when the search box already has a value', function () { | |
beforeEach(function () { | |
$('body').append($('<div/>').html(element)); | |
$('body').find('#search-main-12345').addClass('js-toggle-action'); //class needed to module to operate | |
$('body').find('#search-main-12345').addClass('js-toggle-target'); //element to toggle the class on | |
$('body').find('#search-main-12345').attr('value','I have already searched'); //set the value of the search box | |
$('body').find('#toggle-class-test').attr('data-toggle-onload','onloadCheckInputValue'); | |
$('body').find('#toggle-class-test').attr('data-toggle-onexit','checkValueAndRemoveClassFromElement'); | |
toggle = new GOVUK.Modules.ToggleClass(); | |
toggle.start($(elementid)); | |
}); | |
it('applies the focus style on load', function() { | |
var targetElement = $('body').find('.js-toggle-target'); | |
expect(targetElement.is('.active')).toBe(true); | |
}); | |
it('does not remove the focus style on blur unless the value is removed', function() { | |
var searchInput = $('body').find('.js-toggle-action'); | |
var targetElement = $('body').find('.js-toggle-target'); | |
searchInput.trigger('focus'); | |
expect(targetElement.is('.active')).toBe(true); | |
searchInput.trigger('blur'); | |
expect(targetElement.is('.active')).toBe(true); | |
searchInput.trigger('focus'); | |
searchInput.attr('value',''); | |
searchInput.trigger('blur'); | |
expect(targetElement.is('.active')).toBe(false); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This module will apply and remove a class to an element when specified actions are performed. | |
Default behaviour: | |
- module checks for .js-toggle-action before proceeding, this element will trigger the class toggle | |
- if .js-toggle-action receives a focus, active class is added to container | |
- if .js-toggle-action receives a blur, active class is removed from container | |
Options: | |
- an element of class '.js-toggle-target' will receive the toggle class, defaults to container | |
- data-toggle-on-action specifies the event that will add the class, e.g. 'keydown', 'mouseenter' | |
- data-toggle-off-action specifies the event that will remove the class, e.g. 'keyup', 'mouseleave' | |
- data-toggle-class specifies the class name to toggle, defaults to 'active' | |
- data-toggle-onload specifies an optional function to run when the page loads | |
- data-toggle-onexit specifies an optional function to use when the toggle off is triggered | |
*/ | |
(function (Modules) { | |
'use strict' | |
Modules.ToggleClass = function () { | |
this.start = function ($el) { | |
var self = this; | |
var $toggleElement = $el.find('.js-toggle-action'); | |
if($toggleElement.length) { | |
var $toggleClassOnElement = $el.find('.js-toggle-target'); | |
$toggleClassOnElement = $toggleClassOnElement.length > 0 ? $toggleClassOnElement : $el; | |
var userActionIn = $el.attr('data-toggle-on-action') || 'focus'; | |
var userActionOut = $el.attr('data-toggle-off-action') || 'blur'; | |
var focusClass = $el.attr('data-toggle-class') || 'active'; | |
//check if we should run a function when the page loads | |
var onloadFunction = $el.attr('data-toggle-onload') || 0; | |
if (onloadFunction && typeof this[onloadFunction] === "function") { | |
this[onloadFunction]($toggleClassOnElement,$toggleElement,focusClass); | |
} | |
// check if we should use a function other than the default for removing the class | |
var onExitFunction = $el.attr('data-toggle-onexit') || 0; | |
if (onExitFunction && typeof this[onExitFunction] === "function") { | |
this.onExitFunction = this[onExitFunction]; | |
} | |
$toggleElement.on(userActionIn, function() { | |
$toggleClassOnElement.addClass(focusClass); | |
}); | |
$toggleElement.on(userActionOut, function(e) { | |
self.onExitFunction(e, $toggleClassOnElement, focusClass); | |
}); | |
} | |
} | |
// default function for removing class | |
this.onExitFunction = function (e, $toggleClassOnElement, focusClass) { | |
$toggleClassOnElement.removeClass(focusClass); | |
} | |
// used by search boxes, only removes class if search input has no value | |
this.checkValueAndRemoveClassFromElement = function (e, $toggleClassOnElement, focusClass) { | |
if ($(e.target).val() === '') { | |
$toggleClassOnElement.removeClass(focusClass); | |
} | |
} | |
// used by search boxes to hide label if page loads with search already in search box, e.g. on search results page | |
this.onloadCheckInputValue = function (toggleClassOnElement, $toggleElement, focusClass) { | |
if (toggleClassOnElement.val() !== '') { | |
$toggleElement.addClass(focusClass); | |
} | |
} | |
} | |
})(window.GOVUK.Modules) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment