Skip to content

Commit

Permalink
Added support for setting attributes after the element was put into t…
Browse files Browse the repository at this point in the history
…he DOM.
  • Loading branch information
5cript committed Jul 16, 2024
1 parent f8a8c69 commit 78c90d3
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 2 deletions.
14 changes: 14 additions & 0 deletions nui/include/nui/frontend/attributes/impl/attribute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,24 @@ namespace Nui

bool isRegular() const;
bool isStringData() const;
bool defer() const;
void defer(bool doDefer) &;
Attribute&& defer(bool doDefer) &&
{
defer(doDefer);
return std::move(*this);
}

private:
std::variant<std::monostate, RegularAttribute, StringDataAttribute> attributeImpl_{};
std::function<EventContext::EventIdType(std::weak_ptr<Dom::ChildlessElement>&& element)> createEvent_{};
std::function<void(EventContext::EventIdType const&)> clearEvent_{};
bool defer_{false};
};

inline Attribute&& operator!(Attribute&& attribute)
{
attribute.defer(!attribute.defer());
return std::move(attribute);
}
}
55 changes: 53 additions & 2 deletions nui/include/nui/frontend/dom/element.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ namespace Nui::Dom
: ChildlessElement{elem}
, children_{}
, unsetup_{}
, deferredSetup_{}
{}

explicit Element(Nui::val val)
: ChildlessElement{std::move(val)}
, children_{}
, unsetup_{}
, deferredSetup_{}
{}

Element(Element const&) = delete;
Expand All @@ -69,7 +71,6 @@ namespace Nui::Dom
destroy_(element_);
}

template <typename... Attributes>
static std::shared_ptr<Element> makeElement(HtmlElement const& element)
{
auto elem = std::make_shared<Element>(element);
Expand Down Expand Up @@ -102,6 +103,8 @@ namespace Nui::Dom
{
auto elem = makeElement(element);
element_.call<Nui::val>("appendChild", elem->element_);
if (elem->deferredSetup_)
elem->deferredSetup_(element);
return children_.emplace_back(std::move(elem));
}
auto slotFor(value_type const& value)
Expand Down Expand Up @@ -152,6 +155,8 @@ namespace Nui::Dom
return appendElement(element);
auto elem = makeElement(element);
element_.call<Nui::val>("insertBefore", elem->element_, (*where)->element_);
if (elem->deferredSetup_)
elem->deferredSetup_(element);
return *children_.insert(where, std::move(elem));
}

Expand All @@ -162,8 +167,17 @@ namespace Nui::Dom
{
std::vector<std::function<void()>> eventClearers;
eventClearers.reserve(element.attributes().size());
for (auto const& attribute : element.attributes())
std::vector<std::size_t> deferredIndices;

for (std::size_t i = 0; i != element.attributes().size(); ++i)
{
auto const& attribute = element.attributes()[i];

if (attribute.defer())
{
deferredIndices.push_back(i);
continue;
}
if (attribute.isRegular())
attribute.setOn(*this);

Expand All @@ -188,6 +202,40 @@ namespace Nui::Dom
{
unsetup_ = []() {};
}

if (!deferredIndices.empty())
{
deferredSetup_ = [this, deferredIndices = std::move(deferredIndices)](HtmlElement const& element) {
std::vector<std::function<void()>> eventClearers;
eventClearers.reserve(deferredIndices.size());

for (auto index : deferredIndices)
{
auto const& attribute = element.attributes()[index];

if (attribute.isRegular())
attribute.setOn(*this);

auto clear = attribute.getEventClear();
if (clear)
{
eventClearers.push_back(
[clear = std::move(clear), id = attribute.createEvent(weak_from_base<Element>())]() {
clear(id);
});
}
}
if (!eventClearers.empty())
{
eventClearers.shrink_to_fit();
unsetup_ = [unsetup1 = std::move(unsetup_), eventClearers = std::move(eventClearers)]() {
unsetup1();
for (auto const& clear : eventClearers)
clear();
};
}
};
}
}

auto insert(std::size_t where, HtmlElement const& element)
Expand Down Expand Up @@ -239,13 +287,16 @@ namespace Nui::Dom
element_.call<Nui::val>("replaceWith", replacement);
element_ = std::move(replacement);
setup(element);
if (deferredSetup_)
deferredSetup_(element);
}

private:
using destroy_fn = void (*)(Nui::val&);
destroy_fn destroy_ = Detail::destroyByRemove;
collection_type children_;
std::function<void()> unsetup_;
std::function<void(HtmlElement const& element)> deferredSetup_;
};
}

Expand Down
10 changes: 10 additions & 0 deletions nui/src/nui/frontend/attributes/impl/attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,15 @@ namespace Nui
{
return std::holds_alternative<StringDataAttribute>(attributeImpl_);
}
//---------------------------------------------------------------------------------------------------------------------
bool Attribute::defer() const
{
return defer_;
}
//---------------------------------------------------------------------------------------------------------------------
void Attribute::defer(bool doDefer) &
{
defer_ = doDefer;
}
// #####################################################################################################################
}

0 comments on commit 78c90d3

Please sign in to comment.