Issue with Dart WebUI autogenerated code - dom

I have issue with auto generated code for web components.
Here is piece of HTML:
<div id="hidden-ui">
<div id="auth-form" class="...">
...
<to-button></to-button>
</div>
...
</div>
As you can see, there is custom web component called to-button:
<element name="to-button" constructor="TOSimpleButton" extends="div">
...
</element>
On startup I want to move #auth-form outside from parent node to document root:
Element af = document.query('#auth-form');
Element db = document.query('BODY');
db.children.add(af);
It's OK if there is no custom web-components inside movable node, but while to-button is inside I get run-time RangeError.
Here is piece of auto generated code:
__e1 = __root.nodes[9].nodes[1].nodes[7];
__t.component(new TOSimpleButton()..host = __e1);
As you can see, there is strict old path to component, thus RangeError exception raise.
How can I handle with this?

Sounds like you want to display popup forms every now and then. Here's what I do.
I specify this constructor for the dialog/popup:
var lifecycleCaller;
DialogFooComponent() {
host = new Element.html('<x-dialog-foo></x-dialog-foo>');
lifecycleCaller = new ComponentItem(this)
..create();
document.body.children.add(host);
lifecycleCaller.insert();
}
And as you can see, I add it to the document body. However, this only happens when creating a new instance.
Whenever I need to show that popup, I have code like this:
import '../dialog/foo/foo.dart';
...
// Later at some point I do:
new DialogFooComponent();
And what happens is that you have popup forms appearing in the body whenever you wish them to.
When you want to close the dialog, you can just call this inside the dialog component:
lifecycleCaller.remove();

As mentioned here, this will not be fixed in WebUI package, but will in Polymer.
this won't be fixed in web_ui pkg. It should work in polymer pkg.

Related

How to detect svelte component from DOM?

Currently making an google chrome extension to visualize svelte components, this would only be used only development mode. Currently I am grabbing all svelte components by using const svelteComponets = document.querySelectorAll(`[class^="svelte"]`); on my content scripts but it is grabbing every svelte element. What are some approaches to grab only the components?
Well you mostly can't get to the Svelte component from the DOM elements.
The reason, appart from Svelte won't give you / expose what's needed, is that there isn't a reliable link between components and elements.
A component can have no elements:
<slot />
Or "maybe no elements":
{#if false}<div />{/if}
It can also have multiple root elements:
<div> A </div>
<div> B </div>
<div> C </div>
By bending the cssHash compiler option a lot, you would probably be able to extract the component "name", maybe class name from the CSS scoping classes generated by Svelte. (Which, in turn could break CSS-only HMR updates with Vite, but that's another story.)
But from there, you won't be able to reliably get to the individual component instances... If we keep the component from the last example, once you've grabbed those 6 divs:
<div> A </div>
<div> B </div>
<div> C </div>
<div> A </div>
<div> B </div>
<div> C </div>
... how do you know where one component instance ends and where the other begins? Or even that there are two components?
I believe, the most reliable way to achieve what you want is probably to use internal Svelte APIs, including those that are used by the actual Svelte dev tools that you want to mimic. (Gotta love when private APIs are the "most reliable"!)
Necessary disclaimer: this only seems reasonable to do this in your case because it is a study subject, and because it's dev only. It would certainly not be wise to rely on this for something important. Private / internal APIs can change with any release without any notice.
If you go in the Svelte REPL and look at the generated JS after enabling the "dev" option, you'll see that the compiler adds some events that are provided for the dev tools.
By trials and experimentation, you can get a sense of how Svelte works, and what dev events are available. You'd also probably need to dig the sources of the compiler itself to understand what's happening with some functions... Being comfortable with a good debugger can help a lot!
For your intended usage, that is build a representation of the Svelte component tree, you'll need to know when a component instance is created, what is its parent component, and when it is destroyed. To add it to the tree, in the right place, and remove it when it goes away. With that you should be able to maintain a representation of the component tree for yourself.
You can know when a component is created with the "SvelteRegisterComponent" dev event (squared in red in the above screenshot). You can know the parent component of a component being instantiated by abusing { current_component } from 'svelte/internal'. And you can know when a component is destroyed by abusing the component's this.$$.on_destroy callbacks (which seems like the most fragile part of our plan).
Going into much more detail about how to proceed with this seems of bit out of scope for this question, but the following basic example should give you some ideas of how you can proceed. See it in action in this REPL.
Here's some code that watches Svelte dev events to maintain a component tree, and exposes it as a Svelte store for easy consumption by others. This code would need to run before your first Svelte component is created (or before the components you want to catch are created...).
import { current_component } from 'svelte/internal';
import { writable } from 'svelte/store';
const nodes = new Map();
const root = { children: [] };
// root components created with `new Component(...)` won't have
// a parent, so we'll put them in the root node's children
nodes.set(undefined, root);
const tree = writable(root);
// notify the store that its value has changed, even
// if it's only a mutation of the same object
const notify = () => {
tree.set(root);
};
document.addEventListener('SvelteRegisterComponent', e => {
// current_component is the component being initialized; at the time
// our event is called, it has already been reverted from the component
// that triggered the event to its parent component
const parentComponent = current_component;
// inspect the event's detail to see what more
// fun you could squizze out of it
const { component, tagName } = e.detail;
let node = nodes.get(component);
if (!node) {
node = { children: [] };
nodes.set(component, node);
}
Object.assign(node, e.detail);
// children creation is completed before their parent component creation
// is completed (necessarilly, since the parent needs to create all its
// children to complete itself); that means that the dev event we're using
// is fired first for children... and so we may have to add a node for the
// parent from the (first created) child
let parent = nodes.get(parentComponent);
if (!parent) {
parent = { children: [] };
nodes.set(parentComponent, parent);
}
parent.children.push(node);
// we're done mutating our tree, let the world know
notify();
// abusing a little bit more of Svelte private API, to know when
// our component will be destroyed / removed from the tree...
component.$$.on_destroy.push(() => {
const index = parent.children.indexOf(node);
if (index >= 0) {
parent.children.splice(index, 1);
notify();
}
});
});
// export the tree as a read only store
export default { subscribe: tree.subscribe }

Visual Studio Code with Native Script does not recognize all Native Script components

Visual Studio Code with Native Script does not recognise Native Script components sometimes in the component XML. I have one from the official tutorial and in it the ActionBar is recognized - but GridLayout is not:
'GridLayout' is not a known element:
1. If 'GridLayout' is an Angular component, then verify that it is part of this module.
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component.
XML looks like this:
<ActionBar title="Groceries">
<!-- On iOS devices, <ActionItem>s are placed from left to right in sequence; you can override that (as the code above does) by providing an ios.position attribute. -->
<ActionItem text="Share" (tap)="share()" android.systemIcon="ic_menu_share_holo_dark" ios.systemIcon="9" ios.position="right"></ActionItem>
</ActionBar>
<GridLayout rows="auto, *">
<!-- add-bar necessary since we moved the page up 20 over the status bar on iOS-->
<GridLayout row="0" columns="*, auto" class="add-bar">
<TextField #groceryTextField [(ngModel)]="grocery" hint="Enter a grocery item" (returnPress)="add()" col="0"></TextField>
<Image src="res://add" (tap)="add()" col="1"></Image>
</GridLayout>...
It seems totally arbitrary since for example StackLayout is no problem in another XML in same project.
As suggested in the error log make sure that you have included NO_ERRORS_SCHEMA in the respective NgModule (if using lazily loaded modules include the schema there as well)
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
#NgModule({
schemas: [NO_ERRORS_SCHEMA],
//... more code follows here
Side note: it might be just an incomplete snippet but still... the parent GridLayout does not have an enclosing tag
In my case, it was happening just for one component html though NO_ERRORS_SCHEMA was included in respective module of that file, deleting and creating that file solved the issue for me strange but it did happen.

"Clicking" on a not visible element

So my current situation is that I am trying to click on a marker based in a Google Maps window on a webpage. I have successfully located the markers in two manners: element.all(by.css('.angular-google-map-marker')) and element.all(by.repeater('m in map.markers')).
I have proven that I am obtaining the correct elements by changing the location on the Google Map and using count() to retrieve the number of markers present which returns the correct number in every case.
However, when I try to do for example element.all(by.css('.angular-google-map-marker')).first().click(), I receive the following error:
Failed: element not visible
HTML section
<div ng-transclude="" style="display: none">
<span class="angular-google-map-marker" ng-transclude="" ng-repeat="m in map.markers" options="m.options" coords="m.coords" idkey="m.id" click="onMarkerClick"></span>
<span class="angular-google-maps-window" ng-transclude="" coords="activeMarker.coords" options="windowMapOptions" show="windowMapOptions.show" closeclick="closeInfoWindow" templateurl="'gMapInfoWindow.html'" templateparameter="activeMarker"></span>
</div>
Normally elements that trigger some event due to clicking have an attribute like ng-click= foo(), however the markers above only use click= foo(). In addition if you look the line with the div tag, it says display: none, which might explain the visibility error.
My Question: Is there a way to activate the effect of an attribute like click= foo() without clicking on the element directly?
Aside from trying to make an element visible and then clicking, you can attempt clicking "via JavaScript" (there are some differences though - WebDriver click() vs JavaScript click()):
var marker = $('.angular-google-map-marker');
browser.executeScript("arguments[0].click();", marker.getWebElement());
First of all be sure that you can interact with the element when it is visible, you can do this from within the DevTools of your browser, make it visible by adding a display:block. Then check that if you change the value of the selectbox, the value can also be used with Angular Binding.
If so, you can easily make the element visible with Protractor by injecting a piece of Javascript in the page with the following command:
browser.executeScript('document.querySelector("div").style.display = "block"');
This results in a promise, so be aware of that!

Orchard rendering custom shape, displaying one child only

I'm very new at orchard and I'm having troubles finding a solution for what I think is a basic problem.
I want to render my own custom shape 'Content-Button' for my custom content type 'Button'. This works wonderful!
The Button content is made out of:
Display name
Content picker
My custom shape looks like this:
#using Orchard.Utility.Extensions;
#{
if (Model.Title != null) {
Layout.Title = Model.Title;
}
Model.Classes.Add("content-item");
var contentTypeClassName = ((string)Model.ContentItem.ContentType).HtmlClassify();
Model.Classes.Add(contentTypeClassName);
var tag = Tag(Model, "div");
tag.AddCssClass("row");
}
#tag.StartElement
<div id="" class="col-md-8 col-sm-10 col-xs-8 col-xs-push-2 col-sm-push-1 col-md-push-2 btn btn-secondary center-block">
#Display(Model.Content)
</div>
#tag.EndElement
What I'm however trying to do is instead of calling '#Display(Model.Content)' I would like to call a specific shape to be rendered there. Like #Display(Model.Content.DisplayName).
I would like to do the same for the content picker so i can make a link in the div (through ID)
I've also tried to exlude certain (extra) fields using my theme's placement.info) but it seems I'm doing something wrong there as well.
<Match ContentType="Button">
<Place Parts_Contents_Publish="-"></Place>
<Place Fields_Common_Text="-"/>
</Match>
Note: The 'Fields_Common_Text' was purely a test but it stills renders that shape on my button.
If somebody could point me in the right direction, explain it or send me some very good documentation to read through I would be a very happy man.
You can access fields directly as following:
#Model.ContentItem.ButtonPart.DisplayName.Value
and same thing for content picker field, then you don't need to use placement.info file any more.

