I recently made a simple macOS app that loads an html page form the bundle in a WebKit WebView (the new one, not legacy) but I noticed that when I type some keys in the page (not in an input box, I mean body keypress handled using javascript) an error sound is played. I was wondering if there is a solution for this problem.
I also might say that the html page works perfectly if I open it with Safari and there are no errors in the built-in inspector console as well as no error sound is played (which might tell us that the problem comes with something I'm missing in the application).
Here's my Swift code (App Delegate Obviously):
#IBOutlet weak var contentView: WebView!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let path = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "HTML_Content")
let url = URL(fileURLWithPath: path!)
let request = URLRequest(url: url)
contentView.mainFrame.load(request)
}
My HTML Code (Which works perfectly) [index.html]:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js/jquery-1.12.0.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</head>
<body>
<h2 id="text"></h2>
</body>
</html>
My JavaScript / jQuery Code [js/main.js]:
$(document).keypress(function(e) {
var text = $('#text').text();
if (e.which == 8) {
if (text.length != 0) {
text = text.slice(0, -1);
$('#text').text(text);
}
} else if ('abcdefghijklmnopqrstuvwxyz1234567890 '.indexOf(
String.fromCharCode(e.which).toLowerCase()) != -1) {
$('#text').text(text + String.fromCharCode(e.which));
}
});
Can someone help me fix it?
I finally understood why the application was giving me the error sound:
The WebView needs to perform the key equivalent on its content.
It actually couldn't perform it by default but I forced it using a custom class with this override, excluding the shortcut keys (or I wouldn't be able to use them):
Swift 4:
import WebKit
class WebViewController: WebView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
override func performKeyEquivalent(with event: NSEvent) -> Bool {
if event.modifierFlags.contains(.command) ||
event.modifierFlags.contains(.control) ||
event.modifierFlags.contains(.shift) ||
event.modifierFlags.contains(.option) {
return false
}
return true
}
}
Then I connected the custom class to the xib element using the element inspector's custom class property.
And, in the end, the sound was gone.
Related
I made an iOS app in Swift.
There's also a UIWebView in it. This WebView loads a website of my server that contains a list with events. This list/website should reload once a day to keep it up to date.
What is the best way to do it?
Maybe with this meta tag in HTML?
<meta http-equiv="refresh" content="86400">
But, I think this will only count down if the app is open and actually in use. I think this will not work if the app is only open in the background, right?
If so, what's the best an common way to do that?
I'm using this working solution now:
import UIKit
class FirstViewController: UIViewController, UIWebViewDelegate {
#IBOutlet var homewebview: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
_ = NSTimer.scheduledTimerWithTimeInterval(21600, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
self.homewebview.delegate = self
}
func update() {
homewebview.reload()
NSURLCache.sharedURLCache().removeAllCachedResponses()
NSURLCache.sharedURLCache().diskCapacity = 0
NSURLCache.sharedURLCache().memoryCapacity = 0
}
}
I'm using a UIWebViewthat loads HTML from a database string using webView.loadHTMLString(self.htmlContent, baseURL: nil)
The htmlContent contains the following:
<ul class="anchorNavigation">
<li>
1. Inline Test Link
</li>
<li>
2. Inline Test Link
</li>
...
</ul>
... and later in the HTML:
...
...
However, whenever I click the inline link in the webView nothing happens.
What I've tried so far:
Changing the anchor tag to 'real' valid W3C HTML. E.g. <a id='parsys_47728'>Test</a>
Saving the HTML to a file in the temp directory and loading it using loadRequest(). E.g. let path = tempDirectory.URLByAppendingPathComponent("content.html") and webView.loadRequest(NSURLRequest(URL: path))
Intercepting the loadRequest method by implementing the func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool delegate. The request.URL says something strange like: "applewebdata://1D9D74C2-BBB4-422F-97A7-554BCCD0055A#parsys_47728"
I don't have any idea anymore how to achieve this. I know from previous projects that local HTML files in the bundle work with inline links. I just cannot figure out why this doesn't work.
Help much appreciated! Thank you!
If there's a fragment (e.g., #anchorName), then use JavaScript to scroll. Otherwise, assume it's a link without a fragment and use openURL.
// UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
// NSLog(#"request.URL %#",request.URL); // e.g., file:///.../myApp.app/#anchorName
NSString *anchorName = request.URL.fragment; // e,g, "anchorName"
if ( anchorName ) {
[webView stringByEvaluatingJavaScriptFromString:[NSString swf:#"window.location.hash='%#';",anchorName]];
return NO;
} else { // assume http://
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
}
return YES;
}
I'm still looking for a way to have the scroll position change smoothly (animated) rather than jumping.
I have implemented the accepted solutions here and it does work for
some websites. For eg: Go to www.tomcruise.com and click on his trailers. Each of those links have target="_blank" and started opening after implementing the solution suggested in the previously linked stack overflow post.
But now I found that if we go to here and click on any link(the one I tried, as of writing this question, has a href tag as below
<a rel="nofollow" target="_blank" href="http://www.nowmagazine.co.uk/celebrity-news/victoria-and-david-beckham-fighting-to-be-together-296082" class="ot-anchor aaTEdf" jslog="10929; track:click" dir="ltr">http://www.nowmagazine.co.uk/celebrity-news/victoria-and-david-beckham-fighting-to-be-together-296082</a>
When I click on this link from inside WKWebView, the WKUIDelegate method below, does get called but has navigationAction.request = "" and hence nothing happens when webView.loadRequest("") gets called. Anyone else face this issue?
optional func webView(_ webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration,
forNavigationAction navigationAction: WKNavigationAction,
windowFeatures windowFeatures: WKWindowFeatures) -> WKWebView?{
if navigationAction.targetFrame == nil {
webView.loadRequest(navigationAction.request)
}
return nil
}
What is special about the above specified href tag that is causing the WKUIDelegate method to be called with an empty url?
How do we fix this issue? Let me know how you root caused the issue as I am interested in debugging as well.
I was hoping that I could solve it using the WKWebView delegate methods, but I could not figure it out.
So I went to the UIWebView era's solution of running a javascript function upon completion of web Page loading
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
let jsCode = "var allLinks = document.getElementsByTagName('a');if (allLinks) { var i;for (i=0; i<allLinks.length; i++) {var link = allLinks[i];var target = link.getAttribute('target');if (target && target == '_blank') {link.setAttribute('target','_self');} } }"
webView.evaluateJavaScript(jsCode, completionHandler: nil)
}
This fixed the issue where tapping on the links in any google plus Posts page was resulting in an empty page being loaded
UPDATE on Nov 3rd 2015: The phenomenon explained in the question, no longer happens for me in Swift 2.0 code. So , you should be able to use the solution presented here for all your purposes
I have following issues on conversion:
Text field not working on converting swf file to html5 using swiffy..
some animation are not working..
There is also sound problem in in some browser.
Is there any way to identify the textfield actions ?
I have googled but nothing works.. I think they are saying use js.
1) The key is to send the value to the swiffy object with this line in javascript:
function sendValue() {
myValue=inputFieldName.value;
stage.setFlashVars('myMessageFromTextfield='+myValue);
}
2) Then, inside the fla file, in actionscript2, get the value:
getValue = function() {
if(_level0.myMessageFromTextfield == "undefined" || _level0.myMessageFromTextfield == undefined) {
this.cat.animCat.myText.text = "";
} else {
this.cat.animCat.myText.text = _level0.myMessageFromTextfield;
returnButton._visible = true;
}
}
3) You need to constantly monitor when te data apears so use a setInterval:
myInterval = setInterval(this, "getValue", 100);
4) Now, to send the value back to html file, we use getURL with the data attached:
returnButton.onRelease = function() {
getURL("Javascript:showMessage('"+_level0.myMessageFromTextfield+" says the cat');");
}
5) And finally, again in javascript inside the html we execute the function with the parameter:
function showMessage(message) {
alert(message);
}
It works perfectly in IE, Firefox, Chrome, safari (ios).
So you now can send text in ipad or iphone.
I attached the source files in the next link:
https://onedrive.live.com/redir?resid=E64343A7ADE7D670!1401&authkey=!AO86aUEdyZRqQN4&ithint=file%2czip
Hope this help you (I've been trying to solve this during many months and until today i could).
I'm still busy trying to setup a JSON file to a HTML website. So if the json changes the changes are dynamically loaded in the HTML. Till this far i'm able to retreive the content and even request some content. But not everything that i want because the markup from the JSON is a bit weird.
Because of the cross-site protection I was not able to do a JSOP request directly, so i solved that with a little trick i saw somewhere. I've created a test.php that simply does:
That way I circumvent the cross-site protection, and everything works well. Only problem is that I can't iterate over all the arrays that i want. Currently i'm using the following script to do a JSOP call and get the data. And the output is a nice description between the <li></li>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<ul id="episodes">
</ul>
<script src="http://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min.js"></script>
<script src="http://ps3scenefiles.com/json/handlebars.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script id="episodes-template" type="text/template">
<li>{{description}}</li>
</script>
<script>
$(function() {
$.getJSON('http://ps3scenefiles.com/json/test.php', function(data) {
var template = $('#episodes-template').html();
var info = Mustache.to_html(template, data);
$('#episodes').html(info);
});
});
</script>
</body>
</html>
But when you open the link to the JSON (http://ps3scenefiles.com/json/test.php), you see that the Episodes array has another array with just numbers. How can i create a list like
Episode: 1
Id:13605 Active:true Lang:en Link: url
Id:16525 Active:true Lang:ru Link: url
Episode: 2
Id:14854 Active:true Lang:en Link: url
Id:19445 Active:true Lang:ru Link: url
So to be clear, how can i do a mustache (or handlebars) templating to make it look like the example?
You can use Handlebars helper as mentioned in this answer
Here is a fiddle without styling, that prints out the data you expect (sort of, not all fields).
Here is the helper function -
Handlebars.registerHelper('eachkeys', function(context, options) {
var fn = options.fn, inverse = options.inverse;
var ret = "";
var empty = true;
for (key in context) { empty = false; break; }
if (!empty) {
for (key in context) {
ret = ret + fn({ 'key': key, 'value': context[key]});
}
} else {
ret = inverse(this);
}
return ret;
});