Wykryj przeglądarkę Safari

142

Jak wykryć przeglądarkę Safari za pomocą JavaScript? Wypróbowałem kod poniżej i wykrywa on nie tylko Safari, ale także przeglądarkę Chrome.

function IsSafari() {

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

}
Tomas
źródło
1
Część kodu JS związanego z przesyłaniem plików działa z szacunkiem dla Safari, w przypadku Chrome działa dobrze.
Tomas
1
Prawie na pewno powinieneś testować wszelkie różnice w interfejsach API. Oprócz Safari i Chrome istnieją inne przeglądarki oparte na WebKit.
Quentin
12
Istnieje wiele powodów, dla których można chcieć wykryć przeglądarkę. Na przykład w chwili pisania tego tekstu niektóre aspekty silnika SVG, takie jak filtry, są zepsute w Safari, ale działają w Chrome.
Paul Legato
Czasami po prostu nie możesz naprawić błędu, ponieważ nie możesz go odtworzyć (nie mam dostępu do Maca). Naprawiłem problem na Midori (jakiś problem BlobBuilder / Blob dla podkładki sendAsBinary), ale klient mówi, że nadal występuje problem z przesyłaniem plików, więc najlepszą rzeczą, o której mogę pomyśleć, jest po prostu usunięcie obsługi Safari i użycie do tego ramek iframe (jak w przypadku stary IE)
llamerr

Odpowiedzi:

110

Możesz łatwo użyć indeksu Chrome, aby odfiltrować Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}
david
źródło
6
Nie działa. Obecnie wyprowadza na iPhone'a ciąg chrome UA i nawet nie ma w nim słowa „chrome”.
Paul Carlton,
5
Ciąg IE 11 UA w systemie Windows 10 zawiera również Safari i Chrome
cuixiping
Blackberry zawiera również „Safari”.
Harry Pehkonen
18
@Flimm Istnieje wiele uzasadnionych przypadków użycia do wykrywania przeglądarki. Nie zakładaj, że znasz intencje osoby pytającej lub odpowiadającej. Chociaż wspaniale jest dołączyć pomocną wskazówkę, która może uważasz za istotną, w żadnym wypadku nie jest to wymóg.
Ruben Martinez Jr.
1
To nie działa w przeglądarkach Androida, które obejmują „safari”, ale nie „chrome”: developers.whatismybrowser.com/useragents/explore/software_name/ ...
Eric Andrew Lewis
156

Uwaga: zawsze staraj się wykryć określone zachowanie, które próbujesz naprawić, zamiast kierować go na nieisSafari?

W ostateczności wykryj Safari za pomocą tego wyrażenia regularnego:

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

Używa negatywnych rozejrzeń i wyklucza Chrome, Edge i wszystkie przeglądarki Androida, które zawierają Safarinazwę w swoim kliencie użytkownika.

fregante
źródło
2
To nie działa. Nadal rozumiem, jeśli używam przeglądarki Chrome na iPhonie.
ayjay
27
Dzieje się tak, ponieważ wszystkie przeglądarki na iOS są po prostu opakowaniami dla Safari (z wyjątkiem Opery Mini w trybie Mini ), w tym Chrome. Niekoniecznie oznacza to, że wszystkie będą pasować do tego testu, ponieważ ciąg userAgent zależy od opakowania. Możesz chcieć osobno wykryć Chrome na iOS .
fregante
Koleś to zadziałało dla mnie !!! Wielkie dzięki… navigator.userAgent zwracał wartości takie jak „5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, np. Gecko) Chrome / 39.0.2171.99 Safari / 537.36” zarówno dla przeglądarki Chrome w systemie Windows, jak i Safari w systemie Mac.
KaustubhSV
2
Naprawiono teraz. Zdecydowanie masz rację, problem z wieloma przeglądarkami polega na tym, że zawierają one inne nazwy, aby nie dać się pominąć. Like Edge zawiera zarówno Chrome, jak i Safari w swoim UA. Z tego powodu testy klienta użytkownika są złe: zmieniają się przeglądarki i testy muszą zostać zaktualizowane. Niestety nie ma idealnego sposobu na wykrycie przeglądarki, zawsze jest to domysł.
fregante
1
Zdecydowanie dobrym pomysłem jest użycie wykrywania funkcji, ale niektóre zachowania są po prostu trudne lub prawie niemożliwe do przetestowania, na przykład czy filmy na telefonie komórkowym są automatycznie wyświetlane na pełnym ekranie, co dzieje się tylko na iPhonie i iPodzie. Aby to przetestować, musisz załadować film i poprosić użytkownika o jego odtworzenie.
fregante
91

