Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update JS to use Stimulus framework #48

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Ensure you have access to a Unix-like environment through:
## Developer Guide

### Employed Frameworks
* [Stimulus JS](https://stimulus.hotwired.dev) as the default JavaScript framework, augmenting HTML
* [Stimulus JS](https://stimulus.hotwired.dev) as the default JavaScript framework, augmenting HTML (see [the handbook](https://stimulus.hotwired.dev/handbook/origin) and [this detailed post](https://thoughtbot.com/blog/taking-the-most-out-of-stimulus) for an introduction)
* [Bootstrap](https://getbootstrap.com/docs/5.2) for layout, styling and [icons](https://icons.getbootstrap.com/)
* [Devise](https://github.com/heartcombo/devise) library for authentication
* [FactoryBot](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#defining-factories) to generate test data
Expand Down
11 changes: 0 additions & 11 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,3 @@ import "controllers"
// https://getbootstrap.com/docs/5.2/components/tooltips/
import "popper"
import "bootstrap"

/*
* Enable Bootstrap tooltips
* https://getbootstrap.com/docs/5.2/components/tooltips/#enable-tooltips
*/

// https://turbo.hotwired.dev/reference/events
document.addEventListener('turbo:load', function () {
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
}, false);
43 changes: 43 additions & 0 deletions app/javascript/controllers/clipboard_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Controller } from "@hotwired/stimulus"

// https://stimulus.hotwired.dev/handbook/building-something-real#implementing-a-copy-button
export default class extends Controller {
// Stimulus will automatically create target properties returning first matching target element
// this.buttonTarget & this.sourceTarget
static targets = [ "button", "source" ]

// https://stimulus.hotwired.dev/reference/values
// pass new values in the HTML using e.g. `data-clipboard-success-duration-value="1000"`
static values = {
successDuration: { type: Number, default: 1000 },
successMessage: { type: String, default: "Copied!" }
}

// Stimulus calls connect() method each time a controller is connected to the document
connect() {
// https://stimulus.hotwired.dev/reference/values#properties-and-attributes
if (!this.hasButtonTarget) return
this.originalContent = this.buttonTarget.innerHTML
}

copy(event) {
event.preventDefault() // don't follow links
const text = this.sourceTarget.innerHTML || this.sourceTarget.value
// https://www.w3.org/TR/clipboard-apis/#dom-clipboard-writetext
navigator.clipboard.writeText(text).then(() => {return this.copied()})
}

copied() {
if (!this.hasButtonTarget) return

if (this.timeout) {
clearTimeout(this.timeout)
}

this.buttonTarget.innerText = this.successMessageValue

this.timeout = setTimeout(() => {
this.buttonTarget.innerHTML = this.originalContent
}, this.successDurationValue)
}
}
7 changes: 0 additions & 7 deletions app/javascript/controllers/hello_controller.js

This file was deleted.

25 changes: 25 additions & 0 deletions app/javascript/controllers/tooltip_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Tooltips rely on the third party library Popper for positioning.
* Tooltips are opt-in for performance reasons, so you must initialize them yourself.
* https://getbootstrap.com/docs/5.2/components/tooltips/
*/

import { Controller } from "@hotwired/stimulus";

/*
* Connect to all elements with data-controller="tooltip"
* instead of the default `data-bs-toggle="tooltip"`
*/

// Connects to data-controller="tooltip" HTML elements
export default class extends Controller {
connect() {
// Create a new Bootstrap Tooltip instance
// (https://getbootstrap.com/docs/5.2/components/tooltips/#methods)
// this.element is the HTML element tagged with `data-controller`
// (https://stimulus.hotwired.dev/reference/controllers#properties)
// The library reads config from `data-bs-*` attributes
// (https://getbootstrap.com/docs/5.2/components/tooltips/#directions)
bootstrap.Tooltip.getOrCreateInstance(this.element);
}
}
25 changes: 19 additions & 6 deletions app/views/landing_page/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,24 @@
<% if user_signed_in? %>
<div class="row py-2">
<div class="col">
currently logged in user: <%= current_user.email %> |
<%= link_to edit_user_registration_path, class: "link-primary" do %>
<%# https://stimulus.hotwired.dev/reference/controllers %>
<%# Connect span to `app/javascript/controllers/clipboard_controller.js` %>
<span data-controller="clipboard">
<%# Stimulus marks important elements as targets to reference them in the controller through corresponding properties %>
<%# this.sourceTarget in `clipboard_controller.js` %>
Logged in user: <span data-clipboard-target="source"><%= current_user.email %></span>
<%# In Stimulus, controller methods which handle events are called action methods %>
<%# `click->clipboard#copy` connects the button to the `copy` method in clipboard_controller.js %>
<button data-action="click->clipboard#copy" data-clipboard-target="button" class="btn btn-outline-secondary btn-sm" style="width: 8em;">
<i class="bi bi-clipboard-plus-fill"></i> Copy email
</button>
</span>
<%= link_to edit_user_registration_path, class: "btn btn-primary btn-sm" do %>
<i class="bi bi-pencil-square"></i> Edit user profile
<% end %> |
<%= link_to destroy_user_session_path, data: {"turbo-method": :delete}, class: "link-secondary" do %>
<% end %>
<%= link_to destroy_user_session_path,
data: {"turbo-method": :delete, "controller": "tooltip", "bs-placement": "bottom", "bs-title": "DELETE → #{destroy_user_session_path}"},
class: "btn btn-secondary btn-sm" do %>
<i class="bi bi-door-open-fill"></i> Log out
<% end %>
</div>
Expand All @@ -39,7 +52,7 @@
</div>
<h3 class="fs-3">Feature Number 1</h3>
<p>Text explaining the specifics of the feature and how to use it, including details of how this improves the currently employed workflow.</p>
<a href="#" class="icon-link d-inline-flex align-items-center" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-title="tooltip content">
<a href="#" class="icon-link d-inline-flex align-items-center" data-controller="tooltip" data-bs-placement="right" data-bs-title="tooltip content">
Link with tooltip using Popper.js
<svg class="bi" width="1em" height="1em"><use xlink:href="#chevron-right"></use></svg>
</a>
Expand All @@ -50,7 +63,7 @@
</div>
<h3 class="fs-3">Feature Number 2</h3>
<p>Text explaining the specifics of the feature and how to use it, including details of how this improves the currently employed workflow.</p>
<a href="#" class="icon-link d-inline-flex align-items-center">
<a href="#" class="icon-link d-inline-flex align-items-center" data-controller="tooltip" data-bs-placement="top" data-bs-title="More infos">
Call to action
<svg class="bi" width="1em" height="1em"><use xlink:href="#chevron-right"></use></svg>
</a>
Expand Down