├── .gitignore ├── Gruntfile.js ├── Gulpfile.js ├── Makefile ├── README.md ├── bower.json ├── eslint.json ├── jquery.stage.d.ts ├── jquery.stage.js ├── jshint.json ├── package.json ├── sample ├── app.css ├── app.js └── index.html └── stage.jquery.json /.gitignore: -------------------------------------------------------------------------------- 1 | jquery.stage.min.js 2 | node_modules 3 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** jQuery Stage -- jQuery Stage Information 3 | ** Copyright (c) 2013-2021 Dr. Ralf S. Engelschall 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining 6 | ** a copy of this software and associated documentation files (the 7 | ** "Software"), to deal in the Software without restriction, including 8 | ** without limitation the rights to use, copy, modify, merge, publish, 9 | ** distribute, sublicense, and/or sell copies of the Software, and to 10 | ** permit persons to whom the Software is furnished to do so, subject to 11 | ** the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included 14 | ** in all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* global module: true */ 26 | module.exports = function (grunt) { 27 | grunt.initConfig({ 28 | pkg: grunt.file.readJSON("package.json"), 29 | jshint: { 30 | options: { 31 | jshintrc: "jshint.json" 32 | }, 33 | gruntfile: [ "Gruntfile.js" ], 34 | sourcefiles: [ "jquery.stage.js" ] 35 | }, 36 | eslint: { 37 | options: { 38 | configFile: "eslint.json" 39 | }, 40 | target: [ "jquery.stage.js" ], 41 | }, 42 | uglify: { 43 | options: { 44 | preserveComments: false, 45 | report: "min" 46 | }, 47 | dist: { 48 | src: "jquery.stage.js", 49 | dest: "jquery.stage.min.js" 50 | } 51 | }, 52 | clean: { 53 | clean: [ "jquery.stage.min.js" ], 54 | distclean: [ "node_modules" ] 55 | } 56 | }); 57 | 58 | grunt.loadNpmTasks("grunt-contrib-jshint"); 59 | grunt.loadNpmTasks("grunt-contrib-uglify"); 60 | grunt.loadNpmTasks("grunt-contrib-clean"); 61 | grunt.loadNpmTasks("grunt-eslint"); 62 | 63 | grunt.registerTask("default", [ "jshint", "eslint", "uglify" ]); 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /Gulpfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** jQuery Stage -- jQuery Stage Information 3 | ** Copyright (c) 2013-2021 Dr. Ralf S. Engelschall 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining 6 | ** a copy of this software and associated documentation files (the 7 | ** "Software"), to deal in the Software without restriction, including 8 | ** without limitation the rights to use, copy, modify, merge, publish, 9 | ** distribute, sublicense, and/or sell copies of the Software, and to 10 | ** permit persons to whom the Software is furnished to do so, subject to 11 | ** the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included 14 | ** in all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | var gulp = require("gulp"); 26 | var rename = require("gulp-rename"); 27 | var jshint = require("gulp-jshint"); 28 | var eslint = require("gulp-eslint"); 29 | var uglify = require("gulp-uglify"); 30 | 31 | gulp.task("jshint", function() { 32 | gulp.src("jquery.stage.js") 33 | .pipe(jshint("jshint.json")) 34 | .pipe(jshint.reporter("default")) 35 | }); 36 | 37 | gulp.task("eslint", function() { 38 | gulp.src("jquery.stage.js") 39 | .pipe(eslint({ configFile: "eslint.json" })) 40 | }); 41 | 42 | gulp.task("uglify", function() { 43 | gulp.src("jquery.stage.js") 44 | .pipe(uglify({ preserveComments: false })) 45 | .pipe(rename("jquery.stage.min.js")) 46 | .pipe(gulp.dest(".")); 47 | }); 48 | 49 | gulp.task("default", [ "jshint", "eslint", "uglify" ]); 50 | 51 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | ## jQuery Stage -- jQuery Stage Information 3 | ## Copyright (c) 2013-2021 Dr. Ralf S. Engelschall 4 | ## 5 | ## Permission is hereby granted, free of charge, to any person obtaining 6 | ## a copy of this software and associated documentation files (the 7 | ## "Software"), to deal in the Software without restriction, including 8 | ## without limitation the rights to use, copy, modify, merge, publish, 9 | ## distribute, sublicense, and/or sell copies of the Software, and to 10 | ## permit persons to whom the Software is furnished to do so, subject to 11 | ## the following conditions: 12 | ## 13 | ## The above copyright notice and this permission notice shall be included 14 | ## in all copies or substantial portions of the Software. 15 | ## 16 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | ## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | ## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | ## IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | ## CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | ## TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | ## SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | ## 24 | 25 | NPM = npm 26 | GRUNT = ./node_modules/grunt-cli/bin/grunt 27 | 28 | all: build 29 | 30 | bootstrap: 31 | @if [ ! -x $(GRUNT) ]; then $(NPM) install; fi 32 | 33 | build: bootstrap 34 | @$(GRUNT) 35 | 36 | clean: bootstrap 37 | @$(GRUNT) clean:clean 38 | 39 | distclean: bootstrap 40 | @$(GRUNT) clean:clean clean:distclean 41 | 42 | update-package-json: bootstrap 43 | $(NPM) install npm-check-updates 44 | ./node_modules/npm-check-updates/bin/npm-check-updates -u 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | jQuery Stage 3 | ============ 4 | 5 | (jQuery Stage Information) 6 | 7 | Abstract 8 | -------- 9 | 10 | jQuery Stage is a [jQuery](http://jquery.com/) plugin for detecting 11 | information about the "stage", the browser's viewport. 12 | 13 | Demo 14 | ---- 15 | 16 | See the included [sample/index.html](http://rawgit.com/rse/jquery-stage/master/sample/index.html) 17 | for a small demonstration of jQuery Stage. 18 | 19 | Motivation 20 | ---------- 21 | 22 | A Single-Page Application (SPA) usually has to render its User Interface 23 | (UI) onto multiple kinds of stages, based on device size and current 24 | device orientation. For true responsive design you usually have to take 25 | the two dimensions "stage size" (e.g. phone, tablet and desktop) and 26 | "stage orientation" (e.g. portrait, square, and landscape) into account. 27 | The preferred way to determine this information and react upon it 28 | is via CSS [Media Queries](http://www.w3.org/TR/css3-mediaqueries/). 29 | 30 | But there are multiple problems: 31 | 32 | - CSS for backward compatibility reasons 33 | always uses a hard-coded DPI setting of 96dpi, even if most devices 34 | have an effective DPI in the range of 100dpi to 450dpi. Also, CSS's 35 | DPI (dots per inch) is actually PPI (pixel per inch), as it is an 36 | input resolution and not an output resolution. 37 | 38 | - The "dots per pixel" ratio can be realiably queried via JavaScript, 39 | but even with this neither DPI nor PPI can be reliably determined. 40 | 41 | - Media Queries can only query on width/height but not on the diagonal. 42 | But the diagonal more conveniently discriminates the size of a device. 43 | 44 | - Media Queries can not take a treshold for orientation into account, 45 | i.e., if width and height differ by less than 5% the stage is nearly 46 | square and neither portrait nor landscape. 47 | 48 | This is where jQuery Stage and its guessing algorithm comes into the play. 49 | 50 | Solution 51 | -------- 52 | 53 | jQuery Stage provides stage information in the following form: 54 | 55 | stage: { 56 | w: Int; // stage width (px) 57 | h: Int; // stage height (px) 58 | dp: Int; // stage diagonal length (px) 59 | dppx: Float; // stage dots per pixel (factor) 60 | ppi: Float; // stage pixel per inch (factor) 61 | di: Float; // stage diagonal length (inch) 62 | size: String; // stage size (string) 63 | orientation: String; // stage orientation (string) 64 | } 65 | 66 | The parameters are determined as following: 67 | 68 | - w: This is the exact viewport width in pixels. 69 | - h: This is the exact viewport height in pixels. 70 | - dp: This is the exact viewport diagonal in pixels. 71 | - dppx: This is the exact device dots per pixel ratio (usually 1.0 but up to 3.0 for high-resolution/retina displays). 72 | - ppi: This is guessed pixel per inch of the device. 73 | - di: This is the guessed viewport diagonal in inch. 74 | - size: This is the guessed viewport type: "phone", "tablet" or "desktop". 75 | - orientation: This is the rounded viewport orientation: "portrait", "square", "landscape". 76 | 77 | On every change of any of those parameters (usually either by resizing 78 | the viewport on a desktop device or changing the device orientation of 79 | a portable device), an event named "stage" is trigged on the global 80 | "window" object providing the new stage information and the old stage 81 | information. An application can use this information for responsive 82 | design aspects. 83 | 84 | API 85 | --- 86 | 87 | The Application Programming Interface (API) of jQuery Stage is 88 | (in TypeScript definition syntax): 89 | 90 | /* the jQuery Stage Callback function type */ 91 | interface JQueryStageCB { 92 | (ev: JQueryEventObject, stage: JQueryStageInfo, stageOld: JQueryStageInfo): any; 93 | } 94 | 95 | /* the jQuery Stage Information structure type */ 96 | interface JQueryStageInfo { 97 | w: number; 98 | h: number; 99 | dp: number; 100 | dppx: number; 101 | ppi: number; 102 | di: number; 103 | size: string; 104 | orientation: string; 105 | } 106 | 107 | /* the jQuery Stage Settings structure type */ 108 | interface JQueryStageSettings { 109 | ppi: { [key: string]: string; }; 110 | size: { [key: string]: string; }; 111 | orientation: { [key: string]: string; }; 112 | } 113 | 114 | /* extend the static jQuery API extension (provided by jquery.d.ts) */ 115 | interface JQueryStatic { 116 | stage: { 117 | /* fetch current stage information */ 118 | (): JQueryStageInfo; 119 | 120 | /* global version number */ 121 | version: string; 122 | 123 | /* global debug level */ 124 | debug: number; 125 | 126 | /* configure the stage settings */ 127 | settings(settings: JQueryStageSettings): void; 128 | }; 129 | } 130 | 131 | /* extend the dynamic jQuery result object API extension (provided by jquery.d.ts) */ 132 | interface JQuery { 133 | stage(cb: JQueryStageCB): JQuery; 134 | } 135 | 136 | Settings 137 | -------- 138 | 139 | The actual guessing of the "ppi", "size" and "orientation" fields 140 | of the stage information can be adjusted by the application. The 141 | default is the following: 142 | 143 | $.stage.settings({ 144 | ppi: { 145 | "100": "dp > 1024 && dppx <= 1.0", 146 | "130": "*", 147 | "160": "dp < 1024 && dppx >= 2.0" 148 | }, 149 | size: { 150 | "phone": "0.0 <= di && di < 6.5", 151 | "tablet": "6.5 <= di && di < 12.0", 152 | "desktop": "*" 153 | }, 154 | orientation: { 155 | "portrait": "h > w * 1.2", 156 | "square": "*", 157 | "landscape": "w > h * 1.2" 158 | } 159 | }); 160 | 161 | Event Handling 162 | -------------- 163 | 164 | Reacting on the `stage` event is up to the application. 165 | Usually one wants to react similar to CSS media queries. 166 | A simple example follows: 167 | 168 | /* foo.css */ 169 | .phone.landscape { ... } 170 | .phone.portrait { ... } 171 | .tablet.landscape { ... } 172 | .tablet.portrait { ... } 173 | .desktop.landscape { ... } 174 | .desktop.portrait { ... } 175 | 176 | /* foo.js */ 177 | $(window).bind("stage", function (stage, stageOld) { 178 | $("body") 179 | .removeClass(stageOld.size) 180 | .addClass (stage.size) 181 | .removeClass(stageOld.orientation) 182 | .addClass (stage.orientation); 183 | }); 184 | 185 | Getting jQuery-Stage 186 | -------------------- 187 | 188 | You can conveniently get jQuery-Stage in various ways: 189 | 190 | - Git: directly clone the official jQuery-Stage repository 191 | 192 | `$ git clone https://github.com/rse/jquery-stage.git` 193 | 194 | - NPM: install as client component via the NPM package manager: 195 | 196 | `$ npm install jquery-stage` 197 | 198 | - Bower: install as client component via the Bower component manager: 199 | 200 | `$ bower install jquery-stage` 201 | 202 | - cURL: downloading only the main file from the repository 203 | 204 | `$ curl -O https://raw.github.com/rse/jquery-stage/master/jquery.stage.js` 205 | 206 | Building jQuery Stage 207 | --------------------- 208 | 209 | You can pick the jQuery plugin in file "jquery.stage.js" as is for use, 210 | but for linting and minifying it yourself you need Node.js ("node") and 211 | its Node.js Package Manager ("npm") globally installed. 212 | 213 | # approach 1: use convenient Makefile (author preference) 214 | $ make 215 | 216 | # approach 2: use Grunt locally (contributor recommendation) 217 | $ npm install 218 | $ node_modules/grunt-cli/bin/grunt 219 | 220 | # approach 3: install and use Grunt globally (contributor alternative) 221 | $ npm install -g grunt-cli 222 | $ npm install 223 | $ grunt 224 | 225 | See Also 226 | -------- 227 | 228 | - "Display resolution": Wikipedia article on display resolution
229 | http://en.wikipedia.org/wiki/Display_resolution 230 | 231 | - "Display size": Wikipedia article on display size
232 | http://en.wikipedia.org/wiki/Display_size 233 | 234 | - "ScreenSiz.es": directory of device properties
235 | http://screensiz.es/ 236 | 237 | - "dpiLove": DPI/PPI detection
238 | http://dpi.lv/ 239 | 240 | - "Pixels Per Inch Awareness and CSS Px": article on PPI and CSS
241 | http://static.zealous-studios.co.uk/projects/web_tests/PPI%20tests.html 242 | 243 | - "Designer's Guide to DPI": article on DPI
244 | http://sebastien-gabriel.com/designers-guide-to-dpi/ 245 | 246 | - "Window Resizer": Google Chrome extension for resizing viewport to various sizes
247 | https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh?hl=en 248 | 249 | - "ScreenCalc": calculate screen properties
250 | https://github.com/theodorejb/ScreenCalc 251 | 252 | - "Screen Orientation API": the effort of the W3C
253 | http://www.w3.org/TR/screen-orientation/ 254 | 255 | License 256 | ------- 257 | 258 | Copyright (c) 2013-2021 Dr. Ralf S. Engelschall (http://engelschall.com/) 259 | 260 | Permission is hereby granted, free of charge, to any person obtaining 261 | a copy of this software and associated documentation files (the 262 | "Software"), to deal in the Software without restriction, including 263 | without limitation the rights to use, copy, modify, merge, publish, 264 | distribute, sublicense, and/or sell copies of the Software, and to 265 | permit persons to whom the Software is furnished to do so, subject to 266 | the following conditions: 267 | 268 | The above copyright notice and this permission notice shall be included 269 | in all copies or substantial portions of the Software. 270 | 271 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 272 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 273 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 274 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 275 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 276 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 277 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 278 | 279 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-stage", 3 | "version": "1.1.14", 4 | "description": "jQuery Stage is a jQuery plugin for detecting information about the stage, the browser's viewport.", 5 | "main": "jquery.stage.js", 6 | "homepage": "https://github.com/rse/jquery-stage", 7 | "license": "MIT", 8 | "authors": [ 9 | "Dr. Ralf S. Engelschall " 10 | ], 11 | "keywords": [ 12 | "viewport", "stage", "width", "height", "dpi", "ppi", 13 | "size", "orientation", "diagonal", "portrait", "landscape" 14 | ], 15 | "dependencies": { 16 | "jquery": "latest" 17 | }, 18 | "ignore": [ 19 | "**/.*", 20 | "node_modules", 21 | "bower_components" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "espree", 3 | "rules": { 4 | "no-alert": 0, 5 | "no-array-constructor": 0, 6 | "no-arrow-condition": 0, 7 | "no-bitwise": 0, 8 | "no-caller": 0, 9 | "no-case-declarations": 0, 10 | "no-catch-shadow": 0, 11 | "no-class-assign": 0, 12 | "no-cond-assign": 2, 13 | "no-console": 0, 14 | "no-const-assign": 0, 15 | "no-constant-condition": 2, 16 | "no-continue": 0, 17 | "no-control-regex": 2, 18 | "no-debugger": 2, 19 | "no-delete-var": 2, 20 | "no-div-regex": 0, 21 | "no-dupe-class-members": 0, 22 | "no-dupe-keys": 2, 23 | "no-dupe-args": 2, 24 | "no-duplicate-case": 2, 25 | "no-else-return": 0, 26 | "no-empty": 2, 27 | "no-empty-character-class": 2, 28 | "no-empty-label": 0, 29 | "no-empty-pattern": 0, 30 | "no-eq-null": 0, 31 | "no-eval": 0, 32 | "no-ex-assign": 2, 33 | "no-extend-native": 0, 34 | "no-extra-bind": 0, 35 | "no-extra-boolean-cast": 2, 36 | "no-extra-parens": 0, 37 | "no-extra-semi": 2, 38 | "no-fallthrough": 2, 39 | "no-floating-decimal": 0, 40 | "no-func-assign": 2, 41 | "no-implicit-coercion": 0, 42 | "no-implied-eval": 0, 43 | "no-inline-comments": 0, 44 | "no-inner-declarations": [2, "functions"], 45 | "no-invalid-regexp": 2, 46 | "no-invalid-this": 0, 47 | "no-irregular-whitespace": 2, 48 | "no-iterator": 0, 49 | "no-label-var": 0, 50 | "no-labels": 0, 51 | "no-lone-blocks": 0, 52 | "no-lonely-if": 0, 53 | "no-loop-func": 0, 54 | "no-mixed-requires": [0, false], 55 | "no-mixed-spaces-and-tabs": [2, false], 56 | "linebreak-style": [0, "unix"], 57 | "no-multi-spaces": 0, 58 | "no-multi-str": 0, 59 | "no-multiple-empty-lines": [0, {"max": 2}], 60 | "no-native-reassign": 0, 61 | "no-negated-condition": 0, 62 | "no-negated-in-lhs": 2, 63 | "no-nested-ternary": 0, 64 | "no-new": 0, 65 | "no-new-func": 0, 66 | "no-new-object": 0, 67 | "no-new-require": 0, 68 | "no-new-wrappers": 0, 69 | "no-obj-calls": 2, 70 | "no-octal": 2, 71 | "no-octal-escape": 0, 72 | "no-param-reassign": 0, 73 | "no-path-concat": 0, 74 | "no-plusplus": 0, 75 | "no-process-env": 0, 76 | "no-process-exit": 0, 77 | "no-proto": 0, 78 | "no-redeclare": 2, 79 | "no-regex-spaces": 2, 80 | "no-restricted-modules": 0, 81 | "no-restricted-syntax": 0, 82 | "no-return-assign": 0, 83 | "no-script-url": 0, 84 | "no-self-compare": 0, 85 | "no-sequences": 0, 86 | "no-shadow": 0, 87 | "no-shadow-restricted-names": 0, 88 | "no-spaced-func": 0, 89 | "no-sparse-arrays": 2, 90 | "no-sync": 0, 91 | "no-ternary": 0, 92 | "no-trailing-spaces": 0, 93 | "no-this-before-super": 0, 94 | "no-throw-literal": 0, 95 | "no-undef": 2, 96 | "no-undef-init": 0, 97 | "no-undefined": 0, 98 | "no-unexpected-multiline": 0, 99 | "no-underscore-dangle": 0, 100 | "no-unneeded-ternary": 0, 101 | "no-unreachable": 2, 102 | "no-unused-expressions": 0, 103 | "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], 104 | "no-use-before-define": 0, 105 | "no-useless-call": 0, 106 | "no-useless-concat": 0, 107 | "no-void": 0, 108 | "no-var": 0, 109 | "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], 110 | "no-with": 0, 111 | "no-magic-numbers": 0, 112 | 113 | "array-bracket-spacing": [0, "never"], 114 | "arrow-body-style": [0, "as-needed"], 115 | "arrow-parens": 0, 116 | "arrow-spacing": 0, 117 | "accessor-pairs": 0, 118 | "block-scoped-var": 0, 119 | "block-spacing": 0, 120 | "brace-style": [0, "1tbs"], 121 | "callback-return": 0, 122 | "camelcase": 0, 123 | "comma-dangle": [2, "never"], 124 | "comma-spacing": 0, 125 | "comma-style": 0, 126 | "complexity": [0, 11], 127 | "computed-property-spacing": [0, "never"], 128 | "consistent-return": 0, 129 | "consistent-this": [0, "that"], 130 | "constructor-super": 0, 131 | "curly": [0, "all"], 132 | "default-case": 0, 133 | "dot-location": 0, 134 | "dot-notation": [0, { "allowKeywords": true }], 135 | "eol-last": 0, 136 | "eqeqeq": 0, 137 | "func-names": 0, 138 | "func-style": [0, "declaration"], 139 | "generator-star-spacing": 0, 140 | "global-require": 0, 141 | "guard-for-in": 0, 142 | "handle-callback-err": 0, 143 | "id-length": 0, 144 | "indent": 0, 145 | "init-declarations": 0, 146 | "jsx-quotes": [0, "prefer-double"], 147 | "key-spacing": [0, { "beforeColon": false, "afterColon": true }], 148 | "lines-around-comment": 0, 149 | "max-depth": [0, 4], 150 | "max-len": [0, 80, 4], 151 | "max-nested-callbacks": [0, 2], 152 | "max-params": [0, 3], 153 | "max-statements": [0, 10], 154 | "new-cap": 0, 155 | "new-parens": 0, 156 | "newline-after-var": 0, 157 | "object-curly-spacing": [0, "never"], 158 | "object-shorthand": 0, 159 | "one-var": [0, "always"], 160 | "operator-assignment": [0, "always"], 161 | "operator-linebreak": 0, 162 | "padded-blocks": 0, 163 | "prefer-arrow-callback": 0, 164 | "prefer-const": 0, 165 | "prefer-spread": 0, 166 | "prefer-reflect": 0, 167 | "prefer-template": 0, 168 | "quote-props": 0, 169 | "quotes": [0, "double"], 170 | "radix": 0, 171 | "id-match": 0, 172 | "require-jsdoc": 0, 173 | "require-yield": 0, 174 | "semi": 0, 175 | "semi-spacing": [0, {"before": false, "after": true}], 176 | "sort-vars": 0, 177 | "space-after-keywords": [0, "always"], 178 | "space-before-keywords": [0, "always"], 179 | "space-before-blocks": [0, "always"], 180 | "space-before-function-paren": [0, "always"], 181 | "space-in-parens": [0, "never"], 182 | "space-infix-ops": 0, 183 | "space-return-throw-case": 0, 184 | "space-unary-ops": [0, { "words": true, "nonwords": false }], 185 | "spaced-comment": 0, 186 | "strict": 0, 187 | "use-isnan": 2, 188 | "valid-jsdoc": 0, 189 | "valid-typeof": 2, 190 | "vars-on-top": 0, 191 | "wrap-iife": 0, 192 | "wrap-regex": 0, 193 | "yoda": [0, "never"] 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /jquery.stage.d.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | ** jQuery Stage -- jQuery Stage Information 3 | ** Copyright (c) 2013-2021 Dr. Ralf S. Engelschall 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining 6 | ** a copy of this software and associated documentation files (the 7 | ** "Software"), to deal in the Software without restriction, including 8 | ** without limitation the rights to use, copy, modify, merge, publish, 9 | ** distribute, sublicense, and/or sell copies of the Software, and to 10 | ** permit persons to whom the Software is furnished to do so, subject to 11 | ** the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included 14 | ** in all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /// 26 | 27 | /* the jQuery Stage Callback function type */ 28 | interface JQueryStageCB { 29 | (ev: JQueryEventObject, stage: JQueryStageInfo, stageOld: JQueryStageInfo): any; 30 | } 31 | 32 | /* the jQuery Stage Information structure type */ 33 | interface JQueryStageInfo { 34 | w: number; 35 | h: number; 36 | dp: number; 37 | dppx: number; 38 | ppi: number; 39 | di: number; 40 | size: string; 41 | orientation: string; 42 | } 43 | 44 | /* the jQuery Stage Settings structure type */ 45 | interface JQueryStageSettings { 46 | ppi: { [ key: string ]: string; }; 47 | size: { [ key: string ]: string; }; 48 | orientation: { [ key: string ]: string; }; 49 | } 50 | 51 | /* extend the static jQuery API extension (provided by jquery.d.ts) */ 52 | interface JQueryStatic { 53 | stage: { 54 | /* fetch current stage information */ 55 | (): JQueryStageInfo; 56 | 57 | /* global version number */ 58 | version: string; 59 | 60 | /* global debug level */ 61 | debug: number; 62 | 63 | /* configure the stage settings */ 64 | settings(settings: JQueryStageSettings): void; 65 | }; 66 | } 67 | 68 | /* extend the dynamic jQuery result object API extension (provided by jquery.d.ts) */ 69 | interface JQuery { 70 | stage(cb: JQueryStageCB): JQuery; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /jquery.stage.js: -------------------------------------------------------------------------------- 1 | /*! 2 | ** jQuery Stage -- jQuery Stage Information 3 | ** Copyright (c) 2013-2021 Dr. Ralf S. Engelschall 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining 6 | ** a copy of this software and associated documentation files (the 7 | ** "Software"), to deal in the Software without restriction, including 8 | ** without limitation the rights to use, copy, modify, merge, publish, 9 | ** distribute, sublicense, and/or sell copies of the Software, and to 10 | ** permit persons to whom the Software is furnished to do so, subject to 11 | ** the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included 14 | ** in all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* global jQuery: false */ 26 | /* global window: false */ 27 | /* global document: false */ 28 | (function ($) { 29 | /* jshint -W014 */ 30 | 31 | /* internal stage information (defaults) */ 32 | var stage_default = { 33 | "w": 0, /* stage width (px) */ 34 | "h": 0, /* stage height (px) */ 35 | "dp": 0, /* stage diagonal length (px) */ 36 | "dppx": 1.0, /* stage dots per pixel (factor) */ 37 | "ppi": 0.0, /* stage pixel per inch (factor) */ 38 | "di": 0.0, /* stage diagonal length (inch) */ 39 | "size": "", /* stage size (string) */ 40 | "orientation": "" /* stage orientation (string) */ 41 | }; 42 | 43 | /* internal stage information */ 44 | var stage = $.extend({}, stage_default); 45 | var stageOld = $.extend({}, stage); 46 | 47 | /* hook into jQuery (globally) */ 48 | $.extend({ 49 | /* API: return the current stage information */ 50 | stage: function () { 51 | return stage; 52 | } 53 | }); 54 | 55 | /* hook into jQuery (locally) */ 56 | $.fn.extend({ 57 | /* API: subscribe to a stage event */ 58 | stage: function (callback) { 59 | return this.each(function () { 60 | if ($(this).get(0) !== window) 61 | throw new Error("jquery: stage: you can only bind 'stage' events onto the 'window' object"); 62 | $(this).bind("stage", callback); 63 | }); 64 | } 65 | }); 66 | 67 | /* plugin version number */ 68 | $.stage.version = "1.1.9"; 69 | 70 | /* debug level */ 71 | $.stage.debug = 0; 72 | var debug = function (level, msg) { 73 | /* global console: true */ 74 | if ( $.stage.debug >= level 75 | && typeof console !== "undefined" 76 | && typeof console.log === "function") 77 | console.log("jquery: stage: DEBUG[" + level + "]: " + msg); 78 | }; 79 | 80 | /* internal settings storage */ 81 | var settings = { 82 | ppi: null, 83 | size: null, 84 | orientation: null 85 | }; 86 | 87 | /* API: allow settings to be imported */ 88 | var prefix = "var"; 89 | $.each(stage, function (name /*, value */) { 90 | if (prefix !== "var") 91 | prefix += ","; 92 | prefix += " " + name + " = stage." + name; 93 | }); 94 | prefix += "; return ("; 95 | var postfix = ");"; 96 | $.stage.settings = function (_settings) { 97 | $.each(settings, function (key1 /*, val */) { 98 | settings[key1] = {}; 99 | if (typeof _settings[key1] === "undefined") 100 | throw new Error("jquery: stage: no such field " + key1 + " in provided settings"); 101 | $.each(_settings[key1], function (key2, val) { 102 | if (val === "*") 103 | settings[key1][key2] = val; 104 | else 105 | /* jshint -W054 */ 106 | settings[key1][key2] = new Function("stage", prefix + val + postfix); 107 | }); 108 | }); 109 | }; 110 | 111 | /* provide default settings */ 112 | $.stage.settings({ 113 | ppi: { 114 | "100": "dp > 1024 && dppx <= 1.0", /* large screens with low device pixel ratio */ 115 | "130": "*", /* the reasonable average value */ 116 | "160": "dp < 1024 && dppx >= 2.0" /* small screens with high device pixel ratio */ 117 | }, 118 | size: { 119 | "phone": "0.0 <= di && di < 6.5", /* phone devices usually have a diagonal of up to 6.5in */ 120 | "tablet": "6.5 <= di && di < 12.0", /* tablet devices usually have a diagonal of up to 12.0in */ 121 | "desktop": "*" /* desktop devices usually have a diagonal of 12.0in and higher */ 122 | }, 123 | orientation: { 124 | "portrait": "h > w * 1.2", /* portrait means height is 20% higher than width */ 125 | "square": "*", /* everything else is nearly square */ 126 | "landscape": "w > h * 1.2" /* landscape means width is 20% higher than height */ 127 | } 128 | }); 129 | 130 | /* calculate one single result value */ 131 | var calculate_one = function (name, options, stage) { 132 | debug(2, "(re)calculating the stage " + name + " parameter"); 133 | var res = null; 134 | var def = null; 135 | $.each(options, function (value, fn) { 136 | if (fn === "*") 137 | def = value; 138 | else if (fn.call(null, stage) === true) { 139 | res = value; 140 | return false; 141 | } 142 | return true; 143 | }); 144 | if (res === null && def !== null) 145 | res = def; 146 | return res; 147 | }; 148 | 149 | /* calculate all result values */ 150 | var calculate_all = function () { 151 | debug(1, "(re)calculating all stage parameters"); 152 | var S = $.extend({}, stage_default); 153 | S.w = parseInt($(window).width()); 154 | S.h = parseInt($(window).height()); 155 | S.dp = Math.round(10 * Math.sqrt(S.w * S.w + S.h * S.h)) / 10; 156 | S.dppx = (typeof S.dppx !== "undefined" ? parseFloat(window.devicePixelRatio) : 1.0); 157 | S.ppi = parseFloat(calculate_one("ppi", settings.ppi, S)); 158 | S.di = Math.round(10 * (S.dp / S.ppi)) / 10; 159 | S.size = calculate_one("size", settings.size, S); 160 | S.orientation = calculate_one("orientation", settings.orientation, S); 161 | 162 | /* determine whether an actual parameter change happended */ 163 | var difference = false; 164 | $.each(stage, function (key, val) { 165 | if (val !== S[key]) { 166 | difference = true; 167 | return false; 168 | } 169 | }); 170 | if (difference) { 171 | stageOld = stage; 172 | stage = S; 173 | } 174 | return difference; 175 | }; 176 | 177 | /* update stage information */ 178 | var update_stage = function (forced) { 179 | /* recalculate stage information */ 180 | var difference = calculate_all(); 181 | 182 | if (difference || forced) { 183 | /* optionally notify all subscribers */ 184 | $(window).trigger("stage", [ stage, stageOld ]); 185 | } 186 | }; 187 | 188 | /* bind to the window object for resizing and orientation changes */ 189 | $(window).bind("resize", function (ev) { 190 | if (ev.target !== this) 191 | return; 192 | update_stage(false); 193 | }); 194 | $(window).bind("orientationchange", function (ev) { 195 | if (ev.target !== this) 196 | return; 197 | update_stage(false); 198 | }); 199 | 200 | /* initialize the stage once */ 201 | $(document).ready(function () { 202 | update_stage(true); 203 | }); 204 | })(jQuery); 205 | 206 | -------------------------------------------------------------------------------- /jshint.json: -------------------------------------------------------------------------------- 1 | { 2 | "maxerr": 200, 3 | "bitwise": true, 4 | "camelcase": false, 5 | "curly": false, 6 | "eqeqeq": true, 7 | "forin": false, 8 | "immed": true, 9 | "latedef": true, 10 | "newcap": false, 11 | "noarg": false, 12 | "noempty": false, 13 | "nonew": true, 14 | "plusplus": false, 15 | "quotmark": "double", 16 | "regexp": false, 17 | "undef": true, 18 | "unused": true, 19 | "strict": false, 20 | "trailing": true, 21 | "maxparams": 9, 22 | "maxdepth": 7, 23 | "maxstatements": 150, 24 | "maxlen": 200, 25 | "loopfunc": true 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-stage", 3 | "version": "1.1.15", 4 | "description": "jQuery Stage is a jQuery plugin for detecting information about the stage, the browser's viewport.", 5 | "main": "jquery.stage.js", 6 | "keywords": [ 7 | "jquery-plugin", "ecosystem:jquery", 8 | "jquery", "markup", 9 | "stage", "viewport", "device", "size", "orientation", "landscape", "portrait" 10 | ], 11 | "scripts": { 12 | "test": "grunt" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/rse/jquery-stage.git" 17 | }, 18 | "author": { 19 | "name": "Dr. Ralf S. Engelschall", 20 | "email": "rse@engelschall.com", 21 | "url": "http://engelschall.com" 22 | }, 23 | "license": "MIT", 24 | "homepage": "https://github.com/rse/jquery-stage", 25 | "bugs": "https://github.com/rse/jquery-stage/issues", 26 | "devDependencies": { 27 | "grunt": "1.3.0", 28 | "grunt-cli": "1.3.2", 29 | "grunt-contrib-jshint": "3.0.0", 30 | "grunt-contrib-uglify": "5.0.0", 31 | "grunt-contrib-clean": "2.0.0", 32 | "grunt-eslint": "23.0.0", 33 | "gulp": "4.0.2", 34 | "gulp-rename": "2.0.0", 35 | "gulp-jshint": "2.1.0", 36 | "gulp-eslint": "6.0.0", 37 | "gulp-uglify": "3.0.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sample/app.css: -------------------------------------------------------------------------------- 1 | 2 | .info { 3 | background-color: #333333; 4 | padding: 20px; 5 | -webkit-border-radius: 8px; 6 | border-radius: 8px; 7 | } 8 | .info .label { 9 | font-family: sans-serif; 10 | font-size: 12pt; 11 | font-weight: bold; 12 | text-align: right; 13 | color: #cccccc; 14 | } 15 | .info .value { 16 | font-family: monospace; 17 | font-size: 12pt; 18 | color: #ffffff; 19 | } 20 | 21 | .device { 22 | -webkit-border-radius: 8px; 23 | border-radius: 8px; 24 | margin-top: 20px; 25 | } 26 | .stage-size-phone .device { 27 | background-color: blue; 28 | } 29 | .stage-size-tablet .device { 30 | background-color: green; 31 | } 32 | .stage-size-desktop .device { 33 | background-color: red; 34 | } 35 | .stage-orientation-portrait .device { 36 | width: 90px; 37 | height: 160px; 38 | } 39 | .stage-orientation-square .device { 40 | width: 120px; 41 | height: 120px; 42 | } 43 | .stage-orientation-landscape .device { 44 | width: 160px; 45 | height: 90px; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /sample/app.js: -------------------------------------------------------------------------------- 1 | 2 | $(document).ready(function () { 3 | var showStage = function (stage, stageOld) { 4 | $.each(stage, function (name, value) { 5 | $(".info .value." + name).html(value); 6 | }); 7 | }; 8 | showStage($.stage(), null); 9 | $(window).stage(function (ev, stage, stageOld) { 10 | showStage(stage, stageOld); 11 | }); 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /sample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Trivial jQuery Stage Sample 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
w:
h:
dp:
dppx:
ppi:
di:
size:
orientation:
27 |
28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /stage.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stage", 3 | "title": "jQuery Stage", 4 | "description": "jQuery Stage is a jQuery plugin for detecting information about the stage, the browser's viewport.", 5 | "version": "1.1.14", 6 | "author": { 7 | "name": "Dr. Ralf S. Engelschall", 8 | "email": "rse@engelschall.com", 9 | "url": "http://engelschall.com" 10 | }, 11 | "licenses": [{ 12 | "type": "MIT", 13 | "url": "http://opensource.org/licenses/MIT" 14 | }], 15 | "dependencies": { 16 | "jquery": ">=1.3" 17 | }, 18 | "keywords": [ 19 | "stage", 20 | "viewport", 21 | "device", 22 | "size", 23 | "orientation", 24 | "landscape", 25 | "portrait" 26 | ], 27 | "homepage": "https://github.com/rse/jquery-stage", 28 | "docs": "https://github.com/rse/jquery-stage", 29 | "download": "https://raw.github.com/rse/jquery-stage/1.1.14/jquery.stage.js", 30 | "bugs": "https://github.com/rse/jquery-stage/issues" 31 | } 32 | --------------------------------------------------------------------------------