Git Product home page Git Product logo

stimulus-library's Introduction

Stimulus-Library

Documentation | Full List of Controllers


npm npm bundle size (version)

Installation

To get started, you'll need to add the stimulus-library package to your project.

To do so, either add stimulus-library to your package.json manually

{
  "dependencies": {
    "stimulus-library": "latest"
  }
}

or run npm install --save stimulus-library or yarn add stimulus-library

Then, to get started, import and register the controllers you want to use.

Please Note as below, that when registering the name for the controller, you should use kebab-case and omit the -controller suffix.

import { Application } from "@hotwired/stimulus";
import { AutoSubmitFormController } from "stimulus-library";

const application = Application.start();
application.register("auto-submit-form", AutoSubmitFormController);

Tree-shaking

If you use the ESM builds of the library, this library fully supports tree-shaking, only the controllers you directly import will be bundled with your application.

stimulus-library's People

Contributors

analyzeplatypus avatar dahie avatar dependabot[bot] avatar github-actions[bot] avatar quadule avatar sakin avatar sub-xaero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

stimulus-library's Issues

Tabs controller: setting identifiers for tabs

Working with the documentation and also the examples, the provided examples are not running as per design: all tab contents are shown simultaneously.

In CSS-only versions of tabs the divs are given an identifier between the link and the content. While structurally similar, the examples, as set-up have no means of distinction of content relative to link. All are set:

data-tabs-target="link"
data-tabs-target="content"

The most promising variant attempted was

       <ul class="tabs">
          <li class="tabs-title" data-tabs-target="link-1">
            <a>Product Details</a>
          </li>
          <li class="tabs-title" data-tabs-target="link-2">
            <a>Reviews</a>
          </li>
          <li class="tabs-title" data-tabs-target="link-3">
            <a>FAQ</a>
          </li>
        </ul>
        <div class="tabs-content">
          <div class="tabs-panel" data-tabs-target="content-1">
             dolor, 
          </div>
          <div class="tabs-panel" data-tabs-target="content-2">
            No reviews
          </div>
          <div class="tabs-panel" data-tabs-target="content-3">
            No FAQS
          </div>
        </div>

yet failed.

How is this supposed to run properly?

Does not run under node.js

We're using this package in a Rails 7 app, and have JS unit tests (running under node) against some of our stimulus controllers. In this configuration, we are unable to load components from this package.

Would you be willing to define the main attribute in your package.json files (controllers, mixins, utilities) to enable this configuration? See https://esbuild.github.io/api/#main-fields

Thank you!

Table Truncate Controller

Hoisted from internal development. Finesse and publish:

import { Controller } from "stimulus";
import { useMutation } from "stimulus-use";

export default class extends Controller {

  static targets = ["showMore"];

  static values = {
    limit: Number,
  };

  get tableBody() {
    return this.element.tBodies[0];
  }

  get tableRows() {
    return Array.from(this.tableBody.rows);
  }

  get limit() {
    return this.hasLimitValue ? this.limitValue : 5;
  }

  initialize() {
    this.truncate = this.truncate.bind(this);
    this.expand = this.expand.bind(this);
  }

  connect() {
    useMutation(this, {childList: true, element: this.tableBody});

    requestAnimationFrame(() => {
      this.truncate();
      this.showMoreTarget.addEventListener("click", this.expand);
    });
  }

  showElement(row) {
    row.style.display = "";
  }

  hideElement(row) {
    row.style.display = "none";
  }

  re_truncate() {
    this.tableRows.slice(0, this.limit).forEach((el) => {
      if (el !== this.showMoreTarget) {
        this.showElement(el);
      }
    });
    this.tableRows.slice(this.limit).forEach((el) => {
      if (el !== this.showMoreTarget) {
        this.hideElement(el);
      }
    });
    this.showElement(this.showMoreTarget);
  }

  truncate(event) {
    event?.preventDefault();
    if (this.tableRows.length >= this.limit) {
      this.tableRows.slice(this.limit).forEach((el) => {
        if (el !== this.showMoreTarget) {
          this.hideElement(el);
        }
      });
      this.showElement(this.showMoreTarget);
    } else {
      this.hideElement(this.showMoreTarget);
    }
  }

