Define custom element within another custom element only - shadow-dom

We know that we can register our custom element like this:
customElements.define('x-my-element', MyElement);
And now, this element is available like so:
<x-my-element>Woo</x-my-element>
However, is there some sort of a scoped CustomElementRegistry for a specific ShadowRoot?
I'm working on a browser plugin that needs to inject some custom elements into a page, but I want to avoid accidentally colliding with custom elements that the host page may have defined. If I define an outer custom element, and all elements within are defined to work only within that outer custom element, that solves the problem.
(As an alternative, I'll probably just randomly generate element names with a build script.)

There is a proposal for scope registries, no consensus:
https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Scoped-Custom-Element-Registries.md
https://github.com/WICG/webcomponents/issues?q=is%3Aissue+is%3Aopen+scoped

Related

Can Orbeon controls have multiple values?

I think the answer is no, but the question has been put to me so I'd like to confirm. My understanding is that any custom XBL control that I create for use in Form Builder can have one and only one value. Is this correct?
I have always assumed this because the control name is then used in the data instance as the name of the node which contains the the value.
This question comes from the desire to have reusable components with multiple values, for example, an Address control so that addresses can be recorded consistently and the same set of fields does not need to be added many times. Orbeon does have some support for this in the form of Section Templates but because the control names stay the same in each instance of a Section Template this does not work well with our design.
The best idea I've had is that a custom control which records multiple values could encode all the values into a single text string for example in JSON. Of course, this is not ideal.
Are there any other options?
It is possible for controls to have multiple values. When that happens the values are typically stored in nested elements. I.e. a control could bound to an element <address>, and could create nested elements <street>, <city>,<country>, etc to store the different parts of the address.
In practice, you can look at how this is done in the Image Annotation annotation control (see wpaint.xbl), which creates nested elements <image> and <annotation>, leveraging the xxbl:mirror="true" functionality.

Is it possible to use querySelector() on a dynamically created element?

I'm using appendHtml() in a loop to dynamically add li elements (with unique IDs in the string) to a ul. When I need to access these dynamically created li elements by their IDs to, for example, create nested lists, querySelector() returns null. If I should be able to do this, then there could very well be bugs in my code. But I want to make sure this is the case.
It doesn't matter how elements are added, if the are part of the DOM querySelector can find them.

Orchard CMS conditionally hide widget and suppress zone

I am trying to conditionally suppress a widget from its driver. I basically have logic that if met, should display the widget and if not, should suppress it. The widget loads properties from the current page content item, and based on some properties should display or hide. I've got all the logic working, the only part left is suppressing the actual output.
I've tried returning null from the driver, however this simply outputs an empty widget (with its wrapper). How do I completely remove the widget from view?
Finally, the zone that this widget is placed in should suppress if none of the conditional widgets display.
Is this type of flexibility possible in Orchard? Preferably from my custom module not my theme, I'm trying to separate functionality from styling.
EDIT:
Here is the context of my situation and what I am trying to accomplish. I'm sure there is a much cleaner way to do this within Orchard than how I have naively designed it the first go-around: My client's copywriters tag pages as they see fit (using the Tags module/part). I have created 2 custom content types, "Testimonials" and "Offers", both with tags themselves among other properties [these are managed by a different team of copywriters].
On most "inner pages" of the website (I'm using a layer to determine the appropriate pages), the page's sidebar gets a "Testimonial" widget and a "Offer" widget. These widgets both operate the same, although independently of each other:
They grab the tags of the current page, then pull a random [Testimonial|Offer] that has any matching tags as well. There are 4 cases that can happen given any inner page: a testimonial is displayed and the offer is hidden (testimonial tag matched, offer tag didn't), the testimonial is hidden and the offer is displayed, both the testimonial and offer displays, and finally neither displays. The first 3 use cases are working great, the 4th is what I'm having difficulty with, as the sidebar [zone] still displays even if both widgets do not (returning null from their respective drivers).
A bit of context about widgets: widgets are supposed to be pieces of contents that are visible on some or all pages of the site, and that provide information that is not directly related to the main content item on the page (if there is such a thing).
As a consequence, what you are describing should not be implemented as widgets (all that you had to do to make it work attests to that further), because they are really part of the content item. Instead, you should have implemented a part or a field. You can then simply place the shape for this part of field, using placement, by specifying a top-level zone: <place the_shape_name="/the_zone_where_you_want_it:1"/>
Unfortunately I've had to use a bit of a hack so that I could move on with the project as I'm under an aggressive deadline, but if there is a better method and/or solution I'll test as I get the chance and mark as the answer.
To get it to work, I overwrote the Widget.Wrapper.cshtml file within my theme. There, I assigned a variable to the Display(Model.Child) call, and if the result is an empty string simply return. This removes any empty widget wrapping tags. (I personally feel Orchard should behave this way by default):
var child = Display(Model.Child);
// -- NOTE: shape tracing breaks this logic!
if (string.IsNullOrWhiteSpace(child.ToString())) {
return;
}
Then simply replace the #Display(Model.Child) between the header and footer with #(child)
I then added the following method to my Layout.cshtml file.
Func<dynamic, IHtmlString> CollapsableZone = x =>
{
var display = Display(x);
string zoneName = x.ZoneName;
if (string.Equals(display.ToString(), string.Format("<div class=\"zone zone-{0}\"></div>", zoneName.HtmlClassify()), StringComparison.CurrentCultureIgnoreCase))
{
return new HtmlString(string.Empty);
}
return display;
};
Simple function that assigns the display call to a variable, checks if it is an empty zone tag, and returns. I then create variables for each zone assigned to the value of the function above. I replace all the #if (Model.ZoneName != null) with #if (!string.IsNullOrWhiteSpace(zoneVariable)), and replace the calls to #Zone(Model.ZoneName) with #(zoneVariable).
This is working for the time being. It is quite a hack and brittle solution but I've had to move on to other things.

Rails: Can I use Template Pattern to inject executable code into controller and use rich subclassing?

I've got a widget base class and 50 different kinds of child widget subclasses. Each child widget provides its own partial view. A Page object is defined with a configuration of 2 to 3 of these widgets, and calls a view__generator method that creates a single view erb file for that particular page by retrieving and compositing the partial views that are associated with each of the widgets.
For example, a Page about dolphins might include an Image widget and a radio button choice widget. the generator function creates a single view page. (Yes, I know that it sounds like I should just be using built in rails and html constructs, but there is a method to the madness).
My problem is that I can't figure out how to composite the data requirements into a single set of code that can be run by the controller prior to rendering the composited view.
For example, widget A might require a query of Foo.all while widget B might require a calculation of a form variable called "total_sum".
I've considered two approaches:
1) figure out how to take widget-specific blocks of code and execute them in the context of the base Page controller.
I tried using Procs but the Proc variables aren't available outside of the scope of the Proc. I know that I can write the code into the partial views, but I'd really rather avoid the mixing of concerns.
2) do the data queries and computation on the widget model, and pass the data back as a hash that can then be bound to an instance variable in the base class and made available to the composited view.
I'm pretty sure 2 is the preferred direction, but I'd be interested in guidance on best practices.
I ended up doing what I describe in choice 2. Each model can pull up any data it needs and serialize it into a hash that is always made available to the view.

Dart observable list that does not delete and reinsert all elements on change

We have some code that has a custom web component to display each element in an observable list. It seems that when an element is added to the list, the Web-UI infrastructure sees fit to remove all of the DOM nodes that represent elements in the list, and then re-add them along with the new element.
Not knowing much about the internal workings of the Dart-UI code, I would actually expect the addition of an element in the observable list to simply add one (or more) nodes to the DOM, without removing any of the existing nodes from the DOM.
Is it possible to achieve this sort of behavior?
There is an open issue for this: https://github.com/dart-lang/web-ui/issues/431. John wrote
fwiw, I'm working on a data-binding overhaul right now. The new
implementation includes stable lists by default.
so this should be fixed eventually.

Resources