Online IDE DDS Create

shortcuts to create DDS library component HTML

สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @require https://update.greasyfork.org/scripts/454586/1182771/Online%20IDE%20DDS%20Create.js

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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!)

let createdListeners = [];
const create = {
  actionMenu: (options = {}) => {
    const classAm = options.class || ``;
    const trigger = options.trigger || {};
    const dataAlignment = options[`data-alignment`] || `start`;
    if (!options.trigger) {
      options.trigger = {};
    }
    if (!options.trigger.class) {
      options.trigger.class = `dds__button--secondary`;
    }
    if (!options.trigger.text) {
      options.trigger.text = `Actions`;
    }
    const id = options.id || `actionMenu${create.random()}`;
    const useChevron = options.useChevron || false;

    const noo = {};
    noo.actionMenu = create.element(`div`, {
      id: id,
      class: `dds__action-menu ${classAm}`,
      'data-trigger': `#${id}--trigger`,
      'data-dds': `action-menu`,
      'data-alignment': dataAlignment,
    });
    noo.trigger = create.element(`button`, {
      id: noo.actionMenu.getAttribute(`data-trigger`).replace(`#`, ''),
      type: `button`,
      class: `dds__button ${trigger.class}`,
    });
    noo.trigger.appendChild(create.element(`span`, {
      class: `ddsc__action-menu__trigger-label`,
      text: trigger.text
    }));
    if (useChevron) {
      const handleActionClick = (e) => {
        e.target.querySelector(`.dds__icon`).classList.toggle(`action-rotated`);
      }
      noo.chevron = create.element(`i`, {
        class: `dds__icon dds__icon--chevron-down action-chevron`,
      });
      noo.trigger.appendChild(noo.chevron);
      create.listener(`#${id}`, `ddsActionMenuOpenEvent`, handleActionClick);
      create.listener(`#${id}`, `ddsActionMenuCloseEvent`, handleActionClick);
    }
    noo.container = create.element(`div`, {
      class: `dds__action-menu__container`,
      tabindex: `-1`,
      role: `presentation`,
      'aria-hidden': `true`,
    });
    noo.menu = create.element(`div`, {
      class: `dds__action-menu__menu`,
      role: `menu`,
      tabindex: `-1`,
    });
    noo.menuLi = create.element(`li`, {
      role: `presentation`,
    });
    noo.group = create.element(`span`, {
      id: `${id}--group`
    });
    noo.groupUl = create.element(`ul`, {
      id: `${id}--groupUl`,
      class: `ddsc__action-menu--groupUl`,
      role: `group`,
      'aria-labelledby': noo.group.getAttribute(`id`)
    });
    noo.actionMenu.appendChild(noo.trigger);
    noo.actionMenu.appendChild(noo.container);
    noo.container.appendChild(noo.menu);
    noo.menu.appendChild(noo.menuLi);
    noo.menuLi.appendChild(noo.group);
    noo.group.appendChild(noo.groupUl);
    // Adding a method to the element doesn't seem to be work
    // const observerDefs = [
    //     {
    //       selector: `#${id}`,
    //       callback: (elem) => {
    //         elem.addItem = (itemOptions) => {
    //             document.getElementById(`${id}--groupUl`).appendChild(create.actionMenuItem(itemOptions));
    //         };
    //       }
    //     }
    //   ];
    // createObserver(observerDefs);
    return noo.actionMenu;
  },
  actionMenuItem: (options = {}) => {
    const noo = {};
    const label = options.text || `Item Text`;
    const asOption = options[`data-value`] != null || false;
    const dataValue = options[`data-value`] || undefined;
    const itemClass = options.class || ``;
    const id = `${label.replace(/[^0-9a-zA-Z]+/, ``)}_${create.random()}`;
    noo.item = create.element(`li`, {
      class: asOption ? `dds__action-menu__option` : `dds__action-menu__item`,
      role: `none`,
    });
    noo.itemButton = create.element(`button`, {
      id: id,
      type: `button`,
      class: itemClass,
      role: asOption ? `menuitemcheckbox` : `menuitem`,
      tabindex: `-1`,
      'aria-disabled': `false`,
      'aria-checked': `false`,
      'data-value': dataValue,
    });
    noo.itemSvg = create.element(`svg`, {
      class: `dds__action-menu__icon`,
      'aria-hidden': `true`,
    });
    noo.itemSvgUse = create.element(`use`, {
      'xlink:href': `#dds__icon--copy-alt`,
    });
    noo.itemText = create.element(`span`, {
      class: `ddsc__action-menu__span`,
      text: label,
    });
    noo.item.appendChild(noo.itemButton);
    noo.itemButton.appendChild(noo.itemSvg);
    noo.itemButton.appendChild(noo.itemText);
    noo.itemSvg.appendChild(noo.itemSvgUse);
    if (options.onclick) {
      create.listener(`#${id}`, `click`, options.onclick);
    }
    return noo.item;
  },
  button: (options = {}) => {
    const noo = {};
    const id = options.id || `button_${create.random()}`;
    const chevron = options.chevron || {};
    const bClass = options.class || ``;
    const bText = options.text || `Button`;
    const iconIsString = options.icon && typeof options.icon === `string`;
    const iconObjectName = !iconIsString && options.icon ? options.icon.name : undefined;
    const iconObjectClass = !iconIsString && options.icon && options.icon.class ? options.icon.class : ``;
    const bIcon = {
      name: iconIsString ? options.icon : iconObjectName,
      class: iconObjectClass
    };
    noo.button = create.element(`button`, {
      id: id,
      class: `dds__button ${bClass}`,
      type: `button`,
      text: bText,
    });
    if (bIcon.name) {
      noo.icon = create.element(`i`, {
        class: `dds__icon dds__icon--${bIcon.name} ${bIcon.class}`,
        'aria-hidden': `true`,
      });
      if (options.icon.class.indexOf(`--end`) > -1) {
        noo.button.appendChild(noo.icon);
      } else {
        noo.button.prepend(noo.icon);
      }
    }
    if (options.onclick) {
      create.listener(`#${id}`, `click`, options.onclick);
    }
    if (chevron.use) {
      const handleActionClick = (e) => {
        document.getElementById(id).querySelector(`.dds__icon`).classList.toggle(`action-rotated`);
      }
      noo.chevron = create.element(`i`, {
        class: `dds__icon dds__icon--chevron-down action-chevron`,
      });
      noo.button.appendChild(noo.chevron);
      create.listener(chevron.open.selector, chevron.open.event, handleActionClick);
      create.listener(chevron.close.selector, chevron.close.event, handleActionClick);
    }
    return noo.button;
  },
  badge: (options = {}) => {
    const noo = {};
    const id = options.id || `badge_${create.random()}`;
    const label = options.label || ``;
    const componentClass = options.class || ``;

    noo.component = create.element(`span`, {
      id: id,
      class: `dds__badge ${componentClass}`,
    });
    noo.label = create.element(`span`, {
      class: `dds__badge__label`,
      text: label,
    });

    noo.component.appendChild(noo.label);
    return noo.component;
  },
  element: (nodeType, props) => {
    const domNode = document.createElement(nodeType);
    if (props && "object" === typeof props) {
      for (const prop in props) {
        if (prop === "html") {
          domNode.innerHTML = props[prop];
        } else if (prop === "text") {
          domNode.textContent = props[prop];
        } else {
          if (prop.slice(0, 5) === "aria_" || prop.slice(0, 4) === "data_") {
            const attr = prop.slice(0, 4) + "-" + prop.slice(5);
            domNode.setAttribute(attr, props[prop]);
          } else {
            domNode.setAttribute(prop, props[prop]);
          }
        }
        // Set attributes on the element if passed
        if (["role", "aria-label"].includes(prop)) domNode.setAttribute(prop, props[prop]);
      }
    }
    return domNode;
  },
  checkbox: (options = {}) => {
    const noo = {};
    const id = options.id || `checkbox_${create.random()}`;
    const label = options.label || ``;
    const componentClass = options.class || ``;
    const getCheckboxEl = () => {
      const thisCheckbox = document.getElementById(noo.input.id);
      if (!thisCheckbox) {
        console.error(`Element #${noo.input.id} was not found`);
        return;
      }
      return thisCheckbox;
    }

    // create new components
    noo.component = create.element(`div`, {
      id: id,
      class: `dds__checkxbox ${componentClass}`,
    });
    noo.label = create.element(`label`, {
      id: `${id}--label`,
      class: `dds__checkbox__label`,
      for: `${id}--input`,
    });
    noo.input = create.element(`input`, {
      type: `checkbox`,
      tabindex: `0`,
      id: `${id}--input`,
      name: `${id}--name`,
      class: `dds__checkbox__input`,
    });
    if (options.value) noo.input.value = options.value;
    if (options.checked) noo.input.setAttribute(`checked`, options.checked);
    if (options.required) noo.input.setAttribute(`required`, true);
    noo.content = create.element(`span`, {
      id: `${id}--content`,
      html: label,
    });
    noo.error = create.element(`div`, {
      id: `${id}--error`,
      class: `dds__invalid-feedback`,
      text: options.error,
    });

    // append new elements together
    noo.component.appendChild(noo.label);
    noo.component.appendChild(noo.error);
    noo.label.appendChild(noo.input);
    noo.label.appendChild(noo.content);

    // add methods
    noo.component.indeterminate = (state) => {
      // must return to verify this method
      if (!state) {
        console.error(`indeterminate: must pass state`);
        return;
      }
      const thisCheckbox = getCheckboxEl();
      thisCheckbox.indeterminate = state;
      thisCheckbox.setAttribute(`aria-checked`, state ? `mixed` : `false`);
    };
    noo.component.check = (state = true) => {
      const thisCheckbox = getCheckboxEl();
      thisCheckbox.checked = state;
      thisCheckbox.setAttribute(`aria-checked`, state);
    };
    if (options.onclick) {
      create.listener(`#${noo.input.id}`, `change`, options.onclick);
    }


    // return base component
    return noo.component;
  },
  dropdown: (options = {}) => {
    const noo = {};
    const id = options.id || `dropdown_${create.random()}`;
    const componentClass = options.class || ``;
    const selection = options.selection || `single`;
    const dropdownLabel = options.label || ``;
    const selectAllLabel = options.selectAllLabel || `Select All`;
    const autocomplete = options.autocomplete ? 'on' : `off`;

    noo.component = create.element(`div`, {
      id: id,
      class: `dds__dropdown ${componentClass}`,
      'data-dds': `dropdown`,
      'data-selection': selection,
      'data-select-all-label': selectAllLabel,
    });
    noo.container = create.element(`div`, {
      class: `dds__dropdown__input-container`,
    });
    noo.label = create.element(`label`, {
      id: `${id}--label`,
      for: `${id}--input`,
      html: dropdownLabel,
    });
    noo.wrapper = create.element(`div`, {
      class: `dds__dropdown__input-wrapper`,
      role: `combobox`,
      'aria-haspopup': `listbox`,
      'aria-controls': `${id}--popup`,
      'aria-expanded': false,
    });
    noo.input = create.element(`input`, {
      id: `${id}--input`,
      name: `${id}--name`,
      type: `text`,
      class: `dds__dropdown__input-field`,
      autocomplete: autocomplete,
      'aria-labelledby': `${id}--label ${id}--helper`,
      'aria-expanded': false,
      'aria-controls': `${id}--list`,
      placeholder: options.placeholder || ``,
    });
    noo.feedback = create.element(`i`, {
      class: `dds__icon dds__icon--alert-notice dds__dropdown__feedback__icon`,
      'aria-hidden': true,
    });
    noo.helper = create.element(`small`, {
      id: `${id}--helper`,
      class: `dds__input-text__helper ${!options.helper ? `dds__d-none` : ``}`,
      text: options.helper,
    });
    noo.error = create.element(`div`, {
      id: `${id}--error`,
      class: `dds__invalid-feedback ${!options.error ? `dds__d-none` : ``}`,
      text: options.error,
    });
    noo.popup = create.element(`div`, {
      id: `${id}--popup`,
      class: `dds__dropdown__popup dds__dropdown__popup--hidden`,
      role: `presentation`,
      tabindex: `-1`,
    });
    noo.list = create.element(`ul`, {
      id: `${id}--list`,
      tabindex: `-1`,
      role: `listbox`,
      class: `dds__dropdown__list`,
    });

    noo.component.appendChild(noo.container);
    noo.container.appendChild(noo.label);
    noo.component.appendChild(noo.wrapper);
    noo.wrapper.appendChild(noo.input);
    noo.wrapper.appendChild(noo.feedback);
    noo.wrapper.appendChild(noo.helper);
    noo.wrapper.appendChild(noo.error);
    noo.component.appendChild(noo.popup);
    noo.popup.appendChild(noo.list);
    return noo.component;
  },
  dropdownItem: (options = {}) => {
    const noo = {};
    const label = options.text || `Item Text`;
    const dataValue = options[`data-value`] || undefined;
    const id = options.id || `${label.replace(/[^0-9a-zA-Z]+/, ``)}_${create.random()}`;
    const isSelected = options.selected == `true` ? true : false;
    noo.item = create.element(`li`, {
      class: `dds__dropdown__item`,
      role: `option`,
    });
    noo.itemButton = create.element(`button`, {
      id: id,
      type: `button`,
      class: `dds__dropdown__item-option`,
      role: `option`,
      tabindex: `-1`,
      'data-selected': isSelected,
    });
    if (dataValue) {
      noo.itemButton.setAttribute('data-value', dataValue);
    }
    noo.itemText = create.element(`span`, {
      class: `dds__dropdown__item-label`,
      text: label,
    });
    noo.item.appendChild(noo.itemButton);
    noo.itemButton.appendChild(noo.itemText);
    if (options.onclick) {
      create.listener(`#${id}`, `click`, options.onclick);
    }
    return noo.item;
  },
  listener: function (selector, event, handler) {
    let rootElement = document.querySelector('body');
    const listenerId = `${selector}__${event}`;
    const listenerExists = createdListeners.includes(listenerId);
    const listenerInstance = function (evt) {
      var targetElement = evt.target;
      while (targetElement != null) {
        if (targetElement.matches(selector)) {
          handler(evt);
          return;
        }
        targetElement = targetElement.parentElement;
      }
    };
    if (!listenerExists) {
      createdListeners.push(listenerId);
      rootElement.addEventListener(event, listenerInstance, true);
    }
  },
  popover: (options = {}) => {
    const noo = {};
    const id = options.id || `popover_${create.random()}`;
    const dataTrigger = options['data-trigger'] || undefined;
    const dataPlacement = options['data-placement'] || `bottom-end`;
    const classPo = options.class || ``;
    const callback = options.callback || undefined;
    const arrow = options.arrow === undefined ? true : options.arrow;
    const close = options.close === undefined ? true : options.close;
    if (!dataTrigger) {
      console.error(`Send a data-trigger with a value like "#your-element-id"`);
      return;
    }
    if (!arrow) {
      // if (dataPlacement.indexOf(`bottom`) > -1) {
      //     create.style(`#${id} { top: -12px;}`);
      // } else if (dataPlacement.indexOf(`top`) > -1) {
      //     create.style(`#${id} { top: 12px;}`);
      // } else if (dataPlacement.indexOf(`left`) > -1) {
      //     create.style(`#${id} { left: 12px;}`);
      // } else if (dataPlacement.indexOf(`right`) > -1) {
      //     create.style(`#${id} { left: -12px;}`);
      // }
      create.style(`#${id} .dds__popover__pointer { display: none !important;}`);
    }
    if (!close) {
      create.style(`#${id} .dds__popover__close { display: none !important;}`);
    }
    if (!options.title) {
      create.style(`#${id} .dds__popover__header { display: none !important;}`);
    }
    noo.popover = create.element(`div`, {
      id: id,
      class: `dds__popover ${classPo}`,
      role: `dialog`,
      'aria-labelledby': `${id}--title`,
      'data-placement': dataPlacement,
      'data-dds': `popover`,
      'data-trigger': dataTrigger,
    });
    noo.content = create.element(`div`, {
      class: `dds__popover__content`,
    });
    noo.header = create.element(`div`, {
      class: `dds__popover__header`,
    });
    noo.headline = create.element(`h6`, {
      id: `${id}--title`,
      class: `dds__popover__headline`,
      text: options.title,
    });
    noo.body = create.element(`div`, {
      class: `dds__popover__body`,
      text: options.body,
    });
    if (callback) {
      callback(noo.body);
    }
    noo.popover.appendChild(noo.content);
    noo.content.appendChild(noo.header);
    noo.content.appendChild(noo.body);
    noo.header.appendChild(noo.headline);
    return noo.popover;
  },
  radioButton: (options = {}) => {
    const noo = {};
    const id = options.id || `radiobutton_${create.random()}`;
    const componentClass = options.class || ``;
    const legend = options.legend || ``;
    noo.radioset = create.element(`fieldset`, {
      class: `dds__fieldset dds__radio-button-group ${componentClass}`,
      role: `radiogroup`,
    });
    if (options.required) {
      noo.radioset.setAttribute(`required`, true);
      noo.radioset.setAttribute(`aria-required`, true);
    }
    noo.legend = create.element(`legend`, {
      text: legend,
    })
    if (legend) noo.radioset.appendChild(noo.legend);
    options.buttons.forEach((radio, rIndex) => {
      const radioClass = radio.class || ``;
      const radioValue = radio.value || ``;
      const radioLabel = radio.label || ``;
      noo.button = create.element(`div`, {
        class: `dds__radio-button ${radioClass}`,
      });
      noo.input = create.element(`input`, {
        class: `dds__radio-button__input`,
        type: `radio`,
        name: `${id}--button-name`,
        id: `${id}--button${rIndex}`,
        value: radioValue,
      });
      noo.label = create.element(`label`, {
        class: `dds__radio-button__label`,
        id: `${id}--button-label${rIndex}`,
        for: `${id}--button${rIndex}`,
        text: radioLabel,
      });
      noo.button.appendChild(noo.input);
      noo.button.appendChild(noo.label);
      noo.radioset.appendChild(noo.button);
    });
    noo.error = create.element(`div`, {
      id: `${id}--error`,
      class: `dds__invalid-feedback`,
      text: options.error || ``,
    });
    noo.radioset.appendChild(noo.error);
    return noo.radioset;
  },
  random: (min = 100000000, max = 999999999) => {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min) + min);
  },
  style: (styles) => {
    /* Create style document */
    var css = document.createElement('style');
    css.type = 'text/css';
    if (css.styleSheet)
      css.styleSheet.cssText = styles;
    else
      css.appendChild(document.createTextNode(styles));
    /* Append style to the tag name */
    document.getElementsByTagName("head")[0].appendChild(css);
  },
  tag: (options = {}) => {
    const noo = {};
    const id = options.id || `textinput_${create.random()}`;
    const componentClass = options.class || ``;
    const dismiss = options.dismiss == `true` || `false`;

    noo.tag = create.element(`div`, {
      id: id,
      class: `dds__tag ${componentClass}`,
      'data-dds': `tag`,
      'data-dismiss': options.dismiss || false,
      'data-sr-dismiss': options.dismiss ? `dismiss` : ``,
    });
    noo.button = create.element(`button`, {
      type: `button`,
      text: options.label || `Tag`,
    });
    noo.tag.appendChild(noo.button);
    if (options.onclick) {
      create.listener(`#${id}`, `click`, options.onclick);
    }
    return noo.tag;
  },
  textInput: (options = {}) => {
    const noo = {};
    const id = options.id || `textinput_${create.random()}`;
    const componentClass = options.class || ``;
    const icon = options.icon || ``;
    const iconStart = options.iconStart || true;
    noo.container = create.element(`div`, {
      id: id,
      class: `dds__input-text__container ${componentClass}`,
    });
    noo.label = create.element(`label`, {
      id: `${id}--label`,
      for: `${id}--input`,
      text: options.label,
    });
    noo.wrapper = create.element(`div`, {
      class: `dds__input-text__wrapper`,
    });
    noo.input = create.element(`input`, {
      id: `${id}--input`,
      type: `text`,
      class: `dds__input-text ${icon ? iconStart ? `dds__has__icon--start` : ` dds__has__icon--end` : ``}`,
      name: `${id}--input`,
      placeholder: options.placeholder || ``,
      'aria-labelledby': `${id}--label ${id}--helper`,
    });
    if (options.required) {
      noo.input.setAttribute(`required`, true);
    }
    if (options[`max-length`]) {
      noo.input.setAttribute(`max-length`, options[`max-length`]);
    }
    noo.icon = create.element(`i`, {
      class: `dds__icon dds__icon--${icon || `search`} dds__input-text__icon--${iconStart ? `start` : `end`}`,
      'aria-hidden': true,
    });
    noo.helper = create.element(`small`, {
      id: `${id}--helper`,
      class: `dds__input-text__helper ${!options.helper ? `dds__d-none` : ``}`,
      text: options.helper,
    });
    noo.error = create.element(`div`, {
      id: `${id}--error`,
      class: `dds__invalid-feedback ${!options.error ? `dds__d-none` : ``}`,
      text: options.error,
    });
    if (!options.helper) {
      create.style(`#${id} { margin-top: -12px; margin-bottom: 9px;}`);
    }
    noo.container.appendChild(noo.label);
    noo.container.appendChild(noo.wrapper);
    noo.wrapper.appendChild(noo.input);
    if (icon) noo.wrapper.appendChild(noo.icon);
    noo.wrapper.appendChild(noo.helper);
    noo.wrapper.appendChild(noo.error);
    return noo.container;
  },
  tooltip: (options = {}) => {
    const noo = {};
    const id = options.id || `tooltip_${create.random()}`;
    const componentClass = options.class || ``;
    const icon = options.icon ? `dds__icon--${options.icon.replace('dds__icon--', '')}` : `dds__icon--alert-info-cir`;
    const title = options.title || ``;
    const tip = options.tip || `No options.tip was found.`;

    noo.container = create.element(`span`, {});  
    noo.anchor = create.element(`a`, {
        id: `anchor-${id}`,
        href: `javascript:void(0);`,
        class: `dds__link--standalone ${componentClass}`,
        'aria-describedby': `tooltip-${id}`,
    });
    noo.anchorSr = create.element(`span`, {
        id: `anchorSr-${id}`,
        class: `dds__sr-only`,
        text: `tooltip`,
    });
    noo.anchorIcon = create.element(`i`, {
        id: `anchorIcon-${id}`,
        class: `dds__icon ${icon}`,
    });
    noo.tooltip = create.element(`div`, {
      id: id,
      class: `dds__tooltip`,
      role: `tooltip`,
      'data-dds': `tooltip`,
      'data-trigger': `#anchor-${id}`,
    });
    noo.body = create.element(`div`, {
      class: `dds__tooltip__body`,
      text: tip
    });
    noo.bodyTitle = create.element(`h6`, {
        class: `dds__tooltip__title`,
        text: title,
    });
    
    noo.container.appendChild(noo.anchor);
    noo.anchor.appendChild(noo.anchorSr);
    noo.anchor.appendChild(noo.anchorIcon);

    noo.container.appendChild(noo.tooltip);
    noo.tooltip.appendChild(noo.body);
    noo.body.prepend(noo.bodyTitle);

    return noo.container;
  },
}