diff --git a/app/assets/javascripts/alchemy/admin.js b/app/assets/javascripts/alchemy/admin.js
index 4344b7c90d..037d4c6044 100644
--- a/app/assets/javascripts/alchemy/admin.js
+++ b/app/assets/javascripts/alchemy/admin.js
@@ -5,5 +5,4 @@
//= require handlebars
//= require alchemy/templates
//= require alchemy/alchemy.dialog
-//= require alchemy/alchemy.fixed_elements
//= require alchemy/alchemy.image_overlay
diff --git a/app/assets/javascripts/alchemy/alchemy.fixed_elements.js b/app/assets/javascripts/alchemy/alchemy.fixed_elements.js
deleted file mode 100644
index b52db9eb86..0000000000
--- a/app/assets/javascripts/alchemy/alchemy.fixed_elements.js
+++ /dev/null
@@ -1,45 +0,0 @@
-window.Alchemy = Alchemy || {}
-
-Alchemy.FixedElements = {
- WRAPPER: '',
- TABS: '{{label}}',
-
- // Builds fixed elements tabs
- buildTabs: function (label) {
- var $wrapper = $(this.WRAPPER),
- $tabs = $(this.TABS.replace(/{{label}}/, label))
-
- $("#main-content-elements").wrap($wrapper)
- $("#fixed-elements").prepend($tabs)
- },
-
- // Creates a fixed element tab.
- createTab: function (element_id, label) {
- var $fixed_elements = $("#fixed-elements")
- var panel_name = "fixed-element-" + element_id
-
- var $tab =
- '' + label + ""
- $fixed_elements.append($tab)
-
- var $panel = $(
- ''
- )
- $fixed_elements.append($panel)
- window.requestAnimationFrame(function () {
- $fixed_elements.get(0).show(panel_name)
- })
- },
-
- removeTab: function (element_id) {
- var $fixed_elements = $("#fixed-elements")
-
- $fixed_elements
- .find('sl-tab[panel="fixed-element-' + element_id + '"]')
- .remove()
- $fixed_elements
- .find('sl-tab-panel[name="fixed-element-' + element_id + '"]')
- .remove()
- $fixed_elements.get(0).show("main-content-elements")
- }
-}
diff --git a/app/javascript/alchemy_admin.js b/app/javascript/alchemy_admin.js
index f88abd08c1..593812c7a0 100644
--- a/app/javascript/alchemy_admin.js
+++ b/app/javascript/alchemy_admin.js
@@ -6,6 +6,7 @@ import Rails from "@rails/ujs"
import GUI from "alchemy_admin/gui"
import { translate } from "alchemy_admin/i18n"
import Dirty from "alchemy_admin/dirty"
+import * as FixedElements from "alchemy_admin/fixed_elements"
import { growl } from "alchemy_admin/growler"
import IngredientAnchorLink from "alchemy_admin/ingredient_anchor_link"
import ImageLoader from "alchemy_admin/image_loader"
@@ -39,6 +40,7 @@ Object.assign(Alchemy, {
...Dirty,
GUI,
t: translate, // Global utility method for translating a given string
+ FixedElements,
growl,
ImageLoader: ImageLoader.init,
ImageCropper,
diff --git a/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js b/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js
index 48b9a624b2..343dd170f4 100644
--- a/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js
+++ b/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js
@@ -1,3 +1,4 @@
+import { removeTab } from "alchemy_admin/fixed_elements"
import { growl } from "alchemy_admin/growler"
import { reloadPreview } from "alchemy_admin/components/preview_window"
import { confirmToDeleteDialog } from "alchemy_admin/confirm_dialog"
@@ -20,7 +21,7 @@ export class DeleteElementButton extends HTMLElement {
const elementEditor = this.closest("alchemy-element-editor")
elementEditor.addEventListener("transitionend", () => {
if (elementEditor.fixed) {
- Alchemy.FixedElements.removeTab(elementEditor.elementId)
+ removeTab(elementEditor.elementId)
}
elementEditor.remove()
})
diff --git a/app/javascript/alchemy_admin/fixed_elements.js b/app/javascript/alchemy_admin/fixed_elements.js
new file mode 100644
index 0000000000..78b5a1a888
--- /dev/null
+++ b/app/javascript/alchemy_admin/fixed_elements.js
@@ -0,0 +1,24 @@
+// Creates a fixed element tab.
+export function createTab(element_id, label) {
+ const fixed_elements = document.getElementById("fixed-elements")
+ const panel_name = `fixed-element-${element_id}`
+
+ const tab = `${label}`
+ const panel = ``
+
+ fixed_elements.innerHTML += tab + panel
+
+ window.requestAnimationFrame(function () {
+ fixed_elements.show(panel_name)
+ })
+}
+
+export function removeTab(element_id) {
+ const fixed_elements = document.getElementById("fixed-elements")
+ const panel_name = `fixed-element-${element_id}`
+
+ fixed_elements.querySelector(`sl-tab[panel="${panel_name}"]`).remove()
+ fixed_elements.querySelector(`sl-tab-panel[name="${panel_name}"]`).remove()
+
+ fixed_elements.show("main-content-elements")
+}
diff --git a/app/models/alchemy/page/page_elements.rb b/app/models/alchemy/page/page_elements.rb
index 849391b530..503272d29b 100644
--- a/app/models/alchemy/page/page_elements.rb
+++ b/app/models/alchemy/page/page_elements.rb
@@ -80,21 +80,21 @@ def duplicate_elements(elements, repository, page_version)
# type: Richtext
#
def available_element_definitions(only_element_named = nil)
- @_element_definitions ||= if only_element_named
+ @_available_element_definitions ||= if only_element_named
definition = Element.definition_by_name(only_element_named)
element_definitions_by_name(definition["nestable_elements"])
else
- element_definitions
+ element_definitions.dup
end
- return [] if @_element_definitions.blank?
+ return [] if @_available_element_definitions.blank?
existing_elements = draft_version.elements.not_nested
@_existing_element_names = existing_elements.pluck(:name)
delete_unique_element_definitions!
delete_outnumbered_element_definitions!
- @_element_definitions
+ @_available_element_definitions
end
# All names of elements that can actually be placed on current page.
@@ -186,18 +186,18 @@ def generate_elements
end
end
- # Deletes unique and already present definitions from @_element_definitions.
+ # Deletes unique and already present definitions from @_available_element_definitions.
#
def delete_unique_element_definitions!
- @_element_definitions.delete_if do |element|
+ @_available_element_definitions.delete_if do |element|
element["unique"] && @_existing_element_names.include?(element["name"])
end
end
- # Deletes limited and outnumbered definitions from @_element_definitions.
+ # Deletes limited and outnumbered definitions from @_available_element_definitions.
#
def delete_outnumbered_element_definitions!
- @_element_definitions.delete_if do |element|
+ @_available_element_definitions.delete_if do |element|
outnumbered = @_existing_element_names.select { |name| name == element["name"] }
element["amount"] && outnumbered.count >= element["amount"].to_i
end
diff --git a/app/views/alchemy/admin/elements/create.js.erb b/app/views/alchemy/admin/elements/create.js.erb
index 00813e861a..28b1222326 100644
--- a/app/views/alchemy/admin/elements/create.js.erb
+++ b/app/views/alchemy/admin/elements/create.js.erb
@@ -7,9 +7,6 @@
<%- end -%>
<% if @element.fixed? %>
- if ($('#fixed-elements').length == 0) {
- Alchemy.FixedElements.buildTabs('<%= Alchemy.t(:main_content) %>');
- }
Alchemy.FixedElements.createTab('<%= @element.id %>', '<%= @element.display_name %>');
$element_area = $('[name="fixed-element-<%= @element.id %>"]');
<% elsif @element.parent_element %>
diff --git a/app/views/alchemy/admin/elements/index.html.erb b/app/views/alchemy/admin/elements/index.html.erb
index f9d33c37e0..338e912bbe 100644
--- a/app/views/alchemy/admin/elements/index.html.erb
+++ b/app/views/alchemy/admin/elements/index.html.erb
@@ -32,7 +32,7 @@
- <% if @fixed_elements.any? %>
+ <% if @page.element_definitions.any? { |el| el["fixed"] } %>
<%= Alchemy.t(:main_content) %>
diff --git a/spec/models/alchemy/page_spec.rb b/spec/models/alchemy/page_spec.rb
index fe2665e83f..30e50c6c3f 100644
--- a/spec/models/alchemy/page_spec.rb
+++ b/spec/models/alchemy/page_spec.rb
@@ -590,6 +590,12 @@ module Alchemy
expect(subject.collect { |e| e["name"] }).to include("article")
expect(subject.collect { |e| e["name"] }).not_to include("header")
end
+
+ it "does not mutate the element_definitions collection" do
+ expect(page.element_definitions.collect { |e| e["name"] }).to include("header")
+ subject
+ expect(page.element_definitions.collect { |e| e["name"] }).to include("header")
+ end
end
context "limited amount" do
@@ -650,6 +656,12 @@ module Alchemy
it "should be ignored if unique" do
expect(subject.collect { |e| e["name"] }).not_to include("unique_headline")
end
+
+ it "does not mutate the element_definitions collection" do
+ expect(page.element_definitions.collect { |e| e["name"] }).to include("column_headline")
+ subject
+ expect(page.element_definitions.collect { |e| e["name"] }).to include("column_headline")
+ end
end
describe ".ransackable_scopes" do