记录一个用于检查设备的库

仓库地址

https://github.com/Megasu/current-device

CURRENT-DEVICE

All Contributors
Build Status
Bundle size
Coverage Status
NPM version
NPM downloads

This module makes it easy to write conditional CSS and/or JavaScript based on
device operating system (iOS, Android, Blackberry, Windows, MacOs, Firefox OS, MeeGo,
AppleTV, etc), orientation (Portrait vs. Landscape), and type (Tablet vs.
Mobile).

View the Demo →

EXAMPLES

This module inserts CSS classes into the <html> element.

iPhone

Android Tablet

Blackberry Tablet

DEVICE SUPPORT

  • iOS: iPhone, iPod, iPad
  • Android: Phones & Tablets
  • Blackberry: Phones & Tablets
  • Windows: Phones & Tablets
  • Firefox OS: Phones & Tablets

USAGE

Just include the script. The script then updates the <html> section with the
appropriate classes
based on the device's characteristics.

Installation

npm install current-device

And then import it:

// using es modules
import device from "current-device";

// common.js
const device = require("current-device").default;

Or use script tags and globals.

<script src="https://unpkg.com/current-device/umd/current-device.min.js"></script>

And then access it off the global like so:

console.log("device.mobile() === %s", device.mobile());

CONDITIONAL CSS

The following tables map which CSS classes are added based on device and
orientation.

Device CSS Class Names

Device CSS Classes
iPad ios ipad tablet
iPhone ios iphone mobile
iPod ios ipod mobile
Android Phone android mobile
Android Tablet android tablet
BlackBerry Phone blackberry mobile
BlackBerry Tablet blackberry tablet
Windows Phone windows mobile
Windows Tablet windows tablet
Firefox OS Phone fxos mobile
Firefox OS Tablet fxos tablet
MeeGo meego
Desktop desktop
Television television

Orientation CSS Class Names

Orientation CSS Classes
Landscape landscape
Portrait portrait

CONDITIONAL JAVASCRIPT

This module also includes support for conditional JavaScript, allowing you to
write checks on the following device characteristics:

Device JavaScript Methods

Device JavaScript Method
Mobile device.mobile()
Tablet device.tablet()
Desktop device.desktop()
iOS device.ios()
iPad device.ipad()
iPhone device.iphone()
iPod device.ipod()
Android device.android()
Android Phone device.androidPhone()
Android Tablet device.androidTablet()
BlackBerry device.blackberry()
BlackBerry Phone device.blackberryPhone()
BlackBerry Tablet device.blackberryTablet()
Windows device.windows()
Windows Phone device.windowsPhone()
Windows Tablet device.windowsTablet()
Firefox OS device.fxos()
Firefox OS Phone device.fxosPhone()
Firefox OS Tablet device.fxosTablet()
MeeGo device.meego()
Television device.television()

Orientation JavaScript Methods

Orientation JavaScript Method
Landscape device.landscape()
Portrait device.portrait()

Orientation JavaScript Callback

device.onChangeOrientation(newOrientation => {
  console.log(`New orientation is ${newOrientation}`);
});

Utility Methods

device.noConflict()

Run current-device in noConflict mode, returning the device variable to its
previous owner. Returns a reference to the device object.

const currentDevice = device.noConflict();

Useful Properties

Access these properties on the device object to get the first match on that
attribute without looping through all of its getter methods.

JS Property Returns
device.type 'mobile', 'tablet', 'desktop', or 'unknown'
device.orientation 'landscape', 'portrait', or 'unknown'
device.os 'ios', 'iphone', 'ipad', 'ipod', 'android', 'blackberry', 'windows', 'macos', 'fxos', 'meego', 'television', or 'unknown'

BEST PRACTICES

Environment detection has a high rate of misuse. Often times, folks will attempt
to work around browser feature support problems by checking for the affected
browser and doing something different in response. The preferred solution for
those kinds of problems, of course, is to check for the feature, not the browser
(ala Modernizr).

However, that common misuse of device detection doesn't mean it should never be
done. For example, current-device could be employed to change the interface of
your web app such that it uses interaction patterns and UI elements common to
the device it's being presented on. Android devices might get a slightly
different treatment than Windows or iOS, for instance. Another valid use-case is
guiding users to different app stores depending on the device they're using.

