GWT : How to remove element from it's outermost? - gwt

I have one Anchor widget as
<td class="GAS3MDBHJ">
<div class="GAS3MDBJJ">
<a class="gwt-Anchor" href="#export">Export</a>
</div>
</td>
I would like to remove this anchor element from it's root. How can I achieve it.
If I use widget.getParentElement() , I need to write as ...
myanchor.getElement().getParentElement().getParentElement().removeFromParent();
Now it is in third level.If my widget is in level 7 or 8 or 9 , am I need to write getParentElement() repeatedly ?
Has there anyway for fast code ?
I don't want to get it's parent element, I really want to get was outermost element.

You should simply call
anchor.removeFromParent();
It will remove the entire anchor element with all of its inner HTML. The result will be exactly the same if you call
anchor.getElement().removeFromParent();
because anchor.getElement() will give you the outer most element of this widget, just as you wanted.
If you start calling getParentElement(), you will remove more than your anchor widget.

Related

Validate Element that Doesn't Appear in DOM

I want to test that the text "Name contains Referencia", that I show in the image, appears in a textarea; this text appears as a result of doing a filter action over a data area. However in the DOM this text is not shown. Could anybody explain why it isn’t shown? and how can I get that specific text if I don't have a locator?
I've tried this:
cy.get('textarea[name="cdFilter"]')
.click()
.then(()=>{
cy.contains('(Name contains Referencia)').should('exist')
})
but it doesn't work. I've tried also getting the text attribute from the textarea element but it doesn't make sense since the textarea doesn't have a text attribute.
I appreciate your help and comments.
Thanks in advance!
<td align="left" class="formCell" style="" id="isc_1S" $89="isc_TextAreaItem_1"><textarea name="cdFilter" id="isc_1T" $89="isc_TextAreaItem_1" $9a="$9b" class="textItem" style="resize:none;margin:0px;WIDTH:234px;HEIGHT:96px;" autocomplete="OFF" spellcheck="true" wrap="SOFT" tabindex="2305" oninput="isc_TextAreaItem_1.$43g()" readonly="TRUE" handlenativeevents="false"></textarea>
</td>
It could be in shadow DOM, in which case add includeShadowDom: true to your cypress.json config file and the test might succeed.
The text is definitely not in the textarea element, but it could be another element positioning itself over the text area.
Couple of other things to try
Shorter text search in case the spaces are nbsp
cy.contains('Referencia')
Grab the textarea by id and look at it's text
cy.get('textarea#isc_1D').its('text')
.should('contain', 'Referencia')
//or
.then(text => console.log(text))
There may also be two of these textareas - if you look at style details, they don't quite fit, e.g style attribute width and height don't quite match the numbers in the tooltip, and a small margin is showing even though margin:0px is set (but may be that's due to <td> settings).
Checking how many textareas:
cy.get('textarea[name="cdFilter"]').click()
.then(() => {
// test count after clicking
cy.get('textarea[name="cdFilter"]').then($ta => console.log($ta.length))
})

jQuery nth-child confusion

On this page:
https://weargustin.com/store?filter=all
Why is the first element of this selector:
$('div.funded.product:nth-child(3n)')
The second element of
$('div.funded.product')
?!
The problem is that nth-child loops over all children and tests them against the selector. It does not use the selector and then loop over those that match. So as PSL mentioned, the other items you have which are siblings are throwing the whole thing off.
Here's an example fiddle to break it down: http://jsfiddle.net/Ga5Jq/
<div>
<p>test</p>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
$(function() {
alert($("div span:nth-child(3n)").html());
});
The above code alerts 2 because the second span is really the third child of div matching the selector, span.
I think you want to select every 3rd of that type so you should try using nth-of-type instead of nth-child since there are many other siblings to start with other than div.funded.product. For instance you have the div .product.funding also coming in as the child of the same parent.
$('div.funded.product:nth-of-type(3n+1)')
See :nth-of-type

How to wrap elements under a GWT HTMLPanel

Let's say I create an HTMLPanel with some HTML like:
<p>
Blah blah <span id='1'>more html... </span>
</p>
Now I want to attach an event handler to the span. I want to see it as an InlineHTML GWT widget. I tried:
HTMLPanel html = new HTMLPanel(stringOfHTML);
parentWidget.add(html);
String id = "1";
Element span = html.getElementById(id);
InlineHTML wid = InlineHTML.wrap(span); // -- error here
html.addAndReplaceElement(wid, id);
The second-to-last line dies with the AssertionError: A widget that has an existing parent widget may not be added to the detach list.
Is there a way to wrap sub elements in a HTMLPanel?
This is GWT 2.4.
Note
After a few comments and answers I realized that I forgot to mention: usually UiBinder is the answer here, but I'm not using it because the input is html text created in another context by non-programmers.
No, not really. You getting this exception because <span> element is already a part of some widget. wrap methods can be used only to create widgets on top of elements which are not part of some other widget. If you want to handle clicks on this span, you can add dom handler to the HTMLPanel, and then detect which element was clicked.
Convert your <span> into an InlineLabel inside your UiBinder template and attach anything you want to it :).

Simple jQuery selector

I am trying to select the surround element when a image within the span is clicked 'remove()', but I am a little new to jQuery and can't figure out how to do it. I can't use a unique id as the element are generated dynamically.
For example:
<span class='type_link'> <img src='/images/deleteCross.gif' onclick='remove()' />Example</span>
I want to select the span when the image is clicked.
Here is an example to hide the parent element of the image:
<span class='type_link'> <img src='/images/deleteCross.gif' onclick='$(this).parent().hide();' />Example</span>
The trick is to use "this" and the parent()-function.
Cheers,
Chris
Look at this (for selector) and this (for event)!
Also W3schools provide Good example for first step in Jquery.
How about .parent() http://api.jquery.com/parent/

How to replace element with my GWT widget?

Is it possible to replace known html element with my widget component? (Emphasis on the word 'replace', I don't want to put the widget in that element. :)
<body>
<img />
<div />
<a id="tmpEl" />
...
<img />
</body>
would become
<body>
<img />
<div />
<div class="gwt-panel">...</div>
...
<img />
</body>
I tried something like this...
tmpEl.getParentElement().replaceChild(myPanel.getElement(), tmpEl);
...but the resulting DOM elements were 'deaf', i.e. they did not receive click events. (To make this work I would probably have to call RootPanel.get().adopt(widget), but that method is not accessible.)
For a second I thought HTMLPanel.addAndReplaceElement could be the answer, but that only works when your 'placeholder' element is (direct) child of HTMLPanel widget. Which is obviously not my case. :(
Note please that I only know id of that element, I'm not creating it. Simply put: I need exactly what the question says.
As for 'DOM manipulation at higher level': I will happily manipulate the DOM at highest possible level if it lets me place widget instead of that placeholder element.
It seems that calling widget.onAttach() after inserting widget into DOM does the trick.
class MyWidget extends Composite
{
...
public void attach()
{
/* Widget.onAttach() is protected
*/
onAttach();
/* mandatory for all widgets without parent widget
*/
RootPanel.detachOnWindowClose(this);
}
}
tmpEl.getParentElement().replaceChild(myWidget.getElement(), tmpEl);
myWidget.attach();
Credit goes to André at Google Web Toolkit group.
I still wonder though why there is no RootPanel.addAndReplaceElement(Widget, Element), similar to HTMLPanel.addAndReplaceElement(Widget, Element).
The solution is probably not so much different from what Igor suggested. I'd write something like this:
RootPanel rootPanel = RootPanel.get();
Element anchorElement = DOM.getElementById("tmpEl");
Anchor anchor = Anchor.wrap(anchorElement);
rootPanel.remove(anchor);
rootPanel.insert(new HTML("<div class='gwt-panel'>...</div>", 0);
I agree with markovuksanovic - you should consider DOM manipulation on a "higher level". For example, the functionality you need is provided via the InsertPanel interface, which FlowPanel implements:
FlowPanel mainPanel = new FlowPanel();
Hyperlink link = new Hyperlink("Something cool");
mainPanel.add(link);
mainPanel.add(new Label("Bla bla"));
// Now we want to replace the first element of the FlowPanel with a TextBox
// We can do that by its index...
mainPanel.remove(0);
// ...or Widget instance
mainPanel.remove(link);
// Now we add a TextBox at the beginning
mainPanel.add(new TextBox(), 0);
As you can see, this code is much more readable (at least to me), you don't manipulate the DOM directly (referencing via ids and such). Of course, there are places where direct DOM manipulation is beneficial (optimizing, most notably), but for the most part, I'd avoid juggling Elements, ids and such :) (at least in GWT)
I'm doing something pretty similar. I'm reading the contents of a <div>; using the elements found in the <div> to build an animated menu which then replaces the original content. The animated menu is a widget.
It seems to work...
// DisclosurePanel is a widget
DisclosurePanel accordion_panel = processAccordion(accordionElement);
// accordionElement is found in the DOM (it's a com.google.gwt.user.client.Element)
// clear what was there
accordionElement.setInnerText("");
// add the widget in
RootPanel.get(accordionElement.getId()).add(accordion_panel);
I would suggest you try something like this...
<body>
<a id="tmpEl" />
</body>
then in somewhere create a widget (e.g. textBox widget)
TextBox tb = new TextBox();
After you have created the widget you can get it's DOM object by using tb.getElement() (I'm not sure that's the correct method name, but it's definitely something like getElement)
After that you could use
Element parent = Document.getElementById('tmpEl').getParent();
parent.removeChild(Document.getElementById('tmpEl'));
parent.appendChild(tb.getElement());
One more thing that add() does is call Widget.onAttach() on the widget that is being added to the panel. onAttach does some work to register the widget to receive events.
You could try calling tb.onAttach(); It might also be necessary to call RootPanel.detachOnWindowClose(tb); (as mentioned in a previous post)