Greasy Fork is available in English.

Online IDE DDS Create

shortcuts to create DDS library component HTML

Dette script bør ikke installeres direkte. Det er et bibliotek, som andre scripts kan inkludere med metadirektivet // @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;
  },
}