Online IDE DDS Create

shortcuts to create DDS library component HTML

Αυτός ο κώδικας δεν πρέπει να εγκατασταθεί άμεσα. Είναι μια βιβλιοθήκη για άλλους κώδικες που περιλαμβάνεται μέσω της οδηγίας meta // @require https://update.greasyfork.org/scripts/454586/1182771/Online%20IDE%20DDS%20Create.js

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;
  },
}