I have a html page which has a Close button which on click, should close the window. This html page is being loaded on a Vaadin Dialog. I understand that Vaadin takes care of closing the dialog with window.setClosable(true). But, the button in html page also should do the same. How do I enable this ?
Below is the code :
myHelp.html:
<html>
<head>
</head>
<body>
.
.
<!-- This is at the footer right corner -->
<p class="myClass" align="right"><img src="images/iconclose.gif" width="50" height="10" border="0" onClick="window.close()" title="Close"></p>
.
.
</body>
</html>
Java Code:
.
.
String link = "test/myHelp.html";
MenuItem menuItem = null;
if (link.contains("/test")) {
menuItem = menuBar.addItem("", new ExternalResource(StringUtil.append("/images/", images.get(i))), new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
final Window window = new Window(this.caption);
window.setClosable(true);
window.setWindowMode(WindowMode.NORMAL);
window.setModal(true);
window.setDraggable(true);
window.setResizable(false);
window.center();
window.addStyleName("abcdailog");
VerticalLayout layout = new VerticalLayout();
layout.setSizeFull();
layout.setSpacing(true);
layout.setMargin(true);
if (!CommonUtil.isEmpty(this.styleName)) {
window.addStyleName("abcStyle");
layout.setMargin(false);
}
if (!CommonUtil.isEmpty(link)) {
BrowserFrame browser = new BrowserFrame(null, new ExternalResource(this.link));
browser.setSizeFull();
layout.addComponent(browser);
} else {
verticalLayout.setSizeFull();
layout.addComponent(verticalLayout);
}
window.setContent(layout);
UI.getCurrent().addWindow(window);
}
}
});
.
.
.
What happens is myHtml gets loaded in the new window. As a vaadin window, everything is fine but since the html has a window.close on an image, which is suppose to work is not working. I hope the code helps in better understanding.
The simplest one would be to add a Vaadin button say at the bottom of the window. However if that's not a choice, there are a few ways of doing this, the first one which comes to mind (and possibly the next simplest one) is adding a callback JS function to close the window.
1) Custom window implementation:
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.JavaScript;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
public class MyHtmlWindow extends Window {
private static final String CLOSE_WINDOW_FUNCTION = "closeWindow";
public MyHtmlWindow() {
// some window configuration
setModal(true);
setClosable(true);
setResizable(false);
}
public void show(UI ui) {
// add some HTML content in a label including the call to the closeWindow() JS function
setContent(new Label("<html>\n" +
"<button type=\"button\" onClick=\"" + CLOSE_WINDOW_FUNCTION + "();\">Close</button>\n" +
"<script>\n", ContentMode.HTML));
// add a JS function to close the window
JavaScript.getCurrent().addFunction(CLOSE_WINDOW_FUNCTION, arguments -> this.close());
// show the window
ui.addWindow(this);
}
#Override
public void close() {
// call super so everything gets cleaned up nicely
super.close();
// remove previously added function
JavaScript.getCurrent().removeFunction(CLOSE_WINDOW_FUNCTION);
}
}
2) Usage:
public class MyVaadinUI extends UI {
#Override
protected void init(VaadinRequest request) {
new MyHtmlWindow().show(this);
}
}
3) Result:
P.S.: Suggestions for improvements are welcome
Related
I have an app that has a webview in xamarin and shows a web which has links that are configured in this way:
<a target="_blank" href="http://www.web.com"> http://www.web.com </a>
but they do not work, I suppose this happens because when viewing the web from an app, it is not able to open the link in a new window.
I have also tried window.open without any changes.
How I could configure the link to force open the browser with a new link window.
Thanks.
I think this should happen on Android,if you want to open a new window with browser,you could use SetWebChromeClient method for your WebView in your custom renderer.
create a custom renderer in android project:
[assembly: ExportRenderer(typeof(WebView), typeof(AndroidWebView))]
namespace your namespace
{
class AndroidWebView:WebViewRenderer
{
public AndroidWebView(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
Control.SetWebChromeClient(new MywebviewChrome());
}
private class MywebviewChrome : Android.Webkit.WebChromeClient
{
public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
{
Android.Webkit.WebView.HitTestResult result = view.GetHitTestResult();
string data = result.Extra;
Context context = view.Context;
Intent browserIntent = new Intent(Intent.ActionView,Android.Net.Uri.Parse(data));
context.StartActivity(browserIntent);
return false;
}
}
}
}
in your forms project xaml :
<WebView HeightRequest="800" WidthRequest="600" x:Name="webview" ></WebView>
in your page.xaml.cs:
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = #"<a target='_blank' href='http://www.web.com'> http://www.web.com </a>";
webview.Source = htmlSource;
As you supposed, Xamarin.Forms doesn't support opening new tabs / windows.
BUT the Webview component has an event handler called "Navigating" on which you can subscribe to execute code every time the webview tries to open a new page.
public void NavigatingEventHandler(object sender, WebNavigatingEventArgs args)
{
if (args.Url.StartsWith("https://"))
{
//If you want to open the new window in the OS browser
Device.OpenUri(new Uri(args.Url));
//If you want to open the new window inside the webview
webview.Source = args.Url;
args.Cancel = true;
}
}
XAML:
<WebView x:Name="webview" Navigating="NavigatingEventHandler" />
I'm new to Blazor and I've created a pretty simple Webassembly app. I want a href link to go to a div lower down the page when I click on it, but the Javascript click event won't work. In the Index.razor page the JsRuntime.InvokeVoidAsync("clicker") is working and the alert("In clicker") happens as the page loads, but the click / href to go the "intro" div will not work for love nor money :-/
index.html
<!DOCTYPE html>
<html>
<head>
<title>My Blazor App</title>
<!--script type='text/javascript' src='./scripts/app.js'-->
</head>
<body>
<app>Loading...</app>
<script src="_framework/blazor.webassembly.js"></script>
<script>
function clicker() {
alert("In clicker"); // this works
document.getElementById('skip').onclick = function(e){
alert("clicked"); // this works but the page still won't scroll to the "intro" div :(
}
}
//clicker();
</script>
</body>
</html>
Index.razor (#code section is at top of page)
#page "/"
#code {
[Inject]
protected IJSRuntime JsRuntime { get; set; }
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
JsRuntime.InvokeVoidAsync("clicker");
}
}
}
// This link won't go to the intro div when clicked :(
<a id="skip" class="skip" href="#intro">skip this bit</a>
...
<div id="intro" class="home">
...
</div>
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IComponentsApplicationBuilder app)
{
app.AddComponent<App>("app");
}
}
If anyone could shed some light on this it would save my week.
There is no need for JavaScript here.
If you add a specific target to your markup, it will just work.
You can use target="_top" to avoid Blazor navigation interception.
<a class="skip" href="#intro" target="_top">skip this bit</a>
...
<div id="intro" class="home">
...
</div>
Note that target="_top" just directs the browser to navigate within the topmost frame in the window, it does not mean you will scroll to the top!
The page won’t scroll to the element you’ve specified in the link.This has to do with how routing is handled in Blazor and most other SPA applications as well. A simple solution is that you could create your own AnchorLink component and use a little bit of JavaScript interop magic.
1.Create AnchorLink.razor in Pages/Shared
#code {
public AnchorLink()
{
this.Attributes = new Dictionary<string, object>();
}
private string targetId = null;
private bool preventDefault = false;
/// <summary>
/// This parameter supports arbitrary attributes.
/// </summary>
/// <remarks>
/// Any attribute specified on the component, which is not defined as a parameter, whill be added to this dictionary.
/// It is then uses as the source for attributes rendered onto the resulting HTML element below in the markup section
/// of this component.
/// For details, refer to <see cref="https://learn.microsoft.com/en-us/aspnet/core/blazor/components#attribute-splatting-and-arbitrary-parameters"/>.
/// </remarks>
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> Attributes { get; set; }
/// <summary>
/// Supports child content for the component.
/// </summary>
/// <see cref="https://learn.microsoft.com/en-us/aspnet/core/blazor/components#child-content"/>
[Parameter]
public RenderFragment ChildContent { get; set; }
[Inject]
protected IJSRuntime JsInterop { get; set; }
protected override void OnParametersSet()
{
string href = null;
if (this.Attributes.ContainsKey("href"))
{
// If the href attribute has been specified, we examine the value of it. If if starts with '#'
// we assume the rest of the value contains the ID of the element the link points to.
href = $"{this.Attributes["href"]}";
if (href.StartsWith("#"))
{
// If the href contains an anchor link we don't want the default click action to occur, but
// rather take care of the click in our own method.
this.targetId = href.Substring(1);
this.preventDefault = true;
}
}
base.OnParametersSet();
}
private async Task AnchorOnClickAsync()
{
if (!string.IsNullOrEmpty(this.targetId))
{
// If the target ID has been specified, we know this is an anchor link that we need to scroll
// to, so we call the JavaScript method to take care of this for us.
await this.JsInterop.InvokeVoidAsync("anchorLink.scrollIntoView", this.targetId);
}
}
}
<a href="" #onclick="this.AnchorOnClickAsync" #onclick:stopPropagation="false" />
<a #attributes="this.Attributes" #onclick="this.AnchorOnClickAsync" #onclick:preventDefault="this.preventDefault">Hello #this.ChildContent</a>
2.Add js in wwwroot/Index.html
<script src="_framework/blazor.webassembly.js"></script>
<script>
window.anchorLink = {
scrollIntoView: function (elementId) {
// This function is called from the AnchorLink component using JavaScript interop.
// It will try to find an element using the ID given to the function, and scroll that
// element into view, if an element is found.
var elem = document.getElementById(elementId);
if (elem) {
elem.scrollIntoView();
window.location.hash = elementId;
}
}
}
</script>
3.Index.razor
<AnchorLink class="skip" href="#intro">skip this bit</AnchorLink>
Refer to https://mikaberglund.com/2019/12/28/creating-anchor-links-in-blazor-applications/
I have a very basic application, that shows website content within the WPF app. Everything works fine, except TitleChangedEvent. Here is the code sample (XAML):
<Window xmlns:awe="http://schemas.awesomium.com/winfx" x:Class="ShopChat.Desktop.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:webControls="clr-namespace:System.Web.UI.WebControls;assembly=System.Web"
Title="{Binding ElementName=WebControl, Path=Title}" MinHeight="480" MinWidth="640">
<Grid>
<awe:WebControl x:Name="WebControl"/>
</Grid>
And this is main window code-behind:
public MainWindow()
{
InitializeComponent();
string url = #"http://shopchat.dev";
try
{
url = ConfigurationManager.AppSettings.Get("Url");
}
catch (Exception)
{
}
WebControl.Source = new Uri(url);
WebControl.TitleChanged += WebControl_OnTitleChanged;
this.WindowTitle = "Quickchat";
}
public string WindowTitle
{
get { return (string)GetValue(WindowTitleProperty); }
set { SetValue(WindowTitleProperty, value); }
}
// Using a DependencyProperty as the backing store for WindowTitle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WindowTitleProperty =
DependencyProperty.Register("WindowTitle", typeof(string), typeof(MainWindow), new PropertyMetadata(null));
private void WebControl_OnTitleChanged(object sender, TitleChangedEventArgs e)
{
this.WindowTitle = e.Title;
}
I've also tried to bind to window title directly using Binding ElementName=WebControl. That didn't help me either.
JavaScript client code is very simple: it changes the document title on timer (setInterval).
What am I doing wrong?
try like this code
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyTitle = "Title";
}
Then you just need in the XAML
Title="{Binding MyTitle}"
Then you don't need the dependency property.
Then I would like to use this INotifyPropertyChanged with a standard property.
The issue was solved. TitleChanged event seemed to be insufficient. I've incorporated the usage of global js object to get the necessary behavior.
I have the viewPager component which is containing the several webviews with HTML content from remote server.
Is it simple HTML code without possibility to change the HTMl output on the server side.
I would like to ask, how can i catch the click(tap) event on the specified element with the given ID in Android?
ViewPager
private void initViewPager() {
pager = (ViewPager) findViewById(R.id.my_pager);
adapter = new FragmentStatePagerAdapter(
getSupportFragmentManager()
) {
#Override
public int getCount() {
// This makes sure getItem doesn't use a position
// that is out of bounds of our array of URLs
Logger.d(String.valueOf(mWelcomeController.loadedPagesToDisplay.size()));
return mWelcomeController.loadedPagesToDisplay.size();
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
Logger.d(mWelcomeController.loadedPagesToDisplay.toString());
return BrowserFragment.newInstance(
mWelcomeController.loadedPagesToDisplay.get(position)
);
}
};
//Let the pager know which adapter it is supposed to use
pager.setAdapter(adapter);
}
Because I cannot modify the HTML output on the server side (maybe inject some attributes into DOM on device ?) I cannot use something like that:
http://www.scriptscoop.com/t/21b53b896c9e/javascript-how-to-detect-button-click-in-webview-android.html
Detect click on HTML button through javascript in Android WebView.
I would like just something like this:
Find the given element in the HTML code
Update the HTML code (add
onclick event)
Catch this event in native code
For that you need to parse the html, a good html parser for Java (and therefor also Android) is Jsoup.
You can do something like:
// Connect to the web site
Document doc = Jsoup.connect(url).get();
Element button = doc.select("#buttonid");
button.html("new stuff here");
//parse back and put in webview
String finaloutput = doc.html();
1.
// setting
wv.addJavascriptInterface(new MyJsToAndroid(),"my");
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(true);
2.
// JsCallBack
class MyJsToAndroid extends Object{
#JavascriptInterface
public void myClick(String idOrClass) {
Log.d(TAG, "myClick-> " + idOrClass);
}
}
3.
// JS--
public static String addMyClickCallBackJs() {
String js = "javascript:";
js += "function myClick(event){" +
"if(event.target.className == null){my.myClick(event.target.id)}" +
"else{my.myClick(event.target.className)}}";
js += "document.addEventListener(\"click\",myClick,true);";
return js;
}
4.
#Override
public void onPageFinished(WebView wv, String url) {
//...
wv.evaluateJavascript(addMyClickCallBackJs(),null);
//...
}
So, look at the 2 log.
I am trying to implement some extra feature onto the wikitude sample project
What I tried is the following: I have button ("Take me there") in Poi detail panel near the "More" button and when user clicked to the "Take me there" button, I want to call a java method to do some calculation.
in my js file on button click method I have:
var currentMarker = World.currentMarker;
var architectSdkUrlm = "architectsdk://navigation?id=" + encodeURIComponent(currentMarker.poiData.id) + "&title=" + encodeURIComponent(currentMarker.poiData.title);
document.location = architectSdkUrlm;
where "Navigation" in the architectSdkUrlm is name of the java class that I created for the calculations. Navigation class is:
public class Navigation extends AbstractArchitectCamActivity {
#Override
public ArchitectView.ArchitectUrlListener getUrlListener() {
return new ArchitectView.ArchitectUrlListener() {
#Override
public boolean urlWasInvoked(String uriString) {
Uri invokedUri = Uri.parse(uriString);
// pressed "Take me there" button on POI-detail panel
if ("navigation".equalsIgnoreCase(invokedUri.getHost())) {
Log.d("title",String.valueOf(invokedUri.getQueryParameter("title")) );
/*final Intent navIntent = new Intent(Navigation.this, navigationIntent.class);
navIntent.putExtra(navigationIntent.EXTRAS_KEY_POI_ID, String.valueOf(invokedUri.getQueryParameter("id")) );
navIntent.putExtra(navigationIntent.EXTRAS_KEY_POI_TITILE, String.valueOf(invokedUri.getQueryParameter("title")) );
Navigation.this.startActivity(navIntent);*/
return true;
}
return true;
}
};
}
}
I want to see if I could call the java file from js by a Log message but I don't get anything.
Do you have any idea about what might be the problem?
Thanks.