[AMD] Auto Expand Option(s)

Automatically opens the first option.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         [AMD] Auto Expand Option(s)
// @description  Automatically opens the first option.
// @author       Magic of Lolis <[email protected]>
// @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;
}
...`
*/