Repository: tombigel/detect-zoom
Branch: master
Commit: b94c09c04855
Files: 5
Total size: 16.2 KB
Directory structure:
gitextract_6v6dismt/
├── .gitignore
├── Makefile
├── README.md
├── detect-zoom.js
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Compiled Python files
*.pyc
# Folder view configuration files
.DS_Store
Desktop.ini
# Thumbnail cache files
._*
Thumbs.db
# Files that might appear on external disks
.Spotlight-V100
.Trashes
# IntelliJ
*.iml
*.ipr
*.iws
.idea
# npm
node_modules
================================================
FILE: Makefile
================================================
UGLIFY=./node_modules/uglify-js/bin/uglifyjs
detect-zoom.min.js: detect-zoom.js
$(UGLIFY) detect-zoom.js -c > detect-zoom.min.js
================================================
FILE: README.md
================================================
Cross Browser Zoom and Pixel Ratio Detector
======
------
### READ THIS: Detect-zoom is currently unusable for desktop
Last update: Aug 7 2013
**In the past few months both Mozilla and Google made some changes to their browsers that make it almost impossible to do
what detect-zoom is here to do:**
#### Firefox
On *Firefox 18* Mozilla changes the `devicePixelRatio` value on manual zoom (cmd/ctrl +/-), making it impossible
to know whether the browser is in zoom mode or is it a retina device, ignoring what the word DEVICE represents.
I personally believe someone there refuses to admit this is a mistake and revert this decision.
#### Chrome
On *Chrome 27* (Meaning WebKit and Blink) `webkitTextSizeAdjust` was deprecated on desktops versions of the browser.
This was the only bullet proof way to detect zoom in desktop chrome that I am aware of.
There are couple of other ways, but they don't cover all the bases - one uses SVG but is not working in iFrames, the other
uses window.inner/outerWidth and is not working when there is a sidebar or the DevTools are open on the side.
### Other Known issues:
* In some multi-monitor enviroments where each monitor has a different 'pixel aspect ratio' windows that span accross both monitors might return false pixelAspectRatio values.
What is this for?
------
Detecting the browser zoom level and device pixel ratio relative to the zoom level.
It can be used to show higher-resolution `canvas` or `img` when necessary,
to warn users that your site's layout will be broken in their current zoom level,
and much more.
Personally I'm maintaining it to use Detect-zoom in [Wix.com](http://wix.com)'s editor to warn users
that their browser is in zoom mode before saving important changes to their website.
What happend to @yonran?
------
Don't worry, he is well.
As of January 2013 [@yonran](https://github.com/yonran) stopped maintaining his source of detect-zoom, and transferred the repository to me.
If you are looking to update previous versions note that there were some breaking changes
* **Major Changes from the latest yonran version:**
* `DetectZoom` object name changed to `detectZoom`
* `DetectZoom.ratio()` is no longer publicly accessible
* Supported browsers: IE8+, FF4+, modern Webkit, mobile Webkit, Opera 11.1+
* *IE6, IE7, FF 3.6 and Opera 10.x are no longer supported*
* Added support to be loaded as an AMD and CommonJS module
Live Example
------
See the Live Example section in
http://tombigel.github.com/detect-zoom/
Usage
------
**Detect-zoom has only two public functions:**
* `zoom()` Returns the zoom level of the user's browser using Javascript.
* `device()` Returns the device pixel ratio multiplied by the zoom level (Read [more about devicePixelRatio](http://www.quirksmode.org/blog/archives/2012/07/more_about_devi.html) at QuirksMode)
```html
```
**AMD Usage**
```javascript
require(['detect-zoom'], function(detectZoom){
var zoom = detectZoom.zoom();
});
```
**Installing with NPM**
```bash
> npm install detect-zoom
```
Changelog
------
2013/4/01
* Changed WebKit detection from deprecated webkitTextSizeAdjust to webkitMarquee
* Changed WebKitMobile detection from unreliable 'ontouchstart' event (can be triggered on desktops too) to 'orientation' property that is hopefully more reliable
* Minor version bump to 1.0.4
2013/3/29
* Added package.json (thanks [@TCampaigne](https://github.com/TCampaigne))
* Some documentation fixes
* Added detect-zoom to npm package manager (again, thanks [@TCampaigne](https://github.com/TCampaigne))
2013/2/25
* Fixed a missing 'else' between ie8 and ie10 detection
* Minor version bump to 1.0.2
2013/2/15
* Added a fix for IE10 Metro (or whatever MS calls it these days..) by [@stefanvanburen](https://github.com/stefanvanburen)
* Minor version bump to 1.0.1
* Added minimized version
2013/2/05
* Merged a pull request that fixed zoom on IE being returned X100 (thanks [@kreymerman](https://github.com/kreymerman))
* Refactored the code some more, changed some function names
* Browser dependent main function is created only on initialization (thanks [@jsmaker](https://github.com/jsmaker))
* _Open Issue: Firefox returns `zoom` and `devicePixelRatio` the same. Still looking for a solution here._
* Started versioning - this is version 1.0.0
2013/1/27
* Added a fix to Mozilla's (Broken as I see it - https://bugzilla.mozilla.org/show_bug.cgi?id=809788)
implementation of window.devicePixel starting Firefox 18
2013/1/26
* Repository moved here
* Refactored most of the code
* Removed support for older browsers
* Added support for AMD and CommonJS
Help Needed
------
***Detect-zoom is not complete, many parts of the code are 6 to 12 months old and I'm still reviewing them
I need help testing different browsers, finding better ways to measure zoom on problematic browsers (ahm.. Firefox.. ahm)
patches are more than welcome.***
License
------
Detect-zoom is dual-licensed under the [WTFPL](http://www.wtfpl.net/about/) and [MIT](http://opensource.org/licenses/MIT) license, at the recipient's choice.
================================================
FILE: detect-zoom.js
================================================
/* Detect-zoom
* -----------
* Cross Browser Zoom and Pixel Ratio Detector
* Version 1.0.4 | Apr 1 2013
* dual-licensed under the WTFPL and MIT license
* Maintained by https://github/tombigel
* Original developer https://github.com/yonran
*/
//AMD and CommonJS initialization copied from https://github.com/zohararad/audio5js
(function (root, ns, factory) {
"use strict";
if (typeof (module) !== 'undefined' && module.exports) { // CommonJS
module.exports = factory(ns, root);
} else if (typeof (define) === 'function' && define.amd) { // AMD
define("detect-zoom", function () {
return factory(ns, root);
});
} else {
root[ns] = factory(ns, root);
}
}(window, 'detectZoom', function () {
/**
* Use devicePixelRatio if supported by the browser
* @return {Number}
* @private
*/
var devicePixelRatio = function () {
return window.devicePixelRatio || 1;
};
/**
* Fallback function to set default values
* @return {Object}
* @private
*/
var fallback = function () {
return {
zoom: 1,
devicePxPerCssPx: 1
};
};
/**
* IE 8 and 9: no trick needed!
* TODO: Test on IE10 and Windows 8 RT
* @return {Object}
* @private
**/
var ie8 = function () {
var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* For IE10 we need to change our technique again...
* thanks https://github.com/stefanvanburen
* @return {Object}
* @private
*/
var ie10 = function () {
var zoom = Math.round((document.documentElement.offsetHeight / window.innerHeight) * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* For chrome
*
*/
var chrome = function()
{
var zoom = Math.round(((window.outerWidth) / window.innerWidth)*100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
}
/**
* For safari (same as chrome)
*
*/
var safari= function()
{
var zoom = Math.round(((document.documentElement.clientWidth) / window.innerWidth)*100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
}
/**
* Mobile WebKit
* the trick: window.innerWIdth is in CSS pixels, while
* screen.width and screen.height are in system pixels.
* And there are no scrollbars to mess up the measurement.
* @return {Object}
* @private
*/
var webkitMobile = function () {
var deviceWidth = (Math.abs(window.orientation) == 90) ? screen.height : screen.width;
var zoom = deviceWidth / window.innerWidth;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* Desktop Webkit
* the trick: an element's clientHeight is in CSS pixels, while you can
* set its line-height in system pixels using font-size and
* -webkit-text-size-adjust:none.
* device-pixel-ratio: http://www.webkit.org/blog/55/high-dpi-web-sites/
*
* Previous trick (used before http://trac.webkit.org/changeset/100847):
* documentElement.scrollWidth is in CSS pixels, while
* document.width was in system pixels. Note that this is the
* layout width of the document, which is slightly different from viewport
* because document width does not include scrollbars and might be wider
* due to big elements.
* @return {Object}
* @private
*/
var webkit = function () {
var important = function (str) {
return str.replace(/;/g, " !important;");
};
var div = document.createElement('div');
div.innerHTML = "1
2
3
4
5
6
7
8
9
0";
div.setAttribute('style', important('font: 100px/1em sans-serif; -webkit-text-size-adjust: none; text-size-adjust: none; height: auto; width: 1em; padding: 0; overflow: visible;'));
// The container exists so that the div will be laid out in its own flow
// while not impacting the layout, viewport size, or display of the
// webpage as a whole.
// Add !important and relevant CSS rule resets
// so that other rules cannot affect the results.
var container = document.createElement('div');
container.setAttribute('style', important('width:0; height:0; overflow:hidden; visibility:hidden; position: absolute;'));
container.appendChild(div);
document.body.appendChild(container);
var zoom = 1000 / div.clientHeight;
zoom = Math.round(zoom * 100) / 100;
document.body.removeChild(container);
return{
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* no real trick; device-pixel-ratio is the ratio of device dpi / css dpi.
* (Note that this is a different interpretation than Webkit's device
* pixel ratio, which is the ratio device dpi / system dpi).
*
* Also, for Mozilla, there is no difference between the zoom factor and the device ratio.
*
* @return {Object}
* @private
*/
var firefox4 = function () {
var zoom = mediaQueryBinarySearch('min--moz-device-pixel-ratio', '', 0, 10, 20, 0.0001);
zoom = Math.round(zoom * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom
};
};
/**
* Firefox 18.x
* Mozilla added support for devicePixelRatio to Firefox 18,
* but it is affected by the zoom level, so, like in older
* Firefox we can't tell if we are in zoom mode or in a device
* with a different pixel ratio
* @return {Object}
* @private
*/
var firefox18 = function () {
return {
zoom: firefox4().zoom,
devicePxPerCssPx: devicePixelRatio()
};
};
/**
* works starting Opera 11.11
* the trick: outerWidth is the viewport width including scrollbars in
* system px, while innerWidth is the viewport width including scrollbars
* in CSS px
* @return {Object}
* @private
*/
var opera11 = function () {
var zoom = window.top.outerWidth / window.top.innerWidth;
zoom = Math.round(zoom * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* Use a binary search through media queries to find zoom level in Firefox
* @param property
* @param unit
* @param a
* @param b
* @param maxIter
* @param epsilon
* @return {Number}
*/
var mediaQueryBinarySearch = function (property, unit, a, b, maxIter, epsilon) {
var matchMedia;
var head, style, div;
if (window.matchMedia) {
matchMedia = window.matchMedia;
} else {
head = document.getElementsByTagName('head')[0];
style = document.createElement('style');
head.appendChild(style);
div = document.createElement('div');
div.className = 'mediaQueryBinarySearch';
div.style.display = 'none';
document.body.appendChild(div);
matchMedia = function (query) {
style.sheet.insertRule('@media ' + query + '{.mediaQueryBinarySearch ' + '{text-decoration: underline} }', 0);
var matched = getComputedStyle(div, null).textDecoration == 'underline';
style.sheet.deleteRule(0);
return {matches: matched};
};
}
var ratio = binarySearch(a, b, maxIter);
if (div) {
head.removeChild(style);
document.body.removeChild(div);
}
return ratio;
function binarySearch(a, b, maxIter) {
var mid = (a + b) / 2;
if (maxIter <= 0 || b - a < epsilon) {
return mid;
}
var query = "(" + property + ":" + mid + unit + ")";
if (matchMedia(query).matches) {
return binarySearch(mid, b, maxIter - 1);
} else {
return binarySearch(a, mid, maxIter - 1);
}
}
};
/**
* Generate detection function
* @private
*/
var detectFunction = (function () {
var func = fallback;
//IE8+
if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
func = ie8;
}
// IE10+ / Touch
else if (window.navigator.msMaxTouchPoints) {
func = ie10;
}
//chrome
else if(!!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' Opera') >= 0)){
func = chrome;
}
//safari
else if(Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0){
func = safari;
}
//Mobile Webkit
else if ('orientation' in window && 'webkitRequestAnimationFrame' in window) {
func = webkitMobile;
}
//WebKit
else if ('webkitRequestAnimationFrame' in window) {
func = webkit;
}
//Opera
else if (navigator.userAgent.indexOf('Opera') >= 0) {
func = opera11;
}
//Last one is Firefox
//FF 18.x
else if (window.devicePixelRatio) {
func = firefox18;
}
//FF 4.0 - 17.x
else if (firefox4().zoom > 0.001) {
func = firefox4;
}
return func;
}());
return ({
/**
* Ratios.zoom shorthand
* @return {Number} Zoom level
*/
zoom: function () {
return detectFunction().zoom;
},
/**
* Ratios.devicePxPerCssPx shorthand
* @return {Number} devicePxPerCssPx level
*/
device: function () {
return detectFunction().devicePxPerCssPx;
}
});
}));
================================================
FILE: package.json
================================================
{
"name": "detect-zoom",
"version": "1.0.4",
"description": "Cross Browser Zoom and Pixel Ratio Detector",
"main": "detect-zoom.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git://github.com/tombigel/detect-zoom.git"
},
"keywords": [
"browser",
"zoom",
"compatibility",
"pixel",
"ratio",
"retina"
],
"author": "Yonathan Randolph",
"contributors": [
"Tom Bigelajzen "
],
"license": "MIT",
"readmeFilename": "README.md",
"gitHead": "6eaf3107a6913a4f7b93665ba6d5bc16cdf0f3ab",
"devDependencies": {
"uglify-js": "~3.6.6"
}
}