Виявити браузер Safari


142

Як виявити браузер Safari за допомогою JavaScript? Я спробував код нижче, і він виявляє не тільки Safari, але і браузер Chrome.

function IsSafari() {

  var is_safari = navigator.userAgent.toLowerCase().indexOf('safari/') > -1;
  return is_safari;

}

1
Деякі з JS-кодів, пов’язаних із тим, що файли надсилають файли на Safari, для Chrome працює чудово.
Томаш

1
Ви майже напевно повинні проходити тестування на наявність відмінностей в API. Існують інші веб-браузери на базі WebKit, окрім Safari та Chrome.
Квентін

12
Є багато причин, з яких можна виявити браузер. Наприклад, станом на цей текст певні аспекти двигуна SVG, такі як фільтри, зламані в Safari, але працюють у Chrome.
Пол Легато

Іноді ви просто не можете виправити помилку, оскільки ви не можете її відтворити (у мене немає доступу до Mac). Я вирішив проблему в Midori (деякі проблеми BlobBuilder / Blob для sendAsBinary shim), але клієнт каже, що все ще існує проблема з завантаженням файлів, тому найкраще, що я можу придумати, - це просто видалити підтримку Safari і використовувати для неї iframes (як для старий IE)
llamerr

Відповіді:


110

Ви можете легко використовувати індекс Chrome для фільтрації Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}

6
Не працює. В даний час виводиться хромоване рядок UA на iPhone, і в ньому навіть немає слова "chrome".
Пол Карлтон

5
Рядок IE 11 UA у Windows 10 також містить Safari та Chrome
cuixiping

До ожини також входить «Сафарі».
Гаррі Пеконен

18
@Flimm Існує багато законних випадків використання для виявлення браузера. Не припускайте, що знаєте про наміри запитувача чи відповідача. Хоча добре включити корисну пораду, яку ви можете вважати релевантною, це аж ніяк не є вимогою.
Рубен Мартинес-молодший

1
Це не працює на веб-переглядачах Android, куди входить "сафарі", але не "хром": developers.whatismybrowser.com/useragents/explore/software_name/…
Ерік Ендрю Льюїс

156

Примітка. Завжди намагайтеся виявити конкретну поведінку, яку ви намагаєтеся виправити, а не орієнтуватися на неїisSafari?

В крайньому випадку виявіть Сафарі за допомогою цього виразного тексту:

var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

Він використовує негативні образи, і він виключає Chrome, Edge та всі веб-переглядачі Android, які містять Safariім’я у своєму користувальницькому агенті.


2
Це не працює. Я все ще справджуся, якщо використовую браузер Chrome на iPhone.
ayjay

27
Це тому, що всі браузери на iOS - це просто обгортки для Safari (за винятком Opera Mini в режимі Mini ), включаючи Chrome. Це не обов'язково означає, що всі вони будуть відповідати цьому тесту, оскільки рядок userAgent дорівнює обгортці. Ви можете виявити Chrome на iOS окремо.
fregante

Чувак, це працювало на мене !!! Дякуємо за тону .. navigator.userAgent повертав значення типу "5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, як Gecko) Chrome / 39.0.2171.99 Safari / 537.36" для Chrome у Windows та Safari в mac.
KaustubhSV

2
Виправлено зараз. Ви, безумовно, праві, проблема з великою кількістю браузерів полягає в тому, що вони включають інші імена, щоб намагатися не залишитися без уваги. Як і Edge, в його UA входять і Chrome, і Safari. З цієї причини перевірки агентів користувачів погані: браузери змінюються, і їх потрібно оновлювати. На жаль, немає ідеального способу виявити браузер, це завжди здогадки.
fregante

1
Безумовно, хороша ідея використовувати функції виявлення функцій, але деякі способи поведінки просто важко або майже неможливо перевірити, наприклад, чи відео на мобільному телефоні автоматично йде на повний екран, що відбувається лише на iPhone та iPod. Щоб перевірити його, вам потрібно завантажити відео та дати користувачеві його відтворення.
fregante

91

Як уже зазначали інші, перевагу виявлення функцій віддається перевазі, ніж перевірка конкретного браузера. Однією з причин є те, що рядок агента користувача може бути змінений. Ще одна причина полягає в тому, що рядок може змінювати та порушувати ваш код у новіших версіях.