Jak już zauważyły ​​inne osoby, wykrywanie funkcji jest lepsze niż sprawdzanie konkretnej przeglądarki. Jednym z powodów jest to, że można zmienić ciąg agenta użytkownika. Innym powodem jest to, że ciąg może się zmienić i uszkodzić kod w nowszych wersjach.

Jeśli nadal chcesz to zrobić i przetestować dla dowolnej wersji Safari, sugeruję użycie tego

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

Działa to z każdą wersją Safari na wszystkich urządzeniach: Mac, iPhone, iPod, iPad.

Edytować

Aby przetestować w bieżącej przeglądarce: https://jsfiddle.net/j5hgcbm2/

Edytuj 2

Zaktualizowano zgodnie z dokumentacją Chrome, aby poprawnie wykryć Chrome na iOS

Warto zauważyć, że wszystkie przeglądarki na iOS są po prostu opakowaniami dla Safari i używają tego samego silnika. Zobacz komentarz bfred.it do jego własnej odpowiedzi w tym wątku.

Edytuj 3

Zaktualizowano zgodnie z dokumentacją Firefoksa w celu poprawnego wykrywania Firefoksa na iOS

qingu
źródło
Dzięki za komentarz - Zaktualizowano, aby poprawnie wykryć Chrome na iOS
qingu
@qingu - nie rozumiem tego javascript, jak bym zrobił coś takiego - if (safaribrowser) {zrób to} else {zrób to} używając tego samego kodu jaka wartość to „var isSafari” dzięki
GAV
@GAV: w przeciwnym razie isSafaribędzie truew przeglądarce Safari false. Możesz po prostu użyć powyższego fragmentu kodu, a następnie użyć swojego prawie tak, jak go opublikowałeś. if (isSafari) { do_this(); } else { do_that(); }.
qingu
2
Niestety, powodów, dla których warto spróbować poznać przeglądarkę, jest więcej niż tylko wykrywanie funkcji. Przeglądarka może obsługiwać funkcję, ale zawiera błędy (np. Błąd kanwy w IE10, ale ta sama funkcja działa w IE9). Ponadto Firefox zachowuje się inaczej niż przeglądarki oparte na webkitach, na przykład reaguje na ruch myszy. Safari firmy Apple zawiera błędy ponownego przepływu, które nie istnieją w Chrome. Niektóre przeglądarki są również wydajne podczas wykonywania niektórych zadań wymagających dużej mocy obliczeniowej niż inne.
DemiImp
2
@Andras Dla Firefoksa możesz dodać && !navigator.userAgent.match('FxiOS')podobny test do Chrome - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/ ... )
Petri Pellinen
60

Po prostu użyj:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");
lukyer
źródło
15
Nie wiem, dlaczego to nie jest wyżej - czy to jest doskonałe, krótkie i proste. Musiałem wykluczyć safari na komputerze z powodu braku getUserMedia.
Stephen Tetreault
3
to doskonały sposób na określenie safari na komputerze, ponieważ nie działa na urządzeniach mobilnych
Godblessstrawberry
W jakich wersjach Safari to działa? Wydaje się, że nie działa w wersji 5.1.7
ElliotSchmelliot
Jeśli zależy Ci tylko na przeglądarkach, a nie na urządzeniach mobilnych czy komputerach, to działa idealnie.
Antuan
1
To nie zadziałało w iPhone 11 Pro Max Simulator 13.5
Christian Valentin
19

