JavaScriptCore get API console.log messages - javascript

I have a simple web app that prints streaming data to the console.log. This works just fine in a web page.
I would like to print the log messages directly onto the Xcode console as they come across the stream without using a web view.
Prefer everything to be in Swift if possible but Objective-C solution is ok.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Barchart Market Data API Example</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="../dist/barchart-marketdata-api-1.0.js"></script>
<script type="text/javascript">
$(function() {
var onMarketUpdate = function(message) {
if (message.type == "TRADE") {
var q = client.getMarketState().getQuote(message.symbol);
if (q)
console.log('Symbol: ' + q.symbol +
'\nLast:' + q.lastPrice +
'\nVolume:' + q.volume +
'\nTime:' + q.time);
}
};
var client = new Barchart.RealtimeData.Connection();
client.connect('qsws-us-e-01.aws.barchart.com', 'user', 'password');
client.on('marketUpdate', onMarketUpdate, 'ESZ6');
});
</script>
<body>
</body>
</html>
I have been able to load the script above (everything in the script text/javascript tag into a file called myLib.js) as well as the required libraries
let fileLocation1 = NSBundle.mainBundle().pathForResource("jquery", ofType: "js")!
let jsSource1 : String
do {
jsSource1 = try String(contentsOfFile: fileLocation1)
} catch {
jsSource1 = "Contents of JavaScript not loaded."
}
let fileLocation2 = NSBundle.mainBundle().pathForResource("barchart-marketdata-api", ofType: "js")!
let jsSource2 : String
do {
jsSource2 = try String(contentsOfFile: fileLocation2)
} catch {
jsSource2 = "Contents of JavaScript not loaded."
}
let fileLocation3 = NSBundle.mainBundle().pathForResource("myLib", ofType: "js")!
let jsSource3 : String
do {
jsSource3 = try String(contentsOfFile: fileLocation3)
} catch {
jsSource3 = "Contents of JavaScript not loaded."
}
let context = JSContext()
context.evaluateScript(jsSource1)
context.evaluateScript(jsSource2)
context.evaluateScript(jsSource3)
I am not sure how to get the output from the console.log into the context as it is inside a Jquery anonymous function.
It really does not have to come from the console.log, I could just return the string to the mac/iOS app.

Related

Discord opengraph embeds not showing up from my website

I am making a website that takes URL parameters and then creates meta tags accordingly from them.
Discord is not displaying any embed.
Here is the code:
<!DOCTYPE html>
<html>
<script>
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
var title = getUrlVars()["title"];
var description = getUrlVars()["desc"];
var color = getUrlVars()["color"];
var td = document.createElement("meta");
var tt = document.createElement("meta");
var tc = document.createElement("meta");
td.setAttribute("content", description);
tt.setAttribute("content", title);
tc.setAttribute("content", color);
td.setAttribute("property", "og:description");
tt.setAttribute("property", "og:title");
tc.setAttribute("name", "theme-color");
document.head.appendChild(td);
document.head.appendChild(tt);
document.head.appendChild(tc);
</script>
</html>
Here is the website & result:
As you can see, no embed showed up.
I am relatively new to HTML and DOM, so all help is appreciated.
As far as I know, most web crawlers do not run JavaScript, they just read the HTML in the website.
So your best option, would be to use PHP. Thats what I did with my "user embed generator"
For example:
if(isset($_GET['title']) && !empty($_GET['title'])) {
echo "<meta name='og:title' content='{$_GET['title']}' />";
}
// and so on with more open-graph tags

How can I send data from swift to javascript and display them in my web view?

