FMX - Cancel URL loading - delphi-xe5

Is there any way to cancel URL loading using property TCustomWebBrowser.OnShouldStartLoadWithRequest?
Type of this property is declared as
TWebBrowserShouldStartLoadWithRequest = procedure(ASender: TObject; const URL: string) of object;
So it doesn't return any value based on which one could decide whether to stop or continue URL loading...

Related

where to add a global function in coldbox to call in a view

Where in coldbox would you add a function that would be visible in your view thats global
for instance, i want to create a function that replaces spaces with hyphens for a URL
public string function makeUrl(url) {
replace bit here
return URL;
}
where would you store this?

How would I change the value of a UILabel from a different class in swift?

I am a student trying to make an app in Xcode, and I have run into an issue to which I cannot figure out the solution. I want to access a string I have stored in another class and make it the label text of my ViewController.
In my ViewController, I call a different class, which then calls through an API and finds me a string detailing the weather in a certain place. This is what my call looks like from my ViewController class
func getWeather() {
manager = DataManager()
manager.fetchData(query: getQueryString();
}
And this is what the call looks like from the DataManager Class
func rainyWeatherPopulate(str: String){
LoadEvents.loadEvents(type: EventType.rain, str: str)
}
in the loadEvents function, I get a string detailing the type of weather that I want to put as text of a UILabel in my ViewController class, and I am not sure how to do so
Is there any way that I can pass an instance of my ViewController to my loadEvents static function or any other way in which I can set the text of a UILabel in my ViewController from the LoadEvents class?
There are many potential ways to solve this problem, but one is by passing a closure to be used upon completion of the call.
So, it might look like this in your use case:
class DataManager {
func fetchData(query: String, onComplete: #escaping (String) -> Void) {
LoadEvents.loadEvents(type: .rain, str: query, onComplete: onComplete)
}
}
enum EventType {
case rain
}
class LoadEvents {
static func loadEvents(type: EventType, str: String, onComplete: (String) -> Void) {
//load the data
//then, when it's done, call the completion
onComplete("returnedData")
}
}
func getWeather() {
let manager = DataManager()
let uiLabel = UILabel()
manager.fetchData(query: "queryString", onComplete: { result in
uiLabel.text = result
})
}
I had to mock out some stuff (like EventType) and I had no information about the types of events you're loading, so I just used a generic String for the return type, but the concept is here.
How it works:
In getWeather, there's a closure called onComplete that will get data back once everything has completed. result holds (obviously) the result -- in this case a string, and it sets uiLabel's text property to that value.
LoadEvents does whatever it needs to and then upon finishing, calls onComplete and sends the results back through the closure.
I'd say jnpdx's solution of passing a closure to your data manager is the best answer.
Another way you could do this is to add a delegate property to your data manager. The only thing you know about the delegate is that it conforms to a specific protocol. You'd then invoke methods on the delegate from the data manager that would tell the delegate about data that was available for display. The delegate would decide what to do with that data.
I mention this as an alternative method, but would suggest using closures as jnpdx recommends in their answer.

This is one thing I do not understand in Swift

Consider these lines:
I create a NSButton based class with this:
typealias onClickHandler = (NSTextfieldSuper)->Void
var onClick: onClickHandler?
When the user clicks on an instance of that button, I do this:
if (self.onClick != nil) {
onClick?(self)
}
I use that button later, from another class, with this:
let button = SuperButton()
button.onClick = { (textField: NSTextfieldSuper)->Void in
}
I am not sure if this is the correct syntax. I would like to process the button sent from the first closure on the parent class, where the button is created.
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
I just want to process that button sent.
By the way, as a bonus, I have to initialize several buttons with this, all running the same function. It would be nice to do something like
func doSomething () {
}
and then
let button = SuperButton()
button.onClick = doSomething
any ideas?
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
It is the same as in your typealias, in Swift a function type has the form:
(parameter definitions) -> return type
and functions which return nothing have a return type of Void (similar to C). The full form off a closure expression is:
{ (parameter definitions) ->return typeinbody}
Without any inference this expression provides the full type of the closure, and the -> Void Return type in your example specifies that your closure returns nothing. In your assignment this full type will be checked at compile time to conform to the type of onClick.
Now Swift will infer lots of stuff and there are various shorthands available for closure expressions, you will find that Swift accepts:
button.onClick = { textField in }
as well here with both the argument and return types of the closure being inferred.
By the way, as a bonus, [...] any ideas?
Just make the types match:
func doSomething(textField : NSTextfieldSuper) { }
button.onClick = doSomething
Unlike in (Objective-)C functions and closures (blocks in C) are interchangeable (as they are in plenty of other languages, C is the oddfellow here)
HTH

Inject content from Swift code to WKWebView

I am developing an app which uses WKWebView to show an html document. I want to inject content from my Swift code to this document. This is what I tried:
var myString: String
// ... Code which assigns some value to myString
targetView.evaluateJavaScript("injector.injectSnippet(\(myString);", completionHandler: nil)
This works exactly as I expect so long as the argument in the JavaScript function call is hardcoded:
targetView.evaluateJavaScript("injector.injectSnippet(\"Hello World\");", completionHandler: nil)
The injector object is in a JavaScript file which I have already added to the web view's user controller:
var injector = (function () {
"use strict"
var msgBox;
var injectSnippet = function (test) {
msgBox.innerHTML = "Received value: " + test;
}
var init = function () {
// Create msgBox div element and insert it into the document
}
return {
init: init,
injectSnippet: injectSnippet
};
} ());
injector.init();
How do I get content into the WKWebView?
I went through the Apple docs WebKit Objective-C Programming Guide and WebKit DOM Programming Topics but I don't understand what sort of WebView class they are using there. Both WKWebView and UIWebView don't have all the API they use in these documents.
Is there some way to manipulate the DOM directly in Swift? I get the sense that WebScriptObject might be what I'm looking for but can I use this with WKWebView?
If you want to continue using evaluateJavaScript, you need to inject the value into the javascript string.
Something like
var jsTemplate = "injector.injectSnippet(\"%#\");"
var js = String(format:jsTemplate , myString)

Form object's event can't see inherited method

Problem summary: The OnClick event of a TForm object says that it can't find the method I specify; this method is defined in the Form's superclass, which I expected it to be inherited.
Here I define the base type (i.e. superclass) for the "RAM Editor" window, including a button and what its OnClick event should do.
// File: RAM_Editor_Common.pas
type
TfrmBaseRamEditor = class(TForm)
btnMapfileLaden: TToolButton;
procedure MapfileLaden1Click(Sender: TObject);
// ....
procedure TfrmBaseRamEditor.Mapfileladen1Click(Sender: TObject);
begin
if not OpenDialog2.Execute then Exit;
StatusBar1.Panels[2].Text := OpenDialog2.FileName;
end;
Here I define the sub-class:
// File: RAM_Editor_SXcp.pas
TfrmRAM_Editor_SXcp = class(RAM_Editor_Common.TfrmBaseRamEditor)
Here the sub-class's Form makes use of the button and sets the OnClick event to the method that was defined in the super-class:
// File: RAM_Editor_SXcp.dfm
object frmRAM_Editor_SXcp: TfrmRAM_Editor_SXcp
// ....
// ....
object btnMapfileLaden: TToolButton
Left = 75
Top = 0
Hint = 'Mapfile laden'
Caption = 'btnMapfileLaden'
OnClick = MapfileLaden1Click
ImageIndex = 5
ParentShowHint = False
ShowHint = False
end
But when I attempt to compile I get the error:
"The MapfileLaden1Click method referenced by btnMapfileLaden.OnClick does not exist. Remove this reference?"
Why can it not see the inherited method?
Your .dfm file is incorrect instead of:
object frmRAM_Editor_SXcp: TfrmRAM_Editor_SXcp
you need
inherited frmRAM_Editor_SXcp: TfrmRAM_Editor_SXcp
Similarly instead of:
object btnMapfileLaden: TToolButton
you need
inherited btnMapfileLaden: TToolButton
I guess you are trying to inject a common base class into an existing hierarchy. You've made the changes needed in the .pas file, but failed to make the corresponding changes needed in the .dfm file. The inherited keyword in the .dfm file is required by visual form inheritance.

Resources