Skip to content

Commit

Permalink
Add a element DOM id class
Browse files Browse the repository at this point in the history
By default it uses the elements name and its position on the page.
If the element is nested in a parent element it prefixes the id with the parent elements `dom_id`.

Register your own dom id class with

```rb
Alchemy::Element.dom_id_class = MyDomIdClass
```
  • Loading branch information
tvdeyen committed Sep 4, 2022
1 parent acaf339 commit b78ed37
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 17 deletions.
12 changes: 12 additions & 0 deletions app/models/alchemy/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ def new(attributes = {})
super(element_definition.merge(element_attributes).except(*FORBIDDEN_DEFINITION_ATTRIBUTES))
end

# The class responsible for the +dom_id+ of elements.
# Defaults to +Alchemy::Element::DomId+.
def dom_id_class
@_dom_id_class || DomId
end

# Register a custom +DomId+ class responsible for the +dom_id+ of elements.
# Defaults to +Alchemy::Element::DomId+.
def dom_id_class=(klass)
@_dom_id_class = klass
end

# This methods does a copy of source and all depending contents and all of their depending essences.
#
# == Options
Expand Down
30 changes: 30 additions & 0 deletions app/models/alchemy/element/dom_id.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Alchemy
# Returns a dom id used for elements html id tag.
#
# Uses the elements name and its position on the page.
# If the element is nested in a parent element it prefixes
# the id with the parent elements dom_id.
#
# Register your own dom id class with
#
# Alchemy::Element.dom_id_class = MyDomIdClass
#
class Element < BaseRecord
class DomId
def initialize(element)
@element = element
@parent_element = element.parent_element
end

def call
[parent_element&.dom_id, element.name, element.position].compact.join("-")
end

private

attr_reader :element, :parent_element
end
end
end
2 changes: 1 addition & 1 deletion app/models/alchemy/element/presenters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def display_name_with_preview_text(maxlength = 30)
# Returns a dom id used for elements html id tag.
#
def dom_id
[parent_element&.dom_id, name, position].compact.join("-")
self.class.dom_id_class.new(self).call
end

# The content that's used for element's preview text.
Expand Down
31 changes: 31 additions & 0 deletions spec/models/alchemy/element/dom_id_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Alchemy::Element::DomId do
describe "#call" do
subject(:dom_id) do
described_class.new(element).call
end

let(:element) { build_stubbed(:alchemy_element, position: 1) }

it "returns a string from element name and position" do
expect(dom_id).to eq("#{element.name}-#{element.position}")
end

context "with a parent element" do
let(:parent_element) do
build_stubbed(:alchemy_element, position: 1)
end

let(:element) do
build_stubbed(:alchemy_element, position: 1, parent_element: parent_element)
end

it "returns a string from element name and position" do
expect(dom_id).to eq("#{parent_element.name}-#{parent_element.position}-#{element.name}-#{element.position}")
end
end
end
end
40 changes: 24 additions & 16 deletions spec/models/alchemy/element_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,27 @@ module Alchemy
end
end

describe ".dom_id_class" do
it "defaults to Alchemy::Element::DomId" do
expect(described_class.dom_id_class).to eq(Alchemy::Element::DomId)
end
end

describe ".dom_id_class=" do
let(:dummy_dom_id) { Class.new }

around do |example|
default_class = described_class.dom_id_class
described_class.dom_id_class = dummy_dom_id
example.run
described_class.dom_id_class = default_class
end

it "sets the dom id class" do
expect(described_class.dom_id_class).to eq(dummy_dom_id)
end
end

describe ".copy" do
subject { Element.copy(element) }

Expand Down Expand Up @@ -543,22 +564,9 @@ module Alchemy
describe "#dom_id" do
let(:element) { build_stubbed(:alchemy_element, position: 1) }

it "returns a string from element name and position" do
expect(element.dom_id).to eq("#{element.name}-#{element.position}")
end

context "with a parent element" do
let(:parent_element) do
build_stubbed(:alchemy_element, position: 1)
end

let(:element) do
build_stubbed(:alchemy_element, position: 1, parent_element: parent_element)
end

it "returns a string from element name and position" do
expect(element.dom_id).to eq("#{parent_element.name}-#{parent_element.position}-#{element.name}-#{element.position}")
end
it "calls dom id class" do
expect(Alchemy::Element.dom_id_class).to receive(:new).with(element).and_call_original
element.dom_id
end
end

Expand Down

0 comments on commit b78ed37

Please sign in to comment.