Якщо ви все ще хочете це зробити і перевірити будь-яку версію Safari, я б запропонував скористатися цією

var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&
               navigator.userAgent &&
               navigator.userAgent.indexOf('CriOS') == -1 &&
               navigator.userAgent.indexOf('FxiOS') == -1;

Це працюватиме з будь-якою версією Safari на всіх пристроях: Mac, iPhone, iPod, iPad.

Редагувати

Для тестування у вашому поточному веб-переглядачі: https://jsfiddle.net/j5hgcbm2/

Редагувати 2

Оновлено згідно з документами Chrome, щоб правильно виявити Chrome на iOS

Варто зазначити, що всі браузери на iOS - це просто обгортки для Safari і використовують один і той же двигун. Дивіться коментар bfred.it щодо власної відповіді в цій темі.

Правка 3

Оновлено згідно з документами Firefox, щоб правильно виявити Firefox на iOS


Дякуємо за коментар - Оновлено, щоб правильно виявити Chrome на iOS
qingu

@qingu - я не розумію цей javascript, як би я зробив щось на кшталт - якщо (safaribrowser) {зроби це} ще {зроби це}, використовуючи той самий код, яке значення 'var isSafari' дякую
GAV

@GAV: в іншому випадку isSafariбуде trueв браузері Safari false. Ви можете просто скористатись вищевказаним фрагментом, а потім використовувати свій майже як ви його опублікували. if (isSafari) { do_this(); } else { do_that(); }.
qingu

2
На жаль, існує більше причин намагатися розібратися в браузері, ніж просто виявлення функцій. Веб-браузер може підтримувати функцію, але бути помилковим (наприклад: canvas bug в IE10, але ця сама функція працює в IE9). Також Firefox веде себе інакше, ніж веб-браузери, наприклад, як він реагує на рух миші. Apple Safari має поповнення помилок, яких немає в Chrome. Деякі веб-переглядачі також працюють під час виконання певних обчислювально-інтенсивних завдань, ніж інші.
DemiImp

2
@Andras Для Firefox ви можете додати && !navigator.userAgent.match('FxiOS')схожий до перевірки Chrome - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/… )
Петрі Пеллінен

60

Просто використовуйте:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");

15
Не впевнений, чому це не вище вгору - це ідеально, коротко і просто. Мені потрібно було виключити сафарі на робочому столі через відсутність getUserMedia.
Стівен Тетро

3
це ідеальний спосіб визначити сафарі на робочому столі, оскільки це не працює на мобільних пристроях
godblessstrawberry

Для яких версій Safari це працює? Здається, не працює для v5.1.7
ElliotSchmelliot

Якщо ви дбаєте лише про браузери, а не мобільний та робочий стіл, це прекрасно працює.
Антуан

1
Це не спрацювало в iPhone 11 Pro Max Simulator 13.5
Крістіан Валентин

19

Цей код використовується для виявлення лише браузера сафарі

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}

4
цей код виявляє лише те, що веб-браузер не хромований. У багатьох інших веб-переглядачів погана ідея включати "сафарі" в рядок агентів користувача. Наприклад, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36 OPR/24.0.1558.51 (Edition Next)браузер Opera: або Stock Android:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
рветься

Виявлення підкидання платформи може, можливо, відфільтрувати конкретні випадки сумісності.
ljgww

Я щойно перевірив півтора десятка сторонніх веб-переглядачів iOS, всі вони підробляють дуже точний користувач-агент Safari.
Матч Мітч

