* !!! This is an undocumented "private" service !!! * * @name $sniffer * @requires $window * @requires $document * * @property {boolean} history Does the browser support html5 history api ? * @property {boolean} transitions Does the browser support CSS transition events ? * @property {boolea
()
| 15884 | * This is very simple implementation of testing browser's features. |
| 15885 | */ |
| 15886 | function $SnifferProvider() { |
| 15887 | this.$get = ['$window', '$document', function($window, $document) { |
| 15888 | var eventSupport = {}, |
| 15889 | android = |
| 15890 | int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), |
| 15891 | boxee = /Boxee/i.test(($window.navigator || {}).userAgent), |
| 15892 | document = $document[0] || {}, |
| 15893 | vendorPrefix, |
| 15894 | vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, |
| 15895 | bodyStyle = document.body && document.body.style, |
| 15896 | transitions = false, |
| 15897 | animations = false, |
| 15898 | match; |
| 15899 | |
| 15900 | if (bodyStyle) { |
| 15901 | for (var prop in bodyStyle) { |
| 15902 | if (match = vendorRegex.exec(prop)) { |
| 15903 | vendorPrefix = match[0]; |
| 15904 | vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); |
| 15905 | break; |
| 15906 | } |
| 15907 | } |
| 15908 | |
| 15909 | if (!vendorPrefix) { |
| 15910 | vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; |
| 15911 | } |
| 15912 | |
| 15913 | transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); |
| 15914 | animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); |
| 15915 | |
| 15916 | if (android && (!transitions || !animations)) { |
| 15917 | transitions = isString(document.body.style.webkitTransition); |
| 15918 | animations = isString(document.body.style.webkitAnimation); |
| 15919 | } |
| 15920 | } |
| 15921 | |
| 15922 | |
| 15923 | return { |
| 15924 | // Android has history.pushState, but it does not update location correctly |
| 15925 | // so let's not use the history API at all. |
| 15926 | // http://code.google.com/p/android/issues/detail?id=17471 |
| 15927 | // https://github.com/angular/angular.js/issues/904 |
| 15928 | |
| 15929 | // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has |
| 15930 | // so let's not use the history API also |
| 15931 | // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined |
| 15932 | // jshint -W018 |
| 15933 | history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), |
| 15934 | // jshint +W018 |
| 15935 | hasEvent: function(event) { |
| 15936 | // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have |
| 15937 | // it. In particular the event is not fired when backspace or delete key are pressed or |
| 15938 | // when cut operation is performed. |
| 15939 | // IE10+ implements 'input' event but it erroneously fires under various situations, |
| 15940 | // e.g. when placeholder changes, or a form is focused. |
| 15941 | if (event === 'input' && msie <= 11) return false; |
| 15942 | |
| 15943 | if (isUndefined(eventSupport[event])) { |