"Run all cells" command in Google Colab programmatically - javascript

I need to run certain command "Run all" from Google Colab menu "Runtime" programmatically. It does not have any obvious "onclick" eventHandler which I could call from javascript code on that page.
Other "divs" on the page are OK to be called from js, for exapmle, I can connect to runtime using js code:
document.querySelector('#top-toolbar > colab-connect-button').shadowRoot.querySelector('#connect').click();
Runtime menu is a dropdown menu and I tried to .click() every <div> item inside it but no effect.
Also "Run all" command has a hotkey Ctrl + F9 but dispatching event to the document element has no effect. But I can send Enter command to any input field inside the notebook with this code:
document.querySelector('input.raw_input').dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter'}))
Using Chrome code inspector Ctrl + Shift + I I looked inside "Run all" command and it looks like:
<div command="runall" class="goog-menuitem" role="menuitem" id=":1w" style="user-select: none;"><div class="goog-menuitem-content" style="user-select: none;">Run all<span class="goog-menuitem-accel">Ctrl+F9</span></div></div>
So I searched inside Sources tab of inspector code on the page and found occurrences of "runall" in https://colab.research.google.com/v2/external/external_polymer_binary.js file:
, Eja = X(new W({
id: "runall",
description: "Run all cells in notebook",
shortcut: IG(120)
120 - is a keycode of F9 button by the way. Also I found I think exact place where needed menu item is called:
case "runall":
d.runAll();
break;
but it's almost impossible for me to understand what is d. and where its reference!
Also I found many other interesting and useful commands like this.notebook.getKernel().isRunning() or c.notebook.getKernel().restart() but the question is the same all the time: what is the root object for those commands? I tried document. and window. but the result is "undefined" or "is not a function". I think that I could call runall() command in a string like:
document.**SOMETHING I DONT KNOW**.runAll()
I am very bad with frontend/js and its very difficult to find something in obfuscated code but if we have such function as .runAll() in javascript code which is connected to required menu item I thick it is possible to run it programmatically from console or javascript injection
Or maybe it is possible to dispatch a keyboard event Ctrl + F9 to some element in order to run this command thus the question is WHAT is the required object to dispatch the keyboard event

I spent a while combing through that javascript file for a similar reason, and finally figured out how to make this work.
Here's a function to programmatically run all cells:
function runAll() {
const F9Event = {key: "F9", code: "F9", metaKey: true, keyCode: 120};
document.dispatchEvent(new KeyboardEvent("keydown", F9Event));
}
Note that KeyboardEvent.keyCode is deprecated in favor of KeyboardEvent.code, but you still need to provide it here (as of 5/18/21) since it's the property Colab uses to check keyboard inputs.
You can also use metaKey: true and ctrlKey: true interchangeably, regardless of platform, since Colab just checks whether either KeyboardEvent.metaKey or KeyboardEvent.ctrlKey is present for shortcuts that require them.
Also I found many other interesting and useful commands like this.notebook.getKernel().isRunning() or c.notebook.getKernel().restart() but the question is the same all the time: what is the root object for those commands?
There's a global colab object that provides access to some (but not all) functionality. Most things are accessible through colab.global, e.g. to restart the kernel, you can use:
colab.global.notebook.kernel.restart()

Related

Detect user key/mouse in Python Selenium

I'm using Selenium Browser for day to day browsing, and I'd like to fire some code when I press some keys on any page. At first I thought I can just load javascript on every page that registers keys/mouse input, but I'd actually really prefer to have some python list available with past keys/mouse clicks, e.g. my key example in javascript:
var myhistory = []
document.addEventListener("keydown", keyDownTextField, false);
function keyDownTextField(e) {
var keyCode = e.keyCode;
myhistory.push(keyCode)
}
Is there any way to do this in pure Python/Selenium?
What I would try:
Execute a javascript that registers at the document body
<body onkeyup="my_javasctipt_keyup()" and onkeydown="my_javasctipt_keydown()">
using browser.execute_script. (partially solved, see question)
Save the key up and keydown events in a variable in javascript. (solved, see question)
use browser.execute_script to return the variables.
What I am uncertain about:
The return value of browser.execute_script may return json serializable objects or strings only
keyup and keydown in body may not work if they are used in child elements that define their own event listeners
Hopefully this is of help. If any code results form this I would be interested in knowing.
This code is what I feel should work:
from selenium import webdriver
browser = webdriver.Firefox()
browser.execute_script("""var myhistory = []
document.addEventListener("keydown", keyDownTextField, false);
function keyDownTextField(e) {
var keyCode = e.keyCode;
myhistory.push(keyCode)
}""")
def get_history():
return browser.execute_script("myhistory")
# now wait for a while and type on the browser
import time; time.sleep(5000)
print("keys:", get_history())
The point is that the code of selenium can never run at the same time as the browser handles keyboard input. As such, events need to be handled in javascript, the result saved, e.g. in an array and then, when selenium is asked, the array is returned to Python.
boppreh/keyboard would let you do that.
You install it. pip install keyboard
You import it. import keyboard
You use it. keyboard.add_hotkey('left', print, args=['You pressed the left arrow key'])
Then you disable it. keyboard.remove_all_hotkeys()
Well, in that case you had to choose the right tool for the job, i advice puppeteer a web-automation family instrument a pure-made JS, which can easily interact with the browser ( from js to js ) and catch events directly from the other side without any mediation.
Yet with selenium you can still achieve this transitively without messing too much with the pages's code or overcharging it with unnecessary tasks, also reloading the page content resets all its variables, which means it's lossy approach. The best closest way is to set an eventhandler internally and directly catch it from outside using Runtime.evaluate instead because it doesn't affect the page content and specifically it sticks to the function until it yields something using promise calls, it's better away than probing around some global variable over and over which is seen a bad practise see here.
myhistory = []
evt_handler = """
new Promise((rs,rj) => window.onkeydown= e => rs(e.keyCode) )
"""
def waitforclick():
try:
myhistory.append(browser.execute_cdp_cmd('Runtime.evaluate', {'expression': evt_handler, 'awaitPromise': True,'returnByValue': True})['result']['value'])
except:
waitforclick()
To avoid locking out the cpu you need to fork a thread in parallel.
from threading import Timer
t = Timer(0.0, waitforclick)
then t.start() instead of waitforclick().
Also you can use timeout if you want to reject the promise with a zero value after some time.

JavaScript: How to clear my custom keyboard mappings and use the default ones

In my web application I define my own keyboard event handler and override some default key mappings:
document.onkeydown = function(eventParam)
{
var keycode;
keycode = eventParam.which;
// detect ESC key
if (keycode == 27)
{
//close the window
LightboxFileInfo.close();
}
return true;
};
However, at another point in my web application, i want to clear my custom key mappings and to use again the default ones. This is my problem. Could you please advise how to do just that? How to clear all my keyboard mappings and again to use the default ones without restarting the web-application?
Basically, my web application has numerous windows. The windows are lightboxes. For each window/lightbox I use different functions for the same keys. Remember, that I have a web application, not a website. It means, that everything occurs in one webpage/JavaScript Document, where I display different windows through the already mentioned lightboxes and not as different .html/.php files.
If I need to save the default keyboard mappings before changing them, then fine. Would you please advise how to do that? My JavaScript knowledge simply ends here. Of course, I look for the simplest solution.
I am looking for a solution using:
JavaScript
I do not use jQuery, just plain JavaScript.
Besides that, I use:
HTML 5
CSS 3
PHP 5.5.8
MySQL 5.6.15
Apache 2.4.7
Thank you in advance
Since you aren't disabling the default behavior with eventParam.preventDefault();, the normal defaults should work too in the first place. But to disable your own functionality from being called, you can just override the handler function with empty one
document.onkeydown = function() { };

Lose focus on Embededd/Flash element/tab in Firefox

Without AutoHotkey and Firefox -unfocus since it's involved in operating another program and it doesn't work on linux and without Restore Window Focus After Flash addon since doesn't give you control over flash tabs.
Did anyone succeeded in implementing this gBrowser.selectedTab.unfocus(); method and bind it to a keystroke in Firefox v3.6 ?
I've also tried (based on the addon above)
if (document.getElementsByTagName("EMBED").length == 0) {
return;
}
if (document.activeElement.tagName == "EMBED") {
document.activeElement.blur();
}
return;
But it doesn't work.
Also tried this JS code binded to a keystroke:
var file = Components.classes["#mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
var process = Components.classes["#mozilla.org/process/util;1"].
createInstance(Components.interfaces.nsIProcess);
var args = ["-unfocus"];
file.initWithPath("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
process.init(file);
process.run(false, args, args.length);
Still no go.
Hi I am the author of unfocus extension.
Generally as far as I now you cannot simply bind keystroke in Firefox to unfocus plugin, because Firefox doesn't have focus. Plugin have full keyboard focus, so to unfocus plugin you must use external application.
That's the reason for creating such extension. It's the only way with the most simple implementation.
I run linux and almost every Window Manager I know support keybindings to commands. AutoHotkey is only one of the ways to achieve this on Windows. Because of this I always seen this extension as far more simple for Linux/BSD crowd.
Bind a keystroke to firefox -unfocus command.
If you use metacity (default WM of gnome):
gconf-editor -> / -> apps -> metacity -> global_keybindings and keybinding_commands
If you use kwin (kde):
http://maketecheasier.com/configure-custom-shortcuts-in-kde/2009/09/28
novell.com/coolsolutions/qna/11619.html
If you use xfwm (xfce):
Keyboard Settings -> Shortcuts
If you use openbox (lxde):
http://urukrama.wordpress.com/openbox-guide/#Key_mouse
Note that I don't use previously mentioned WM-s and DE-s, I just searched a little.
If you use tiling wm you should already know how to bind a keystroke.

How can I discover what JavaScript function is called when clicking on something on a page?

I'm trying to deconstruct part of Gmail and can't seem to be able to find what is happening (what functions are called) when a specific button is clicked.
I used Google Chrome's inspector and found the HTML for the button:
<tbody id=":8y" class="vC " idlink="" role="option" aria-labelledby=":8x :8w"><tr class="vI"><td><img class="vt SFzvCe IRnhDe BUw1sf" id=":8x" src="images/cleardot.gif" alt="Call phone"></td><td id=":8v" class="vr" colspan="2"><span id=":8w" class="HHshnc ">Call phone</span></td></tr></tbody>
In the "Event Listeners" section of the inspector under "click" I got this information:
isAttribute: false
lineNumber: 213
listenerBody: function B(H){return g.call(B.src,B.key,H)}
node: tbody#:8y
sourceName: https://mail.google.com/mail/u/0/?ui=2&view=js&name=main,tlist&ver=q0qiADndhKA.en.&am=!k3sV9...
type: click
useCapture: true
but that doesn't help me understand what's being called onClick.
What I'm trying to do is create a Greasemonkey script that will add this button to Gmail when it doesn't exist on a page.
TIA!
function B(H){return g.call(B.src,B.key,H)}
is clearly only a wrapper function that calls g. Function.call
[c]alls a function with a given this value and arguments provided individually.
As you can read on the linked MDC page, the first argument is the this object inside g, in this case B.src. The second and third parameter are passed as parameters to g.
So, you'll have to look for a function named g. The toString method might be helpful.
That said, given the goal you're trying to reach (“create a Greasemonkey script that will add this button to Gmail when it doesn't exist on a page”), I think it's not worth your time. If the button doesn't exist, I suspect it doesn't exist for a reason (e.g., g not being available on that page, or some other back-end function).

How to use condition in a TestGen4Web script for a child popup window?

I have TestGen4Web script for automating testing on a web-based user interface that has a popup window (hey i didn't write that ui..). In order to write a complete test script that branches the flow based on the some presence of some content in the popup window, I need to write a simple if condition that does something like if document.getElementById("xyz").value - that will run on the popup window and not the parent window.
Any ideas on how to accomplish this? currently, the condition fails because it runs on the parent window.
Also, how to extract some text from the dom and spit it out to a file at the end of the test?
Talked with the author of TestGen4Web. He concluded this was a bug and will be fixed in the next release. Here is the email with the temporary workaround fix:
I have a fix for your problem - which I will add in the next release.
Until then, you can use this patch.
Under your profile's
extensions/{3c20433a-61bc-42fe-831d-415860e17283}/chrome/recorder/cont
ent/
directory,
find recorder.js under the extension installation directory.
in recorder.js, find the method named
Recorder.prototype.fixAction = function(action) {
just before the return method, add the following 2 lines.
newAction.winref = this.fixDatasetsAndVariables(newAction.winref);
newAction.pagerefreshed =
this.fixDatasetsAndVariables(newAction.pagerefreshed);
restart firefox, and run your test.
Hope that solves your problem. Let me know if there are more issues
with the fix.
outside your loop initalize a loop count variable initialize it to
"1" ('count', in the attached example) 2. replace all "tg4wnamed1" with
"tg4wnamed${count}"
outside your loop initalize a loop count variable initialize it to
"1" ('count', in the attached example) 2. replace all "tg4wnamed1" with
"tg4wnamed${count}"

Categories