For the latest travel advice from the Foreign & Commonwealth Office, please visit: www.gov.uk/foreign-travel-advice.

 

document.head.appendChild(style) } function isValidDate(dateString) { const date = new Date(dateString) return !isNaN(date.getTime()) } // Function to create and populate the table function createRoyalTable(jsonData) { const table = document.createElement('table') table.classList.add('royal-table') // Get headers dynamically from the first item in the JSON data const headers = Object.keys(jsonData[0]) // Create table header const headerRow = document.createElement('tr') headerRow.classList.add('royal-table__row') headers.forEach(headerText => { const th = document.createElement('th') th.classList.add('royal-table__column') const headerTitle = document.createElement('h2') headerTitle.textContent = headerText th.appendChild(headerTitle) headerRow.appendChild(th) }) table.appendChild(headerRow) // Create table rows from JSON data jsonData.forEach(rowData => { const row = document.createElement('tr') row.classList.add('royal-table__row') headers.forEach(header => { const cell = document.createElement('td') cell.classList.add('royal-table__column') const cellContent = document.createElement('h3') // Check if the value contains a tag if (rowData[header].includes('')) { cellContent.innerHTML = rowData[header] } else if (typeof rowData[header] === 'string' && rowData[header].includes('http')) { const link = document.createElement('a') link.href = rowData[header] link.textContent = 'View Itinerary Update' cellContent.appendChild(link) } else { if (isValidDate(rowData[header])) { cellContent.innerHTML = rowData[header].split('/').join('/') } else { cellContent.innerHTML = rowData[header].split(' ').join(' ') } } cell.appendChild(cellContent) row.appendChild(cell) }) table.appendChild(row) }) return table } // ******************** MAIN CODE ******************************** function main() { logger.log('main') injectCss2Head(table_styles) lookForDomElement(`#${html_container_id}.royal-table-wrapper`) .then(html_container => { logger.log('royal-table-wrapper has been found successfully') // Append the dynamically created table to the wrapper element html_container.appendChild(createRoyalTable(json_table_data)) }) .catch(error => { // Handle error when element is not found within the timeout logger.error(error.message) }) } // ******************** CODE UTILITIES ******************************* /* * createCustomLogger returns an object, referred to as a custom logger, * that functions similarly to the console object but provides additional * methods to enable or disable log messages. * * By default, the custom logger is disabled. It can be enabled by pressing * the 'L' key within the first 3 seconds of the page load. * * Note: * - The `logger_name` is always displayed in the console to indicate that * the custom logger object has been created. * - The `msg()` method allows printing log messages regardless of whether * logging is enabled or disabled. */ function createCustomLogger() { const logger_name = '>>>' + custom_snippet_codename // Initial message to indicate logger has been initialized console.info(logger_name) // Store the original console methods const originalLog = console.log const originalError = console.error const originalWarn = console.warn const originalInfo = console.info // Private variable to keep track of logging state let enabled = false // Listen for 'keydown' L window.addEventListener('keydown', checkLogKey, { once: true }) var log_timeout_id = setTimeout(() => { window.removeEventListener('keydown', checkLogKey) }, 3000) function checkLogKey(event) { if (event.key === 'L' || event.key === 'l') { enabled = true console.info(logger_name, '☆') clearTimeout(log_timeout_id) } } // Return the logger object with msg, log, error, warn, and info methods return { // Log a message even when logging is enabled msg: function (...args) { args.unshift(logger_name) originalInfo.apply(console, args) }, // Log a message regardless enable value log: function (...args) { args.unshift(logger_name) if (enabled) originalLog.apply(console, args) }, // Log an error message if logging is enabled error: function (...args) { args.unshift(logger_name) if (enabled) originalError.apply(console, args) }, // Log a warning message if logging is enabled warn: function (...args) { args.unshift(logger_name) if (enabled) originalWarn.apply(console, args) }, // Log an info message if logging is enabled info: function (...args) { args.unshift(logger_name) if (enabled) originalInfo.apply(console, args) }, // Enable logging enable: function () { enabled = true }, // Disable logging disable: function () { enabled = false }, } } // *** lookForDomElement Promise *** // function lookForDomElement(selector, timeout = 15000) { return new Promise((resolve, reject) => { const element = document.querySelector(selector) if (element) resolve(element) //check if element already exists in the DOM //If element doesn't exist in the DOM an observer will be created to check if it is added later (during timeout) const observer = new MutationObserver((mutations, observer) => { const element = document.querySelector(selector) if (element) { observer.disconnect() } }) observer.observe(document.body, { childList: true, subtree: true }) setTimeout(() => { observer.disconnect() reject(new Error('Element with selector ' + selector + ' not found within ' + timeout + 'ms')) }, timeout) }) } // *** lookForFunctionDefinition Promise *** // const lookForFunctionDefinition = (funcName, timeout = 15000) => { return new Promise((resolve, reject) => { let intervalId // Interval to check if the function is defined intervalId = setInterval(() => { if (typeof window[funcName] === 'function') { clearInterval(intervalId) // Clear the interval resolve(funcName + ' is defined within ' + timeout + 'ms') } }, 500) // Check every 0.5 second // Timeout to stop checking after the specified time setTimeout(() => { clearInterval(intervalId) // Clear the interval if (typeof window[funcName] !== 'function') { reject(new Error(funcName + ' was not defined within ' + timeout + 'ms')) } }, timeout) }) } // *** lookForVariableDefinition Promise *** // function lookForVariableDefinition(variableName, timeout = 1000) { return new Promise((resolve, reject) => { let intervalId // Interval to check if the variable is defined intervalId = setInterval(() => { if (typeof window[variableName] !== 'undefined') { clearInterval(intervalId) resolve(variableName + 'is defined within ' + timeout + 'ms') } }, 1000) // Timeout to stop checking after the specified time setTimeout(() => { clearInterval(intervalId) if (typeof window[variableName] === 'undefined') { reject(new Error(variableName + ' was not defined within ' + timeout + 'ms')) } }, timeout) }) } })()

There are currently no travel updates.

This page is updated to provide guests with information when a situation develops. Please know that the safety and comfort of our guests are always our highest priority and we are committed to keeping you informed. For the latest information on itinerary changes and weather-related updates, please check back here. We will also contact you or your Travel Advisors as soon as possible, should your itinerary be impacted.





Questions or concerns? Contact Us with your questions.
 
 
Follow us for the latest alerts
Like us on FacebookFollow us on TwitterRead more on our SeaViews BlogLike us on FacebookFollow us on TwitterRead more on our SeaViews BlogLike us on FacebookFollow us on TwitterRead more on our SeaViews Blog

 

Previewing: Promo Dashboard Campaigns

My Personas

code: