Cloning parsys component functionality - adobe

I wish to take the component libs/foundation/components/parsys/colctrl/... and modify its text so that I can use it for css tabs instead. I recreated it as apps/-site-/components/content/tabsys/ (and all it's subfolders/components/etc. The only thing I didn't change was in tabsys/tabctrl/virtual/2tabs/cq:editConfig/cq:formParameters (same for 3tabs/ as well):
sling:resourceType = foundation/components/parsys/colctrl
layout = 2;cq-colctrl-lt0
In the sidekick I now have a Tabs component option, with the same options as Columns. However, when I drag any of the Tabs into the content area, I don't get any of the border content areas to drag content pieces into; only the Edit/Delete/New bar. When I click Edit I should have a dropdown for the number of columns I want to have (Columns component has it for reference). What am I missing?

I ran into this same issue, and the reason for this seems to be that the ParagraphSystem class used by the parsys component only parses/generates the columns/containers if the sling:resourceType of the content node ends in "/colctrl".
private String colCtrlSuffix = "/colctrl";
if (res.getResourceType().endsWith(this.colCtrlSuffix)) { /*creates columns*/ }
In your example, the tabctrl should have a reference to the Super type:
sling:resourceSuperType = "foundation/components/parsys/colctrl"
Secondly, if tabctrl were renamed to colctrl then the ParagraphSystem would attempt to parse the columns based on the number specified in first part of the layout attribute and create the additional content nodes for each column.
If the ParagraphSystem class looked for "-colctrl" rather than "/colctrl" it would have allowed for customized components like "my-colctrl". Instead, I guess we need to use folders to avoid naming collisions. (i.e., apps/-site-/components/content/tabsys/colctrl)

Related

angular showing/hiding DOM elements based on what class they have

I'm going to simplify my problem a bit, because I really want to avoid adding a lot of code, because this is a gigantic project we are working on if I started adding code snippets, there would be a lot of it.
My project has one feature, where you have a list of different div elements in the left column of the page, and they can be individually dragged to the right column, where you can make your own list out of these elements in the order you choose.
These div elements are all the same child component. My task is to add a dropdown to these div elements, but only to the ones that have been dragged to the right column (you can choose additional preferences, once it's in the right column). It shouldn't be there on the divs in the left column.
The only way to differentiate between them is by the class name. The ones on the left have a class="left" and the ones on the right get the class="right".
Now I'm wondering if there's a way where I can write some code to the effect: if the element has the class 'left', hide the dropdown, else show the dropdown?
Yes, this is definitely possible.
Create a Directive that has a #HostBinding() for a specific class and just add the directive to every component.
Inject ChildComponent into the constructor of that Directive. You can also inject ViewContainerRef and then call this.viewContainerRef["_data"].componentView.component This will give you reference to that child element that the directive is put on.
Once the #HostBinding('.left') event handler is triggered this will be the function that gets called when the class you're looking for is added. Here you can then access that ChildComponent and then presumably call a method on that child component to show/hide the mat-select
I haven't actually tested this but thats the approach I would take.
You might also achieve this thru your css. Something like
div[class*="left"] dropdown-element {
display: none;
~or~
visibility: hidden;
}

How can I scrape a website for the nav menu only

I'm building a program that scrapes a website. It looks at the entire website and takes only the header and footer navigation menus from that website, then inserts new html tags (div, p, table, etc.) in between the header and footer menus.
I'm looking for some ideas on how to strip only the header and footer nav menus, as well as add code in between the two.
I'm using HTML Agility Pack and have worked on a few methods.
Method 1:
In most cases, the header and footer navigation menus are mostly
links, and have very little text. I used a threshold variable that
was a ratio of text to links. If the ratio text:links for a node is
less than the threshold, the node would be considered a menu node, and
it would be saved. Any node whose text:links ratio was greater than
the threshold value would be removed.
Method 1 worked for some sites, but not for others, so I ditched it.
Method 2:
I searched each node for an id or class attribute that included "nav"
or "menu". "n","a","v", "m","e","n","u" could have been upper case or
lower case, and "nav" and "menu" could have been surrounded by any
combination of characters. That way, it would include id's and
classes such as "bottomNav", "navRight1", "LeftMenu2", etc. If the id
or class contained either "nav" or "menu", the node would be saved.
If the node's attributes did not contain either of those terms, or any
of the node's descendants did not contain either of those terms, the
node would be deleted.
Again, method 2 worked for some sites, but not for others.
For the sites where either of these methods worked, I still wasn't able to put new html code in between the two menus, because I had no way of telling where the header menu ended, and where the footer menu began.
I'm just looking for other ideas on how to scrape only the header and footer navigation menus from a website, and insert new html code in between the two.
Other than looking for specific elements or element classes (header, nav, ...), you can try to look at the problem in a different way:
first, fetch and parse two (or more) pages from each website, preferably checking that they vary substantially (but not totally);
then, do a diff (of the DOM, preferably), and retain only the common structure.
This common structure should consist mostly of headers, footers, navbars and other elements more or less constant across each website.
A final step might be to look in this common structure for small gaps caused by headers/footers that vary depending on context, as opposed to large gaps caused by different (main) content, and scrape their possible values from the largest set of pages you can fetch from each website.

What's the easiest way to create an extensible custom container in Flex?

I want to create an MXML container component that has some of its own chrome -- a standard query display, et al -- and that supports the addition of child components to it. Something a lot like the existing mx:Panel class, which includes a title label, but acts like a plain mx:Box with regards to adding children.
What's the easiest way to do this?
Edit:
To be clear, I want to be able to extend the container using MXML, so the "Multiple visual children" problem is relevant.
Extend a container and add a title label. Probably the <mx:Canvas/> will work here. Make the title a public var and include a var for the styleName of the label.
Then override the addChild() method so that any child that is added is added instead to the that is your container.
Leave enough space for your title when you position your Box element (i.e., give its y property enough space. If there is no title you may want to reclaim that space.
That's the basics. Customize to your heart's content.
EDITED TO ADD: I do this creating an ActionScript class first, extending the container I am targeting, and I add the "furniture" — items the class will always use, like title in your case — by overriding createChildren and calling super.addChild(item) for those items. Calling addChild from then on, even in MXML markup, adds items to the inner container.
We do this with states.
We put the chrome for the base container in a state (in mx:AddChild elements) and then use the initialize event to switch to that state when the control is created. All the chrome is then added to the container.
That gets round the multiple sets of visual children problem.
The downsides to this approach are:
You don't see the chrome when editing descendents of the base.
You can't directly access the parent chrome controls from descendent components as they are not there at compile time (instead, you need to define properties, methods or events on the base that the descendents can access)
However, it works well for us.

Auto-sizing and positioning in Flex

I am working on a flex app that uses XML templates to dynamically create DisplayObjects. These templates define different layouts that can be used for each page of content in the app (ie , 2 columns, 3 columns etc etc). The administrator can select from one of these and populate each area with their content.
The templates add one of 3 types of DisplayObject - HBox, VBox or a third component - LibraryContentContainer (an mxml component that is defined as part of the app) - which is effectively a canvas element with a TextArea inside.
The problem that I am getting is that I need each of these areas to automatically resize to fit the length of the content but don't seem to be able to find an effective way to do so.
In the LibraryContentContainer, when the value of the TextArea is set, I am calling .validateNow() on the LibraryContentContainer. I then set the height property on both the TextArea and LibraryContentContainer to match the textHeight property of the TextArea.
In the following example, this is the LibraryContentContainer, viewer is the TextArea and the value property of the TextArea is bound to this.__Value. v is the variable containing the content for the textarea
this.__Value = v;
this.validateNow();
this.viewer.height = this.viewer.textHeight;
this.height = this.viewer.height;
This works to a degree in that the TextArea grows or shrinks depending on the length of content, but it's still not great - sometimes there are still vertical scrollbars even tho the size of the TextArea has grown.
Anyone got any ideas?
Thanks
Adam
I think the problem lies not with your dynamically added components, but with the component they're being added to. How is the height of this component being determined? If you set verticalScrollPolicy and horizontalScrollPolicy on this container to off, do your scrollbars disappear? If that's the case, then you'll need to look at how this component is sized rather than your hbox, vbox, or whatever it is you're adding.

Formatting AdvancedDataGrid Cells

I have a quick question about rendering the advanceddatagrid cells.
I need to programatically color the cell of the datagrid based on the conditions. Lets say, the stock quotes. If there is an increase from the previous day, I need to have the cell colored in GREEN and in RED, when there is a decrease.
Now, the important part here is, I need to do these things dynamically, which means, when the user enables the comparison/conditions, then the cells are colored. And when the user disables the comparison, then it again goes back to its default behavior.
I know I have to use renderers. But not sure, how to use it for the cells and that too dynamically. Can anyone please explain how to go for it?
Thanks
Item renderers are components used to define the appearance of a component's "items" or subcomponents. In the case of the ADG, the "items" are the individual cells. You can create a completely custom class to function as the renderer (given it implements certain required interfaces) or, in most cases, you extend an existing component. Since the default renderer for ADG cells doesn't support background colors, you have to create or extend a component that does and use that as the renderer. That is the basic premise that these tutorials, linked to in the following question, work from:
Setting background color for datagrid row in Adobe Flex
After creating an itemRenderer that supports a background color, you have two options as to where you can define your "conditions"; inside of the itemRenderer or using the ADG's styleFunction (additionally requiring that your itemRenderer defines a "background" style).
In your case, you could include both today's and yesterday's stock price values in the data sent to each cell and compare the two to determine the color used to draw the background. Again, more on that in the tutorial links provided above. In either the itemRenderer or the styleFunction, you would compare properties on the itemRenderer's/styleFunction's data object (corresponding to the row you're looking at), e.g.:
if(data.today > data.yesterday)
{
// set color or return style
}
else ...
To "toggle" custom cell colors, switch between your custom renderer and the default (colorless) renderer. In other words, set the itemRenderer property to your custom itemRenderer class when you need display the colors and set it to "null" when you want the "default behavior".

Resources