Greasy Fork is available in English.

[AMD] Auto Expand Option(s)

Automatically opens the first option.

// ==UserScript==
// @name         [AMD] Auto Expand Option(s)
// @description  Automatically opens the first option.
// @author       Magic of Lolis <magicoflolis@tuta.io>
// @icon         https://www.amd.com/themes/custom/amd/favicon.ico
// @version      1.0.5
// @supportURL   https://github.com/magicoflolis/userscriptrepo/issues/new
// @namespace    https://github.com/magicoflolis/userscriptrepo/tree/master/AMDAutoOpen#amd-auto-expand
// @homepageURL  https://github.com/magicoflolis/userscriptrepo/tree/master/AMDAutoOpen#amd-auto-expand
// @match        https://www.amd.com/*/support/*
// @grant        navigator.userAgent
// @compatible   chrome
// @compatible   firefox
// @compatible   edge
// @compatible   opera
// @run-at       document-end
// @noframes
// ==/UserScript==

'use strict';
(() => {
  //#region Config
  /** Choice Options:
   * @param {string} choice - first | all | none | windows or Windows 11 - 64-Bit Edition...etc */
  let choice = 'first';
  /** Enable/disable Reduce Clutter:
   * @param {boolean} reduce_clutter - Removes some clutter */
  let reduce_clutter = true;
  /** Auto Scroll Amount:
   * @param {number} scroll_amount - Set to 0 disables auto scroll AND 'Top' button */
  let scroll_amount = 110;
  /** Top Button CSS:
   * @param {string} css - You can customize the look here */
  let css = `.aeo-top-btn {
  bottom: 1rem;
  right: 1rem;
  color: #000;
  border: 2px solid #000;
  font-size: 14px;
  font-weight: bold;
  width: auto;
  min-height: 5px;
  margin: 0 3px;
  padding: 10px 15px;
  cursor: pointer;
  text-transform: uppercase;
  text-align: center;
  white-space: normal;
  position:fixed;
}
.os-group summary .summary {
  margin-left: .5em;
}
/** Removes more clutter */
[id="colorbox"],
[id="cboxOverlay"],
.PPLightBox {
  display: none !important;
  z-index: -1 !important;
  visibility: hidden !important;
}`;
  //#endregion

  const err = (...msg) =>
    console.error(
      '[%cAMD%c] %cERROR',
      'color: rgb(237, 28, 36);',
      '',
      'color: rgb(249, 24, 128);',
      ...msg
    );
  // const log = (...msg) =>
  //   console.log(
  //     '[%cAMD%c] %cDBG',
  //     'color: rgb(237, 28, 36);',
  //     '',
  //     'color: rgb(255, 212, 0);',
  //     ...msg
  //   );
  // const info = (...msg) => console.info('[%cAMD%c] %cINF', 'color: rgb(237, 28, 36);', '', 'color: rgb(0, 186, 124);', ...msg);

  /**
   * Object is Null
   * @param {Object} obj - Object
   * @returns {boolean} Returns if statement true or false
   */
  const isNull = (obj) => {
    return Object.is(obj, null) || Object.is(obj, undefined);
  };
  /**
   * Object is Blank
   * @param {(Object|Object[]|string)} obj - Array, Set, Object or String
   * @returns {boolean} Returns if statement true or false
   */
  const isBlank = (obj) => {
    return (
      (typeof obj === 'string' && Object.is(obj.trim(), '')) ||
      (obj instanceof Set && Object.is(obj.size, 0)) ||
      (Array.isArray(obj) && Object.is(obj.length, 0)) ||
      (obj instanceof Object &&
        typeof obj.entries !== 'function' &&
        Object.is(Object.keys(obj).length, 0))
    );
  };
  /**
   * Object is Empty
   * @param {(Object|Object[]|string)} obj - Array, object or string
   * @returns {boolean} Returns if statement true or false
   */
  const isEmpty = (obj) => {
    return isNull(obj) || isBlank(obj);
  };
  /**
   * Add Event Listener
   * @param {Object} root - Selected Element
   * @param {string} type - root Event Listener
   * @param {Function} callback - Callback function
   * @param {Object} [options={}] - (Optional) Options
   * @returns {Object} Returns selected Element
   */
  const ael = (root, type, callback, options = {}) => {
    try {
      root = root || document || document.documentElement;
      if (/Mobi/.test(navigator.userAgent) && type === 'click') {
        type = 'mouseup';
        root.addEventListener('touchstart', callback);
        root.addEventListener('touchend', callback);
      }
      if (type === 'fclick') {
        type = 'click';
      }
      return root.addEventListener(type, callback, options);
    } catch (ex) {
      return err(ex);
    }
  };
  /**
   * Form Attributes of Element
   * @param {Object} elt - Element
   * @param {string} cname - (Optional) Element class name
   * @param {Object} [attrs={}] - (Optional) Element attributes
   * @returns {Object} Returns created Element
   */
  const formAttrs = (el, cname, attrs = {}) => {
    try {
      if (!isEmpty(cname)) {
        el.className = cname;
      }
      if (!isEmpty(attrs)) {
        for (const key in attrs) {
          if (key === 'dataset') {
            for (const key2 in attrs[key]) {
              el[key][key2] = attrs[key][key2];
            }
          } else if (key === 'click') {
            ael(el, 'click', attrs[key]);
          } else if (key === 'container') {
            if (typeof key === 'function') {
              key();
            }
          } else {
            el[key] = attrs[key];
          }
        }
      }
      return el;
    } catch (ex) {
      err(ex);
      return el;
    }
  };
  const make = (element, cname, attrs = {}) => {
    let el;
    try {
      el = document.createElement(element);
      return formAttrs(el, cname, attrs);
    } catch (ex) {
      err(ex);
      return el;
    }
  };
  const loadCSS = (css, name = 'common') => {
    const s = make('style', `aeo-${name}`, {
      innerHTML: css,
    });
    return !document.head.contains(s) ? document.head.appendChild(s) : false;
  };
  /**
   * Prefix for document.querySelector()
   * @param {Object} element - Element for query selection
   * @param {Object} [root=document] - Root selector Element
   * @returns {Object} Returns root.querySelector(element)
   */
  const qs = (element, root) => {
    root = root ?? document ?? document.body;
    return root.querySelector(element);
  };
  /**
   * Prefix for document.querySelectorAll()
   * @param {Object} element - Elements for query selection
   * @param {Object} [root=document] - Root selector Element
   * @returns {Object} Returns root.querySelectorAll(element)
   */
  const qsA = (element, root) => {
    root = root ?? document ?? document.body;
    return root.querySelectorAll(element);
  };
  /**
   * Prefix for document.querySelector() w/ Promise
   * @param {Object} element - Element for query selection
   * @param {Object} [root=document] - Root selector Element
   * @returns {Object} Returns root.querySelector(element)
   */
  const query = async (element, root) => {
    root = root ?? document ?? document.body;
    while (root.querySelector(element) === null) {
      await new Promise((resolve) => requestAnimationFrame(resolve));
    }
    return root.querySelector(element);
  };
  const top_btn = make('input', 'aeo-top-btn', {
    value: 'Top',
    type: 'button',
    onclick: () => {
      return window.scroll(0, scroll_amount);
    },
  });
  const initScript = async () => {
    try {
      loadCSS(css);
      if (scroll_amount > 0) {
        document.body.append(top_btn);
        window.scroll(0, scroll_amount);
        window.onscroll = () => {
          document.documentElement.scrollTop > scroll_amount
            ? top_btn.setAttribute('style', 'display: inline-block !important')
            : top_btn.setAttribute('style', 'display: none !important');
        };
      }
      if (reduce_clutter) {
        if (qs('[id="scrollspy"]')) {
          qs('[id="scrollspy"]').setAttribute(
            'style',
            'padding: 0px !important'
          );
        }
        const ads = [
          qs('.panel'),
          qs('[role="banner"]'),
          qs('[role="contentinfo"]'),
        ];
        for (const ad of ads) {
          if (isEmpty(ad)) continue;
          ad.remove();
        }
      }
      if (!isEmpty(choice) && !choice.match(/none/gi)) {
        if (choice === 'first') {
          qs('details.os-group').setAttribute('open', '');
        } else {
          for (const details of qsA('details.os-group')) {
            if (choice === 'all') {
              details.setAttribute('open', '');
            } else {
              const re = new RegExp(`${choice}+`, 'gi');
              const txt = details.children[0].textContent;
              if (!isEmpty(txt)) {
                const find = txt.match(re) ?? [];
                if (!isEmpty(find)) {
                  details.setAttribute('open', '');
                }
              }
            }
          }
        }
      }
      await query('details.os-group .os-row a');
      await query('details.os-group summary .summary');
      for (const details of qsA('details.os-group')) {
        const summary = qs('summary > span.summary', details);
        // for(const driver of qsA('.driver .field--type-uri > a[href]', details)) { };
        const driver = qs('.driver-metadata a', details);
        summary.textContent = driver.href;
        summary.onclick = (e) => {
          e.preventDefault();
          const dlBtn = make('a', 'amd_Downloader');
          dlBtn.href = driver.href;
          dlBtn.click();
          dlBtn.remove();
        };
      }
    } catch (ex) {
      err(ex);
    }
  };
  initScript();
})();
/**
* Defaults:
*
* choice = 'first'
* reduce_clutter = true
* scroll_amount = 110
* css = `.aeo-top-btn {
  bottom: 1rem;
  right: 1rem;
  color: #000;
  border: 2px solid #000;
  font-size: 14px;
  font-weight: bold;
  width: auto;
  min-height: 5px;
  margin: 0 3px;
  padding: 10px 15px;
  cursor: pointer;
  text-transform: uppercase;
  text-align: center;
  white-space: normal;
  position:fixed;
}
...`
*/