I am doing an iOS hybrid app using swift 2 and HTML/Javascript. I have a native shell which get some information from the calendar and the GPS. I would like to display those information in my WKWebView and update them every seconds. I am working with local HTML.
I have found some example showing how to communicate between the native code and the JS but nothing on how to transfer my "native" datas and display them in the web view.
Thanks.
You should ask the Location Manager to update the location for you instead of setting up a 1-second NSTimer to do it yourself. And to pass data to Javascript, you can use evaluateJavaScript method of WKWebView:
import UIKit
import WebKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
weak var webView: WKWebView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
createWebView()
locationManager.delegate = self
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createWebView() {
let url = NSBundle.mainBundle().URLForResource("my_page", withExtension: "html")!
let webView = WKWebView()
webView.loadFileURL(url, allowingReadAccessToURL: url)
webView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(webView)
// Auto Layout
let views = ["webView": webView]
let c1 = NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: [], metrics: nil, views: views)
let c2 = NSLayoutConstraint.constraintsWithVisualFormat("V:[webView]|", options: [], metrics: nil, views: views)
let c3 = NSLayoutConstraint(item: webView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide , attribute: .Bottom, multiplier: 1, constant: 0)
NSLayoutConstraint.activateConstraints(c1 + c2 + [c3])
// Pass the reference to the View's Controller
self.webView = webView
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let lastLocation = locations.last!
let dict = [
"lat": lastLocation.coordinate.latitude,
"long": lastLocation.coordinate.longitude
]
let jsonData = try! NSJSONSerialization.dataWithJSONObject(dict, options: [])
let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding)!
// Send the location update to the page
self.webView.evaluateJavaScript("updateLocation(\(jsonString))") { result, error in
guard error == nil else {
print(error)
return
}
}
}
}
And my_page.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<title>This is a test page</title>
<script type="text/javascript">
function updateLocation(data)
{
var ele = document.getElementById('location');
ele.innerHTML = 'Last location: lat = ' + data['lat'] + ', long = ' + data['long'];
}
</script>
</head>
<body>
<p id="location">Last location:</p>
</body>
</html>
If you are testing this in the Simulator, choose Debug > Location > City Run to see it update continuously (as if you are running through a park).

Pass an Array from Javascript via UIWebView in Swift

I have to use UIWebView in my project and I seem that I got a problem.
Well I have html as below.
<html>
<a onclick="myFunction(1)">element1</a>
<a onclick="myFunction(2)">element1</a>
<a onclick="myFunction(3)">element1</a>
</html>
When I click to the a href link I have to execute my javascript code
<script>
var arr = [];
function myFunction(number) {
arr.push(number);
}
</script>
now how I can pass an Array to UIViewController?
and how I know in swift if I call myFunction() from UIWebView?
You can use WKWebView, available since OS X 10.10 or iOS 8 to do the job. In Xcode 9 and later, you can add the WkWebView directly to Interface Builder and connect the IBOutlet. For earlier versions of Xcode, you must do so programmatically. For full compatibility, the code below shows how to add the WKWebView programmatically.
Make your view controller conform to the WKScriptMessageHandler protocol and add the following code:
class ViewController: UIViewController, WKScriptMessageHandler {
weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// myAction is the pipe name Javascript uses to post messages
// to your app. You can define more than 1 pipe.
let controller = WKUserContentController()
controller.addScriptMessageHandler(self, name: "myAction")
let config = WKWebViewConfiguration()
config.userContentController = controller
// Add the WKWebView to the view
let frame = CGRectMake(20, 20, 200, 200)
let webView = WKWebView(frame: frame, configuration: config)
self.view.addSubview(webView)
// Load your HTML file
let url = NSBundle.mainBundle().URLForResource("mydoc", withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessToURL: url)
// Pass reference to the view controller
self.webView = webView
}
// Handle the message posted by Javascript
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
if let arr = message.body as? [Int] {
print(arr)
}
}
}
And the HTML + Javascript:
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Hello world</title>
<script type="text/javascript">
var arr = [];
function myFunction(number) {
arr.push(number);
// Send a message to your app on the myAction pipe
window.webkit.messageHandlers.myAction.postMessage(arr);
}
</script>
</head>
<body>
element1
element2
element3
</body>
</html>

Node.js -- Robust HTML parsing + access to javascript functions in HTML