Ten kod służy do wykrywania tylko przeglądarki Safari

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}
wahid
źródło
4
ten kod wykrywa tylko to, czy przeglądarka webkit nie jest chrome. Wiele innych przeglądarek ma zły pomysł, aby włączyć „safari” do łańcucha agenta użytkownika. Na przykład Opera: 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)lub standardowa przeglądarka systemu Android:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
rupps
wykrywanie platformy podrzucającej może prawdopodobnie odfiltrować określone przypadki zgodności.
ljgww
Właśnie sprawdziłem sześć przeglądarek iOS innych firm, wszystkie podszywają się pod bardzo dokładnego agenta użytkownika Safari.
Mitch Match
Więc to wykryje tylko Chrome. A jednak właśnie się dowiedziałem, że Chrome 44 nie ma już Chrome w UA, ale zamiast tego „CriOS” :(
Mitch Match
Powinniśmy zawsze starać się wykrywać funkcje i używać wykrywania przeglądarki w ostateczności, ponieważ ta ostatnia jest znacznie bardziej podatna na awarie i blokowanie legalnych użytkowników. Każda odpowiedź, która w ogóle nie wspomina o wykrywaniu funkcji, jest ode mnie negatywna.
Flimm
12

Ponieważ userAgent dla chrome i safari są prawie takie same, łatwiej będzie przyjrzeć się dostawcy przeglądarki

Safari

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

Chrom

navigator.vendor ==  "Google Inc."

FireFox (dlaczego jest pusty?)

navigator.vendor ==  ""

IE (dlaczego jest niezdefiniowane?)

navigator.vendor ==  undefined
tylerlindell
źródło
1
Szukałem czegoś, aby wyłączyć komunikaty ostrzegawcze w safari w pracy na różnych komputerach (komputery stacjonarne Mac, iPady itp.) I działało idealnie.
dylnmc
Jednak dostawcą Chrome na iOS będzie też „Apple Computer, Inc.”. Przepraszamy ...
Piotr Kowalski
@PiotrKowalski - z jakiego rozwiązania wybrałeś?
tylerlindell
@tylerlindell Zobacz moją odpowiedź na dole tej strony ze słowem „wersja”.
Piotr Kowalski
7

Tylko Safari bez Chrome:

Po wypróbowaniu innych kodów nie znalazłem żadnego, który działałby z nową i starszą wersją Safari.

Na koniec zrobiłem ten kod, który działa bardzo dobrze:

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>

leoledmag
źródło
5

Zauważyłem, że tylko jedno słowo odróżnia Safari - „Wersja”. Więc to wyrażenie regularne będzie działać idealnie:

/.*Version.*Safari.*/.test(navigator.userAgent)
Piotr Kowalski
źródło
5

Nie wiem, dlaczego operator operacyjny chciał wykryć Safari, ale w rzadkich przypadkach, gdy potrzebujesz wąchania przeglądarki, obecnie prawdopodobnie ważniejsze jest wykrycie silnika renderującego niż nazwy przeglądarki. Na przykład w iOS wszystkie przeglądarki używają silnika Safari / Webkit, więc nie ma sensu umieszczać „chrome” lub „firefox” jako nazwy przeglądarki, jeśli podstawowym rendererem jest Safari / Webkit. Nie testowałem tego kodu ze starymi przeglądarkami, ale działa ze wszystkim, co jest całkiem nowe na Androidzie, iOS, OS X, Windows i 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>

W celu wyjaśnienia:

  • Wszystkie przeglądarki w systemie iOS będą zgłaszane jako „safari / webkit”
  • Wszystkie przeglądarki w systemie Android oprócz Firefox będą zgłaszane jako „chrome / blink”
  • Chrome, Opera, Blisk, Vivaldi itp. Zostaną zgłoszone jako „chrome / blink” w systemie Windows, OS X lub Linux
Christopher Martin
źródło
4

używam tego

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));
}
lovepong
źródło
4