In short, check for features when you need features, and check for the browser
when you need the browser.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Matthew Hudson

💻 🚧

Rafael Terán

💻

Allan

👀

martinwepner

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

源码参考

// Save the previous value of the device variable.
const previousDevice = window.device

const device = {}

const changeOrientationList = []

// Add device as a global object.
window.device = device

// The <html> element.
const documentElement = window.document.documentElement

// The client user agent string.
// Lowercase, so we can use the more efficient indexOf(), instead of Regex
const userAgent = window.navigator.userAgent.toLowerCase()

// Detectable television devices.
const television = [
  'googletv',
  'viera',
  'smarttv',
  'internet.tv',
  'netcast',
  'nettv',
  'appletv',
  'boxee',
  'kylo',
  'roku',
  'dlnadoc',
  'pov_tv',
  'hbbtv',
  'ce-html'
]

// Main functions
// --------------

device.macos = function() {
  return find('mac')
}

device.ios = function() {
  return device.iphone() || device.ipod() || device.ipad()
}

device.iphone = function() {
  return !device.windows() && find('iphone')
}

device.ipod = function() {
  return find('ipod')
}

device.ipad = function() {
  const iPadOS13Up =
    navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1
  return find('ipad') || iPadOS13Up
};

device.android = function() {
  return !device.windows() && find('android')
}

device.androidPhone = function() {
  return device.android() && find('mobile')
}

device.androidTablet = function() {
  return device.android() && !find('mobile')
}

device.blackberry = function() {
  return find('blackberry') || find('bb10')
}

device.blackberryPhone = function() {
  return device.blackberry() && !find('tablet')
}

device.blackberryTablet = function() {
  return device.blackberry() && find('tablet')
}

device.windows = function() {
  return find('windows')
}

device.windowsPhone = function() {
  return device.windows() && find('phone')
}

device.windowsTablet = function() {
  return device.windows() && (find('touch') && !device.windowsPhone())
}

device.fxos = function() {
  return (find('(mobile') || find('(tablet')) && find(' rv:')
}

device.fxosPhone = function() {
  return device.fxos() && find('mobile')
}

device.fxosTablet = function() {
  return device.fxos() && find('tablet')
}

device.meego = function() {
  return find('meego')
}

device.cordova = function() {
  return window.cordova && location.protocol === 'file:'
}

device.nodeWebkit = function() {
  return typeof window.process === 'object'
}

device.mobile = function() {
  return (
    device.androidPhone() ||
    device.iphone() ||
    device.ipod() ||
    device.windowsPhone() ||
    device.blackberryPhone() ||
    device.fxosPhone() ||
    device.meego()
  )
}

device.tablet = function() {
  return (
    device.ipad() ||
    device.androidTablet() ||
    device.blackberryTablet() ||
    device.windowsTablet() ||
    device.fxosTablet()
  )
}

device.desktop = function() {
  return !device.tablet() && !device.mobile()
}

device.television = function() {
  let i = 0
  while (i < television.length) {
    if (find(television[i])) {
      return true
    }
    i++
  }
  return false
}

device.portrait = function() {
  if (
    screen.orientation &&
    Object.prototype.hasOwnProperty.call(window, 'onorientationchange')
  ) {
    return includes(screen.orientation.type, 'portrait')
  }
  if (
    device.ios() &&
    Object.prototype.hasOwnProperty.call(window, 'orientation')
  ) {
    return Math.abs(window.orientation) !== 90
  }
  return window.innerHeight / window.innerWidth > 1
}

device.landscape = function() {
  if (
    screen.orientation &&
    Object.prototype.hasOwnProperty.call(window, 'onorientationchange')
  ) {
    return includes(screen.orientation.type, 'landscape')
  }
  if (
    device.ios() &&
    Object.prototype.hasOwnProperty.call(window, 'orientation')
  ) {
    return Math.abs(window.orientation) === 90
  }
  return window.innerHeight / window.innerWidth < 1
}

// Public Utility Functions
// ------------------------

// Run device.js in noConflict mode,
// returning the device variable to its previous owner.
device.noConflict = function() {
  window.device = previousDevice
  return this
}

// Private Utility Functions
// -------------------------

