-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow easy access to DOM/HTML #77
Comments
Hey I just saw your projects on nuget yesterday but haven't had a chance to look into them yet. Thanks for trying it out! Did you run into any interesting issues etc? We are planning on producing a WPF & WinForms controls sometime by the first half of next year with a dev preview earlier than that. |
Just to clarify, they aren't my projects ;-) |
Oh I see. If I understand what you're planning, no. Similar to the EdgeHtml WebView (and unlike the mshtml WebView/WebControl), we don't plan to expose the DOM via our API and instead it should be accessed via script. |
Thanks David, for clarifying. |
I'm really keen to see the Winforms control, as early as possible. |
Hi All, Also, our win32 c++ application uses the mshtml (WebBrowser control) many times, and we want to replace them with the new webview2, but need a way to access DOM/HTML directly, is there any news about this? Thanks |
Any news about DOM access in WebView2? It's been more than 1.5 years since this issue was opened and a lot of similar issues have been grouped together in this issue. but no new information. Please can we get an updated status on this! |
For those interested I've just released WebView2.DevTools.Dom to NuGet.org. The project has a public GitHub Page Unlike some of the other packages currently available it's Chrome DevTools Protocol based framework for JavaScript execution, DOM access/manipulation and automation. Requires
More details and examples in the Readme await webView.EnsureCoreWebView2Async();
// WebView2DevToolsContext implements IAsyncDisposable and can be Disposed
// via await using or await devToolsContext.DisposeAsync();
// https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync#using-async-disposable
await using var devToolsContext = await coreWebView2.CreateDevToolsContextAsync();
// Get element by Id
// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var element = await devToolsContext.QuerySelectorAsync("#myElementId");
//Strongly typed element types
//Only a subset of element types have been added so far, use HtmlElement as a generic type for all others
var htmlDivElement = await devToolsContext.QuerySelectorAsync<HtmlDivElement>("#myDivElementId");
var htmlSpanElement = await devToolsContext.QuerySelectorAsync<HtmlSpanElement>("#mySpanElementId");
var htmlSelectElement = await devToolsContext.QuerySelectorAsync<HtmlSelectElement>("#mySelectElementId");
var htmlInputElement = await devToolsContext.QuerySelectorAsync<HtmlInputElement>("#myInputElementId");
var htmlFormElement = await devToolsContext.QuerySelectorAsync<HtmlFormElement>("#myFormElementId");
var htmlAnchorElement = await devToolsContext.QuerySelectorAsync<HtmlAnchorElement>("#myAnchorElementId");
var htmlImageElement = await devToolsContext.QuerySelectorAsync<HtmlImageElement>("#myImageElementId");
var htmlTextAreaElement = await devToolsContext.QuerySelectorAsync<HtmlImageElement>("#myTextAreaElementId");
var htmlButtonElement = await devToolsContext.QuerySelectorAsync<HtmlButtonElement>("#myButtonElementId");
var htmlParagraphElement = await devToolsContext.QuerySelectorAsync<HtmlParagraphElement>("#myParagraphElementId");
var htmlTableElement = await devToolsContext.QuerySelectorAsync<HtmlTableElement>("#myTableElementId");
// Get a custom attribute value
var customAttribute = await element.GetAttributeAsync<string>("data-customAttribute");
//Set innerText property for the element
await element.SetPropertyValueAsync("innerText", "Welcome!");
await element.SetInnerTextAsync("Welcome 2!");
//Get innerText property for the element
var innerText = await element.GetInnerTextAsync();
//Can also be acessed via calling GetPropertyValueAsync
//Can use this method to get any property that isn't currently mapped
innerText = await element.GetPropertyValueAsync<string>("innerText");
//Get all child elements
var childElements = await element.QuerySelectorAllAsync("div");
//Change CSS style background colour
_ = await element.EvaluateFunctionAsync("e => e.style.backgroundColor = 'yellow'");
//Type text in an input field
await element.TypeAsync("Welcome to my Website!");
//Scroll Element into View (if needed)
//Can optional specify a Rect to be scrolled into view, relative to the node's border box,
//in CSS pixels. When omitted, center of the node will be used
await element.ScrollIntoViewIfNeededAsync();
//Click The element
await element.ClickAsync();
//Event Handler
//Expose a function to javascript, functions persist across navigations
//So only need to do this once
await devToolsContext.ExposeFunctionAsync("jsAlertButtonClick", () =>
{
_ = devToolsContext.EvaluateExpressionAsync("window.alert('Hello! You invoked window.alert()');");
});
var jsAlertButton = await devToolsContext.QuerySelectorAsync("#jsAlertButton");
//Write up the click event listner to call our exposed function
_ = jsAlertButton.AddEventListenerAsync("click", "jsAlertButtonClick");
//Get a collection of HtmlElements
var divElements = await devToolsContext.QuerySelectorAllAsync<HtmlDivElement>("div");
foreach (var div in divElements)
{
// Get a reference to the CSSStyleDeclaration
var style = await div.GetStyleAsync();
//Set the border to 1px solid red
await style.SetPropertyAsync("border", "1px solid red", important: true);
await div.SetAttributeAsync("data-customAttribute", "123");
await div.SetInnerTextAsync("Updated Div innerText");
}
//Using standard array
var tableRows = await htmlTableElement.GetRowsAsync().ToArrayAsync();
foreach(var row in tableRows)
{
var cells = await row.GetCellsAsync().ToArrayAsync();
foreach(var cell in cells)
{
var newDiv = await devToolsContext.CreateHtmlElementAsync<HtmlDivElement>("div");
await newDiv.SetInnerTextAsync("New Div Added!");
await cell.AppendChildAsync(newDiv);
}
}
//Get a reference to the HtmlCollection and use async enumerable
//Requires Net Core 3.1 or higher
var tableRowsHtmlCollection = await htmlTableElement.GetRowsAsync();
await foreach (var row in tableRowsHtmlCollection)
{
var cells = await row.GetCellsAsync();
await foreach (var cell in cells)
{
var newDiv = await devToolsContext.CreateHtmlElementAsync<HtmlDivElement>("div");
await newDiv.SetInnerTextAsync("New Div Added!");
await cell.AppendChildAsync(newDiv);
}
} |
Just as a follow up I'm working on a guide Porting from the IE WebBrowser control, I'm looking for ~3 people to provide real world samples that they'd be interested in porting over. I'll provide a port of those examples that can be used as a reference for everyone. I'll also be offering paid consultancy services for those that need/require more than just a guide. |
Are there any plans to adopt this functionality and make it part of the WV2? |
I've just started writing one to compliment this implementation: https://github.com/michael-russin/webview2-control
But wondering if it's worth waiting if you have plans for one.
Thanks
AB#28556146
The text was updated successfully, but these errors were encountered: