I'm writing a user script for a complex web app. The existing code is catching the 'j' and 'k' keydown events.
I'd like to be able to find this function to see what it's doing. Is there a way to list all the key event handlers in a document? Or maybe a way to set a breakpoint somehow in Chrome Developer Tools for when I press the letter?
Yes, in the developer tools, go to the Scripts tab, select the page, go to Event Listener Breakpoints, Keyboard, keydown.
Though this might not necessarily help you much, e.g. if the script is minified or they use a library. But you can give it a try.
If you can get a piece of your script to run first and if the keys are handled at the document level, you can install this intercept to see what part of the code is setting the keyboard handler:
var oldListener = document.addEventListener;
document.addEventListener = function(type, listener, capture) {
if (type == "keydown" || type == "keyup" || type == "keypress") {
console.log("type=" + type + " listener=" + listener.toString().slice(0, 80));
}
return (oldListener.apply(this, arguments));
}
Related
I need to disable the indentation of ordered and unordered lists (<ul>, <ol>) in CKEditor (4.2 or 4.3) entirely, because i need to convert (a very limited subset of) HTML into another markup language which does not support indentation.
I've tried several approaches, but didn't have any luck:
Try 1: Remove plugin via configuration
config.removePlugins = 'indent,indentlist,indentblock';
I guess that is not working because these plugins seem to be required - you can't remove them when building a CKEditor package from the website.
When viewing CKEDITOR.plugins via the FireBug console, those plugins are still there. There doesn't even exist an own plugin folder - seems they are builtin to the core.
Try 2: Override TAB key
I created a new plugin disableTab that does entirely nothing (except return true; on execution).
The plugin is registered as a handler for keystroke of the TAB key:
config.keystrokes = [
[ 9, 'disableTab' ] // disable TAB key to avoid nesting!
];
Unfortunately, the plugin doesn't work when pressing tab on the first level of a list (<li> or <ol>). Interestingly, it works when pressing TAB in the second level of a list (ol > li > ol > li), it does not produce more nested lists below the second level. I know for sure my plugin is executed, because i inserted an alert() in my plugin for testing. At least, this is what happens in my Firefox.
But i need to disable indentation entirely, not only above level > 2.
Try 3: Block keystroke via blockedKeystrokes in editor configuration:
Doesn't work, even though it should according to the documentation:
config.blockedKeystrokes = [ 9 ];
Try 4: Remove keystroke during runtime
According to the API documentation this code should disable the keystroke, but it doesn't work for some reason:
for (instance in CKEDITOR.instances) {
var editor = CKEDITOR.instances[instance];
editor.setKeystroke(9, false);
}
Any idea how to remove the indentation of lists in CKEditor?
I don't understand why none of these approaches work. If you know why, please let me know.
Update:
Interestingly, this code greets me for almost every key event, except pressing the TAB key:
editor.on('key', function(e) { alert ("hi"); return false; });
So it seems my setup (LinuxMint 13 [Gnome 2] + Firefox 18 + CKEditor 4.2) does not fire the key event handler for the TAB key. Maybe the indent plugin uses some other event? Blur?
Update 2:
This is a Firefox (maybe linux only) issue. Several approaches work fine with Chrome or Internet Explorer.
I just checked quickly and it looks like although indentlist is required by the list plugin, if you:
0) Download CKEditor sources from http://github.com/ckeditor/ckeditor-dev
1) Remove
requires: 'indentlist',
from plugins/list/plugin.js
2) Remove
indentlist: 1,
indentblock: 1,
from dev/builder/build-config.js
3) Build release package with dev/builder/build.sh (on Windows use "Git Bash" shell)
You will find in the dev/builder/release/ckeditor folder the release version that you need.
(it's rather uncommon that a required plugin is not really required, but it's uncommon as well that one do not need indentation for lists ;-) )
try changing your code to:
editor = CKEDITOR.replace( 'element_name' );
editor.on('key', function(e) {
var key = e.data.keyCode;
if(key==9) {
return false;
}
that should work, just change 'element_name' to the textarea that you are replacing with ckeditor
The built-in indentlist plugin cancels the event bubbling when it is processed, so a standard event listener for the tab key isn't being fired. If you prioritize your event to run first, you can capture the tab key event and stop it from indenting your lists.
Ex:
editor.on('key', function (evt) {
if (editor.mode != 'wysiwyg') {
return false;
}
if (evt.data.keyCode == this.indentKey || evt.data.keyCode == 9) {
evt.cancel();
return false;
}
}, null, null, 1);
If you want to only block the indentation on numbered lists, you can add these conditionals:
editor.on('key', function (evt) {
var path = editor.elementPath();
if (editor.mode != 'wysiwyg') {
return false;
}
if (evt.data.keyCode == this.indentKey || evt.data.keyCode == 9 && path.contains('ol')) {
evt.cancel();
return false;
}
}, null, null, 1);
The event priority is outlined in the documentation here: https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_event.html#method-on
I'm building a node-webkit app, am listening for keypress events (in an angular directive).
Most combinations of keypress are working, but ctrl+f and ctrl+a are both not working.
This problem is specific to node-webkit. I've got the ctrl+a etc. working in the browser, but not in node-webkit.
I'm listening for keypress with the usual
document.bind('keypress',function...)
window.bind('keypress', function...)
window.bind('onkeypress', function...)
window.bind('keydown', function...)
any suggestions? Remember, the other combinations of keys ctrl+shift+o, etc. are working.
As this is a node-webkit app, there is no browser based 'find' function, and I'm disabling the 'select all'.
Isn't it an answer you where looking for?
There is a fiddle in answer of ctrl+f. If you replace 70 to 65 in this example, it will also work for ctrl+a.
document.onkeydown = function (e) {
/// check ctrl + f key
if (e.ctrlKey === true && e.keyCode === 70/*65*/) {
e.preventDefault();
console.log('Ctrl + f was hit...');
return false;
}
}
Here is a library you can use to add ctrl+f "find" support in NW.js.
https://github.com/nwutils/find-in-nw
ctrl+a to "select all" is already built in to Normal and SDK versions of NW.js
However, if you want to override the default "ctrl+a", then Andrew's answer is correct and will do that. Listen for the event and prevent default.
I am trying to write a code to bind the save as option on click event.I don't want to use filesaver.js. I want pure javascript to write this code.
HTML5 standards introduced the File API, which should allow scripts to offer up "files" (Blobs) for users to save. Support is shoddy, though, which is why polyfills like FileSaver.js exist. Filesaver.js is "pure" javascript, too, so I'm not sure why needing a pure javascript solution precludes its use (unless you mean you can't load outside scripts - just minify and inline it (along with licence, etc.)) Right now, if you must code it yourself, any cross-browser solution you come up with is likely to be an effective rewrite of the polyfil.
Once you have an implementation of saveAs(), simply attach it to whatever event trigger you like:
myButton.addEventListener( 'click', function() { window.saveAs( fileBlob, 'filename.txt' ) } );
Clarification: As per the W3C spec on Events, all untrusted events (includes key-press events) act as if event.preventDefault() was called - so there is explicitly no way to simulate an actual ctrl+s keypress - only ways to simulate its effects.
You could do something like this:
var isCtrlPressed = false;
function onKeyDown(event) {
if (event.keyCode == 17) { // Control got pressed
isCtrlPressed = true;
}
if (event.keyCode == 83) { // "s" got pressed
// if control is pressed too execute some code
if (isCtrlPressed) {
// Your code here
}
}
}
function onKeyUp(event) {
if (event.keyCode == 17) { // Control got pressed
isCtrlPressed = false;
}
}
Then on your body tag add the following events:
<body onkeydown="onKeyDown(event)" onkeyup="onKeyUp(event)">
</body>
You can find a lifedemo here:
http://jsbin.com/eBIRAfA/1/edit
Imagine a web application which uses custom keyboard event handlers which might do event bubbling - or event catching.
Is there a way (e.g. Firefox/Firebug addon) to debug each keystroke/keyboard event, something like:
displaying the event type and all attributes
trace which javascript method had been called
in case of event bubbling which further methods have been called
To clarify my question: I don't know which method handlers exist and where they are defined - this is what I am trying to find out.
You could try to visualize the vents with the Firebug + Eventbug extension.
For a general overview on keyboard events in different browsers, try this: http://unixpapa.com/js/key.html
In IE you can use the debugger; keyword. Not sure about the x-browser friendliness:
function sayHello() {
debugger; // will break here and launch script debugging in IE
alert('hello world');
}
In the context of your challenge:
function someKeyPress(e) {
debugger;
// inspect e.keyCode ... etc
}
I find this to be the most effective debugging technique, but then again I spend a lot of time in IE. Many folks are comfy with Firebug but I find it cumbersom and far less intuitive than IE's debugger. IE's debugger provides for easier watches and expression evaluation, and also provides interactive reflection based tooltips (like VS debugger).
Also, per your question "trace what method was called" - the call stack is very responsive and easy to follow back/up.
UPDATE:
Here's a script to place on the bottom of each page to trap and debug events, in IE:
<script type="text/javascript">
function wrapIfHandled(el, evt) {
if (el && evt && el['on' + evt]) {
el['_on' + evt] = el['on' + evt];
el['on' + evt] = function (e) {
foo(e, el['_on' + evt]);
};
}
}
function wrapAll() {
var allEl = document.getElementsByTagName("*");
for (var i = 0; i < allEl.length; i++) {
wrapIfHandled(allEl[i], 'click');
// wrapIfHandled(allEl[i], other event names <keyup, keydown, etc>
}
}
function foo(e, d) {
debugger;
d(e);
}
wrapAll();
</script>
I don't know any extensions for this purpose. But, you can write handlers for key events and then print appropriate output to the javascript console. Also you can dump traces too. Firebug has builtin trace functionality: console.trace(). You can google with js trace keywords to find some trace tools too.
This page is a good example to handle keyboard events.
How does one capture a Mac's Cmd key via JavaScript?
EDIT: As of 2019, e.metaKey is supported on all major browsers as per the MDN.
Note that on Windows, although the ⊞ Windows key is considered to be the "meta" key, it is not going to be captured by browsers as such.
This is only for the command key on MacOS/keyboards.
Unlike Shift/Alt/Ctrl, the Cmd (“Apple”) key is not considered a modifier key—instead, you should listen on keydown/keyup and record when a key is pressed and then depressed based on event.keyCode.
Unfortunately, these key codes are browser-dependent:
Firefox: 224
Opera: 17
WebKit browsers (Safari/Chrome): 91 (Left Command) or 93 (Right Command)
You might be interested in reading the article JavaScript Madness: Keyboard Events, from which I learned that knowledge.
You can also look at the event.metaKey attribute on the event if you are working with keydown events. Worked wonderfully for me! You can try it here.
I found that you can detect the command key in the latest version of Safari (7.0: 9537.71) if it is pressed in conjunction with another key. For example, if you want to detect ⌘+x:, you can detect the x key AND check if event.metaKey is set to true. For example:
var key = event.keyCode || event.charCode || 0;
console.log(key, event.metaKey);
When pressing x on it's own, this will output 120, false. When pressing ⌘+x, it will output 120, true
This only seems to work in Safari - not Chrome
Basing on Ilya's data, I wrote a Vanilla JS library for supporting modifier keys on Mac: https://github.com/MichaelZelensky/jsLibraries/blob/master/macKeys.js
Just use it like this, e.g.:
document.onclick = function (event) {
if (event.shiftKey || macKeys.shiftKey) {
//do something interesting
}
}
Tested on Chrome, Safari, Firefox, Opera on Mac. Please check if it works for you.
For people using jQuery, there is an excellent plugin for handling key events:
jQuery hotkeys on GitHub
For capturing ⌘+S and Ctrl+S I'm using this:
$(window).bind('keydown.ctrl_s keydown.meta_s', function(event) {
event.preventDefault();
// Do something here
});
keyCode and which are now deprecated so it's advisable to avoid the answers that use those here.
One way to do this now is using the key property on the event argument that comes with DOM keyup and keypress events. Here's a simple example of how to do it:
document.onkeypress = (event) => {
if (event.key === 'Meta') {
console.log("Mac or Windows key was pressed!");
} else {
console.log("Another key was pressed")
}
}
This will trigger on the cmd key press on Mac (See Meta on the MDN docs). The only thing to note here is it will also trigger on the Windows key press too for the users keyboard/OS that support it.
If you need more granular understanding of which Meta key has been pressed, you can use the code property on event which can be either MetaLeft or MetaRight depending on which physical meta key ( cmd) was pressed.
Here is how I did it in AngularJS
app = angular.module('MM_Graph')
class Keyboard
constructor: ($injector)->
#.$injector = $injector
#.$window = #.$injector.get('$window') # get reference to $window and $rootScope objects
#.$rootScope = #.$injector.get('$rootScope')
on_Key_Down:($event)=>
#.$rootScope.$broadcast 'keydown', $event # broadcast a global keydown event
if $event.code is 'KeyS' and ($event.ctrlKey or $event.metaKey) # detect S key pressed and either OSX Command or Window's Control keys pressed
#.$rootScope.$broadcast '', $event # broadcast keyup_CtrS event
#$event.preventDefault() # this should be used by the event listeners to prevent default browser behaviour
setup_Hooks: ()=>
angular.element(#.$window).bind "keydown", #.on_Key_Down # hook keydown event in window (only called once per app load)
#
app.service 'keyboard', ($injector)=>
return new Keyboard($injector).setup_Hooks()
var element = //the DOM element to listen for the key on.
element.onkeyup = function(e) {
if(e.metaKey) {
//command key was pressed
}
}
if you use Vuejs, just make it by vue-shortkey plugin, everything will be simple
https://www.npmjs.com/package/vue-shortkey
v-shortkey="['meta', 'enter']"·
#shortkey="metaEnterTrigged"