Najprostsza odpowiedź:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}
SudarP
źródło
2
Działa, chociaż można to zrobić prościej bez navigator.vendor.toLowerCase().indexOf('apple') > -1
wyrażenia regularnego
5
Jeszcze prostsze… if (navigator.vendor.match(/apple/i)) { ... }.
Brad
To nie działa dla iOS 13.3.1 w przeglądarce Firefox, ponieważ pokazuje Apple Computer, Inc.
nuttynibbles
1
@nuttynibbles: Prawdopodobnie tego chcesz, ponieważ każda przeglądarka na iOS to Safari w przebraniu.
wortwart
3

Dla przypomnienia, najbezpieczniejszym sposobem, jaki znalazłem, jest zaimplementowanie części Safari kodu wykrywania przeglądarki z tej odpowiedzi :

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

Oczywiście najlepszym sposobem radzenia sobie z problemami specyficznymi dla przeglądarki jest zawsze wykrywanie funkcji, jeśli jest to w ogóle możliwe. Użycie fragmentu kodu takiego jak powyższy jest jednak nadal lepsze niż wykrywanie ciągu agentów.

Marcos Sandrini
źródło
1
To nie działa z wersją Safari / 13.1 Mobile / 15E148 Safari / 604.1 na iPhone OS 13_4_1.
mindo
2

Wiem, że to pytanie jest stare, ale i tak pomyślałem o zamieszczeniu odpowiedzi, ponieważ może to komuś pomóc. Powyższe rozwiązania zawodziły w niektórych skrajnych przypadkach, więc musieliśmy zaimplementować je w sposób, który obsługuje osobno iOS, Desktop i inne platformy.

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;
}
HH
źródło
1

Zmodyfikowane wyrażenie regularne dla powyższej odpowiedzi

var isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);
  • crios - Chrome
  • fxios - Firefox
Yurii Sherbak
źródło
1

Ten wyjątkowy „problem” jest w 100% oznaką, że przeglądarka to Safari (wierz lub nie).

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

Oznacza to, że deskryptor obiektu cookie jest ustawiony na false w Safari, podczas gdy w pozostałych jest true, co w rzeczywistości przyprawia mnie o ból głowy w innym projekcie. Miłego kodowania!

zoxxx
źródło
Wydaje się, że to już nieprawda. Ponadto ulega awarii w przeglądarce Firefox „Object.getOwnPropertyDescriptor (...) jest niezdefiniowana”
Offirmo
0

Może to działa:

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

EDYCJA: BEZ PRACY

Harshal Carpenter
źródło
Co dokładnie to robi, ponieważ zwraca -1 we wszystkich przeglądarkach?
Petroff
@Petroff nie działa już w nowszym safari. Dzięki za wskazanie tego.
Harshal Carpenter
2
Zapraszam do usunięcia odpowiedzi.
Flimm
0

Tworzę funkcję, która zwraca typ boolowski:

export const isSafari = () => navigator.userAgent.toLowerCase().indexOf('safari') !== -1
Idan
źródło
-2

Wąchanie klienta użytkownika jest naprawdę trudne i zawodne. Próbowaliśmy wykryć Safari na iOS z czymś w rodzaju odpowiedzi @ qingu powyżej, działało całkiem dobrze w Safari, Chrome i Firefox. Ale fałszywie wykrył Operę i Edge jako Safari.

Poszliśmy więc z wykrywaniem funkcji, jak wygląda na dzień dzisiejszy, serviceWorkerjest obsługiwane tylko w Safari, a nie w żadnej innej przeglądarce na iOS. Jak podano w https://jakearchibald.github.io/isserviceworkerready/

Wsparcie nie obejmuje wersji iOS przeglądarek innych firm na tej platformie (patrz Obsługa Safari).

Więc zrobiliśmy coś takiego

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

Uwaga : nie testowano w Safari na MacOS.

AG
źródło