in kitsune/sumo/static/sumo/js/showfor.js [412:530]
ShowFor.prototype.matchesCriteria = function (criteria) {
/* The basic logic for showfor is that there are two kinds of
* things: platforms and products. If one or more platforms are
* in the criteria, at least one has to match. If one or more
* products are in the criteria, at least one has to match.
*
* To be succinct, this has to be true for a set of criteria to match:
*
* (any(browsers) or browsers.length == 0) and
* (any(platforms) or platforms.length == 0)
*
* Versions are seen as more specific products. Platforms don't
* have versions.
*/
var hasProduct = false;
var matchProduct = false;
var hasPlatform = false;
var matchPlatform = false;
/* This cheats a bit. Platforms are presented as being tied to a
* platform, but we ignore that. Just assume that all selected
* platforms apply to all products. */
var enabledPlatforms = [];
for (var slug in this.state) {
var prod = this.state[slug];
if (prod.enabled && prod.platform) {
enabledPlatforms.push(prod.platform);
}
}
/* This will loop through every item in criteria. It will set the
* has/matches variables above to true if at least one
* product/platform is found, and at least one of those matches
* respectively. */
criteria.forEach(function (name) {
var productSlug, elemVersion;
// Does this start with "not" ? Set a flag.
var not = (name.indexOf('not') === 0);
if (not) {
name = name.replace(/^not ?/, '');
}
// "fx" -> "firefox", etc.
name = this.productShortMap[name] || name;
// Check for exact-equals. Maybe this will get smarter later.
var oper = '>=';
if (name[0] === '=') {
name = name.slice(1);
oper = '=';
}
/* Not that the below things never set anything false, only to
* true. This way they work like a big OR. */
// Is this a product? (without a version) {for fx}
if (this.productSlugs.indexOf(name) >= 0) {
hasProduct = true;
if (this.state[name].enabled !== not) {
matchProduct = true;
}
// Is this a product+version? {for fx27}
} else if (this.versionSlugs[name] !== undefined) {
/* elemVersion is the version indicated in the element being
* shown/hidden. stateMin and stateMax are the min and max
* versions from this.state, which reflects the UI. */
productSlug = this.versionSlugs[name];
hasProduct = true;
elemVersion = parseFloat(/^[a-z]+([\d\.]+)$/.exec(name)[1]);
// name = 'fx27' -> productSlug = 'fx', elemVersion = 27
var stateMin = this.state[productSlug].version.min;
var stateMax = this.state[productSlug].version.max;
var enabled = this.state[productSlug].enabled;
var rightVersion = ((oper === '>=' && elemVersion < stateMax) ||
(oper === '=' && elemVersion >= stateMin && elemVersion < stateMax));
if ((enabled && rightVersion) !== not) {
matchProduct = true;
}
// Is it a platform?
} else if (this.platformSlugs.indexOf(name) >= 0) {
hasPlatform = true;
if ((enabledPlatforms.indexOf(name) >= 0) !== not) {
matchPlatform = true;
}
// Special case for windows.
} else if (name === 'win') {
hasPlatform = true;
/* Loop through each of the possible slugs for windows. If
* any of them match, then this name matches. */
var windowsTypes = ['winxp', 'win7', 'win8', 'win10', 'win11'];
var winMatches = false;
windowsTypes.forEach(function (fakeName) {
if (enabledPlatforms.indexOf(fakeName) >= 0) {
winMatches = true;
}
});
if (winMatches !== not) {
matchPlatform = true;
}
}
}.bind(this));
// If a platform matches, or no platform matchers exist AND
// if a product matches, or no product matchers exist.
return (!hasProduct || matchProduct) && (!hasPlatform || matchPlatform);
};