  expand(event) {
    event?.preventDefault();
    this.tableRows.slice(this.limit).forEach((el) => {
      if (el !== this.showMoreTarget) {
        this.showElement(el);
      }
    });
    this.hideElement(this.showMoreTarget);
  }

  mutate(entries) {
    this.re_truncate();
  }

}

Feature Request - Bus Controllers

A pair of controllers, an emitter and a listener, that can convert between DOM events and MITT events, to enable action-based DOM communication without element co-location.

Feature Request - Controller to submit/reset a form with a button/action that is outside of the form

Turbo requires that former UJS buttons use button_to instead of link_to which generates a form. Forms can't be nested.

Might also want this to be able to handle "Reset" buttons.

If you want your "destroy" button to be on the edit page - and have all your buttons in one place, i.e.
image
You can see where the destroy button has been forced to be disparate in the design.

This controller would let all the buttons be outside the form. With a small inline form wrapping the individual "destroy" button, and this controller dispatching the "Submit" and "Reset" events from outside the main form.

Feature Request - Mixin for temporary text changes

Common scenario

    this.sourceTarget.select();
    document.execCommand('copy');

    this.promptTarget.innerText = 'Copied!';

    setTimeout(function() {
      controller.promptTarget.innerText = 'Copy';
    }, 1000);

Might want to have variants for ones where timeouts set the text back, and others where a closure is returned to set it back manually.

Feature Request - LoadBlock

A controller like AsyncBlock controller, that can be loaded via an action/event, instead of on page load.

DisableWithController prevents form sumitting

Hello,
First, thank you for this useful set of controllers!

I have a problem with the DisableWithController, when I use it in a rails form, the form is not submitted anymore.

Stimulus-library 1.0.2
Rails 6.1.7.6

Here is the form:

<%= form_with url: sessions_path do |form| %>
<%= text_field_tag 'email' %>
<%= password_field_tag 'password' %>
<%= form.submit 'Sign in', data: { controller: "disable-with", 'disable-with-message-value': "Bear with us..." } %>
<% end %>

When I click the button is disabled with the good text but the form is not submitted. If I remove the controller, the form is submitted.
It does not work no matter if turbo is enabled or not.

What I'm doing wrong?

Thanks

CountdownController to show readable time

Current view for time display of countdown_controller's time in minute:second format is 2:9 instead showing 02:09, I wonder is this a bug or any reason behind this?

Working back to get a controller runnning with its dependencies.

Being interested in the trix-modifier, the code of that controller states:

import {BaseController} from "../utilities/base_controller";
import {TrixElementsPayload, useTrixModifiers} from "../mixins/use_trix_modifiers";

Which implies dependencies...
src/utilites/base_controller requires to import another two:

import {Context, Controller} from "@hotwired/stimulus";
import {log, logProperty} from "./logging";
import {dispatchEvent} from "./events";

then we have to deal with use_trix_modifiers mixin:

import {controllerMethod} from "../utilities/stimulus";
import {Controller} from "@hotwired/stimulus";

Working with the rails 7 ecosystem, I assume, given this repository's readme the first action should be

bin/importmap pin stimulus-library

yes?
Then, to get started, import and register the controllers you want to use.

OK. but now I am inferring from this page one should, again with the rails 7 ecosystem, import and regsiter as one of the follwoing:

bin/importmap pin trix-modifier
     [or]
bin/importmap pin stimulus-library/trix-modifier

?

Other curiosity, to this reader, the controller is suffixed .ts . Should it remain so in the rails assets/javascript/controllers directory?

Then what about the aforementioned dependencies; must anything be done for those?
It is opaque to this reader... leading to a large number of uncertainties in this process.

AnchorSpy Controller

Controller that can read and set the navigator anchor and wire up other actions.

I.e. update the URL when an accordion opens, and reopen an accordion when the user navigates back to the page.

i.e. Open an accordion when the user opens a page by URL with a corresponding anchor.

