Using the https://pub.dev/packages/webview_flutter package and on the onPageFinished callback, I'd like to add some javascript to scroll to a section in a website based on ID after a time delay.
This works:
WebViewController _controller;
Timer(const Duration(seconds: 2), () async {
_controller.runJavaScript(
'var tag = document.getElementsByTagName("body")[0];tag.innerHTML = "This is my new content!";'
);
});
and replaces all text on the page with This is my new content!, however, when I try and add other js like getElementById:
var tag = document.getElementById("pagetitletop");tag.innerHTML = "This is my new content!";
I get Unhandled Exception: PlatformException(FWFEvaluateJavaScriptError, Failed evaluating JavaScript., Instance of 'NSError', null)
In the end I just want to do this:
var e = document.getElementById('pagetitletop');
e.scrollIntoView();
I cannot find any documentation on what is allowed and not selector wise?
Related
I've made a website that utilizes Bootstrap's tab navigation. For my blog, I have an iframe set into one of these tabs. I am currently trying to make it so that if I were to give someone a link with the query ?blogPost=a_post it would automatically redirect the SRC of the Iframe to /blog/a_post.html. I started by setting up the script to get the queries based on this article: https://www.sitepoint.com/get-url-parameters-with-javascript/. Then, I adapted the code to look like this:
function onload() {
let queryString = window.location.search;
let urlParams = new URLSearchParams(queryString);
if (urlParams.has('blogPost')) {
let blogPost = urlParams.get('blogPost');
document.getElementById('pills-home-tab').classList.remove('active');
document.getElementById('pills-blog-tab').classList.add('active');
document.getElementById("child-iframe").src = `./blog/${blogPost}.html`;
} else {
return;
}
}
window.onload = onload;
However, when I load the page https://website.com/?blogPost=welcome_to_my_blog none of the classList properties change, and the Iframe stays at /blog.html
I'm not sure where I'm going wrong, but I'm certain what I'm trying to do is possible, and under that assumption know I am at error in my code. No errors come up on my browser's console, either.
You declared a global function called onload, this has overwritten the native window.onload, making it not work. You can change the name of your function, or just add directly like this:
window.onload = () => {
let queryString = window.location.search;
let urlParams = new URLSearchParams(queryString);
if (urlParams.has("blogPost")) {
let blogPost = urlParams.get("blogPost");
document.getElementById("pills-home-tab").classList.remove("active");
document.getElementById("pills-blog-tab").classList.add("active");
document.getElementById("child-iframe").src = `./blog/${blogPost}.html`;
}
};
I need to change a web page source in GeckoFX web browser including html, css and js.
This is my code:
geckoWebBrowser1.Navigate("http://example.com/");
geckoWebBrowser1.DocumentCompleted += GeckoWebBrowser1_DocumentCompleted;
private void GeckoWebBrowser1_DocumentCompleted(object sender, Gecko.Events.GeckoDocumentCompletedEventArgs e)
{
WebClient w = new WebClient();
string s = (w.DownloadString("http://example.com/"));
//after do changes on (s)
geckoWebBrowser1.LoadHtml(s, "http://example.com/");
But it's not working on javascript, can anyone help me?
The problem is that geckoWebBrowser1.LoadHtml also triggers GeckoWebBrowser1_DocumentCompleted(). So you will loop endlessly.
Move the LoadHtml to another function, or change the content live as below.
Also, are you're using WebClient to download the same page? There is no need, the source is already available.
GeckoHtmlElement element = null;
var geckoDomElement = e.Window.Document.DocumentElement;
if (geckoDomElement is GeckoHtmlElement)
{
element = (GeckoHtmlElement)geckoDomElement;
element.InnerHtml = element.InnerHtml.Replace("Google", "Göggel");
}
Javascript is most easily executed using the following:
using (AutoJSContext context = new AutoJSContext(ActiveBrowser.Window.DomWindow))
{
var result = context.EvaluateScript("testFunction();");
}
I'm trying to program my first website scraper, and my first step is to save the HTML to a string. However, from what I can tell, the data that I need to get is not in the HTML code per se, but rather is added after JavaScript executes some stuff.
My current code is this:
let myURLString = "Example URL"
let myURL = URL(string: myURLString)
var myHTMLString = ""
do {
myHTMLString = try String(contentsOf: myURL!)
} catch let error {
print("Error: \(error)")
}
But this doesn't seem to execute the javascript and instead just gives me the 'unprocessed' HTMl.
I read this answer here, but it's written in Swift 2.0 and since I, to be honest, didn't really understand what was going on ( I don't have much programming experience ): I couldn't get to work in Swift 3.
So, Is there a way to take the HTML from a website, run the JavaScript and then save that as a String in Swift 3? And if so, how do you do it?
Thanks!
After some digging I got something that worked:
import Cocoa
import WebKit
class ViewController: NSViewController, WebFrameLoadDelegate {
#IBOutlet var myWebView: WebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.myWebView.frameLoadDelegate = self
let urlString = "YOUR HTTPS URL"
self.myWebView.mainFrame.load(NSURLRequest(url: NSURL(string: urlString)! as URL) as URLRequest!)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
let doc = myWebView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")! //get it as html
//doc now has the 'processed HTML'
}
}
I try to schedule a script using the 'Scheduled Tasks' in ML8. The documentation explains this a bit but only for xQuery.
Now I have a JavaScript file I'd like to schedule.
The error in the log file:
2015-06-23 19:11:00.416 Notice: TaskServer: XDMP-NOEXECUTE: Document is not of executable mimetype. URI: /scheduled/cleanData.js
2015-06-23 19:11:00.416 Notice: TaskServer: in /scheduled/cleanData.js [1.0-ml]
My script:
/* Scheduled script to delete old data */
var now = new Date();
var yearBack = now.setDate(now.getDate() - 65);
var date = new Date(yearBack);
var b = cts.jsonPropertyRangeQuery("Dtm", "<", date);
var c = fn.subsequence(cts.uris("", [], b), 1, 10);
while (true) {
var uri = c.next();
if (uri.done == true){
break;
}
xdmp.log(uri.value, "info"); // log for testing
}
Try the *.sjs extension (Server-side JavaScript).
The *.js extension can be used for static JavaScript resources to return to the client instead of executed on the server.
Hoping that helps,
I believe that ehennum found the issue for you (the extension - which is what the mime-type error is complaining about.
However, on the same subject, not all items in ML work quite as you would expect for Serverside Javascript. For example, using sjs as a target of a trigger is (or recently) did not work. So for things like that, it is also possible to wrap the sjs call inside of xqy using xdmp-invoke.
I was just trying to get the document of a tab and read information from it, but if I try to read the information on the Add-on-side I get an error "doc.getElementById is not a function". In the content-script it works fine. So is there a problem with passing whole objects through self.port?
var tabs = require('sdk/tabs');
var myTab;
var myScript = "self.port.on('getDocument', function() {" +
" var doc = window.document;" +
" console.log(doc.getElementById('lga').style.height);" +
" self.port.emit('answer', doc);" +
"})";
for each (var tab in tabs) {
if (tab.url == "https://www.google.com/") {
myTab = tab;
}
}
worker = myTab.attach({
contentScript: myScript
});
worker.port.emit("getDocument");
worker.port.on("answer", function(doc) {
console.log(doc.getElementById('lga').style.height);
});
You can only pass values via a message that could be serialized to JSON. doc, being a document, cannot be passed.
In your message, you could pass the actual value of the style instead:
self.port.emit('answer', doc.getElementById('lga').style.height);
Rather than try to import the document into main.js, create a new Javascript file in the data folder, ContentScript.js. Inject it with contentScriptFile into the page like so:
worker = myTab.attach({
contentScriptFile: require('sdk/self').data.url('ContentScript.js')
});
Meanwhile, in ContentScript.js
var doc = window.document;
//Now have your way with the document
Then if you ever need any variables in main.js, do what #nmaier said.
I realize that this may be obvious, but this is the intended behaviour, and it means you don't have to write a script as a string and provides more detailed logging.