// Check if element exists
function includes(haystack, needle) {
  return haystack.indexOf(needle) !== -1
}

// Simple UA string search
function find(needle) {
  return includes(userAgent, needle)
}

// Check if documentElement already has a given class.
function hasClass(className) {
  return documentElement.className.match(new RegExp(className, 'i'))
}

// Add one or more CSS classes to the <html> element.
function addClass(className) {
  let currentClassNames = null
  if (!hasClass(className)) {
    currentClassNames = documentElement.className.replace(/^\s+|\s+$/g, '')
    documentElement.className = `${currentClassNames} ${className}`
  }
}

// Remove single CSS class from the <html> element.
function removeClass(className) {
  if (hasClass(className)) {
    documentElement.className = documentElement.className.replace(
      ` ${className}`,
      ''
    )
  }
}

// HTML Element Handling
// ---------------------

// Insert the appropriate CSS class based on the _user_agent.

if (device.ios()) {
  if (device.ipad()) {
    addClass('ios ipad tablet')
  } else if (device.iphone()) {
    addClass('ios iphone mobile')
  } else if (device.ipod()) {
    addClass('ios ipod mobile')
  }
} else if (device.macos()) {
  addClass('macos desktop')
} else if (device.android()) {
  if (device.androidTablet()) {
    addClass('android tablet')
  } else {
    addClass('android mobile')
  }
} else if (device.blackberry()) {
  if (device.blackberryTablet()) {
    addClass('blackberry tablet')
  } else {
    addClass('blackberry mobile')
  }
} else if (device.windows()) {
  if (device.windowsTablet()) {
    addClass('windows tablet')
  } else if (device.windowsPhone()) {
    addClass('windows mobile')
  } else {
    addClass('windows desktop')
  }
} else if (device.fxos()) {
  if (device.fxosTablet()) {
    addClass('fxos tablet')
  } else {
    addClass('fxos mobile')
  }
} else if (device.meego()) {
  addClass('meego mobile')
} else if (device.nodeWebkit()) {
  addClass('node-webkit')
} else if (device.television()) {
  addClass('television')
} else if (device.desktop()) {
  addClass('desktop')
}

if (device.cordova()) {
  addClass('cordova')
}

// Orientation Handling
// --------------------

// Handle device orientation changes.
function handleOrientation() {
  if (device.landscape()) {
    removeClass('portrait')
    addClass('landscape')
    walkOnChangeOrientationList('landscape')
  } else {
    removeClass('landscape')
    addClass('portrait')
    walkOnChangeOrientationList('portrait')
  }
  setOrientationCache()
}

function walkOnChangeOrientationList(newOrientation) {
  for (let index = 0; index < changeOrientationList.length; index++) {
    changeOrientationList[index](newOrientation)
  }
}

device.onChangeOrientation = function(cb) {
  if (typeof cb == 'function') {
    changeOrientationList.push(cb)
  }
}

// Detect whether device supports orientationchange event,
// otherwise fall back to the resize event.
let orientationEvent = 'resize'
if (Object.prototype.hasOwnProperty.call(window, 'onorientationchange')) {
  orientationEvent = 'orientationchange'
}

// Listen for changes in orientation.
if (window.addEventListener) {
  window.addEventListener(orientationEvent, handleOrientation, false)
} else if (window.attachEvent) {
  window.attachEvent(orientationEvent, handleOrientation)
} else {
  window[orientationEvent] = handleOrientation
}

handleOrientation()

// Public functions to get the current value of type, os, or orientation
// ---------------------------------------------------------------------

function findMatch(arr) {
  for (let i = 0; i < arr.length; i++) {
    if (device[arr[i]]()) {
      return arr[i]
    }
  }
  return 'unknown'
}

device.type = findMatch(['mobile', 'tablet', 'desktop'])
device.os = findMatch([
  'ios',
  'iphone',
  'ipad',
  'ipod',
  'android',
  'blackberry',
  'macos',
  'windows',
  'fxos',
  'meego',
  'television'
])

function setOrientationCache() {
  device.orientation = findMatch(['portrait', 'landscape'])
}

setOrientationCache()

export default device
posted @ 2022-02-07 11:36  MegaSu  阅读(42)  评论(0编辑  收藏  举报