Отже, це виявить лише Chrome. І все-таки я щойно з’ясував, що Chrome 44 більше не має Chrome в ОАЕ, а замість цього «CriOS» :(
Mitch Match

Ми завжди повинні намагатися виконувати виявлення функцій і використовувати виявлення браузера в крайньому випадку, оскільки це набагато більше шансів зламати та заблокувати законних користувачів. Будь-яка відповідь, яка взагалі не згадує про виявлення функцій, отримує відгук від мене.
Флейм

12

Оскільки userAgent для хрому та сафарі майже однаковий, можна легше подивитися на постачальника браузера

Сафарі

navigator.vendor ==  "Apple Computer, Inc."

Хром

navigator.vendor ==  "Google Inc."

FireFox (чому він порожній?)

navigator.vendor ==  ""

IE (чому це не визначено?)

navigator.vendor ==  undefined

1
Я шукав щось, щоб відключити попереджувальні повідомлення в сафарі під час роботи на різних комп’ютерах (на комп’ютерах mac, ipads тощо), і це спрацювало чудово.
dylnmc

Але постачальником Chrome на iOS також буде "Apple Computer, Inc.". Вибачте ...
Пьотр Ковальський

@PiotrKowalski - з яким рішенням ти пішов?
tylerlindell

@tylerlindell Дивіться мою відповідь внизу цієї сторінки зі словом "версія".
Пьотр Ковальський

7

Тільки Safari без Chrome:

Спробувавши інші коди, я не знайшов жодного, який би працював з новими та старими версіями Safari.

Нарешті, я зробив цей код, який працює для мене дуже добре:

var ua = navigator.userAgent.toLowerCase(); 
var isSafari = false;
try {
  isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);
}
catch(err) {}
isSafari = (isSafari || ((ua.indexOf('safari') != -1)&& (!(ua.indexOf('chrome')!= -1) && (ua.indexOf('version/')!= -1))));

//test
if (isSafari)
{
  //Code for Safari Browser (Desktop and Mobile)
  document.getElementById('idbody').innerHTML = "This is Safari!";
}
else
{
  document.getElementById('idbody').innerHTML = "Not is Safari!";
}
<body id="idbody">
</body>


5

Я зауважив, що лише одне слово відрізняє Safari - "Версію". Тож цей регулярний вираз буде працювати ідеально:

/.*Version.*Safari.*/.test(navigator.userAgent)

5

Я не знаю, чому ОП хотіла виявити Safari, але в рідкісних випадках вам потрібен нюхаючи браузер, але сьогодні, мабуть, важливіше виявити движок візуалізації, ніж ім'я браузера. Наприклад, в iOS всі браузери використовують механізм Safari / Webkit, тому безглуздо отримувати "chrome" або "firefox" як назву браузера, якщо основним рендером є Safari / Webkit. Я не перевіряв цей код у старих браузерах, але він працює зі всіма останніми версіями на Android, iOS, OS X, Windows та Linux.

