What is the difference between applyTo and contentEl in extJS? They are two config properties of the panel.
applyTo renders the panel into a target element (the panel body could still contain any content), contentEl uses the target element as its body content (the panel could still be rendered to any other element). The two methods are unrelated.
Edit: Just a note that as of Ext 4.0+ the applyTo config no longer exists. As time went on, the declarative / progressive enhancement strategy became less viable for Ext (it never was fully supported in all components anyway), and they finally stopped supporting it. You would always use renderTo now (to render programmatically to a target element), whereas contentEl is still valid and still indicates the element from which to take content and add it into the panel's body.contentEl is most useful when you have some existing HTML on the page that you want to display inside a Panel component without having to reproduce the content markup in JS code.
While I'm here, I suppose I'll clarify something else... It's important to understand that renderTo is typically only used by the top-most container in an application layout. All child components should always be added as items to a Container -- rendering child components directly to a target element via renderTo means that those components will not participate in the Ext-managed layout system, which you typically do NOT want in an application.
Another difference is that every component in Ext supports renderTo, but only certain components (most usefully Panel) will honor contentEl in a meaningful way. Even though contentEl is defined on AbstractComponent, most components are not designed to handle arbitrary HTML content.
Generally, applyTo uses the specified element as the main element of the Component, while contentEl is only for Panels that simply moves the specified element into the body of the Panel when the Panel is rendered to use as the content!
Related
I have a dropdown element directive to display in essence a styled dropdown list with additional capabilities.
My dropdown controller has a function called openDropdownItems that get's executed when the list should be displayed.
Then I also have another attribute directive called setInViewWhen that provides an expression when the element should be scrolled into view when condition is true.
<x set-in-view-when="something.item === selectedItem">
This is just an example of some X element with my attribute directive applied.
The thing is that I would like my dropdown list items (LIs namely) to have this directive on them so when user navigates over them using a keyboard, it would automatically scroll them in view when they get passed visible viewport. Whether these items are displayed within a scrollable container or as a whole in a list longer than the browser viewport isn't really relevant.
The main idea is for scrolling to follow dropdown list selection. Whether that should scroll the main window.
The problem
I can make my setInViewWhen directive completely independent but that means that I would have to search for the closest scrollable container whenever condition changes on an item. This seems to be quite a bit of processing that I would like to avoid to repeat (I need to traverse the DOM upwards, checking each node's calculated stylesheet property OverflowY + some additional checks.
This basically seems redundant because whenever I get the closest scrolling ancestor all sibling elements with the same directive could reuse the calculation result.
Question 1
How can I share this knowledge between sibling directives? If I was to fire an event I could not know whether receivers are siblings or not without any additional processing.
Question 2
Instead of checking for scrollable container every time when my directive's condition becomes true I could theoretically change dropdown parent's openDropdownItems to first complete it's original execution an then also execute the scrollability check and use the result of it along with my directive's condition.
I can gain access to dropdown's controller in my directive via directive requires property and adjust it in the post-link phase.
But this also means that I couldn't use my directive outside of dropdown which I would like to as it is a generally usable directive I could attach on several elements in my app to scroll elements into view under certain conditions.
What would you suggest how to do this?
To sum up the comments:
For Question 1, there is no direct way for sibling directives to communicate with each other. I usually create a wrapper parent directive to relay the messages.
As per the comments, the condition something.item === selectedItem introduces a watch; for a list of select items this can be many watches and detrimental to performance. Even if it doesn't occur now, it is a trap and someone may be lured into using this for a long list of items in the future. I would rather have a single watch in the parent of the <li>s and add the "scroll into view" logic there.
With the previous point in mind, you could still have a standalone setInViewWhen directive (seems useful) and have the controller of your X-select replacement directive share code with it. E.g.:
a service containing the common functionality,
an angular value containing a base class (Typescript or JS) and have the controller of both the setInViewWhen and X directives extend from it
or any other solution that is convenient for your case
Related to Question 2: The children could require their parent and change a method in it (this technique is even endorsed by Angular, see ng-model and custom controls where they override ngModel.$render() by replacing it). If you do that however, there would be many children changing the method of the parent, which could lead to a mess.
Issue: I have an accessibility issue that I am struggling with. I have an angular web application. A page loading spinner/indicator is shown when content is loading. And when the page content has loaded the spinner is hidden. This "div" is never removed from DOM.
Content of the loading div are not read (by NVDAor jaws) when the loading div is shown.
<div class='loading' aria-live='polite' aria-label='Do not refresh the page' tabindex="-1">Do not refresh the page</div>
I wouldn't like to change the structure of the application but work around using 'aria tags' to resolve this, just wondering if I will have to do anything more to make aria-live work?
Updated (27/July/2016)
Further clarification: I am not removing the content from DOM but using css to show/hide content (display: none to display: block and vice versa)
aria-live triggers screen readers when an element with aria-live (or text within an element with aria-live) is added or removed from the DOM. In contrast, when you unhide a hidden element, neither elements nor text are added or removed from the DOM, so the element's aria-live property doesn’t come into play.
To get screen readers to announce “Do not refresh the page”, either of these options should do the trick:
You can create the <div class='loading' aria-live='polite'> element and its text content from scratch and then add that element to the DOM.
Or you can start with an empty <div class='loading' aria-live='polite'> element and then populate its text content.
A few other tidbits:
As long as the text inside the element is what you want to be read aloud, you can omit the element’s aria-label='Do not refresh the page' attribute.
For icing on the cake, it can’t hurt to include a role attribute on the div that has aria-live. If you’re not sure which role to use, go with role="status"—that’s a pretty safe bet.
When or if the page is at a state where you no longer need to display "Do not refresh the page”, be sure to reverse the steps above. (That is, if you went with the first option and you added the whole element to the DOM, remove that entire element from the DOM. Or if you went with the second option and you populated the element’s text content, clear out the element’s text content.)
There are several issues with dynamically added or shown/hidden live-region.
Firstly a quote from MDN - ARIA live regions:
Simply including an aria-live attribute or a specialized live region role (such as role="alert") in the initial markup as it's loaded will have no effect.
Dynamically adding an element with an aria-live attribute or specialized role to the document also won't result in any announcement by assistive technologies (as, at that point, the browser/assistive technologies are not aware of the live region yet, so cannot monitor it for changes).
Always make sure that the live region is present in the document first, and only then dynamically add/change any content.
From my personal experience, even if a live regoin exists in the DOM on page load if you use show/hide then NVDA also has a bug which requires a small delay before a text update in a live region after it was shown initially. Apparently because the region didn't exist when the first text was added, so this isn't an "update". Regarding the timeout, you'd need to set it to something greater than the browser's refresh tick. I use 100ms. Disclaimer: I am strongly against such workarounds to make up for the issues with screen readers or browsers but it might be useful for someone in some cases.
I know that i require foundation/components/parbase as a sling:resourceSuperType, as Parbase allows components to inherit attributes from other components.
As an Example, i removed parbase as resourceSuperType from foundation/components/image component and the dialog was not able to load properly as seen in the Screenshot, Crop, Rotate, Clear functionality is no longer working.
I've confirmed that Ext Js library is being loaded properly for xtype 'html5SmartImage', So what extra things does foundation/components/parbase provides for this functionality ?
Parbase allows components to inherit attributes from other components.
The above statement is a bit wrong in my opinion. It doesn't allow you to inherit attributes from other components. Rather any component which defines foundation/components/parbase as it's parent would inherit the scripts of parbase.
If you look at the parbase component within AEM, you would find a servlet which renders an image, when the URL contains img selector. Additionally you may also find a script that caters to the selector scaffolding.
Thus, whenever you define parbase or any other component inheriting from parbase as the super type for your component, you are able to use the image rendering features without the need to write separate logic for the same.
Coming to your example of the image component, the html5smartimage makes a request to the resource using the request suffix (.img.png), which is when your Image rendering servlet kicks in and draws the image. Since you have removed parbase from the super type, you would receive a 404 for the request thereby showing empty panel. However, the buttons displayed as disabled is altogether a different issue. It's a bug/feature in AEM, that when the requested image is not found, further processing of the panel stops thereby rendering them disabled.
I'm actually not sure if this is possible, but I will ask it anyway. I have a group of accordion controls, and within the content body of each I need to display a grid panel. The grid panel needs to have a click event attached to it. I have tried simply creating the grid panel and setting the html property of the accordion to it, but this produces no content.
Is there somehow I can achieve the above?
You cannot have html content (inserted by the property) along with any other content. If you add any item the html property value will not set/overriden. But for sure you can place anything you want into one accordion panel. Even a grid. But for that case, and based on the last question, I would recommend you to reference the view into the grid. You may do this simply by using a ComponentQuery
The click events can be applied by using the control function of the controller.
For your basic understanding:
In ExtJS you seldom use plain html code. In most scenarios you use any sort of component. All is nested within the items-array or dockedItem-array. Items within these arrays get also processed by the layout system.
Some Query examples applicable to the control function
In the following this refers to the controller itself.
You know the Id of the grid (normally you didn't do this). Id's are marke by a starting #
control({'#yourId': {itemclick: this.onItemclick }});
You know the xtype and that there is only one instance of this type. You can also describe a path by using spaces between the xtypes.
control({'grid': {itemclick: this.onItemclick }});
You have set a custom property to grid (you can refer any property this way). This one is fully compatible the the one above. I recommend this one in your case
control({'grid[customIdent=accordionGrid]': {itemclick: this.onItemclick }});
This are just some ways to use ComponentQueries, there are more. For a more detailed explanation you should refer the sencha API for ComponentQuery
Also note that every component implements the up() and down() methods which also support ComponentQueries.
I forgot to mention: For a control the query strictly need to return just one result (only the first one will be taken) a ComponentQuery on the other hand can return multiple results.
This is perfectly possible but the accordion's body is not the place to put that in. You'll need to add it to the items: [] array of the accodion. The body (or html) only accepts html.
Example:
http://docs.sencha.com/ext-js/4-1/#!/example/layout/accordion.html
this one has a grid within it.
Since the ComboBox and FilteringSelect use a 'dijitPopup' whose DOM element gets inserted just before the closing body tag (presumably to help with ensuring it appears above everything else z-index-wise) this means that if the ComboBox is contained in an element that scrolls independent of the window itself and the user opens the dropdown and then scrolls the window (or whatever containing element) using the scroll wheel, that the menu part doesn't move with the control itself.
Is there a straightforward way to ensure that the menu part of the view remains positioned correctly relative to the control itself rather than simply assuming that its starting position is ok?
EDIT: appears to be a known issue (http://bugs.dojotoolkit.org/ticket/5777). I understand why they put the dijit popup just before the closing body tag for z-index stacking and overflow clipping issues, but it seems like it's maybe not the ideal way to do things given the bug in question here and things like:
You can restrict the Dijit theme to only small portions of a page; you
do this by applying the CSS class of the theme to a block-level
element, such as a div. However, keep in mind that any popup-based
widget (or widgets that use popups, such as dijit.form.ComboButton,
dijit.form.DropDownButton, and dijit.form.Select) create and place the
DOM structure for the popup as a direct child of the body
element—which means that your theme will not be applied to the popup.
~ from http://dojotoolkit.org/documentation/tutorials/1.6/themes_buttons_textboxes/
Not sure if this is the very best solution, but here's what I came up with:
Since the widget may be programmatically added/removed, and to avoid coupling a solution with some particular surrounding markup that we can't always count on in all cases, what I did was to hook the _showResultList and _hideResultList methods of ComboBox and when the popup opens, traverse up the DOM till we reach the <html> tag, adding onscroll listeners on each ancestor.
The handler for the onscroll event is simply:
var myPos = dojo.position(this.domNode, true);
this._popupWidget.domNode.parentNode.style.top = '' + (myPos.y + myPos.h) + "px";
where this is the widget in question. I scope the handler to the widget using dojo.hitch. In the close method I remove the listeners. I have to clean up the code a bit before it's presentable, but when it's finalized I'll add it to this answer.
Note: I only show updating the y position here. Part of the cleanup is to add x position updating in case someone scrolls horizontally.
Though its old I just faced this same problem and it looks like a Dojo issue and the fix is available here https://bugs.dojotoolkit.org/changeset/30911/legacy