Firefox: set focus to tab
-
Hallo,
ich wollte fragen, wie ich in WebExtensions den Fokus auf einen anderen Tab richten kann, sodass dieser dann angezeigt wird. Also wie ich von einem anderen Tab aus diesen Tab aktivieren kann. Ich finde dazu leider nichts. Funktioniert das mit tabs.move()? Wenn ja, wie?
Danke!
-
Tab erstellen:
var foo = browser.tabs.create( // init object siehe https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/Tab { url: "foo.bar", active: true, } )
das ganze returned einen promise der entweder resolved oder rejected wird. Im promise bekommst du dein
tabs.Tab
object welchem du viaid
messages senden kannst, solltest du ihn nicht direkt active haben wollen:var switched = (callback, tab) => { browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {/* yes/no ?!*/}); }
-
Ich weiß nicht, ob du mich missverstehst oder ich dich.
Aber ich will letztendlich einfach nur eine WebExtension für Firefox schreiben, mit der ich unter Linux, wo ALT+1-9 zum Wechseln des Tabs verwendet wird statt dem praktischerern CTRL+1-9, diese Shortcuts eben in die CTRL-Variante verändere und CTRL+Q deaktivieren kann. Da ich mich aber mit JavaScript aber nicht so auskenne, muss ich mein gesamtes Wissen im Prinzip aus der Dokumentation ziehen und da konnte ich eben das Ändern des aktiven Tabs (des im Vordergrund geöffneten Tabs) nicht finden.Was ich bisher habe:
"commands": { "first_tab": { "suggested_key": { "default": "Ctrl+1" } } "second_tab": { "suggested_key": { "default": "Ctrl+2" } } "third_tab": { "suggested_key": { "default": "Ctrl+3" } } "fouth_tab": { "suggested_key": { "default": "Ctrl+4" } } "fifth_tab": { "suggested_key": { "default": "Ctrl+5" } } "sixth_tab": { "suggested_key": { "default": "Ctrl+6" } } "seventh_tab": { "suggested_key": { "default": "Ctrl+7" } } "eighth_tab": { "suggested_key": { "default": "Ctrl+8" } } "last_tab": { "suggested_key": { "default": "Ctrl+9" } } "close-q": { "suggested_key": { "default": "Ctrl+q" } } } "background": { "scripts": [ "handle-shortcuts.js" ] }
und handle-shortcuts.js:
browser.commands.onCommand.addListener((command) => { });
Dort hinein muss jetzt, wenn ich das richtig verstanden habe einfach eine Abfrage des Objekts command, durch welchen Shortcut es ausgelöst wurde und dann will ich eben zu dem entsprechenden Tab wechseln.
Es geht nicht darum, einen neuen Tab zu erstellen. Oder habe ich deine Antwort missinterpretiert?
-
Ich dachte du wolltest eine extension schreiben, die irgendwelche settings oder sowas im tab anzeigt.
Als erstes braucht dein manifest die permission fuer
tabs
, sowieactiveTab
"permissions": [ "tabs", "activeTab" ]
Danach kannst du alle tabs via query bekommen:
const windowTabs = browser.tabs.query({ "currentWindow": true });
Ueber die objects kannst du dann mit
for of
iterieren, oder den kram weg-if
-en.Mir will grade auch keine elegante moeglichkeit dazu einfallen.
Active setzt du den tab (sofern er existiert) einfach wie folgt:
browser.tabs.update(windowTabs[foo].id, { active: true });
-
Vielen Dank, sieht gut aus.
Aber leider kann ich das irgendwie nicht laden. Wenn ich in Firefox "\1:debugging" öffne und mein manifest.json laden will, dann kommt:There was an error during installation: Extension is invalid
Hier manifest.json:
{ "manifest-version": "2", "name": "shortcuts", "version": "1.0", "description": "sets shortcuts", "permissions": [ "tabs", "activeTab" ], "applications": { "gecko": { "id": "my_extension_SHORTCUTS" } }, "commands": { "first_tab": { "suggested_key": { "default": "Ctrl+1" } }, "second_tab": { "suggested_key": { "default": "Ctrl+2" } }, "third_tab": { "suggested_key": { "default": "Ctrl+3" } }, "fouth_tab": { "suggested_key": { "default": "Ctrl+4" } }, "fifth_tab": { "suggested_key": { "default": "Ctrl+5" } }, "sixth_tab": { "suggested_key": { "default": "Ctrl+6" } }, "seventh_tab": { "suggested_key": { "default": "Ctrl+7" } }, "eighth_tab": { "suggested_key": { "default": "Ctrl+8" } }, "last_tab": { "suggested_key": { "default": "Ctrl+9" } }, "close-q": { "suggested_key": { "default": "Ctrl+q" } } }, "background": { "scripts": ["shortcuts.js"] } }
Und shortcuts.js:
browser.commands.onCommand.addListener((command) => { const windowTabs = browser.tabs.query({ "currentWindow": true }); if(command == "first_tab") { browser.tabs.update(windowTabs[0].id, { active: true }); } if(command == "second_tab") { browser.tabs.update(windowTabs[1].id, { active: true }); } if(command == "third_tab") { browser.tabs.update(windowTabs[2].id, { active: true }); } if(command == "fouth_tab") { browser.tabs.update(windowTabs[3].id, { active: true }); } if(command == "fifth_tab") { browser.tabs.update(windowTabs[4].id, { active: true }); } if(command == "sixth_tab") { browser.tabs.update(windowTabs[5].id, { active: true }); } if(command == "seventh_tab") { browser.tabs.update(windowTabs[6].id, { active: true }); } if(command == "eighth_tab") { browser.tabs.update(windowTabs[7].id, { active: true }); } if(command == "ninth_tab") { browser.tabs.update(windowTabs[windowTabs.length - 1].id, { active: true }); } if(command == "close-q") { } });
Ich habe schon einiges ausprobiert, aber irgendwie funktioniert nichts davon.
Danke!
-
Wie erstellst du die extension?
Ausserdem, hast du deine extension signiert? Wenn nicht, musst du in\1:config
den keyxpinstall.signatures.required
auf false setzen.Edit: Deine loesung ist nicht sonderlich optimal, wenn nur 3 tabs existieren, bekommst eine
IndexOutOfRangeException
geschmissen, sobald zb. "CTRL+8" nimmst.Als quick'n'dirty solution wuerde ich die ganzen
if
's einfach stumpf in try/catch wrappen, indexOutOfRange catchen undwindowTabs[windowTabs.length - 1]
zurueckgeben...bzw active setzen.Edit 2:
"last_tab" != "ninth_tab"
!
-
Stimmt, es war last_tab und nicht ninth_tab, danke.
An den Fall habe ich gar nicht gedacht.
Ich habe jetzt einfach überall if(command == "Xth_tab" && windowsTabs.length > hinzugefügt.Ich erstelle die Extension gar nicht. Ich versuche die manifest.json-Datei in \1:debugging zu öffnen, wie es hier (https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Your_first_WebExtension) in dem Video unten unter Installing gezeigt wird. Bzw. wird da die *.js-Datei geladen, funktioniert bei mir aber auch nicht.
Das sollte es also eigentlich nicht sein. Die Ordnerstruktur habe ich genauso aufgebaut wie dort.
-
Du hattest einige typos im manifest.
{ "applications": { "gecko": { "id": "addon@example.com", "strict_min_version": "55.0" } }, "background": { "scripts": ["shortcuts.js"] }, "commands": { "one": { "suggested_key": { "default": "Alt+1" } }, "two": { "suggested_key": { "default": "Alt+2" } } }, "permissions": [ "activeTab", "tabs" ], "content_scripts": [ { "exclude_matches": [ "*://*/*.xml" ], "matches": [ "<all_urls>" ], "js": [ "shortcuts.js" ], "all_frames": true } ], "manifest_version": 2, "name": "foo", "version": "0.1" }
Aber selbst mit dem file ist das noch nicht ganz sauber. Kannst die extension zwar laden, wird aber noch nicht das tun, was du dir erhoffst. Hauptsaechlich, da die commands syncron abgearbeitet werden und der Promise (query nach tabs) asynchron arbeitet.
Ich schlaf da mal eine nacht drueber, vielleicht habe ich morgen eine saubere loesung.
-
Ich kann irgendwie keine Fehler finden. Das einzige, was ich jetzt nach mehrmaligem durchlesen gefunden habe, ist, dass ich die manifest-version mit "" geschrieben habe. Nach der Korrektur funktionierte es aber immer noch nicht (Extension ließ sich weiterhin nicht laden).
Kennst du denn sonst eine andere zuverlässige Extension, die das kann? Meine alte Extension Keybinder funktioniert eben nicht mehr. Und ansonsten habe ich keine gute Alternative gefunden.
Ich danke dir auf jeden Fall für deine Mühe.
-
manifest**_**version, bekommt einen integer, keinen string und wird mit underscore geschrieben.
strict_min_version
ist mandatory.
Dein ID-string, ist nicht konform.Hast du deine fehlenden direktiven hinzugefuegt?
Bist du sicher das dein manifest file das richtige encoding hat? Steht da vielleicht noch ein BOM am anfang?
Ich konnte sie mit dem file hinzufuegen und debuggen.
Generell kann ich dir das node-moduleweb-ext
empfehlen. Das startet die extension von CLI und logged besseren error output.
-
Oh, den underscore habe ich übersehen.
Das komplette "applications" habe ich jetzt testweise einfach 1:1 übernommen. Geht immer noch nicht. Genauso "content_scripts".Müsste eigentlich in UTF-8 codiert sein. Ich habe es mit nano erstellt, das ich üblicherweise auch für kleinere C-Programme verwende. Der Compiler müsste sich ja sonst eigentlich auch beschweren. Ich glaube also nicht, dass es daran liegt.
Die fehlenden Teile habe ich nach bestem Wissen und Gewissen jetzt ergänzt.
Ich versuche es sonst einmal mit web-ext. Ich habe schon davon gelesen, da ich es aber nicht in dem Repository von Ubuntu gefunden habe, dachte ich, dass es den Zusatzaufwand nicht wert sei. Jetzt installiere ich es aber über npm.
Bisher immer über \1:debugging im Browser probiert. Müsste aber ja eigentlich gleich funktionieren. Sollte es gleich mit web-ext funktionieren, melde ich mich.Ansonsten hier jetzt meine beiden Dateien:
{ "manifest_version": 2, "name": "shortcuts", "version": "1.0", "description": "shortcuts", "permissions": [ "tabs", "activeTab" ], "icons": { "ico": "icon/icon.png" }, "applications": { "gecko": { "id": "addon@example.com", "strict_min_version": "55.0" } }, "content_scripts": [ { "exclude_matches": [ "*://*/*.xml" ], "matches": [ "<all_urls>" ], "js": [ "shortcuts.js" ], "all_frames": true } ], "commands": { "first_tab": { "suggested_key": { "default": "Ctrl+1" } }, "second_tab": { "suggested_key": { "default": "Ctrl+2" } }, "third_tab": { "suggested_key": { "default": "Ctrl+3" } }, "fouth_tab": { "suggested_key": { "default": "Ctrl+4" } }, "fifth_tab": { "suggested_key": { "default": "Ctrl+5" } }, "sixth_tab": { "suggested_key": { "default": "Ctrl+6" } }, "seventh_tab": { "suggested_key": { "default": "Ctrl+7" } }, "eighth_tab": { "suggested_key": { "default": "Ctrl+8" } }, "last_tab": { "suggested_key": { "default": "Ctrl+9" } }, "close-q": { "suggested_key": { "default": "Ctrl+q" } } }, "background": { "scripts": ["shortcuts.js"] } }
und shortcuts.js:
browser.commands.onCommand.addListener((command) => { const windowTabs = browser.tabs.query({ "currentWindow": true }); if(command == "first_tab") { browser.tabs.update(windowTabs[0].id, { active: true }); } if(command == "second_tab" && windowsTabs.length > 1) { browser.tabs.update(windowTabs[1].id, { active: true }); } if(command == "third_tab" && windowsTabs.length > 2) { browser.tabs.update(windowTabs[2].id, { active: true }); } if(command == "fouth_tab" && windowsTabs.length > 3) { browser.tabs.update(windowTabs[3].id, { active: true }); } if(command == "fifth_tab" && windowsTabs.length > 4) { browser.tabs.update(windowTabs[4].id, { active: true }); } if(command == "sixth_tab" && windowsTabs.length > 5) { browser.tabs.update(windowTabs[5].id, { active: true }); } if(command == "seventh_tab" && windowsTabs.length > 6) { browser.tabs.update(windowTabs[6].id, { active: true }); } if(command == "eighth_tab" && windowsTabs.length > 7) { browser.tabs.update(windowTabs[7].id, { active: true }); } if(command == "last_tab") { browser.tabs.update(windowTabs[windowTabs.length - 1].id, { active: true }); } if(command == "close-q") { } });
Aber wenn das sowieso nicht funktioniert, dann ist das eigentlich auch nicht so wichtig.
Was ich noch gefunden habe, sind folgende Überreste von Keybinder in \1:config:{"overlays":[{"_type":"overlay","key":{"_type":"key","id":"key_selectTab1"},"shortcut":{"_type":"shortcut","keycode":"VK_1","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab2"},"shortcut":{"_type":"shortcut","keycode":"VK_2","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab3"},"shortcut":{"_type":"shortcut","keycode":"VK_3","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab4"},"shortcut":{"_type":"shortcut","keycode":"VK_4","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab5"},"shortcut":{"_type":"shortcut","keycode":"VK_5","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab6"},"shortcut":{"_type":"shortcut","keycode":"VK_6","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab7"},"shortcut":{"_type":"shortcut","keycode":"VK_7","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectTab8"},"shortcut":{"_type":"shortcut","keycode":"VK_8","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_selectLastTab"},"shortcut":{"_type":"shortcut","keycode":"VK_9","modifiers":{"_type":"modifiers","modifiers":["control"]}}},{"_type":"overlay","key":{"_type":"key","id":"key_quitApplication"},"shortcut":{"disabled":true}}]}
Das sind vermutlich aber nur die Daten von KeyBinder, die es dort gespeichert hat, oder? Damit kann ich dann ja vermutlich nichts anfangen.
Über \1:config kann man, was Shortcuts angeht, ja nichts machen, oder doch?
-
Gerade noch folgende Fehlermeldung in web-ext bekommen:
SyntaxError: Unexpected token . at exports.runInThisContext (vm.js:53:16) at Module._compile (module.js:374:25) at Object.Module._extensions..js (module.js:417:10) at Module.load (module.js:344:32) at Function.Module._load (module.js:301:12) at Module.require (module.js:354:17) at require (internal/module.js:12:17) at Object.<anonymous> (/usr/local/lib/node_modules/web-ext/node_modules/whatwg-url/lib/public-api.js:3:15) at Module._compile (module.js:410:26) at Object.Module._extensions..js (module.js:417:10)
Ich finde aber keinen Punkt zu viel.
-
Nr 1:
[firefox/index.js][debug] Firefox stdout: 1511459919791 addons.webextension.<unknown> ERROR Loading extension 'null': Reading manifest: Error processing icons: Unexpected property "ico"
siehe: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/icons
Nr 2:
[firefox/index.js][debug] Firefox stdout: 1511460114570 addons.webextension.<unknown> ERROR Loading extension 'null': Reading manifest: Error processing commands.close-q.suggested_key.default: Value "Ctrl+q" must either: match the pattern /^\s*(Alt|Ctrl|Command|MacCtrl)\s*\+\s*(Shift\s*\+\s*)?([A-Z0-9]|Comma|Period|Home|End|PageUp|PageDown|Space|Insert|Delete|Up|Down|Left|Right)\s*$/, match the pattern /^\s*((Alt|Ctrl|Command|MacCtrl)\s*\+\s*)?(Shift\s*\+\s*)?(F[1-9]|F1[0-2])\s*$/, or match the pattern /^(MediaNextTrack|MediaPlayPause|MediaPrevTrack|MediaStop)$/
(hint: uppercase)
--verbose
ist dein freund.Ich kann dir heute nacht noch den js part schicken.
Hau mal bitte ein paar linebreaks in dein json, ich muss soweit zum send button scrollen...
-
Ich dachte, dass sei nur ein ganz normaler Variablenname für das Icon. Danke.
An --verbose habe ich ehrlich gesagt gar nicht gedacht.
Das waren schon echt zwei dumme Fehler.
Funktioniert jetzt auch tatsächlich. Also es lädt, die erwünschte Wirkung hat es nicht, ich vermute aufgrund von dem Verhalten der Abfrage, die du anfangs schon erwähnt hast.
Hast du noch eine Idee, mit der sich das eventuell bewerkstelligen ließe?Ich habe jetzt, indem ich in Firefox das Ganze debuggt habe, herausgefunden, dass irgendwie browser.commands nicht erkannt wird. Ich bekomme:
ReferenceError: commands is not defined TypeError: browser.commands is undefined TypeError: browser.commands is undefined
Das kann ich mir auch irgendwie nicht erklären.
Allerdings scheint web-ext bei mir gar nicht zu funktionieren. Da scheint es irgendeinen internen Fehler zu geben. Die Fehlermeldung bezog sich also entsprechend gar nicht auf mein manifest.json.
-
Es funktioniert!
Ich danke dir.Meine Vorgehensweise:
Erst einmal das Script aus content_script in background. content_script stimmt natürlich nicht.
Dann nach einer Möglichkeit gesucht, auf Promises zu warten, da dies das Problem zu sein schien. Da "await" nicht funktionierte, stieß ich schließlich auf "then" und es funktioniert.
Hier der Code, falls es noch jemand braucht:manifest.json:
{ "manifest_version": 2, "name": "shortcuts", "version": "1.0", "description": "shortcuts", "permissions": [ "tabs", "activeTab" ], "icons": { "96": "icon/icon.png" }, "applications": { "gecko": { "id": "addon@example.com", "strict_min_version": "55.0" } }, "commands": { "first_tab": { "suggested_key": { "default": "Ctrl+1" } }, "second_tab": { "suggested_key": { "default": "Ctrl+2" } }, "third_tab": { "suggested_key": { "default": "Ctrl+3" } }, "fouth_tab": { "suggested_key": { "default": "Ctrl+4" } }, "fifth_tab": { "suggested_key": { "default": "Ctrl+5" } }, "sixth_tab": { "suggested_key": { "default": "Ctrl+6" } }, "seventh_tab": { "suggested_key": { "default": "Ctrl+7" } }, "eighth_tab": { "suggested_key": { "default": "Ctrl+8" } }, "last_tab": { "suggested_key": { "default": "Ctrl+9" } }, "close-q": { "suggested_key": { "default": "Ctrl+Q" } } }, "background": { "scripts": ["shortcuts.js"] } }
shortcuts.js:
browser.commands.onCommand.addListener(function(command) { const windowTabs = browser.tabs.query({ "currentWindow": true }); windowTabs.then(handle.bind(null, command), error); }); function handle(command, windowTabs) { if(command == "first_tab") { browser.tabs.update(windowTabs[0].id, { active: true }); console.log("Tab 1!"); } if(command == "second_tab" && windowTabs.length > 1) { browser.tabs.update(windowTabs[1].id, { active: true }); } if(command == "third_tab" && windowTabs.length > 2) { browser.tabs.update(windowTabs[2].id, { active: true }); } if(command == "fouth_tab" && windowTabs.length > 3) { browser.tabs.update(windowTabs[3].id, { active: true }); } if(command == "fifth_tab" && windowTabs.length > 4) { browser.tabs.update(windowTabs[4].id, { active: true }); } if(command == "sixth_tab" && windowTabs.length > 5) { browser.tabs.update(windowTabs[5].id, { active: true }); } if(command == "seventh_tab" && windowTabs.length > 6) { browser.tabs.update(windowTabs[6].id, { active: true }); } if(command == "eighth_tab" && windowTabs.length > 7) { browser.tabs.update(windowTabs[7].id, { active: true }); } if(command == "last_tab") { browser.tabs.update(windowTabs[windowTabs.length - 1].id, { active: true }); } if(command == "close-q") { } } function error(msg) { console.log("Error: " + msg); }
Danke Cardiac für deine ausdauernde Hilfe.
Falls du noch Verbesserungsvorschläge hast, bin ich aber auch offen dafür.Cardiac schrieb:
Hau mal bitte ein paar linebreaks in dein json, ich muss soweit zum send button scrollen...
Und hier verstehe ich leider nicht dein Anliegen? Wenn ich mehr Zeilenumbrücke benutze, dann musst du doch noch länger scrollen? Am Anfang der Seite ist doch außerdem auch ein "Beitrag verfassen"-Button?