|
|
|
@ -44,109 +44,107 @@ import { performAnchorHijacking } from './global-listeners/link-hijacking'; |
|
|
|
|
/** |
|
|
|
|
* A set of listeners that are relevant on every page to set sensible defaults |
|
|
|
|
*/ |
|
|
|
|
(function ($:JQueryStatic) { |
|
|
|
|
$(() => { |
|
|
|
|
$(document.documentElement) |
|
|
|
|
.on('click', (evt:any) => { |
|
|
|
|
const target = jQuery(evt.target) as JQuery; |
|
|
|
|
|
|
|
|
|
// Create datepickers dynamically for Rails-based views
|
|
|
|
|
augmentedDatePicker(evt, target); |
|
|
|
|
|
|
|
|
|
// Prevent angular handling clicks on href="#..." links from other libraries
|
|
|
|
|
// (especially jquery-ui and its datepicker) from routing to <base url>/#
|
|
|
|
|
performAnchorHijacking(evt, target); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Jump to the element given by location.hash, if present
|
|
|
|
|
const { hash } = window.location; |
|
|
|
|
if (hash && hash.startsWith('#')) { |
|
|
|
|
try { |
|
|
|
|
const el = document.querySelector(hash); |
|
|
|
|
el && el.scrollIntoView(); |
|
|
|
|
} catch (e) { |
|
|
|
|
// This is very likely an invalid selector such as a Google Analytics tag.
|
|
|
|
|
// We can safely ignore this and just not scroll in this case.
|
|
|
|
|
// Still log the error so one can confirm the reason there is no scrolling.
|
|
|
|
|
console.log(`Could not scroll to given location hash: ${hash} ( ${e.message})`); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
export function initializeGlobalListeners():void { |
|
|
|
|
jQuery(document.documentElement) |
|
|
|
|
.on('click', (evt:any) => { |
|
|
|
|
const target = jQuery(evt.target) as JQuery; |
|
|
|
|
|
|
|
|
|
// Global submitting hook,
|
|
|
|
|
// necessary to avoid a data loss warning on beforeunload
|
|
|
|
|
$(document).on('submit', 'form', () => { |
|
|
|
|
window.OpenProject.pageIsSubmitted = true; |
|
|
|
|
}); |
|
|
|
|
// Create datepickers dynamically for Rails-based views
|
|
|
|
|
augmentedDatePicker(evt, target); |
|
|
|
|
|
|
|
|
|
// Add to content if warnings displayed
|
|
|
|
|
if (document.querySelector('.warning-bar--item')) { |
|
|
|
|
const content = document.querySelector('#content') as HTMLElement; |
|
|
|
|
if (content) { |
|
|
|
|
content.style.marginBottom = '100px'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Prevent angular handling clicks on href="#..." links from other libraries
|
|
|
|
|
// (especially jquery-ui and its datepicker) from routing to <base url>/#
|
|
|
|
|
performAnchorHijacking(evt, target); |
|
|
|
|
|
|
|
|
|
// Global beforeunload hook
|
|
|
|
|
$(window).on('beforeunload', (e:JQuery.TriggeredEvent) => { |
|
|
|
|
const event = e.originalEvent as BeforeUnloadEvent; |
|
|
|
|
if (window.OpenProject.pageWasEdited && !window.OpenProject.pageIsSubmitted) { |
|
|
|
|
// Cancel the event
|
|
|
|
|
event.preventDefault(); |
|
|
|
|
// Chrome requires returnValue to be set
|
|
|
|
|
event.returnValue = I18n.t('js.work_packages.confirm_edit_cancel'); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Disable global drag & drop handling, which results in the browser loading the image and losing the page
|
|
|
|
|
$(document.documentElement) |
|
|
|
|
.on('dragover drop', (evt:any) => { |
|
|
|
|
evt.preventDefault(); |
|
|
|
|
return false; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
refreshOnFormChanges(); |
|
|
|
|
// Jump to the element given by location.hash, if present
|
|
|
|
|
const { hash } = window.location; |
|
|
|
|
if (hash && hash.startsWith('#')) { |
|
|
|
|
try { |
|
|
|
|
const el = document.querySelector(hash); |
|
|
|
|
el && el.scrollIntoView(); |
|
|
|
|
} catch (e) { |
|
|
|
|
// This is very likely an invalid selector such as a Google Analytics tag.
|
|
|
|
|
// We can safely ignore this and just not scroll in this case.
|
|
|
|
|
// Still log the error so one can confirm the reason there is no scrolling.
|
|
|
|
|
console.log(`Could not scroll to given location hash: ${hash} ( ${e.message})`); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Allow forms with [request-for-confirmation]
|
|
|
|
|
// to show the password confirmation dialog
|
|
|
|
|
registerRequestForConfirmation($); |
|
|
|
|
// Global submitting hook,
|
|
|
|
|
// necessary to avoid a data loss warning on beforeunload
|
|
|
|
|
jQuery(document).on('submit', 'form', () => { |
|
|
|
|
window.OpenProject.pageIsSubmitted = true; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const deviceService:DeviceService = new DeviceService(); |
|
|
|
|
// Register scroll handler on mobile header
|
|
|
|
|
if (deviceService.isMobile) { |
|
|
|
|
scrollHeaderOnMobile(); |
|
|
|
|
// Add to content if warnings displayed
|
|
|
|
|
if (document.querySelector('.warning-bar--item')) { |
|
|
|
|
const content = document.querySelector('#content') as HTMLElement; |
|
|
|
|
if (content) { |
|
|
|
|
content.style.marginBottom = '100px'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Global beforeunload hook
|
|
|
|
|
jQuery(window).on('beforeunload', (e:JQuery.TriggeredEvent) => { |
|
|
|
|
const event = e.originalEvent as BeforeUnloadEvent; |
|
|
|
|
if (window.OpenProject.pageWasEdited && !window.OpenProject.pageIsSubmitted) { |
|
|
|
|
// Cancel the event
|
|
|
|
|
event.preventDefault(); |
|
|
|
|
// Chrome requires returnValue to be set
|
|
|
|
|
event.returnValue = I18n.t('js.work_packages.confirm_edit_cancel'); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Detect and trigger the onboarding tour
|
|
|
|
|
// through a lazy loaded script
|
|
|
|
|
detectOnboardingTour(); |
|
|
|
|
// Disable global drag & drop handling, which results in the browser loading the image and losing the page
|
|
|
|
|
jQuery(document.documentElement) |
|
|
|
|
.on('dragover drop', (evt:any) => { |
|
|
|
|
evt.preventDefault(); |
|
|
|
|
return false; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Legacy scripts from app/assets that are not yet component based
|
|
|
|
|
//
|
|
|
|
|
refreshOnFormChanges(); |
|
|
|
|
|
|
|
|
|
// Toggable fieldsets
|
|
|
|
|
setupToggableFieldsets(); |
|
|
|
|
// Allow forms with [request-for-confirmation]
|
|
|
|
|
// to show the password confirmation dialog
|
|
|
|
|
registerRequestForConfirmation(jQuery); |
|
|
|
|
|
|
|
|
|
// Top menu click handling
|
|
|
|
|
new TopMenu(jQuery('.op-app-header')); |
|
|
|
|
const deviceService:DeviceService = new DeviceService(); |
|
|
|
|
// Register scroll handler on mobile header
|
|
|
|
|
if (deviceService.isMobile) { |
|
|
|
|
scrollHeaderOnMobile(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Action menu logic
|
|
|
|
|
jQuery('.project-actions, .toolbar-items').each((idx:number, menu:HTMLElement) => { |
|
|
|
|
installMenuLogic(jQuery(menu)); |
|
|
|
|
}); |
|
|
|
|
// Detect and trigger the onboarding tour
|
|
|
|
|
// through a lazy loaded script
|
|
|
|
|
detectOnboardingTour(); |
|
|
|
|
|
|
|
|
|
// Legacy settings listener
|
|
|
|
|
listenToSettingChanges(); |
|
|
|
|
//
|
|
|
|
|
// Legacy scripts from app/assets that are not yet component based
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// Color patches preview the color
|
|
|
|
|
makeColorPreviews(); |
|
|
|
|
// Toggable fieldsets
|
|
|
|
|
setupToggableFieldsets(); |
|
|
|
|
|
|
|
|
|
// Danger zone input validation
|
|
|
|
|
dangerZoneValidation(); |
|
|
|
|
// Top menu click handling
|
|
|
|
|
new TopMenu(jQuery('.op-app-header')); |
|
|
|
|
|
|
|
|
|
// Bootstrap legacy app code
|
|
|
|
|
setupServerResponse(); |
|
|
|
|
// Action menu logic
|
|
|
|
|
jQuery('.project-actions, .toolbar-items').each((idx:number, menu:HTMLElement) => { |
|
|
|
|
installMenuLogic(jQuery(menu)); |
|
|
|
|
}); |
|
|
|
|
}(jQuery)); |
|
|
|
|
|
|
|
|
|
// Legacy settings listener
|
|
|
|
|
listenToSettingChanges(); |
|
|
|
|
|
|
|
|
|
// Color patches preview the color
|
|
|
|
|
makeColorPreviews(); |
|
|
|
|
|
|
|
|
|
// Danger zone input validation
|
|
|
|
|
dangerZoneValidation(); |
|
|
|
|
|
|
|
|
|
// Bootstrap legacy app code
|
|
|
|
|
setupServerResponse(); |
|
|
|
|
} |
|
|
|
|