I'm new to node, and looking to extract javascript info from the following example page:
contrived.html:
<html>
<head>
<title>
This is a contrived example
</title>
<script type="text/javascript">
var filenames = new Array()
filenames[filenames.length] = "http://domainwhatever.s3.amazonaws.com/780BONNYVILLECOLDLAKECHRYSLER/4431716.jpg";
filenames[filenames.length] = "http://domainwhatever.s3.amazonaws.com/780BONNYVILLECOLDLAKECHRYSLER/4431716_1.jpg";
filenames[filenames.length] = "http://domainwhatever.s3.amazonaws.com/780BONNYVILLECOLDLAKECHRYSLER/4431716_2.jpg";
filenames[filenames.length] = "http://domainwhatever.s3.amazonaws.com/780BONNYVILLECOLDLAKECHRYSLER/4431716_3.jpg";
filenames[filenames.length] = "http://domainwhatever.s3.amazonaws.com/780BONNYVILLECOLDLAKECHRYSLER/4431716_4.jpg";
function pixplosion_Content()
{
var eElement = document.getElementById('idLoading');
if( eElement ) eElement.style.display = 'none';
return "<pixplosion test=\"test\" flashGasket=\"http://www.realelivepeople.com/pixplosion/assets/flashGasket.swf?contentPath=\" ytBridge=\"/images/image.php?pixplosion=ytbridge\"><tab test=\"test\" label=\"Photos (%1)\" icon=\"Image\" autoIterate=\"false\" ><tab test=\"test\" label=\"Vehicle Photos (%1)\" icon=\"\" autoIterate=\"true\" startFocused=\"true\" >
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102537.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102538.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102539.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102540.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102541.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102542.jpg</image>
<image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102543.jpg</image><image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102544.jpg</image><image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102545.jpg</image><image>http://s3.domainwhatever_2.com/vehicles/photos/3726/1300025/35102546.jpg</image></tab></tab></pixplosion>";
}
</script>
</head>
<body>
</body>
</html>
Jsdom chokes on this HTML using its default parser, so I've used aredridel/html5 parser from github. It seems to work for reading in HTML, through jQuery, but I don't have access to function definitions like I did with jsdom and its default parser.
For example, the following:
console.log(window.filenames);
With the default parser gives me an array.
With the HTML5 parser, it gives me:
undefined
Here is my code:
var jsdom = require("jsdom"),
fs = require('fs'),
HTML5 = require('html5');
fs.readFile('contrived.html', 'utf-8', function(err, data) {
if (err) {
throw err;
}
var document = jsdom.jsdom(data, null, {parser: HTML5});
// HTML data should be in document creation call
var script = document.createElement("script");
// HTML data SHOULD NOT be in window creation call
var window = document.createWindow();
var parser = new HTML5.Parser({document: window.document});
parser.parse(data);
script.src = 'http://code.jquery.com/jquery-1.4.2.js';
script.onload = function(window) {
console.log('this is a test');
console.log(window.filenames);
console.log(window.pixplosion_Content);
}
document.head.appendChild(script);
});
Am I missing something, or is this functionality just not available?
Many thanks.

Running Exe in Firefox why do I get an error

I run this in Firefox, when clicking on link, Firefox says NS_ERROR_FILE_UNRECOGNIZED_PATH wheread I followed the instruction from here How to open .EXE with Javascript/XPCOM as Windows "Run..."?
<html>
<head>
<script>
function RunExe(path) {
try {
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf("msie") != -1) {
MyObject = new ActiveXObject("WScript.Shell")
MyObject.Run(path);
} else {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var exe = window.Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath(path);
var run = window.Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
var parameters = [""];
run.run(false, parameters, parameters.length);
}
} catch (ex) {
alert(ex.toString());
}
}
</script>
</head>
<body>
Open Word
</body>
In javascript literals, a backslash indicates the beginning of an escape sequence. If you actually want to represent a backslash, you can escape it with a double backslash.
ie
'C:\\Windows\\System32\\cmd.exe /c start winword.exe'
http://www.javascriptkit.com/jsref/escapesequence.shtml
EDIT:
From the comments on the correct answer from the post you linked, it looks like the way he got it working was:
only pass the path to runexe:
javascript:RunExe('C:\Windows\System32\cmd.exe')
set the params equal to the command args:
var parameters = ["/c start winword.exe"];
So this would work theoretically:
<html>
<head>
<script>
function RunExe(path) {
try {
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf("msie") != -1) {
MyObject = new ActiveXObject("WScript.Shell")
MyObject.Run(path);
} else {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var exe = window.Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath(path);
var run = window.Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
var parameters = ["/c start winword.exe"];
run.run(false, parameters, parameters.length);
}
} catch (ex) {
alert(ex.toString());
}
}
</script>
</head>
<body>
Open Word
</body>
Although clearly it would be better to pass in the params as an argument than hardcode them as I've done here (or pass them in as part of the path and parse them out)

Categories