dist/index.d.ts missing from distribution

Your package.json states you include typescript types:

  "types": "dist/index.d.ts",

but, there is no index.d.ts in the dist folder. This means I can't import individual controllers in my typescript project, because typescript won't resolve imports for this library.

For some reason, you disabled declarations in 3b374f6, can you please set declarations in tsconfig.json back to true?

Table Sorting Controller

Hoisted from internal development. Finesse and publish:

import { Controller } from "stimulus";

export default class extends Controller {

  lastIndex = null;
  reverse = false;

  get tableHead() {
    return this.element.tHead;
  }

  get tableHeaders() {
    return Array.from(this.tableHead.rows[0].cells);
  }

  get tableBody() {
    return this.element.tBodies[0];
  }

  get tableRows() {
    return Array.from(this.tableBody.rows);
  }

  initialize() {
    this.sort = this.sort.bind(this);
  }

  connect() {
    requestAnimationFrame(() => {
      this.tableHeaders.forEach(cell => cell.addEventListener("click", this.sort));
    });
  }

  disconnect() {
    this.tableHeaders.forEach(cell => cell.removeEventListener("click", this.sort));
  }

  sort(event) {
    event.preventDefault();
    let headerCell = event.target;
    let headerCellIndex = this.indexOfHeaderCell(headerCell);
    this.sortByColumn(headerCellIndex);
  }

  indexOfHeaderCell(cell) {
    return this.tableHeaders.indexOf(cell);
  }

  sortByColumn(index) {
    this.reverse = index === this.lastIndex && !this.reverse;
    let frag = document.createDocumentFragment();
    let rows = this.tableRows;

    let newRows = rows.sort((row, otherRow) => {
      let cells = row.cells;
      let otherCells = otherRow.cells;

      if (row.dataset.sortTop || otherRow.dataset.sortBottom) {
        return -1;
      }
      if (row.dataset.sortBottom || otherRow.dataset.sortTop) {
        return 1;
      }

      // TODO: Handle colspans
      let x = cells[index]?.innerText || "";
      let y = otherCells[index]?.innerText || "";

      let sortVal = x.localeCompare(y, "en", {sensitivity: "base", numeric: true, caseFirst: "upper"});

      if (this.reverse) {
        return sortVal > 0 ? -1 : 1;
      }
      return sortVal;
    });

    newRows.forEach(row => frag.appendChild(row));

    this.tableBody.innerHTML = "";
    this.tableBody.appendChild(frag);
    this.lastIndex = index;
  }

}

Feature Request - TurboFrameHistory Controller

import { Turbo } from '@hotwired/turbo-rails';
import { BaseController } from '../../utilities/base_controller';
import { useMutationObserver } from '../../mixins';

const { navigator } = Turbo;

export class TurboFrameHistoryController extends BaseController{
  initialize() {
    this.mutate = this.mutate.bind(this);
  }

  connect() {
    useMutationObserver(this, this.element, this.mutate, { attributes: true });
  }

  mutate(entries) {
    entries.forEach((mutation) => {
      if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
        const src = this.element.getAttribute('src');
        if (src != null) {
          navigator.history.push(new URL(src));
        }
      }
    });
  }
}

How to install when only using a mixin (w/ tree shaking)?

The installation instructions prescribe yarn install npm install, but that did not work in my project because I use import maps.

I then ran the following:

bin/importmap pin stimulus-library

Which pinned a ton of dependencies:

