Beginner - Why is execCommand() obsolete? - javascript

Not a coding question, and the question applies to a wider tag of XYZ becoming obsolete, but asking as there seems to be tons of comments on the web about how there are so many apps out there that use this command.
Why is this now obsolete? (tried executing on vscode, would not work)

Based on the MDN entry for Document.execCommand, in most cases the APIs made available by execCommand can be achieved using other modern, purpose-built JavaScript APIs that behave the same way across browsers.
Each command in execCommand's toolbox was contentiously implemented in different ways across browsers meaning that testing on every single browser was a necessity of web development. Just skimming through the draft spec you linked in the comments shows all of the notes detailing some of the different ways they were implemented. Because of these differences there was a shift away from HTML-based rich-text document rendering to canvas-based rendering for Google Docs and img-based rendering for Office 365 Web Apps (at least for viewing them, editing is still HTML-based).
Additionally, the MDN entry notes:
Return value
A boolean value that is false if the command is unsupported or disabled.
Note: document.execCommand() only returns true if it is invoked as part of a user interaction. You can't use it to verify browser support before calling a command. From Firefox 82, nested document.execCommand() calls will always return false.
Because execCommand can only be invoked as part of user interaction, it might work in one bit of your code, and not in another - which can cause time-consuming headaches that involve learning the intricacies of JavaScript's event loop.
Importantly, with the advent of JavaScript running on mobile devices and modern JavaScript frameworks having their own "event->queue->render" loops, what even defines a user interaction event? A click, tap, keypress, etc? What about a screen rotation or resizing the window? What about asynchronous event changes where you make a server request and then show the user something based on the result? How would the engine know those two things are linked together with modern Promise-based APIs rather than callback-based APIs?
If you want to do some further digging, take a look at this thread on another question asking about what replacements are available to execCommand().

Related

How can one detect browser version via javascript WITHOUT using `navigator` and `navigator.userAgent`?

tldr; Can one get the browser version from the front end without using navigator strings or Client Hints?
So with Google's announcement about freezing the navigator.userAgent string, I've been tasked with going through a bunch of javascript libraries at work in an effort to replace browser sniffing (aka userAgent). I know, I know, we shouldn't use userAgent in the first place because it's a sack of confusion and lies, but I'm inheriting this code and not creating it. Luckily, a bunch of the use cases were dated (IE8-10, PhantomJS, Windows Phone) and I could remove them completely. Others I could figure out which features/intentions the original authors were using and I could swap their conditions for feature detection.
But some of the public facing logic is using navigator.userAgent to figure out the browser version and this has been more challenging to replace because everything I find on the interwebs related to this search points to using one of the navigator properties. I don't know how and why clients care which "version of Firefox a user is on" and I'm awaiting that answer, but in the meantime I'm trying to see if there is a solution out there that can detect browser version on the front end. I'm not restricting the answer to just javascript, if there is a CSS/HTML/JS combination, I'm all for it.
I'm also aware the Google says we should use Client Hints but that requires hitting the server which is out of scope for my task.
Freezing plan via the Google Announcement:
Different parts of the UA string have different compatibility
implications.
Some parts of it, such as the browser version and the OS version, can
be frozen without any backwards compatibility implications. Values
that worked in the past will continue to work in the future.
Other parts, such as the model (for mobile devices) and the OS
platform, can have implications on sites that tailor their UI to the
underlying OS or that target a very specific model in their layout. Such sites will need to migrate to use UA-CH.
If I am reading the second bullet here correctly, then the version parts of the navigator strings will be frozen and unreliable by Early June 2020.
Again, just so it's clear, I know this should be replace by feature detection, but I don't have full control over our clients and users and I'm just seeing if there is a solution out there. I have a feeling lots of folks will end up trying to solve this problem soon enough.

Why CasperJS and browsers show different behaviors with CAPTCHA? [duplicate]

