I am pretty new to GWT, and I have these dynamic divs setup on my starting GWT html page:
<div id="nav">
Navigation goes here...
</div>
<div id="core">
</div>
<div id="footer">
footer info goes here
</div>
I have my main class that implements EntryPoint and ValueChangeHandler to dynamically change the "core" div so it renders different information based on what the user clicks on the main page (so it mimicks using different pages, but only using one through History and Hyperlink classes Like this). I tried doing this with something like:
VerticalPanel panel = new VerticalPanel();
HTML mapHtmlDiv = new HTML("<div id=\"maps\"></div>");
panel.add(mapHtmlDiv);
RootPanel.get("core").add(panel);
// add a widget to the maps div downstream
Once the condition is met. However this is not allowed on GWT, as it throws an error along the lines of "A widget that has an existing parent widget may not be added to the detach list", what is the correct way of adding content and divs to HTML?
HTML widget in GWT is not a container. This means you can't add widgets into it. Use HTMLPanel instead.
VerticalPanel panel = new VerticalPanel();
HTMLPanel mapPanel = new HTMLPanel(""); //automatically creates a div.
panel.add(mapPanel);
RootPanel.get("core").add(panel);
// add a widget to the maps div downstream
mapPanel.add(new Label("Sample label"));
http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/HTMLPanel.html
VerticalPanel panel = new VerticalPanel();
HTML mapHtmlDiv = new HTML("<div id=\"maps\"></div>");
panel.add(mapHtmlDiv);
Element coreDiv = DOM.getElementById("core");
coreDiv.appendChild(panel.getElement());
Related
Hi all,
I've been working on a set of Razor templates that is either Site Editable with the Experience Manager and at the same time is fully responsive for several screenwidths with the Twitter bootstrap. As a result, I need to dynamically manipulate the DOM output based on what the Experience Manager editor adds or deletes but still maintain the responsive design. Part of this construction is adhering to the rules the twitter bootstrap dictates.
The twitter bootstrap allows for excellent responsive design by introducing dynamically calculated div widths using classes. A <div class="span12> uses the entire width of the wrapper, for example. A "span6" effectively uses half, with a certain margin calculated as well to allow for another div with "span6". However, this only works if the preceding class is called <div class="row-fluid">,and as long as the span<numbers> actually add up to exactly 12. The problem arises when I need to close the <div class="row-fluid"> when this number is actually reached.
To clarify: it has to output like this
<div class="row-fluid">
<div class="span6">..code</div>
<div class="span4">..code</div>
<div class="span2">..code</div>
</div>
The <div class="span[#]"> are rendered with a component template, in order to allow for multiple components within the <div class="row-fluid>, which the Page Template renders.
However, from a component template level I cannot seem to retrieve the actual amount of components of this template actually exist on the Page itself. I calculate the width of the component used based on a schema option of the component itself. I use the following Component Template code to render it correctly:
#{
var spanClass = String.Empty;
if (Fields.HasField("component_width") && Fields.component_width != null) {
if (Fields.component_width.ToLower() == "full") {
spanClass = "span12";
} else if (Fields.component_width.ToLower() == "half") {
spanClass = "span6";
} else if (Fields.component_width == "40%") {
spanClass = "span5";
} else if (Fields.component_width == "35%") {
spanClass = "span4";
} else if (Fields.component_width == "25%") {
spanClass = "span3";
}
}
}
<div class="#spanClass">...code
To get to my question: I need to be able to close the <row-fluid> div if the number 12 has been reached. So if one component with the options 'Full' (width) is selected, the following output code needs to appear:
<div class="row-fluid">
<div class="span12">..code</div>
</div>
If there are two components on the page with the option "half" are selected, it must allow
<div class="row-fluid">
<div class="span6">..code</div>
<div class="span6">..code</div>
</div>
mind the closing div on the end. Is there some way I can reach the variable i created on the Component Template var spanClass = String.Empty; from Page Template? Something like:
#foreach (var cp in GetComponentPresentationsByTemplate("XM_Generic Content")) {
#if (cp.Component.spanClass == "span6") {
<div class="row-fluid">
#cp.RenderComponentPresentation()
#if (cp.Index == 1) {
</div>
}
}
}
I'm still getting to know Razor templates, the practicalities of Responsive design and ofcourse StackOverflow. Chances are that I completely missed something, made dumb errors in my code of just asked a silly question. By all means, let me know.
The package is not shared between template runtimes, so this behavior is normal (not being able to see variables set in one template from a different instance).
There are ways around this, but you should consider that perhaps there is a good reason why Tridion chose to isolate the template execution.
See here for one of the ways to go around this.
Standard techniques using the ContextVariables dictionary don't allow you to set something in the CT and access it from the PT. Effectively, each time a Component is rendered, the render context gets a fresh copy of the variables from the page render context. Writing back to them, therefore isn't effective. There is a technique that gets round this, which is described in detail on tridion-practice. As already noted, resorting to these kinds of techniques shouldn't be your first option, but sometimes you need to.
Currently, its seems, the user is defining the width position in the component field. I think, its quite typical, but if you create 5 Component Template which will call a same Razor TBB, and also define, a parameter schema on component Template where can set the width of component then afterwards you can easily call these different CTs in the page template.
I'm writing a Webpage in GWT and I use the following structure: I have a VerticalPanel as navigationmenu containing some gwt-buttons. Then I have a VerticalPanel as a contentPanel where different HTML-Pages could be loaded into (via ClientBundle).
The contentPane contains a single gwt-HTML-Object for that, in which the HTML-File is loaded.
Now I have some buttons in the navigationmenu, I'd like to use like HTML anchors in the contentPanel. Is that possible?
So when a longer HTML-File is loaded into the contentPanel and I perform a click on one of these buttons, that the page jumps to the specific anchor in the HTML-Object.
Any ideas how to realize this?
Well I think there should be two solutions:
If you use Anchor widgets or plain html anchor's in the navigation menu you can do it just like with regular html:
Navigation menu:
<a href='#myAnchor'>
If you really want to use GWT-Buttons you probably have to use Window.Location. Something like this might work tough I haven't tried it myself:
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Window.Location.assign('#myAnchor');
}
});
Alternatively you could set the id of the Anchor's in your contentPanel <a id='myAnchor'> and use following function to scroll to the anchor.
Element elem = DOM.getElementById('myAnchor');
if (elem != null) {
elem.scrollIntoView();
}
I recommend the first approach.
I´m evaluating GWT as one of the alternatives to develop AJAX applications for my future projects. Untill now it is as good as it gets, but now I´m stuck looking for a way to capture a click on a tag inside HTML widget. I want to write links inside the HTML but I want to process the clicks in my application, withou reloading the page. Imagine I have the following HTML:
<p>GWT is a great tool and I think it will be my preferred tool to develop web applications. To check out my samples <a id='mylink'>click here</a></p>
I want to capture the click over the "click here" part of the text. What I´ve done so far is to try to attach the id "mylink" to some sort of clickable widget and process the click with a ClickHandler for that widget, but nothing is working.
Is there a way to do that? By the way, I know very little about Javascript.
Thank you in advance.
You can also do it like this:
Anchor.wrap(DOM.getElementById("mylink")).addClickHandler(yourClickHandler);
DOM class is com.google.gwt.user.client.DOM.
Edit after comments.
OK, the method works for elements out of GWT widgets (element comes with HTML file). If you need to generate it in GWT code then you can add link element separately. But it won't work if your content goes for instance from DB.
HTMLPanel html = new HTMLPanel("GWT is a great tool and I think it will be my preferred tool to develop web applications. To check out my samples ");`
Anchor a = new Anchor("click here");
a.addClickHandler(yourClickHandler);
html.add(a);
If it is fully dynamic I don't have an idea at this point. I was trying with HTML() widget, where you can plug your click handler, but I couldn't find a right way to determine whether the click was in A element. Strange.
The final approach (I hope)
This one should work finally. And I think this is the way it should be done, especially that it allows any structure of the HTML. The are two ways:
1. Convert links within HTMLPanel
This one will find all A elements and convert them into Anchors. It ignores href attribute, but you can add it easily :)
HTMLPanel html = new HTMLPanel("<p>Multilink example 2: <a>link1</a> and <a>link2</a></p>");
NodeList<Element> anchors = html.getElement().getElementsByTagName("a");
for ( int i = 0 ; i < anchors.getLength() ; i++ ) {
Element a = anchors.getItem(i);
Anchor link = new Anchor(a.getInnerHTML());
link.addClickHandler(...);
html.addAndReplaceElement(link, a);
}
2. Insert links into prepared spots
Just insert placeholders, where the widgets should be inserted. You could also use the addAndReplaceElement() method but with string ID.
Anchor a1 = new Anchor("a1");
a1.addClickHandler(...);
Anchor a2 = new Anchor("a2");
a2.addClickHandler(...);
HTMLPanel html = new HTMLPanel("<p>Multilink example: <span id='a1'></span> and <span id='a2'></span></p>");
html.add(a1, "a1");
html.add(a2, "a2");
Try something like this.
For your web page, you can use UiBinder:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:HTMLPanel ui:field="panel">
<p>
GWT is a great tool and I think it will be my preferred tool to
develop web applications. To check out my samples
<g:Anchor ui:field="myLink" text="click here" />
</p>
</g:HTMLPanel>
</ui:UiBinder>
Notice that I've replaced your tag with an Anchor widget. There is also a Hyperlink widget, which has hooks into the history system.
The Anchor has a id of "myLink", which is used in the GWT companion to the XML file:
public class So extends Composite {
private static SoUiBinder uiBinder = GWT.create(SoUiBinder.class);
interface SoUiBinder extends UiBinder<Widget, So> {
}
#UiField
Anchor myLink;
public So() {
initWidget(uiBinder.createAndBindUi(this));
myLink.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
GWT.log("caught the click");
}
});
}
}
I've added a ClickHandler that captures and acts on the click event.
The main program is simple:
public class SOverflow implements EntryPoint {
public void onModuleLoad() {
RootLayoutPanel.get().add(new So());
}
}
Run this after and a webpage appears with the text and hyperlink. Click on it and "caught the click" appears in the console window (I'm using Eclipse).
I hope this is what you're after. If not exactly, it might at least give you some ideas of how to attack your problem.
I have a situation where I need to integrate a gwt dialog (which to the best of my understanding is implemented as a div with z-index manipulation) into an existing html page.
There are two scenarios:
1. Which is the preferrable and more complicated is where i give the host html page another page which they embed as an iframe and I work my magic through there (maybe connect somehow to the parent window and plant my dialog I'm not sure).
2. Where I have limited access to the html page and I plant some code there which will load my dialog box.
Any ideas or thoughts on how I can implement these?
I've been working for a few months now with GWT and have found it quite nice although I have stayed far far away from the whole HTML area and until now all my work has been done strictly inside my java classes.
Thanks for any ideas and help handed
Ittai
I'll assume by dialog you mean a popup that is invisible at page load and made visible by, say, a click on something in the existing HTML. A simple strategy to make this happen is wrapping the existing HTML.
I have no experience with option 1. As for 2, all you need to alter in the existing HTML is
adding the JS import, e.g.
<script type="text/javascript" language="javascript" src="/com.your.org.Module/com.your.org.module.client.Module.nocache.js"></script>
then adding an id to some clickable element you want to activate your dialog, e.g.
<button id="launchDialog">Show Dialog</button>
and finally adding an empty div with an id to insert your dialog into the DOM.
<div id="dialog"></div>
Then all you need in your Module is
public class Module implements EntryPoint {
#Override
public void onModuleLoad() {
Button b = Button.wrap(DOM.getElementById("launchDialog"));
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
RootPanel panel = RootPanel.get("dialog");
Widget w = ... // your dialog widget here
panel.add(w);
}
});
}
}
Lastly, you can play with the visibility of your popup div with the "display: none" style and the show() and hide() methods on the widget.
I have a block of HTML that I would like to use as the basis of a GWT widget, but am not quite sure the best way to do so. As an example, my HTML block looks something like this:
<div class="my-widget">
<div class="header">
<span class="title">Title Text</span>
</div>
<div class="body">
<span class="content">Content Text</span>
</div>
</div>
Now, I can of course paste this as a static string into an HTML widget, but in this case I need the ability to set the text of the "title" and "content" elements on the fly. This kills (or at least makes significantly more difficult) the static text option.
The first thing that comes to mind in that case is to build out the elements in GWT manually and hold references to the ones I need to alter, like so:
DivElement container = document.createDivElement();
setStyleName(container, "my-widget");
setElement(container);
DivElement header = document.createDivElement();
setStyleName(header, "header");
container.appendChild(header);
// Hold onto this element for later manipulation
DivElement title = document.createDivElement();
setStyleName(title, "title");
header.appendChild(title);
But this quickly get unmanageable for all but the simplest of layouts (which mine is not.)
What I would like is the ability to send the HTML in as static text and then do some sort of selector, like jQuery, to query the elements I want to manipulate. I'm aware of GWT-Query but I haven't been able to get it to run without error, and it seems to me to be a bit too early in it's lifespan for me to be comfortable integrating it into a professional product just yet.
I'm also aware of Google's UiBinder, which sounds exactly like what I want. The problem there is, as far as I can tell, that functionality is only available in GWT 2.0, which is still in a release candidate state and therefore unusable for me.
So, given all that (sorry for the long question!) do you have any suggestions about how best to achieve something like this?
GWT 2.0 will be out before the end of the year. So unless you need to deliver in a few days time, I would start working with the RC2 and try out the new UIBinder approach.
How about using HTML.wrap(). For example, if you added an id of "my-widget" to your outer-most div you could then do something like:
HTML myWidget = HTML.wrap(RootPanel.get("my-widget").getElement());
You can use the InlineHTML widget to produce a span and control its content.
As you probably know, GWT doesn't provide a built in widget that maps directly to a span element. If you can use a div for the title and content, then this bit of code should (no GWT on this machine, going a bit by memory) generate the DOM structure you have.
FlowPanel myWidget = new FlowPanel();
myWidget.setStyleName("my-widget");
SimplePanel header = new SimplePanel();
header.setStyleName("header");
Label title = new Label(titleText);
title.setStyleName("title");
header.add(title);
myWidget.add(header);
SimplePanel body = new SimplePanel();
body.setStyleName("body");
Label content = new Label(contentText);
content.setStyleName("content");
body.add(content);
myWidget.add(body);
From here, you can provide accessors to the content and title labels and update them as needed.
title.setText(newTitle);
content.setText(newContent);
The same as above, but getting a GWT Panel (be able to append childs). This is also useful when you need to wrapp a 3rd party toolkit GUI object as a GWT widget:
Panel gwtPanel = HTMLPanel.wrap(anElement);
The following code suites for me:
HorizontalPanel divContainer = new HorizontalPanel ();
Element div = DOM.createDiv();
div.appendChild(...); // whatever element it could fit inside
divContainer.getElement().appendChild(div);
Edit
The idea behind this is manipulating the DOM with the other widgets you have already programmed.
PS: I'm using GWT 2.4