@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
151 lines (121 loc) • 4.65 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
/**
* Defines support rules of the Image control of sap.m library.
*/
sap.ui.define(["sap/ui/support/library"],
function(SupportLib) {
"use strict";
// shortcuts
var Categories = SupportLib.Categories, // Accessibility, Performance, Memory, ...
Severity = SupportLib.Severity, // Low, Medium, High
Audiences = SupportLib.Audiences; // Control, Internal, Application
//**********************************************************
// Utils
//**********************************************************
var HIGH_DENSITIES = [1.5, 2], // these are the densities mostly expected to be supported by the app (3x and 4x will be skipped to avoid too many requests that prolong the check)
REQUEST_TIMEOUT = 3000; //ms
function downloadHighDensityImage(oImage, iDensity) {
return new Promise(function(resolve, reject) {
var sSrc = oImage.getSrc(),
sDensityAwareSrc = oImage._generateSrcByDensity(sSrc, iDensity),
oDomElement = document.createElement("IMG"),
bDone = false;
// check src availability using src property of a dummy dom element
// to avoid making AJAX request (may be forbidden if conflicts with CORS)
oDomElement.setAttribute("src", sDensityAwareSrc);
oDomElement.style.position = "absolute";
oDomElement.style.left = "-10000px";
oDomElement.style.top = "-10000px";
function onLoad() {
cleanup();
resolve(true);
}
function onError() {
cleanup();
resolve(false);
}
function cleanup() {
if (oDomElement && oDomElement.parentNode !== null) { // allow this element and its attached listeners be picked up by the GC
oDomElement.parentNode.removeChild(oDomElement);
}
bDone = true;
}
oDomElement.addEventListener("load", onLoad);
oDomElement.addEventListener("error", onError);
document.body.appendChild(oDomElement);
// ensure check is completed even if none of the events are called
// (e.g. iOS may not fire load for an already loaded and cached image)
setTimeout(function() {
if (!bDone) {
reject(); // densityAwareSrc availability is not confirmed
}
}, REQUEST_TIMEOUT);
});
}
//**********************************************************
// Rule Definitions
//**********************************************************
/**
* Checks if the <code>densityAware</code> property of <code>sap.m.Image</code> is enabled when density-perfect image version exists
*/
var oImageRule = {
id : "densityAwareImage",
audiences: [Audiences.Control],
categories: [Categories.Usability],
enabled: true,
async: true,
minversion: "1.60",
title: "Image: Density awareness disabled",
description: "We checked that your application provides high-density version(s) of the listed image(s). "
+ "However, the high-density version(s) will be ignored, because the \"densityAware\" property of this image is disabled. "
+ "Since UI5 1.60, the \"densityAware\" property is no longer enabled by default. You need to enable it explicitly.",
resolution: "Enable the \"densityAware\" property of this image control",
resolutionurls: [{
text: "API Refrence for sap.m.Image",
href: "https://sdk.openui5.org/api/sap.m.Image"
}],
check: function (oIssueManager, oCoreFacade, oScope, fnResolve) {
var aAsyncTasks = [],
aIssuedImageIds = [],
oTask,
sImageId,
sImageName;
oScope.getElementsByClassName("sap.m.Image")
.forEach(function(oImage) {
if (!oImage.getDensityAware()) {
HIGH_DENSITIES.forEach(function(iDensity) {
oTask = downloadHighDensityImage(oImage, iDensity);
aAsyncTasks.push(oTask);
oTask.then(function(bSuccess) {
if (!bSuccess) {
return;
}
sImageId = oImage.getId();
if (aIssuedImageIds.indexOf(sImageId) > -1) {
return; // already issued warning for this image
}
aIssuedImageIds.push(sImageId);
sImageName = oImage.getMetadata().getElementName();
oIssueManager.addIssue({
severity: Severity.Low,
details: "Image '" + sImageName + "' (" + sImageId + ") has 'densityAware' disabled even though high-density version is also available",
context: {
id: sImageId
}
});
})
.catch(function() {
// ignore as only the cases of successful executions are of interest to this rule
});
});
}
});
Promise.all(aAsyncTasks).then(fnResolve);
}
};
return [oImageRule];
}, true);