I want to automatically swipe tik-tok videos, so I tried this in Chrome console, but it doesn't work.
var event = new KeyboardEvent('keydown');
document.dispatchEvent(event);
I think Tiktok is most likely preventing untrusted keyboard events from triggering the scroll. If you run this code
window.addEventListener('keydown', (e) => {
console.log(e)
})
window.dispatchEvent(
new KeyboardEvent('keydown',{
//keycode and code for down arrow
keyCode:40,
code:'ArrowDown'
})
)
You'll get a KeyboardEvent object logged that looks something like this
KeyboardEvent {isTrusted: false, key: "", code: "ArrowDown", location: 0, ctrlKey: false, …}
Im pretty sure that Tiktok's keypress/keydown listener ignores synthetic keypresses (prolly by checking event.isTrusted) and thus automatically scrolling by simulating the down arrow press is probably out of question. However, you could target the next button on page and click it.
// this is the class name for the up and down button
let buttonSelector = '.up-and-down';
let buttons = document.querySelectorAll(buttonSelector)
let prev, next = null;
// if theres one button, then its the next
if(buttons.length == 1)
next = buttons[0]
//if not then the first button is prev, and the last next
else
[prev, next] = buttons
//now click
next && next.click();
Related
I'm writing a desktop app using nwjs, and I want to use the right mouse button for some UI functions. This is working pretty ok right now; I am able to disable the context menu when the right click was for a UI function.
However, I am having an awful time figuring out how to not only stop right click events from opening a context menu, but also to stop them from selecting the text under the cursor.
Here is an example of what is happening (that I do not want to happen) - I am left-click dragging a handle to resize a UI view, and then while the left mouse is held down I am right clicking to cancel the resize. When the right click ends over any text, the text is selected. (Normally, a context menu would also appear.)
When handling the right mouse down event and context menu event, I am calling event.preventDefault() and returning false.
What the actual event handler code looks like (appearing in the same order as the events are spawned and handled)...
this.windowMouseDownListener = event => {
if(this.draggingResize &&
event.button === 2 && !event.ctrlKey
){
for(let view of this.area.views){
view.size = view.sizeBeforeDrag;
}
this.area.updateElementSizes();
this.draggingResize = false;
this.recentDraggingResize = true;
event.preventDefault();
event.stopPropagation();
return false;
}
};
this.windowContextMenuListener = event => {
if(this.recentDraggingResize){
event.preventDefault();
return false;
}
};
this.windowMouseUpListener = event => {
this.sizeBeforeDrag = this.size;
if(this.size <= 0.0001){
this.area.removeView(this);
}
if(this.draggingResize || this.recentDraggingResize){
this.recentDraggingResize = false;
this.draggingResize = false;
event.preventDefault();
event.stopPropagation();
return false;
}
};
How can I fix this behavior?
Using AG-Grid, I need to be able to hit the tab key and have the focused element change from the grid/cell currently selected, to the next element on the page outside of the grid. The problem is that the tab key seems to be locked within the grid, and will not move outside of the data table to the next element.
I have an even listener on the cells that stores the last focused cell (used to store the last location to be able to tab back into the grid to the previously focused cell), but need to have the next focused cell be outside of the data grid:
const cells = document.getElementsByClassName('ag-cell');
[...cells].map(cell => {
cell.addEventListener("keydown", function(e) {
if(e.key === "Tab") {
let lastCell = cell.attributes[2].value;
console.log("Last Cell Focused: ", lastCell)
}
})
})
How can I remove the focus selection from the grid on keypress to the next focusable page element?
Here's a plnkr link to the current grid: Link
=====================================================
UPDATE
I've updated my code, and instead of attaching an event listener to every cell, it's now looking for the event triggered on the document. However, I'm still running into the issue that it's not getting the last_cell value and seeing the focus-visible class on hasFocusVisible.
//on arrow right if last_call === header that has 'focus-visible', set focus to first cell in body
const headerCells = document.getElementsByClassName('ag-header-cell-label');
const last_cell = headerCells[headerCells.length-1].attributes[2];
const hasFocusVisible = document.querySelector('.ag-header-cell-label').classList.contains('focus-visible');
document.addEventListener("keydown", function(e) {
if(e.key === "ArrowRight") {
// if(hasFocusVisible && last_cell) {
console.log("EVENT TRIGGERED FROM: ", event.target, "Last Cell Value: ", last_cell, hasFocusVisible);
//if last_call and 'ag-header-cell-label' has 'focus-visible', set focus to first cell in body
const bodyCell = document.getElementsByClassName('ag-cell')[0];
// }
}
});
UPDATED Plnkr: Link
====================================================
UPDATE 2
I've updated the element selector to the following:
const last_cell = document.querySelector('.ag-header-cell:last-child');
const hasFocusVisible = document.querySelector('.ag-header-cell-label').classList.contains('.focus-visible');
document.addEventListener("keydown", function(e) {
console.log('document.activeElement', document.activeElement)
const activeElement = document.activeElement;
if(e.key === "ArrowRight" && activeElement) {
if(last_cell) {
console.log("EVENT TRIGGERED FROM: ", event.target, "Last Cell Value: ", last_cell, hasFocusVisible);
//if last_call and 'ag-header-cell-label' has 'focus-visible', set focus to first cell in body
const bodyCell = document.getElementsByClassName('ag-cell')[0];
}
}
else if(e.key === "ArrowDown"){
//look for first child in first row with same id as header and set focus
document.querySelector('.ag-cell').focus();
}
});
however, the hasFocusVisible variable is always coming up false when logging out the div that has the focus-visible class. I'm not sure if I have my logic incorrect, or its not able to get the focus-visible class on the ag-header-cell-label when the event listener is fired.
If tab works within the cells, don't add a listener to every cell, just add a single one to your document, and make it move focus to whatever you know is next on the page manually. For instance:
var b = document.querySelector('button');
b.passThrough = true;
b.update = pass => {
b.passThrough = pass;
b.textContent = "click me to " + (b.passThrough ? "block" : "allow") + " tabbing";
}
b.addEventListener('click', e => b.update(!b.passThrough));
b.update(b.passThrough);
var focussable = Array.from(
document.querySelectorAll([
'button',
'[href]',
'input',
'select',
'textarea',
'[tabindex]:not([tabindex="-1"])'
].join(','))
);
// let's pretend this is your last cell.
var p = document.querySelector('p');
// make it kill off keydown events, BUT, also have it redirect focus
// to "the next focussable element", so you can see what that code looks like.
p.addEventListener('keydown', e => e.preventDefault());
document.addEventListener('keydown', e => {
if (b.passThrough && e.target === p) {
var next = focussable.indexOf(p) + 1;
focussable[next % focussable.length].focus();
}
});
<button>toggle</button>
<p tabindex=0>first</p>
second
third
Run this snippet, click the button, hit tab, notice that the tab event is now trapped (like in your cells). Now, click the button again, hit tab, hit tab again: notice it seems like the event is no longer trapped, when it fact it is: the event for the element itself is getting killed off, but the event listener for the document now explicitly moves focus for us.
I have a mobile menu that opens when the open menu button is clicked. I am trying to add a trap focus functionality to the menu when it is open so that users cannot access outside of my menu with a keyboard when tabbing.
I have used an event listener to listen for tab and shift tab keydown events in the menu. The logic is that if the active element does not have a class that only my menu items have then to lock focus back onto the close button of my menu.
Problem is that the focus gets stuck on my close button instantly and I cannot move it (even though it has the class "in-listview"). I realise that my code may not be the best way to implement this feature but for now I would just like to know why my class does not seem to be recognised and I can tidy up after. My app is built using ReactJS.
openNav = () => {
const listView = document.querySelector(".listview");
listView.classList.remove('closeMobMenu');
listView.style.visibility = "visible";
listView.classList.add('openMobMenu');
document.addEventListener('keydown', this.trapTabMobMenu)//Maybe move this to componentDidMount()?
}
trapTabMobMenu = (event) => {
if(event.keyCode === 9) { // if the tab key is pressed in the mobile menu
const closeBtn = this.closeBtn;
let activeElement = document.activeElement;
if(event.shiftKey) { // shift-tab
event.preventDefault();
//if focused element does not have class in-list-view
if(!activeElement.classList.contains("in-listview")) {
closeBtn.focus();
}
} else { // normal tab
event.preventDefault();
if(!activeElement.classList.contains("in-listview")) {
closeBtn.focus();
}
}
}
if(event.keyCode === 27) {
this.closeNav();
}
}
<button ref={(close) => { this.closeBtn = close; }} className="closebtn in-listview" onClick={closeNav} onKeyPress={handleKeyPress} tabIndex="2">×</button>
document.activeElement is not set until after the focus event has been completed, so the above code is not performing your logic on the new element that is firing the onFocus event.
You need to change document.activeElement to be event.target then perform your logic.
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
I have a scenario where I have to prepare a JS method where Tab key should fire . i.e. When the Function is executed Tab button click should fire. preferably using Key code.
You can dispatch keyboard events, but the results might be less than overwhelming.
As shown below, you can dispatch an event with appropriate properties, but in some browsers the values are empty and the browser virtually ignores it. You can tab to the button and press "Enter" to click it. It dispatches a tab, but focus doesn't move and the associated event doesn't report the values set in the constructor.
Typing into the input shows the type of result you should get. Try it in lots of browsers.
function showEventProperties(evt) {
document.getElementById('details').innerHTML = ['type','key','code','keyIdentifier','charCode','which','keyCode'].map(function(key) {
return key + ': ' + evt[key];
}).join('<br>');
}
function sendTab(node) {
var evt = new KeyboardEvent('keypress', {
'view': window,
'bubbles': true,
'key': 'Tab',
'charCode': 9,
'keyCode': 9,
'which': 9
});
node.dispatchEvent(evt);
}
window.onload = function() {
document.addEventListener('keypress', showEventProperties, false);
}
<input onkeypress="showEventProperties(event)">
<br>
<button onclick="sendTab(this)">Do tab</button><button>Next button</button>
<p id="details"></p>
You can also try the older initKeyEvent.
I'm creating a touch application in the "Itunes LP" format which uses html, css and javascript within Itunes to create a "digital LP". The application will have several LP's to explore through a touchscreen.
In fullscreen mode (within Itunes and the LP) you can press the "esc key" to exit the LP and enter "coverflow view" where you can choose another LP to explore. I will have no keyboard or mouse so I need to create a button/link that do one thing when the user clicks on this link and that is to simualte the ESC key being pressed.
So my question is; Is it possible to simulate a keyboard shortcut being pressed using JavaScript in a link? My link would be "Home" and by clicking on this link the browser behaves as the ESC key was pressed.
Any tips on this would be most helpful.
Thanks!
David
ADDED 30/6;
(Part of TuneKit.js for Itunes LP)
/* ==================== Keyboard Navigation ==================== */
TKSpatialNavigationManager.prototype.handleKeydown = function (event) {
var key = event.keyCode;
// check if our controller knows what it's doing and let it take over in case it does
if (this._managedController.wantsToHandleKey(key)) {
// prevent default actions
event.stopPropagation();
event.preventDefault();
// have the controller do what it think is best in this case
this._managedController.keyWasPressed(key);
return;
}
// reset the sound
TKSpatialNavigationManager.soundToPlay = null;
// check we know about this key, otherwise, do nothing
if (TKSpatialNavigationManagerKnownKeys.indexOf(key) == -1) {
return;
}
var navigation = TKNavigationController.sharedNavigation;
// first, check if we're hitting the back button on the home screen, in which case
// we don't want to do anything and let the User Agent do what's right to exit
if (event.keyCode == KEYBOARD_BACKSPACE && navigation.topController === homeController) {
return;
}
// before we go any further, prevent the default action from happening
event.stopPropagation();
event.preventDefault();
// check if we're busy doing other things
if (TKSpatialNavigationManager.busyControllers > 0) {
return;
}
// see if we pressed esc. so we can pop to previous controller
if (event.keyCode == KEYBOARD_BACKSPACE) {
var top_controller = navigation.topController;
if (top_controller !== homeController) {
// at any rate, play the exit sound
TKUtils.playSound(SOUND_EXIT);
// see if the top controller has a custom place to navigate to with the back button
if (top_controller.backButton instanceof Element && top_controller.backButton._navigationData !== undefined) {
navigation.pushController(TKController.resolveController(top_controller.backButton._navigationData.controller));
}
// otherwise, just pop the controller
else {
navigation.popController();
}
}
}
****My script will look like this:****
var albumHelper = {};
albumHelper.playAlbum = function() {
var playlist = bookletController.buildPlaylist(appData.songs);
playlist.play();
};
var event = {};
event.keyCode = function() {
var escapeKeyProxy = TKSpatialNavigationManager.prototype.handleKeydown({'keyCode':27});
document.getElementById('btnExitFullScreen').onclick = escapeKeyProxy;
};
var homeController = new TKController({
id: 'home',
actions : [
{ selector: '.menu > .play', action: albumHelper.playAlbum },
{ selector: '.menu > .linernotes', action: event.keyCode }
],
navigatesTo : [
{ selector: '.menu > .songs', controller: 'songs' },
{ selector: '.menu > .photos', controller: 'photos' },
{ selector: '.menu > .videos', controller: 'videos' },
{ selector: '.menu > .credits', controller: 'credits' }
],
// make the PLAY button be default highlight
highlightedElement : '.menu > .play'
});
So what I want is the .linernotes' image, when clicked, simulate a ESC key being pushed!
This answer assumes there is a JS function that the iTunes LP application uses to exit full-screen.
Though you probably can, you shouldn't have to simulate the event. The Key event you're working with is tied by either an event listener or an event handler to a function (in this case, a function that exits full-screen mode). You should be able to create a button and tie it (by a similar event listener or an event handler) to the same function.
You can't tie it directly, because the key events pass information about which key was pressed, and mouse events don't, so you need to send it through a proxy. Your code might look something like this. In this case, the code that takes in the Key event in the iTunes LP library would be called iTunesLPKeyPressEvent. I have no idea what it's actually called.
var escapeKeyProxy = function() {
iTunesLPKeyPressEvent({'keyCode':27});
}
document.getElementById('btnExitFullScreen').onclick = escapeKeyProxy;
You may need to massage this a bit, but the basic idea should work.
[EDIT]
Based on your update, I'd say that
TKSpatialNavigationManager.prototype._managedController is the object you need to work with and most probably TKSpatialNavigationManager.prototype._managedController.keyWasPressed(key) is the code that captures the escape key. Take a look through the code for addEventListener("keypress",SOME_METHOD,true) (or keyup or keydown) and it will be the SOME_METHOD that's handling the event. That's the method you'll want to hijack. Hopefully it will be in a scope you can easily get to.