Or a version which works with Safari and or Chrome:
Find and activate specific tab (Chrome and:or Safari).kmmacros (22.4 KB)
![](https://forum.keyboardmaestro.com/uploads/default/original/2X/8/8efa3ccfd2e049b209258ba220f8a2a29d134c37.png)
// Rob Trew MIT license 2015
// Ver 0.2: Works with Safari and or Google
// (searches all tabs of both, if both open)
(function (blnTypeString) {
'use strict';
// s -> [window, tab]
function tabsMatching(s, lstBrowsers) {
return mb(lstBrowsers, function (b) { // Each browser,
var blnChrome = b.name()[0] === "G";
return mb(browserWindows(b, blnChrome), function (w) { // each window,
return mb(w.tabs(), function (t) { // each tab.
return ([t.name(), t.url()].reduce(function (acc, x) {
return acc ? acc : (x.toLowerCase().indexOf(s) !== -1);
}, false)) ? [[b, w, t]] : [];
})})});
}
// () -> [app]
function browserNames() {
return Application("System Events").applicationProcesses.whose({
_or: [{
name: "Safari"
}, {
name: "Google Chrome"
}]
})().map(function (a) {
return a.name();
});
}
// app -> Bool -> [window]
function browserWindows(a, blnChrome) {
return blnChrome ? a.windows() : a.windows.whose({
_not: [{
'document': null
}]
})();
}
// Monadic bind (chain) for lists
// [a] -> (a -> [b]) -> [b]
function mb(xs, f) {
return [].concat.apply([], xs.map(f));
}
// Int -> Int -> String
function padNum(n, lngDigits) {
return Array(
lngDigits - n.toString().length + 1
).join('0') + n;
}
// CHROME AND/OR SAFARI ?
var a = Application.currentApplication(),
sa = (a.includeStandardAdditions = true, a),
lstBrowserNames = browserNames(),
lstBrowsers = lstBrowserNames.map(function (x) {
return Application(x);
}),
strBrowsers = lstBrowserNames.join(' or '),
strTitle = "Find and activate " + strBrowsers + " tab";
sa.activate();
// DIALOG INVITING SEARCH STRING (CLICK ON OK TO LIST ALL TABS)
// OR STRAIGHT TO LIST OF ALL TABS ?
var s = blnTypeString ? sa.displayDialog("Search:", {
withTitle: strTitle,
defaultAnswer: '',
defaultButton: "OK"
}).textReturned.toLowerCase() : '';
var lstFound = tabsMatching(s, lstBrowsers),
lstChosen = [],
lngFound = lstFound.length;
// MULTIPLE MATCHES ? OFFER CHOICE
if (lngFound > 1) {
var lngDigits = lngFound.toString().length,
lstNames = lstFound.map(function (x, i) {
var strName = x[2].name();
return padNum(i, lngDigits) + '\t' + (strName || x[2].url());
}).concat('').concat(lstFound.map(function (x, i) {
return padNum(i, lngDigits) + '\t' + x[2].url();
}));
sa.activate();
var varChosen = sa.chooseFromList(lstNames, {
withTitle: strTitle,
withPrompt: "Choose a " + strBrowsers + " tab:",
defaultItems: [''],
multipleSelectionsAllowed: false
});
if (varChosen && varChosen[0].length) {
lstChosen = [lstFound[parseInt(varChosen[0].split('\t')[0], 10)]];
};
} else lstChosen = lstFound;
// ACTIVATE WINDOW AND TAB, RETURNING NAME & URL
return lstChosen.map(function (oTab) {
var b = (oTab[0]),
w = (oTab[1]),
t = (oTab[2]);
b.activate();
w.visible = false;
if (b.name()[0] === "G") {
var idTab = t.id();
w.activeTabIndex = w.tabs().reduce(function (acc, x, i) {
return idTab === x.id() ? i : acc;
}, 0) + 1;
} else w.currentTab = t;
w.visible = true;
return '[' + t.name() + '](' + t.url() + ')';
}).join('\n');
})(false);