<script>
    let browserName = "";

    if(navigator.vendor.match(/google/i)) {
        browserName = 'chrome/blink';
    }
    else if(navigator.vendor.match(/apple/i)) {
        browserName = 'safari/webkit';
    }
    else if(navigator.userAgent.match(/firefox\//i)) {
        browserName = 'firefox/gecko';
    }
    else if(navigator.userAgent.match(/edge\//i)) {
        browserName = 'edge/edgehtml';
    }
    else if(navigator.userAgent.match(/trident\//i)) {
        browserName = 'ie/trident';
    }
    else
    {
        browserName = navigator.userAgent + "\n" + navigator.vendor;
    }
    alert(browserName);
</script>

Для уточнення:

  • Усі браузери під iOS будуть повідомлятися як "safari / webkit"
  • Усі веб-переглядачі під Android, окрім Firefox, повідомляться як "хром / блимання"
  • Про Chrome, Opera, Blisk, Vivaldi і ін. Буде повідомлено як "хром / блимання" під Windows, OS X або Linux

4

Я цим користуюся

function getBrowserName() {
    var name = "Unknown";
    if(navigator.userAgent.indexOf("MSIE")!=-1){
        name = "MSIE";
    }
    else if(navigator.userAgent.indexOf("Firefox")!=-1){
        name = "Firefox";
    }
    else if(navigator.userAgent.indexOf("Opera")!=-1){
        name = "Opera";
    }
    else if(navigator.userAgent.indexOf("Chrome") != -1){
        name = "Chrome";
    }
    else if(navigator.userAgent.indexOf("Safari")!=-1){
        name = "Safari";
    }
    return name;   
}

if( getBrowserName() == "Safari" ){
    alert("You are using Safari");
}else{
    alert("You are surfing on " + getBrowserName(name));
}

4

Найпростіша відповідь:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}

2
Це працює, хоча це можна зробити простіше без regexp:navigator.vendor.toLowerCase().indexOf('apple') > -1
fviktor

5
Ще простіше if (navigator.vendor.match(/apple/i)) { ... }.
Бред

Це не працює для ios 13.3.1 на Firefox, як показує Apple Computer, в т.ч.
nuttynibbles

1
@nuttynibbles: Це, мабуть, те, що ви хочете, тому що кожен браузер на iOS є переодягненим Safari.
wortwart

3

Для записів найбезпечніший спосіб, який я знайшов, - це реалізувати частину Safari коду виявлення браузера з цієї відповіді :

const isSafari = window['safari'] && safari.pushNotification &&
    safari.pushNotification.toString() === '[object SafariRemoteNotification]';

Звичайно, найкращий спосіб вирішення проблем, пов’язаних із браузером, - це завжди виявлення функцій, якщо це можливо. Однак використання фрагмента коду, як описано вище, все ж краще, ніж виявлення рядка агента.


1
Це не працює з версією safari Version / 13.1 Mobile / 15E148 Safari / 604.1 в ОС iPhone 13_4_1.
mindo

2

Я знаю, що це питання давнє, але я думав все-таки опублікувати відповідь, оскільки це може комусь допомогти. Вищевказані рішення були відмовлені в деяких крайніх випадках, тому нам довелося реалізувати його таким чином, що обробляє iOS, Desktop та інші платформи окремо.

function isSafari() {
    var ua = window.navigator.userAgent;
    var iOS = !!ua.match(/iP(ad|od|hone)/i);
    var hasSafariInUa = !!ua.match(/Safari/i);
    var noOtherBrowsersInUa = !ua.match(/Chrome|CriOS|OPiOS|mercury|FxiOS|Firefox/i)
    var result = false;
    if(iOS) { //detecting Safari in IOS mobile browsers
        var webkit = !!ua.match(/WebKit/i);
        result = webkit && hasSafariInUa && noOtherBrowsersInUa
    } else if(window.safari !== undefined){ //detecting Safari in Desktop Browsers
        result = true;
    } else { // detecting Safari in other platforms
        result = hasSafariInUa && noOtherBrowsersInUa
    }
    return result;
}

1

Змінений регулярний вираз для відповіді вище

var isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);
  • crios - Хром
  • fxios - Firefox

1

Ця унікальна "проблема" є 100% ознакою того, що браузер Safari (вірите чи ні).

if (Object.getOwnPropertyDescriptor(Document.prototype, 'cookie').descriptor === false) {
   console.log('Hello Safari!');
}

Це означає, що дескриптор об'єктів cookie встановлений на Сафарі на помилковому, а на всіх інших - істинно, що насправді призводить до головного болю в іншому проекті. Щасливого кодування!


Здається, це вже не так. Також виходить з ладу на Firefox "Object.getOwnPropertyDescriptor (...) не визначено"
Offirmo

0

Можливо, це працює:

Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')

РЕДАКТУВАННЯ: НЕ БІЛЬШЕ РОБОТИ


Що саме це робить, бо повертаємо -1 у всіх браузерах?
Петроф

@Petroff більше не працює в новіших сафарі. Дякуємо, що вказали на це.
Харшал Карпентер

2
Сміливо видаляйте відповідь.
Flimm

0

Я створюю функцію, яка повертає булевий тип:

export const isSafari = () => navigator.userAgent.toLowerCase().indexOf('safari') !== -1

-2

Нюхання агента користувача справді складне і ненадійне. Ми намагалися виявити Safari на iOS, начебто відповідь @ qingu вище, це спрацювало досить добре для Safari, Chrome та Firefox. Але він помилково виявив Оперу та Край як Сафарі.

Тому ми пішли з виявленням функцій, як це виглядає, як сьогодні, serviceWorkerпідтримується лише в Safari, а не в будь-якому іншому браузері на iOS. Як зазначено в https://jakearchibald.github.io/isserviceworkerready/

Підтримка не включає версії iOS сторонніх веб-переглядачів на цій платформі (див. Підтримку Safari).

Тож ми зробили щось подібне

if ('serviceWorker' in navigator) {
    return 'Safari';
}
else {
    return 'Other Browser';
}

Примітка : Не тестується на Safari на MacOS.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.