Is there any way to consistently detect PhantomJS/CasperJS? I've been dealing with a spat of malicious spambots built with it and have been able to mostly block them based on certain behaviours, but I'm curious if there's a rock-solid way to know if CasperJS is in use, as dealing with constant adaptations gets slightly annoying.
I don't believe in using Captchas. They are a negative user experience and ReCaptcha has never worked to block spam on my MediaWiki installations. As our site has no user registrations (anonymous discussion board), we'd need to have a Captcha entry for every post. We get several thousand legitimate posts a day and a Captcha would see that number divebomb.
I very much share your take on CAPTCHA. I'll list what I have been able to detect so far, for my own detection script, with similar goals. It's only partial, as they are many more headless browsers.
Fairly safe to use exposed window properties to detect/assume those particular headless browser:
window._phantom (or window.callPhantom) //phantomjs
window.__phantomas //PhantomJS-based web perf metrics + monitoring tool
window.Buffer //nodejs
window.emit //couchjs
window.spawn //rhino
The above is gathered from jslint doc and testing with phantom js.
Browser automation drivers (used by BrowserStack or other web capture services for snapshot):
window.webdriver //selenium
window.domAutomation (or window.domAutomationController) //chromium based automation driver
The properties are not always exposed and I am looking into other more robust ways to detect such bots, which I'll probably release as full blown script when done. But that mainly answers your question.
Here is another fairly sound method to detect JS capable headless browsers more broadly:
if (window.outerWidth === 0 && window.outerHeight === 0){ //headless browser }
This should work well because the properties are 0 by default even if a virtual viewport size is set by headless browsers, and by default it can't report a size of a browser window that doesn't exist. In particular, Phantom JS doesn't support outerWith or outerHeight.
ADDENDUM: There is however a Chrome/Blink bug with outer/innerDimensions. Chromium does not report those dimensions when a page loads in a hidden tab, such as when restored from previous session. Safari doesn't seem to have that issue..
Update: Turns out iOS Safari 8+ has a bug with outerWidth & outerHeight at 0, and a Sailfish webview can too. So while it's a signal, it can't be used alone without being mindful of these bugs. Hence, warning: Please don't use this raw snippet unless you really know what you are doing.
PS: If you know of other headless browser properties not listed here, please share in comments.
There is no rock-solid way: PhantomJS, and Selenium, are just software being used to control browser software, instead of a user controlling it.
With PhantomJS 1.x, in particular, I believe there is some JavaScript you can use to crash the browser that exploits a bug in the version of WebKit being used (it is equivalent to Chrome 13, so very few genuine users should be affected). (I remember this being mentioned on the Phantom mailing list a few months back, but I don't know if the exact JS to use was described.) More generally you could use a combination of user-agent matching up with feature detection. E.g. if a browser claims to be "Chrome 23" but does not have a feature that Chrome 23 has (and that Chrome 13 did not have), then get suspicious.
As a user, I hate CAPTCHAs too. But they are quite effective in that they increase the cost for the spammer: he has to write more software or hire humans to read them. (That is why I think easy CAPTCHAs are good enough: the ones that annoy users are those where you have no idea what it says and have to keep pressing reload to get something you recognize.)
One approach (which I believe Google uses) is to show the CAPTCHA conditionally. E.g. users who are logged-in never get shown it. Users who have already done one post this session are not shown it again. Users from IP addresses in a whitelist (which could be built from previous legitimate posts) are not shown them. Or conversely just show them to users from a blacklist of IP ranges.
I know none of those approaches are perfect, sorry.
You could detect phantom on the client-side by checking window.callPhantom property. The minimal script is on the client side is:
var isPhantom = !!window.callPhantom;
Here is a gist with proof of concept that this works.
A spammer could try to delete this property with page.evaluate and then it depends on who is faster. After you tried the detection you do a reload with the post form and a CAPTCHA or not depending on your detection result.
The problem is that you incur a redirect that might annoy your users. This will be necessary with every detection technique on the client. Which can be subverted and changed with onResourceRequested.
Generally, I don't think that this is possible, because you can only detect on the client and send the result to the server. Adding the CAPTCHA combined with the detection step with only one page load does not really add anything as it could be removed just as easily with phantomjs/casperjs. Defense based on user agent also doesn't make sense since it can be easily changed in phantomjs/casperjs.

Can I recognise (graphic tablet) Pen Pressure in Javascript?

Is there any way to recognise pen pressure using javascript.
Preferably I don't want to make any use of Flash and try get this done as pure JS.
EDIT: okay I realised that it is kind of possible for Wacom tablets as they come with software that can work with their javascript api to make it possible (demos). But it's no good for people with Trust tablets or any other brand... So no good really.
Any body know how to do it in C# if not JS?
Yes - if the user has a Wacom tablet installed, then their browser will have a plugin for it that you can access. http://www.wacomeng.com/web/index.html
edit from author: I wrote this a very long time ago. Please see the comments below
Microsoft implemented something called Pointer Events in IE 11. It allows you to access pressure property along with stuff like pen tilt and size of contact geometry.
So far it only works on IE11 (and IE10 with vendor prefixes) but there is a W3C candidate recommendation so maybe it will be standard in future.
Javascript as a programming language in itself has no more ability or lack of ability to read this kind of data than any other language.
The language isn't important. What is important are the APIs available to you from within the language.
Javascript can be run in a number of different environments, some of which may possibly have access to APIs for this kind of hardware. However most Javascript is run in a web browser environment, and this is clearly what you mean.
The web browser environment provides a number of APIs. The most obvious is the DOM, which gives you the ability to manipulate the page, etc. There are other APIs available in the browser as well though. For example, the Geolocation API.
All these are standard APIs which have been defined by the W3C (or in some cases are in the process of being defined by the W3C), meaning that all browsers that support them should make them work the same way.
Unfortunately for you there isn't a standard API for working with pressure pads, so the direct answer to your question is no, it can't be done.
Whether one will become available in the future remains to be seen, but I have my doubts.
There is one way that you can do it though: ActiveX.
ActiveX is an API provided by Microsoft in older versions of IE. It basically provides a way of accessing virtually any Windows DLL code from within the browser.
Since the pressure pen device driver for Windows will be provided as a DLL, this means you should theoretically be able to access it in the browser via an ActiveX control. So therefore yes, you would be able to program it using Javascript.
The bad news, though, is that this is not something I'd recommend. ActiveX as a browser-based technology has long since been abandoned, due to the massive security holes it caused. I don't think the latest versions of IE even support it (I hope not, anyway), which means you'd be forced to use old versions of IE (and only IE - no other browser ever supported it) in order to run your code. Not ideal.
No, that's not possible. Probably not even with Flash.
You can only do so in an Native app. Javascript does not have access to pen pressure information

Is there an Android built-in browser developer guide? Where to look for JS engine differences?

as I am getting more and more into Android PhoneGap app development, I can see more and more nuances and little details between built-in Android browsers throughout the versions. I searched for some official or fan document, which would deal with these browser version differences. But I can't find anything useful.
It's a lot frustrating, because you have to test everything on all versions of Android emulator and if app grows big, it's A LOT of work to test all the features in all versions.
Everyone is excited about HTML5, I was too, but only to the point when I moved to doing the real thing. I realized that there is so many problems when dealing with different versions of Android behaving sometimes a lot differently.
If anyone has some good resource to share, I would be very happy. Thanks
EDIT: Added example of different behaviour betweeen Android browser versions ( but there is many of them):
This works in Android browser in 1.6, 2.2, 2.3 and 2.3.3. But it failes (application crashes or stops JS execution) in Android 2.1:
Object.keys(var).length
You asked a pretty general question. The general purpose answer is that any sort of cross browser development (even cross versions of the same browser) requires that you develop a familiarity with what features are safe across the targeted browsers, which features are not safe across the targeted browsers and which ones must be used only with careful testing or feature detection with fallback.
While one wouldn't exactly expect the type of difference you saw with the one example you referenced, it is clear that that is a fairly new feature in ECMAScript and it's not consistently implemented across normal browsers so I would put it in the category where it is not safe to assume that it works on all versions of Android, even if you've seen it some versions of Android. That means to me that you should only use it if you've explicitly tested that it's reliable in all the browser versions you are targeting or devise a feature test and only use it when you know it's present and reliable or develop a safer work-around.
As I think has been mentioned previously, this thread has a bunch of proposed work-arounds for the specific issue you mentioned.
I am not aware of any detailed written material that would document in advance for you the details of the differences between different Android browser versions. Since it's open source, there are probably developer checkin notes and some level of release notes, but that will probably be like looking for a needle in a haystack and may not even contain what you want. It is rare for any developers to produce such detailed information. We don't generally get that level of detail from any of the existing desktop browsers or iOS browsers and, even if you were on the development team itself, you probably would only see part of this info. I don't think you're going to find official documentation that covers what you want.
You're going to have to learn to treat is as more of an unknown and learn what areas are "safe", what areas require extensive testing before using and what areas are just too risky. Even when doing that, you'll find Android bugs in some version that trip you up. That's just the nature of building on someone else's platform. At least the Android set of browsers are a much simpler target than trying to target all desktop browsers from IE6 to IE9, Firefox 3 to 5, Safari 3 to 5, Opera 9 to 11, Chrome 9 to 12, all Android, all iOS and use HTML5 when available which is what I'm working on.
Once you've been through this wringer a couple times, you will realize that if the newer language/library feature carries any risk, you shouldn't use it at all unless it's absolutely central to what you're trying to accomplish and then you will have to test the hell out of it. If it's something like getting the length of the associative array which is just a programmer's convenience, then it's probably simpler to stick with a work-around that is guaranteed to be safe and just not spend your time dealing with any browser-support risk.
The only official documentation I am aware of is part of the Android developer documentation. If I were a betting man, I would bet that it only covers a subset of what you are seeking.
The general idea behind cross browser Javascript is inline feature testing (at least how I've come to accept it.) I don't know exactly what "features" you are specifically looking for but it's generally wise to test for the existence of a feature set then use it and have a fallback if that doesn't exist. (Even if the fallback is, "This site requires a browser that supports 'foo'")
Since you didn't give any examples, I'll pick on Ajax. It's always best to check for the existence of window.XMLHttpRequest, then act upon it. Of course, this is not performant if you are doing it for every instance of need so you could write a check procedure or a wrapper to accept your list of necessity let your wrapper cache/call the appropriate methods to perform that task.
Without examples of "features" that you are talking about being different from browser to browser though, it's hard to give any concrete advice on direction.

Is it possible to profile built-in JavaScript functions with Firebug?

I'm building a graphics-intensive site in HTML5 that makes heavy use of the canvas context's drawImage() function. In IE9 on Windows 7, performance is smooth, but in Firefox 4, things get choppy. I'm trying to isolate bottlenecks so I can start optimizing.
If I use the JavaScript performance profiling feature of Firebug 1.7.0, I can see statistics for my own functions, but I'd like to see calls to the built-in JavaScript functions as well. Is there any way to do this in Firebug or some other tool?
As a workaround, I suppose I could make the profiling granularity finer by breaking things down into lots of tiny functions, but I'd rather my design not be driven by how easy it is to profile.
Update: Looking back at this question, it occurs to me that the built-in functions in question are not truly JavaScript functions but functions provided by the host. In this case, they're DOM objects from the browser. Just thought I'd clarify that technical detail.
Last I used it Firebug doesn't give you the ability to profile native code.
What you can do is make your own function that just calls the native piece you want to call. As in turn the code:
ctx.fillRect(50,50,50,50);`
Into:
// wrap in function
function fillR() {
ctx.fillRect(50,50,50,50);
};
// call it immediately afterwards
fillR();
Then you can get the stats for fillR. Not the best fix, but it may useful enough.
You might try playing around with Venkman, Mozilla's JS debugger. At the moment the version on addons.mozilla.org is broken in Firefox 4.0.
You can get the most recent version via mercurial, which does work with Firefox 4.0:
hg clone http://hg.mozilla.org/venkman/
cd venkman/xpi
./makexpi.py
firefox venkman-0.9.88.1.xpi
After contemplating this on and off for a couple of days, I came up with a new solution and wrote a blog post about it:
http://andrewtwest.com/2011/03/26/profiling-built-in-javascript-functions-with-firebug/
This method does the following:
Checks to see if the Firebug console
is open.
Does a combination of overriding and
wrapping native functions with
user-defined functions.
These steps combined provide a way to profile DOM functions that doesn't affect your original script code unless you're debugging.

Categories

Resources