I am creating a headless C# application and one of my HTML elements looks like
<input name="SUBMIT-chn.pss" title="Select" class="image selectIcon" type="image" alt="Select" src="docs/pics/select.png">
My method looks like
private void AddInputElement(HtmlNode element)
{
string name = element.GetAttributeValue("name", "");
string value = element.GetAttributeValue("value", "");
string type = element.GetAttributeValue("type", "");
if (string.IsNullOrEmpty(name)) return;
switch (type.ToLower())
{
case "image":
'I would like to do something like element.Click to go to the next page.
default:
Add(name, value);
break;
}
}
I am using HtmlAgilityPack 1.4.9 with .Net 4.5.2
Thank you
HtmlAgilityPack (HAP) is the wrong tool for this kind of task. It is only a HTML parser, which enable you to extract information from the source HTML, modify a bit of the HTML, and so on. HAP works on HTML markup level, and you can't interact with the HTML controls through HAP.
To click on a link, type on a textbox and so on, you need a real browser or something that emulate a real browser. You might want to look into .NET binding of Selenium WebDriver using PhantomJS headless browser to accomplish this. See a simple example here.
Related
I was pretty easily able to get npm's mathjax-full working, for parsing TeX to CommonHTML:
const MathJax = await require("mathjax-full").init({
options: {
enableAssistiveMml: true
},
loader: {
source: {},
load: ["adaptors/liteDOM", "tex-chtml"]
},
tex: {
packages: ["base", "ams", "newcommand"]
},
chtml: {
fontURL: "https://cdn.jsdelivr.net/npm/mathjax#3/es5/output/chtml/fonts/woff-v2"
},
startup: {
typeset: false
}
});
MathJax.tex2chtmlPromise("x^2-2x+1", {
display: true,
em: 16,
ex: 8
}).then((node) => {
var adaptor = MathJax.startup.adaptor;
console.log(adaptor.outerHTML(node));
});
However, unlike typeset/typesetPromise, rather than a DOM node or string of HTML, this works with the TeX directly. Of course I could parse the page myself, finding MathJax delimiters (outside of code blocks) and passing the contents to tex2chtmlPromise, but this would have the potential of bugs or differences in behavior between a client-side preview using MathJax's typeset and the server-side rendered version.
I've looked around in the internals of the liteDOM adaptor quite a bit, but can't seem to find any way of setting the innerHTML of its body, if that would be the correct approach (which would allow me to just use typesetPromise normally).
Is there a recommended way to do what I'm trying to do, namely, take some HTML, and typeset it with MathJax without parsing for the delimiters myself?
The MathJax node demos repository includes examples of how to process an HTML page that should give you what you need. There are several different ways to load and call mathJax, so there are separate directories that illustrate each of them. You are using the "simple" approach, but may also want to look at the "component" and "direct" approaches. Look for files that end in -page.
The main idea for the simple case is to use the document option in the startup section of your MathJax configuration. This allows you to provide a serialized HTML string to be used as the document to be processed. So in your case, you could change
startup: {
typeset: false
}
to
startup: {
typeset: false,
document: html
}
where html is the HTML string to be processed. E.g.,
html = `
<!DOCTYPE html>
<html>
<head>
<title>My Document</title>
</head>
<body>
<p>
Some math: \(E = mc^2\).
</p>
</body>
</html>
`;
If you want the same invocation of your node app to be able to process multiple pages, then you will need to use the "direct" approach, as illustrated in direct/tex2chtml-page, and do these lines for each html file you want to process. You can reuse the same output jax, but should create a new InputJax and MathDocument for each page you process.
On certain actions, I want to open a modal/popup on the website user is visiting.
I am doing it right now as:
//contentScript.js
function on_certain_action(message) {
const injectElement = document.createElement("div");
injectElement.className = 'app_modal'
document.body.appendChild(injectElement);
}
But, it is getting complex and difficult to understand. Is there some way I can write it in HTML? OR how do you handle it, if you are injecting complex script in content?
Our Firefox addon issues queries to Google at the backend (main.js), then extracts some content through xpath. For this purpose, we use innerHTML to create a document instance for xpath parsing. But when we submit this addon to Mozilla, we got rejected because:
This add-on is creating DOM nodes from HTML strings containing potentially unsanitized data, by assigning to innerHTML, jQuery.html, or through similar means. Aside from being inefficient, this is a major security risk. For more information, see https://developer.mozilla.org/en/XUL_School/DOM_Building_and_HTML_Insertion
Following the link provided, we tried to replace innerHTML with nsIParserUtils.parseFragment(). However, the example code:
let { Cc, Ci } = require("chrome");
function parseHTML(doc, html, allowStyle, baseURI, isXML) {
let PARSER_UTILS = "#mozilla.org/parserutils;1";
...
The Cc, Ci utilities can only be used on main.js, while the function requires a document (doc) as the argument. But we could not find any examples about creating a document inside main.js, where we could not use document.implementation.createHTMLDocument("");. Because main.js is a background script, which does not have reference to the global built-in document.
I googled a lot, but still could not find any solutions. Could anybody kindly help?
You probably want to use nsIDOMParser instead, which is the same as the standard DOMParser accessible in window globals except that you can use it from privileged contexts without a window object.
Although that gives you a whole document with synthesized <html> and <body> elements if you don't provide your own. If you absolutely need a fragment you can use the html5 template element to extract a fragment via domparser:
let partialHTML = "foo <b>baz</b> bar"
let frag = parser.parseFromString(`<template>${partialHTML}</template>`, 'text/html').querySelector("template").content
I try to figure out how to set active links in a navbar or sitebar for an async ufront application.
On the server I can load and parse it dynamically inside the main (top level) controller via an api call like:
#inject public function init(context:HttpContext) {
ufTrace("HomeController::init");
var navStr:String = "";
//getNavbar loads the navbar html snippet and parses the code to set 'active' some tags in relation to the request uri
var navbarSurprise = siteApi.getNavbar(context.request.uri);
navbarSurprise.handle(function (outcome) {
switch (outcome) {
case Success(navbarStr): navStr = navbarStr;
case Failure(err): navStr = "<h1>Could not load navigation: $err</h1>";
}
} );
ViewResult.globalValues["navBar"] = navStr;
}
but that doesn't work on the client for pushstate urls. (navStr would always be empty)
The ViewResult.hx (line:126) doc states:
Helpers (dynamic functions) can be included in your ViewResult also.
Could this be a place to handle that?
But unfortunately I couldn't find any help/examples how to add helper functions to a ViewResult.
I was also thinking about doing it in a custom ViewEngine. But that seems a bit like overcomplicating things.
Any thoughts about that would be appreciated.
Seems your are looking to render the navbar on the server when processing the request.
I did something like that some time ago by using sipple (another templating engine) but you can also use other engine (i think) like haxe template or erazor etc.
This issue sums up how i processed different partials using stipple
Hope it helps.
I want to build a Firefox extension which will use Firefox parser(Rendering Engine). I want to feed some HTML data to parser and in return, it will give me HTML and java-script content separately. Then I will do some processing on it. Is there any API or another way to do it?
you mean something like this...
let s = "<i>cool</i><script>alert('cool!')</script>";
var parser = new DOMParser();
let doc = parser.parseFromString(s, "text/html");
//do whatever you want....
doc.body.appendChild(doc.createElement('hr'));
alert(doc.documentElement.outerHTML)