fix(ui): Change angular material to fix issues with Safari iOS 18+

This commit is contained in:
smizrahi
2025-04-15 19:00:33 +02:00
parent 0fadd4cb72
commit 07c75280bb
9 changed files with 49687 additions and 93 deletions

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "UI/WebServerResources/angular-material"] [submodule "UI/WebServerResources/angular-material"]
path = UI/WebServerResources/angular-material path = UI/WebServerResources/angular-material
url = https://github.com/angular/material url = https://github.com/Alinto/material.git

View File

@@ -0,0 +1,182 @@
/**
* AngularJS-Material-Mocks
*
* Developers interested in running their own custom unit tests WITH angular-material.js loaded...
* must also include this *mocks* file. Similar to `angular-mocks.js`, `angular-material-mocks.js`
* will override and disable specific AngularJS Material performance settings:
*
* - Disabled Theme CSS rule generations
* - Forces $mdAria.expectWithText() to be synchronous
* - Mocks $$rAF.throttle()
* - Captures flush exceptions from $$rAF
*/
// eslint-disable-next-line no-shadow-restricted-names
(function(window, angular, undefined) {
'use strict';
// Allow our code to know when they are running inside of a test so they can expose extra services
// that should NOT be exposed to the public but that should be tested.
//
// As an example, see input.js which exposes some animation-related methods.
window._mdMocksIncluded = true;
/**
* @ngdoc module
* @name ngMaterial-mock
* @packageName angular-material-mocks
*
* @description
* The `ngMaterial-mock` module provides support
*/
angular.module('ngMaterial-mock', ['ngMock', 'ngAnimateMock', 'material.core']).config([
'$provide',
function($provide) {
$provide.factory('$material', [
'$animate', '$timeout',
function($animate, $timeout) {
return {
flushOutstandingAnimations: function() {
// this code is placed in a try-catch statement
// since 1.3 and 1.4 handle their animations differently
// and there may be situations where follow-up animations
// are run in one version and not the other
try {
$animate.flush();
// eslint-disable-next-line no-empty
} catch (e) {}
},
flushInterimElement: function() {
this.flushOutstandingAnimations();
$timeout.flush();
this.flushOutstandingAnimations();
$timeout.flush();
this.flushOutstandingAnimations();
$timeout.flush();
}
};
}
]);
/**
* AngularJS Material dynamically generates Style tags
* based on themes and palettes; for each ng-app.
*
* For testing, we want to disable generation and
* <style> DOM injections. So we clear the huge THEME
* styles while testing...
*/
$provide.constant('$MD_THEME_CSS', '/**/');
/**
* Add throttle() and wrap .flush() to catch `no callbacks present`
* errors
*/
$provide.decorator('$$rAF', function throttleInjector($delegate) {
$delegate.throttle = function(cb) {
return function() {
cb.apply(this, arguments);
};
};
const ngFlush = $delegate.flush;
$delegate.flush = function() {
try {
ngFlush();
// eslint-disable-next-line no-empty
} catch (e) {}
};
return $delegate;
});
/**
* Capture $timeout.flush() errors: "No deferred tasks to be flushed"
* errors
*/
$provide.decorator('$timeout', function throttleInjector($delegate) {
const ngFlush = $delegate.flush;
$delegate.flush = function() {
const args = Array.prototype.slice.call(arguments);
try {
ngFlush.apply($delegate, args);
// eslint-disable-next-line no-empty
} catch (e) {}
};
return $delegate;
});
}
]);
/**
* Stylesheet Mocks used by `animateCss.spec.js`
*/
window.createMockStyleSheet = function createMockStyleSheet(doc, wind) {
doc = doc ? doc[0] : window.document;
wind = wind || window;
const node = doc.createElement('style');
const head = doc.getElementsByTagName('head')[0];
head.appendChild(node);
const ss = doc.styleSheets[doc.styleSheets.length - 1];
return {
addRule: function(selector, styles) {
styles = addVendorPrefix(styles);
try {
ss.insertRule(selector + '{ ' + styles + '}', 0);
} catch (e) {
try {
ss.addRule(selector, styles);
// eslint-disable-next-line no-empty
} catch (e2) {}
}
},
destroy: function() {
head.removeChild(node);
}
};
/**
* Decompose styles, attached specific vendor prefixes
* and recompose...
* e.g.
* 'transition:0.5s linear all; font-size:100px;'
* becomes
* '-webkit-transition:0.5s linear all; transition:0.5s linear all; font-size:100px;'
*/
function addVendorPrefix(styles) {
const cache = {};
// Decompose into cache registry
styles.match(/([-A-Za-z]*)\w:\w*([A-Za-z0-9.\-\s]*)/gi).forEach(function(style) {
const pair = style.split(':');
const key = pair[0];
switch (key) {
case 'transition':
case 'transform':
case 'animation':
case 'transition-duration':
case 'animation-duration':
cache[key] = cache['-webkit-' + key] = pair[1];
break;
default:
cache[key] = pair[1];
}
});
// Recompose full style object (as string)
styles = '';
angular.forEach(cache, function(value, key) {
styles = styles + key + ':' + value + '; ';
});
return styles;
}
};
})(window, window.angular);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1055,7 +1055,7 @@ var nextUniqueId = 0, isIos, isAndroid, isFirefox;
// Support material-tools builds. // Support material-tools builds.
if (window.navigator) { if (window.navigator) {
var userAgent = window.navigator.userAgent || window.navigator.vendor || window.opera; var userAgent = window.navigator.userAgent || window.navigator.vendor || window.opera;
isIos = userAgent.match(/ipad|iphone|ipod/i); isIos = false;//userAgent.match(/ipad|iphone|ipod/i);
isAndroid = userAgent.match(/android/i); isAndroid = userAgent.match(/android/i);
isFirefox = userAgent.match(/(firefox|minefield)/i); isFirefox = userAgent.match(/(firefox|minefield)/i);
} }
@@ -6135,95 +6135,95 @@ function InterimElementProvider() {
(function(){ (function(){
"use strict"; "use strict";
/** /**
* @ngdoc module * @ngdoc module
* @name material.core.liveannouncer * @name material.core.liveannouncer
* @description * @description
* AngularJS Material Live Announcer to provide accessibility for Voice Readers. * AngularJS Material Live Announcer to provide accessibility for Voice Readers.
*/ */
MdLiveAnnouncer.$inject = ["$timeout"]; MdLiveAnnouncer.$inject = ["$timeout"];
angular angular
.module('material.core') .module('material.core')
.service('$mdLiveAnnouncer', MdLiveAnnouncer); .service('$mdLiveAnnouncer', MdLiveAnnouncer);
/** /**
* @ngdoc service * @ngdoc service
* @name $mdLiveAnnouncer * @name $mdLiveAnnouncer
* @module material.core.liveannouncer * @module material.core.liveannouncer
* *
* @description * @description
* *
* Service to announce messages to supported screenreaders. * Service to announce messages to supported screenreaders.
* *
* > The `$mdLiveAnnouncer` service is internally used for components to provide proper accessibility. * > The `$mdLiveAnnouncer` service is internally used for components to provide proper accessibility.
* *
* <hljs lang="js"> * <hljs lang="js">
* module.controller('AppCtrl', function($mdLiveAnnouncer) { * module.controller('AppCtrl', function($mdLiveAnnouncer) {
* // Basic announcement (Polite Mode) * // Basic announcement (Polite Mode)
* $mdLiveAnnouncer.announce('Hey Google'); * $mdLiveAnnouncer.announce('Hey Google');
* *
* // Custom announcement (Assertive Mode) * // Custom announcement (Assertive Mode)
* $mdLiveAnnouncer.announce('Hey Google', 'assertive'); * $mdLiveAnnouncer.announce('Hey Google', 'assertive');
* }); * });
* </hljs> * </hljs>
* *
*/ */
function MdLiveAnnouncer($timeout) { function MdLiveAnnouncer($timeout) {
/** @private @const @type {!angular.$timeout} */ /** @private @const @type {!angular.$timeout} */
this._$timeout = $timeout; this._$timeout = $timeout;
/** @private @const @type {!HTMLElement} */ /** @private @const @type {!HTMLElement} */
this._liveElement = this._createLiveElement(); this._liveElement = this._createLiveElement();
/** @private @const @type {!number} */ /** @private @const @type {!number} */
this._announceTimeout = 100; this._announceTimeout = 100;
} }
/** /**
* @ngdoc method * @ngdoc method
* @name $mdLiveAnnouncer#announce * @name $mdLiveAnnouncer#announce
* @description Announces messages to supported screenreaders. * @description Announces messages to supported screenreaders.
* @param {string} message Message to be announced to the screenreader * @param {string} message Message to be announced to the screenreader
* @param {'off'|'polite'|'assertive'} politeness The politeness of the announcer element. * @param {'off'|'polite'|'assertive'} politeness The politeness of the announcer element.
*/ */
MdLiveAnnouncer.prototype.announce = function(message, politeness) { MdLiveAnnouncer.prototype.announce = function(message, politeness) {
if (!politeness) { if (!politeness) {
politeness = 'polite'; politeness = 'polite';
} }
var self = this; var self = this;
self._liveElement.textContent = ''; self._liveElement.textContent = '';
self._liveElement.setAttribute('aria-live', politeness); self._liveElement.setAttribute('aria-live', politeness);
// This 100ms timeout is necessary for some browser + screen-reader combinations: // This 100ms timeout is necessary for some browser + screen-reader combinations:
// - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout. // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
// - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
// second time without clearing and then using a non-zero delay. // second time without clearing and then using a non-zero delay.
// (using JAWS 17 at time of this writing). // (using JAWS 17 at time of this writing).
self._$timeout(function() { self._$timeout(function() {
self._liveElement.textContent = message; self._liveElement.textContent = message;
}, self._announceTimeout, false); }, self._announceTimeout, false);
}; };
/** /**
* Creates a live announcer element, which listens for DOM changes and announces them * Creates a live announcer element, which listens for DOM changes and announces them
* to the screenreaders. * to the screenreaders.
* @returns {!HTMLElement} * @returns {!HTMLElement}
* @private * @private
*/ */
MdLiveAnnouncer.prototype._createLiveElement = function() { MdLiveAnnouncer.prototype._createLiveElement = function() {
var liveEl = document.createElement('div'); var liveEl = document.createElement('div');
liveEl.classList.add('md-visually-hidden'); liveEl.classList.add('md-visually-hidden');
liveEl.setAttribute('role', 'status'); liveEl.setAttribute('role', 'status');
liveEl.setAttribute('aria-atomic', 'true'); liveEl.setAttribute('aria-atomic', 'true');
liveEl.setAttribute('aria-live', 'polite'); liveEl.setAttribute('aria-live', 'polite');
document.body.appendChild(liveEl); document.body.appendChild(liveEl);
return liveEl; return liveEl;
}; };
})(); })();
(function(){ (function(){
@@ -17364,7 +17364,7 @@ angular.module('material.components.datepicker', [
var CALENDAR_PANE_WIDTH = 360; var CALENDAR_PANE_WIDTH = 360;
/** Used for checking whether the current user agent is on iOS or Android. */ /** Used for checking whether the current user agent is on iOS or Android. */
var IS_MOBILE_REGEX = /ipad|iphone|ipod|android/i; var IS_MOBILE_REGEX = false;///ipad|iphone|ipod|android/i;
/** /**
* Controller for md-datepicker. * Controller for md-datepicker.

View File

@@ -8,7 +8,7 @@
"angular-aria": "^1.8.0", "angular-aria": "^1.8.0",
"angular-cookies": "^1.8.0", "angular-cookies": "^1.8.0",
"angular-file-upload": "^2.6.1", "angular-file-upload": "^2.6.1",
"angular-material": "1.2.4", "angular-material": "file:./js/vendor/angular-material-dist",
"angular-messages": "^1.8.0", "angular-messages": "^1.8.0",
"angular-sanitize": "^1.8.0", "angular-sanitize": "^1.8.0",
"angular-ui-router": "^1.0.29", "angular-ui-router": "^1.0.29",