'use strict'
/**
* Window size global handler.
* @namespace size
* @memberof UCASDesignFramework
*/
UCASDesignFramework.size = {
initOnLoad: true,
resizeTimeout: 0,
scrollTimeout: 0,
clientWidth: 0,
dfResize: {},
position: null,
positionLocked: false,
/**
* Get breakpoint, based on pixels.
* @deprecated
* @type {string}
* @memberof! UCASDesignFramework.size
* @public
*/
get breakpoint () {
return this.currentBreakpoint(document.body.clientWidth);
},
/**
* Get cssBreakpoint, based on em.
* @type {string}
* @memberof! UCASDesignFramework.size
* @public
*/
get cssBreakpoint () {
return window.getComputedStyle(document.querySelector('body'), ':before').getPropertyValue('content').replace(/\"/g, '');
},
/**
* Initialise plugin.
* @function init
* @memberof! UCASDesignFramework.size
* @public
*/
init: function () {
document.body.setAttribute('data-breakpoint', this.cssBreakpoint)
var event = document.createEvent('Event')
// @event dfpAdvertResize
event.initEvent('dfpAdvertResize', true, true)
window.addEventListener('resize', function () {
// If the screen has switched to a new breakpoint and we have ad placements
// refresh the adverts by dispatching advertResize event.
if (document.body.getAttribute('data-breakpoint') !== UCASDesignFramework.size.cssBreakpoint) {
var placements = document.querySelectorAll('[data-google-slot-id]')
if (placements.length > 0) {
document.dispatchEvent(event)
}
}
document.body.setAttribute('data-breakpoint', UCASDesignFramework.size.cssBreakpoint)
}, false)
// Add the custom resize event.
UCASDesignFramework.size.clientWidth = document.body.clientWidth
UCASDesignFramework.size.dfResize = document.createEvent('Event')
UCASDesignFramework.size.dfResize.initEvent('dfResize', true, true)
window.addEventListener('resize', UCASDesignFramework.size.resizeThrottler, false)
// Add a throttled scroll event.
UCASDesignFramework.size.dfScroll = document.createEvent('Event')
UCASDesignFramework.size.dfScroll.initEvent('dfScroll', true, true)
window.addEventListener('scroll', UCASDesignFramework.size.scrollThrottler, false)
},
breakpoints: { small: 720, medium: 992, large: 1200 },
/**
* Calculate current breakpoint, based on pixel width.
* @function currentBreakpoint
* @memberof! UCASDesignFramework.size
* @public
* @deprecated
* @param {number} width - browser width in pixels
* @return {string} - the keyword for the breakpoint
*/
currentBreakpoint: function (width) {
var breakpoints = UCASDesignFramework.size.breakpoints
if (width < breakpoints.small) {
return 'small'
}
if (width > breakpoints.large) {
return 'xlarge'
}
if (width > breakpoints.small && width < breakpoints.medium) {
return 'medium'
}
return 'large'
},
/**
* Calculate if a breakpoint, based on pixel width, is greater than the
* current browser width.
* @function greaterThan
* @memberof! UCASDesignFramework.size
* @public
* @deprecated
* @param {String} width - a breakpoint keyword
* @return {Boolean} - true if the breakpoint is greater than the current browser width
*/
greaterThan: function (width) {
return document.body.clientWidth > UCASDesignFramework.size.breakpoints[width]
},
/**
* Slow down the resize handler so we don't repaint too much.
* Triggers a custom event which can be used instead of window.resize.
* @function resizeThrottler
* @memberof! UCASDesignFramework.size
* @public
*/
resizeThrottler: function () {
if (!UCASDesignFramework.size.resizeTimeout) {
UCASDesignFramework.size.resizeTimeout = setTimeout(function () {
UCASDesignFramework.size.resizeTimeout = null
// Check width as triggering the keyboard on Android changes page size.
// We're only interested if the width changes.
if (UCASDesignFramework.size.clientWidth !== document.body.clientWidth) {
UCASDesignFramework.size.clientWidth = document.body.clientWidth
window.dispatchEvent(UCASDesignFramework.size.dfResize)
}
}, 100)
}
},
/**
* Slow down the scroll handler so we don't repaint too much.
* Triggers a custom event which can be used instead of window.scroll.
* @function scrollThrottler
* @memberof! UCASDesignFramework.size
* @public
*/
scrollThrottler: function () {
if (!UCASDesignFramework.size.scrollTimeout) {
UCASDesignFramework.size.scrollTimeout = setTimeout(function () {
UCASDesignFramework.size.scrollTimeout = null
window.dispatchEvent(UCASDesignFramework.size.dfScroll)
}, 100)
}
},
/**
* Resize a text input field by setting the size attribute
* to the length of the value.
* @function resizeTextFieldToFitContent
* @memberof! UCASDesignFramework.size
* @public
* @param {Node} field - an input field
* @param {Number} [max=50] - the maximum size
*/
resizeTextFieldToFitContent: function (field, max) {
max = max || 50
if (field.nodeName === 'INPUT' && field.value.length) {
var length = field.value.length > 50 ? 50 : field.value.length
var size = Math.ceil(length * 0.95) // This is a best guess at not allowing too big a size.
field.setAttribute('size', size)
}
},
/**
* Resize an element by setting its width to that of its inner text plus any extra that might be needed.
* @function resizeElementToContentWidth
* @memberof! UCASDesignFramework.size
* @public
* @param {Node} element - an element
* @param {Number} padding - any extra padding to be added to the width
*/
resizeElementToContentWidth: function (element, padding) {
var textElement = element
// Assign a specific textElement as required by the element type.
if (element.nodeName === 'SELECT') {
textElement = element[element.selectedIndex]
}
// Work out the padding if it's not set.
if (padding === undefined) {
padding = parseFloat(getComputedStyle(element).paddingLeft) + parseFloat(getComputedStyle(element).paddingRight)
padding += parseFloat(getComputedStyle(element).borderLeftWidth) + parseFloat(getComputedStyle(element).borderRightWidth)
if (element !== textElement) {
padding += parseFloat(getComputedStyle(textElement).paddingLeft) + parseFloat(getComputedStyle(textElement).paddingRight)
padding += parseFloat(getComputedStyle(textElement).borderLeftWidth) + parseFloat(getComputedStyle(textElement).borderRightWidth)
}
}
if (textElement.innerText) {
element.style.width = UCASDesignFramework.size.getWidthOfText(textElement) + padding + 'px'
} else {
console.warn('Element type ' + element.nodeName + ' is not currently supported by resizeElementToContentWidth(). Please raise a ticket.')
}
},
/**
* Work out the width of some text in pixels
* by recreating it in a temporary span.
* @function getWidthOfText
* @memberof! UCASDesignFramework.size
* @public
* @param {Node} element - an element that contains text
* @return {Number} width in px
*/
getWidthOfText: function (element) {
var text = element.innerText
var span = document.createElement('span')
var width
span.innerText = text
// Make sure we have all the right styles on the text.
span.style.fontFamily = getComputedStyle(element).fontFamily
span.style.fontSize = getComputedStyle(element).fontSize
span.style.fontWeight = getComputedStyle(element).fontWeight
span.style.zIndex = -1
span.style.position = 'absolute'
document.body.appendChild(span)
width = span.offsetWidth
document.body.removeChild(span)
return width
},
/**
* Lock the page position.
* @function lockPosition
* @public
* @param {Boolean} hide - hide the main content.
*/
lockPosition: function (hide) {
if (!this.positionLocked) {
UCASDesignFramework.size.position = window.pageYOffset
var wrapper = document.documentElement
wrapper.style.top = -UCASDesignFramework.size.position + 'px'
wrapper.style.overflow = 'hidden'
// We lock position when we display something on top of the main content, such as a modal.
// To cope with the HTML not being in the correct order for z-index, we set the z-index
// of the header to something low.
var header = document.getElementById('section--upper-header')
header.style.zIndex = '0'
if (hide) {
var mainContent = document.getElementById('wrapper')
if (mainContent) {
mainContent.style.opacity = '0'
}
}
this.positionLocked = true
}
},
/**
* Unlock the page position.
* @function unlockPosition
* @public
*/
unlockPosition: function () {
if (this.positionLocked) {
var mainContent = document.getElementById('wrapper')
if (mainContent) {
mainContent.style.opacity = ''
}
// Reset the z-index of the header.
var header = document.getElementById('section--upper-header')
header.style.zIndex = ''
var wrapper = document.documentElement
wrapper.style.top = null
wrapper.style.overflow = null
window.scrollTo(0, UCASDesignFramework.size.position)
this.positionLocked = false
}
},
// Add possible subscriptions to the DF bus.
addSubscriptions: true
}