how to interact with HTML forms in delphi using TChromium - html

i need to update the design of a browser in delphi7 I was using the twebbrowser but he had many problems with javascript and navigation.. so i decide to migrate to Chromium. the problem is that I cannot find code on these components. does anyone know which command would be equivalent to this one in tchromium:
OleObject.Document.all.Item ('ElementbyId', 0) .value: = 'edit1.text';
i need to transfer a text from memo to textarea in html form and at the end send a click on the button on the html form. if anyone knows the commands and can share I appreciate it.

A more flexible alternative than DOM access could be to perform this in Javascript, with the ExecuteJavaScript method of TChromium.
From your summary description, the JS could be something like
document.getElementById('yourtextarea').value = <JSON stringified content of your memo>;
document.getElementById('yourform').submit();
Alternatively, you could implement a JS function in your HTML, and call it with ExecuteJavascript, this way there would not be anything specific (besides the function name) on the Delphi side, and the HTML would be free to evolve.
function setTextAreaAndSubmit(value) {
document.getElementById('yourtextarea').value = value;
document.getElementById('yourform').submit();
}

Related

SQL Query - extracting data between html tags in a text column into new table

A web form was developed and instead of saving individual fields the whole form was saved in a text column as html. I need to extract data between various html tags so want to create a query that writes each set of tags to a table for me to then use - if this is possible please can someone advise how this can be achieved.
Thank you.
Ok, i've noticed you weren't happy with my last answer, however i am still certain you need server side code to handle SQL queries. Basically without having any sort of server side code you wanna do something like "here's a TV i bought, and here's the DVD release of the "John Wick" movie, i wanna watch it on this TV. Without a DVD player you can't really do it tho', that is the role of the PHP or ASP.NET in this case. Since I am not familiar with PHP, I am only able to show a solution in ASP.NET C# which i put together some time ago.
Here's how I solved this in a site i've built some time ago. It is not the cleanest, but it most certainly worked.
In ASP.NET you have the page file, which is similar to a HTML or an XML file, using a lot of pointy brakcets. Create one like this:
page file, body:
<asp:TextBox ID="HiddenTextBox" style="display: none;" runat="server"
onclick="OnStuff" OnTextChanged="TheUserChangedMe"
AutoPostBack="true"></asp:TextBox>
scroll up a bit, and in the section add some javascript, where you can handle on text change instantly. So as soon as something happens, like the user clicks on an image, or... well does anything you want him to do (and respond to that) you need the ID of that element he clicked on.
page file, head:
<script type="text/javascript">
function MarkItems_onclick() {
var Sender = window.event.srcElement;
document.getElementById('<%= HiddenTextBox.ClientID%>').value = Sender.id;
__doPostBack('<%= HiddenTextBox.ClientID%>', 'TextChanged');
}
</script>
page's .cs file, the C# code behind
//
//add these on top:
//
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
//
// later somewhere write this:
//
protected void TheUserChangeMe(object sender, EventArgs e)
{
SqlConnection conn1 = new SqlConnection(ConfigurationManager.ConnectionStrings["UserRegConnectionString"].ConnectionString);
//
Note: the connection string has to be set up earlier. make sure you make one, visual studio will let you do that in no time. Do not forget, that this connection string defines where your DB is located, and grants the required information for the site how to even reach it at the first place.
//
// somewhere you need to read out what you have in your HiddenTextbox:
//
String stringToProcess = HiddenTextBox.Text;
process your stuff, here i assume you cut it up accordingly and you will have an insertQ variable with a proper syntax. in order to add these values it should look something like this:
String insertQ = "insert into OrdersTable(OrderId, Type, Quantity) " +
"values (#OrderId, #StuffType, #StuffQuantity)";
How to access the database in asp.net C#:
conn1.Open();
SqlCommand insertComm = new SqlCommand(insertQ, conn1);
insertComm.Parameters.AddWithValue("#OrderId", nonStringVariable.ToString());
insertComm.Parameters.AddWithValue("#StuffType", aStringVariable);
insertComm.Parameters.AddWithValue("#StuffQuantity", "some random text");
insertComm.ExecuteNonQuery();
conn1.Close();
that's pretty much it. Your SQL database will have 3 fields filled up every time this function runs. It's a bit messy, but for my site it was crucial to handle any onclick event, and with this you can flush out 23 checkboxes, 10 pictures and whatnot as page elements, yet you'll know what happened every time the user clicked something.
i'm not a professional either, however i think you're gonna need something on the server side to process this query, like asp.net or php. Basically the server side code would have no problem generating your page's content according to what comes back from the DB.

Dynamically load an entire angular app

So I have a curious situation and I don't think it's going to work, but I figured I'd ask in case it is and someone knows how to. I am using a 3rd party website to create marketing funnels. You can add your own custom html and javascript, but it parses out the html in a rather unfavorable manor. Basically you specify an element on the page and it appends it as a data attribute and dynamically loads it into the DOM. Since this is happening this way, my app isn't being initialized because it's not in the DOM on page load. Is there a way to make this work? I'll explain a little deeper my configuration.
I add custom html such as:
<div data-ng-app="AppName"><div data-ng-controller="ControllerName"><div>perform controller logic here</div></div>
As you can see, this needs to be in the DOM for the app to initialize and, well work. Is there a way to initialize the app after the page has loaded dynamically? I can add my own JS files in the custom html field, but thats about as far as I can go for customization. Any help is appreciated!
Maybe you should execute angular's bootstrap function manually in your script after the required dom loaded.
var app = angular.module('appName', []);
app.controller([...]);
angular.bootstrap(document.getElementById('divId'), ['appName']);
For more information, you can see this doc https://docs.angularjs.org/api/ng/function/angular.bootstrap

is it possible to trigger c++ code, initiated by html events in minko?

Using minko, "html overlay" feature, is it possible to send events to c++ code from html?
The example provided, with the framework clearly demonstrate how to send events from c++ towards html (by incrementing a counter and having it reflect in html), is it possible to have the communication the other way around?
Yes.
HTML DOM events are wrapped and made available as C++ signals. So you can do something like:
dom->getElementById("my-element-id")->onclick()->connect(
[](dom::AbstractDOMMouseEvent::Ptr event)
{
// do something...
}
);
It's actually done in the same example: https://github.com/aerys/minko/blob/master/example/html-overlay/src/Main.cpp#L110
You can also send and receive "messages" both ways using the AbstractDOM::sendMessage() method in C++ or Minko.sendMessage() function in JS. You can listen to those messages using AbstractDOM::onmessage() in C++ and Minko.addEventListener("message", yourCallbackFunction).
Note that you can also call AbstractDOM::eval() in your C++ code to execute JavaScript code. It's how we've implemented most of the things actually.

Get innerHTML via Jsoup

Im trying to scrape data from this website: http://www.bundesliga.de/de/liga/tabelle/
In the source code i can see the tables but there's no content, just things like:
<td>[no content]</td>
<td>[no content]</td>
<td>[no content]</td>
<td>[no content]</td>
....
With firebug (F12 in Firefox) i wont see any content too but i can select the table and then copy the innerHTML via firebug option. In that case i get all the informations about the teams, but i dont know how to get the table with the content in Jsoup.
To get the value of an attribute, use the Node.attr(String key) method
For the text on an element (and its combined children), use Element.text()
For HTML, use Element.html(), or Node.outerHtml() as appropriate
For example:
String html = "<p>An <a href='http://example.com/'><b>example</b></a> link.</p>";
Document doc = Jsoup.parse(html);
Element link = doc.select("a").first();
String text = doc.body().text(); // "An example link"
String linkHref = link.attr("href"); // "http://example.com/"
String linkText = link.text(); // "example""
String linkOuterH = link.outerHtml();
// "<b>example</b>"
String linkInnerH = link.html(); // "<b>example</b>"
reference:
http://jsoup.org/cookbook/extracting-data/attributes-text-html
The table is not rendered on the server directly, but build by the client side JavaScript of the page and constructed with data that is getting to the client via AJAX. So what you get with the naive Jsoup approach is expected.
I see two possible solutions:
You analyze the network traffic and identify the ajax calls that the site is making. Then you try to reconstruct the format and fire the same requests as the JavaScript would. Then you can reconstruct the table.
you don't use Jsoup but a real browser, that loads the page and runs the JavaScript including all AJAX calls. You could use Selenium webdriver for that. There is a headless browser called phantomjs which has a relatively small footprint that you can use in combination with selenium webdriver.
both options have their (dis)advantages:
This takes more time, since you need to understand the network traffic pretty good. The reward will be a very fast and memory efficient scraper.
The programming of selenium is very easy and you should not have any difficulties achieving your goal. You don't need to understand the inner workings of the site you want to scrape. However, the price is a further dependency in your project. Memory consumption is high. Another process runs. The scraping will be slow.
Maybe you find another source with the soccer table that is holding the infos you want? That might be the easiest. For example http://www.fussballdaten.de/bundesliga/

Model Validation without the ValidationSummary?

I have a LoginModel for my Login Action, but I'm wanting to use just HTML.
Example...
public class LoginModel
{
[Required]
public string Email { get;set; }
}
in my HTML, I have
<input type="text" value="" name="Email">
This is because I'm going to be storing my HTML in my database, problem I'm having is, how do I get model validation without using Html.ValidationSummary()?
I was hoping I could just do <div class="validation-summary-errors"></div>
As this is what is in the HTML, but does not work..
Ideas?
Regardless of where you store your HTML the validation is done on the client side. There are various posts on how to use the virtual path provider to store your views somewhere else (DB) and then validation should still work fine. I think I'm missing why it's not working for you though so I have to imagine you aren't using the path provider to find your views.
Edit
Seems you want to inject messages into a Div. This wont happen automaticaly unless you work some magic in the path provider. Use your own helper method in the view to avoid hacks or just use what's provided by default. If you really want to do it render your view in your controlllet and search for your Div pattern to replace.
custom ValidationForMessage helper removing css element
Note Darin's method
var expression = ExpressionHelper.GetExpressionText(ex);
var modelName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expression);
var modelState = htmlHelper.ViewData.ModelState[modelName];
without access to ViewContext in your controller you can only render your html for your View. However, somewhere in your view you need (as far as I can tell) a helper method to stick your error collection into ViewData.
Your Virtual Path Provider may have to inject this helper method into your view text so it is there for Razor to parse. Actually - duh. This may be much easier. Your provider may be able to just simply read your html from the database, find the div, and inject the #Html.ValidationSummary into that div. I believe this would work. Why not just put the validation summary in there though if its going to end up there in the end anyways (essentially)