Pinning "stimulus-library" to https://ga.jspm.io/npm:[email protected]/dist/index.js
Pinning "@hotwired/stimulus" to https://ga.jspm.io/npm:@hotwired/[email protected]/dist/stimulus.js
Pinning "date-fns/formatDistanceToNow" to https://ga.jspm.io/npm:[email protected]/esm/formatDistanceToNow/index.js
Pinning "date-fns/formatDuration" to https://ga.jspm.io/npm:[email protected]/esm/formatDuration/index.js
Pinning "date-fns/intervalToDuration" to https://ga.jspm.io/npm:[email protected]/esm/intervalToDuration/index.js
Pinning "date-fns/isPast" to https://ga.jspm.io/npm:[email protected]/esm/isPast/index.js
Pinning "date-fns/toDate" to https://ga.jspm.io/npm:[email protected]/esm/toDate/index.js
Pinning "dialog-polyfill" to https://ga.jspm.io/npm:[email protected]/dist/dialog-polyfill.js
Pinning "lodash-es/camelCase" to https://ga.jspm.io/npm:[email protected]/camelCase.js
Pinning "lodash-es/clamp" to https://ga.jspm.io/npm:[email protected]/clamp.js
Pinning "lodash-es/debounce" to https://ga.jspm.io/npm:[email protected]/debounce.js
Pinning "lodash-es/get" to https://ga.jspm.io/npm:[email protected]/get.js
Pinning "lodash-es/set" to https://ga.jspm.io/npm:[email protected]/set.js
Pinning "lodash-es/upperFirst" to https://ga.jspm.io/npm:[email protected]/upperFirst.js
Pinning "mitt" to https://ga.jspm.io/npm:[email protected]/dist/mitt.mjs
Pinning "smoothscroll-polyfill" to https://ga.jspm.io/npm:[email protected]/dist/smoothscroll.js

Will all these dependencies ship with my bundle?

I'm only interested in useLocalStorage for now.

multiple controllers, textarea limitation or controller dependencies

the following sets two controllers to act on the same base input area, but done seperately (using the example ), as the rails tag has no way of applying the second controller data: { controller: 'trix-modifier char-count' on a tag with data-char-count-target="output" that is in existent within the generated trix-editor tag.

      <div
        data-controller="char-count"
        data-char-count-min-value="250"
        data-char-count-max-value="1000"
        data-char-count-error-class="error"
      >
        <label class="form-label">
          What is your quest? We suggest at least 250 chars, but no more than
          1000 chars.
        </label>
          <%= form.rich_text_area "translatable_content_#{Mobility.normalize_locale(user_idioma.idioma.code.to_s)}", rows: 20, data: { controller: 'trix-modifier', 'no-file-uploads' => true, 'char-count-target' => "input" } %>
        <div class="text-right">
          <span data-char-count-target="output"></span>
          <span>/1000</span>
        </div>
      </div>

as the count output span is not firing, three sources of errors are in play:

  1. the controller references mixins and utilities
import {BaseController} from "../../utilities/base_controller";
import {useEventListener} from "../../mixins/use_event_listener";
import {installClassMethods} from "../../mixins/install_class_methods";

and the browser console complains

Failed to register controller: char-count (controllers/char_count_controller)  
Error: 404 Not Found http://localhost:3000/utilities/base_controller imported from [http://localhost:3000/assets/controllers/char_count_controll…f761ed463509d756aa20e74eef6c801851b7c91e869061e002d6d5cfd.js](http://localhost:3000/assets/controllers/char_count_controller-ee02639f761ed463509d756aa20e74eef6c801851b7c91e869061e002d6d5cfd.js)

do these have to be copied from the repository's src into the application's javascript/controllers directory? or is there another mechanism? (it is not clear from the installation instructions - or via pinning - if they get brought along). The base controller also has other dependencies, so this can become a wet bar of soap...

This first one needs resolving as this ocntext arises for other controllers.

  1. could the char_count_controller be applicable to only textarea and not to trix-editor tags?
<trix-editor rows="20" data-controller="trix-modifier" data-no-file-uploads="true" data-char-count-target="input" data-direct-upload-url="http://localhost:3000/rails/active_storage/direct_uploads" data-blob-url-template="http://localhost:3000/rails/active_storage/blobs/redirect/:signed_id/:filename" id="article_translatable_content_en" input="article_translatable_content_en_trix_input_article" class="trix-content" role="textbox" trix-id="1" toolbar="trix-toolbar-1" contenteditable=""><div><!--block-->asdkjaksjda</div></trix-editor>
  1. the converted js from ts source file is mistaken
import { BaseController } from "../../utilities/base_controller";
import { useEventListener } from "../../mixins/use_event_listener";
import { installClassMethods } from "../../mixins/install_class_methods";
export class CharCountController extends BaseController {
    connect() {
        installClassMethods(this);
        requestAnimationFrame(() => {
            useEventListener(this, this.inputTarget, "input", this._updateCharCount);
            this._updateCharCount();
        });
    }
    _updateCharCount() {
        let charCount = this.inputTarget.value.length;
        this.outputTarget.innerText = charCount.toString();
        if (this._isValidCount(charCount)) {
            this.removeErrorClasses(this.outputTarget);
        }
        else {
            this.addErrorClasses(this.outputTarget);
        }
    }
    _isValidCount(count) {
        let min = 0;
        let max = 99999;
        if (this.hasMinValue) {
            min = this.minValue;
        }
        if (this.hasMaxValue) {
            max = this.maxValue;
        }
        return count >= min && count <= max;
    }
}
// Config
CharCountController.targets = ["input", "output"];
CharCountController.values = { min: Number, max: Number };
CharCountController.classes = ["error"];

UJS Form Controller ?

import {Controller} from 'stimulus';

export default class extends Controller {
  static targets = [];

  static values = {selector: String};

  declare readonly hasSelectorValue: boolean;
  declare readonly selectorValue: string;

  get selector(): string {
    return this.hasSelectorValue ? this.selectorValue : '[data-controller~="form"]';
  }

  reload(event: { detail: [Element, any, XMLHttpRequest] }) {
    const [data, status, xhr] = event.detail;
    if (data instanceof Node) {
      let new_element = data.querySelector(this.selector);

      if (new_element == null) {
        throw new Error('expected new form DOM with [data-controller="form"] to be present in returned payload');
      }

      let parentNode = this.element.parentNode;
      if (parentNode == null) {
        throw new Error('expected form to have a DOM parent, could not execute replaceChild');
      }
      parentNode.replaceChild(new_element, this.element);
    } else {
      console.log('Unknown', data);
    }
  }
}

Tree-shaking question

Using webpacker and the latest version of stimulus-library, and added these lines to controllers/index.js

+import { IntersectionController } from "stimulus-library";
+application.register("intersection", IntersectionController);

My compressed compiled javascript bundle increased in size by 100kb - is that expected?

Feature Request - Turbo Refresh Controller

Values:

  • poll interval (optional)

Actions

  • Refresh - Set turboframe src to same value, triggers re-fetch of frame.

Can either be composed, by wiring up "turbo-refresh#refresh" to events. Or by setting poll interval, to make set auto polling interval

pinning and unpinning change of state.

initial state of importmap.rb which is stock rails 7 installation + trix

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"

pin the library: bin/importmap pin stimulus-library and the process installs two external references (stimulus and actiontext) without preload: true on stimulus

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:@hotwired/[email protected]/dist/stimulus.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"pin "stimulus-library", to: "https://ga.jspm.io/npm:[email protected]/dist/index.js"
pin "date-fns/formatDistanceToNow", to: "https://ga.jspm.io/npm:[email protected]/esm/formatDistanceToNow/index.js"
pin "date-fns/formatDuration", to: "https://ga.jspm.io/npm:[email protected]/esm/formatDuration/index.js"
pin "date-fns/intervalToDuration", to: "https://ga.jspm.io/npm:[email protected]/esm/intervalToDuration/index.js"
pin "date-fns/isPast", to: "https://ga.jspm.io/npm:[email protected]/esm/isPast/index.js"
pin "date-fns/toDate", to: "https://ga.jspm.io/npm:[email protected]/esm/toDate/index.js"
pin "dialog-polyfill", to: "https://ga.jspm.io/npm:[email protected]/dist/dialog-polyfill.js"
pin "lodash-es/camelCase", to: "https://ga.jspm.io/npm:[email protected]/camelCase.js"
pin "lodash-es/clamp", to: "https://ga.jspm.io/npm:[email protected]/clamp.js"
pin "lodash-es/debounce", to: "https://ga.jspm.io/npm:[email protected]/debounce.js"
pin "lodash-es/get", to: "https://ga.jspm.io/npm:[email protected]/get.js"
pin "lodash-es/set", to: "https://ga.jspm.io/npm:[email protected]/set.js"
pin "lodash-es/upperFirst", to: "https://ga.jspm.io/npm:[email protected]/upperFirst.js"
pin "mitt", to: "https://ga.jspm.io/npm:[email protected]/dist/mitt.mjs"
pin "smoothscroll-polyfill", to: "https://ga.jspm.io/npm:[email protected]/dist/smoothscroll.js"

unpin ... bin/importmap unpin stimulus-library and the situation is a far cry from the initial situation

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"pin "stimulus-library", to: "https://ga.jspm.io/npm:[email protected]/dist/index.js"

The information about stimulus call being a wrapper for @hotwired/stimulus needs to be searched out with great effort; so it is not obvious how to handle this when osmethign goes wrong. Combine that with the lack of preload and the number of variables at play are increasing past a comfort zone.

I am posting this because I have had issues in past & could not trace, nor rollback efficiently and effectively. without spinning up a new application (bare minimum a trace is here)

Letting auto-submit-form see external inputs

As of v1.0.7, auto-submit-form only takes into account inputs inside the form.

HTML allows to define inputs outside the form, using the form="<form_id>" attribute. I find it very useful in complex layouts.

In order to profit from autosubmission, get inputElements() in AutoSubmitFormController could add to the list of inputs all input elements in the document with the form="<form_id>" attribute

I'd like to submit this small PR myself, but I'm totally out of date re TypeScript dev tooling, and quite busy at the moment.
Thanks to anybody able to add the feature faster than me.

MediaPlayerController

Thin wrapper around HTML5 <video> and <audio> APIs.

import { Controller } from "stimulus";

export class MediaPlayerController extends Controller {

static targets= ["media"]

  connect() {}

  play() {
    this.mediaTarget.play();
  }

  pause() {
    this.mediaTarget.pause();
  }

  restart() {
    this.mediaTarget.currentTime = 0;
  }
}

Test Coverage

Need to set up a nice E2E test framework and start building up the test coverage

Trix Controllers - I.e. disabling file attachments for certain contexts

i.e.

import { BaseController } from "stimulus-library";

export default class extends BaseController {
  initialize() {
    this._setup = this._setup.bind(this);
    this._teardown = this._teardown.bind(this);
    this.preventUploads = this.preventUploads.bind(this);
  }

  attemptInterval = 200;
  attempts = 50;

  connect() {
    // Trix takes time to initialize, so try every 200ms, for 10 seconds
    setTimeout(this._setup, this.attemptInterval);
  }

  disconnect() {
    this._teardown()
  }

  _setup() {
    if (this.el.tagName !== 'TRIX-EDITOR') {
      throw new Error('Expected controller to be mounted on an instance of <trix-editor>');
    }

    let toolbar = this.el.parentElement.querySelector('trix-toolbar');

    if (!toolbar && this.attempts > 0) {
      this.attempts -= 1;
      setTimeout(this._setup, this.attemptInterval);
      return;
    } else if (!toolbar) {
      throw new Error('Could not find <trix-toolbar> that is a sibling of this <trix-editor> element');
    }

    toolbar.querySelectorAll('.trix-button-group.trix-button-group--file-tools').forEach(el => el.style.display = 'none');
    this.el.addEventListener('trix-file-accept', this.preventUploads);
  }

  _teardown() {
    if (this.element.tagName !== 'TRIX-EDITOR') {
      throw new Error('Expected controller to be mounted on an instance of <trix-editor>');
    }

    let toolbar = this.el.parentElement.querySelector('trix-toolbar');
    if (!toolbar) {
      throw new Error('Could not find <trix-toolbar> that is a sibling of this <trix-editor> element');
    }

    toolbar.querySelectorAll('.trix-button-group.trix-button-group--file-tools').forEach(el => el.style.display = null);
    this.el.removeEventListener('trix-file-accept', this.preventUploads);
  }

  preventUploads(e) {
    e.preventDefault();
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.