How to stop MooTools stripping element IDs when clicked in Joomla 2.5.x using the 'modal' class [duplicate]

I have a form in a module that I want to appear in a modal window. Depending on the id the window may be blank, or if it does show any content all classes and ids are removed, so I can't validate or style the form.
Truncated Code:
...
<div id="feedback">
<div class="feedbackinner">
<!-- form module -->
<div id="contact-wrapper">
<!--form elements with ids and classes-->
</div>
<!-- end module -->
</div><!-- end .feedbackinner -->
</div><!-- end #feedback -->
This triggers the modal window without any ids or classes (using Firefox Web Developer outline current elements):
Click for ugly unstyled form that won't validate
This triggers a blank modal window:
Click if you like staring at a blank white box
So most importantly how do I keep all the ids and classes inside the modal window, and why won't calling the parent div work?
( As a work around I moved the form to a component view then called it using handler: 'iframe' instead of clone. I still want to know what's going on with the modal window. )
Thanks!
not seen the code but implications of using Element.clone on an element are apparent. By nature of HTML, id is meant to be unique. This means you are not really supposed to have more than one element with the same id injected into the DOM at the same time.
MooTools mirrors the sentiment correctly by implicitly removing the id from any element it creates a clone of:
https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L860
the .clone method accepts optional arguments which allow you to override stuff:
clone: function(contents, keepid){ - see http://mootools.net/docs/core/Element/Element#Element:clone as well.
cloned elements also lose all the events you may have assigned to them (but cloneEvents can help with that).
I would recommend looking at the squeezebox implementation and double check that the clone is implemented in the intended way. A better practice may be to adopt and re-attach the elements instead - or to copy the whole innerHTML (though this will once again cause non-delegated events to fail).