├── .npmignore ├── example-images ├── 1_zoom.jpg ├── 2_zoom.jpg ├── 3_zoom_1.jpg ├── 3_zoom_2.jpg ├── 3_zoom_3.jpg ├── 3_zoom_4.jpg ├── 1_standard.jpg ├── 2_standard.jpg ├── test_zoom.jpg ├── 3_standard_1.jpg ├── 3_standard_2.jpg ├── 3_standard_3.jpg ├── 3_standard_4.jpg ├── 3_thumbnail_1.jpg ├── 3_thumbnail_2.jpg ├── 3_thumbnail_3.jpg ├── 3_thumbnail_4.jpg └── test_standard.jpg ├── .gitignore ├── .editorconfig ├── bower.json ├── package.json ├── .jshintrc ├── LICENSE ├── test ├── runner.html ├── spec │ └── easyzoom.js └── lib │ ├── qunit-2.19.1.css │ └── jquery-3.6.0.min.js ├── css ├── easyzoom.css ├── example.css └── pygments.css ├── Gruntfile.js ├── README.md ├── dist └── easyzoom.js ├── src └── easyzoom.js └── index.html /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | example-images 3 | .jshintrc 4 | .editorconfig 5 | Gruntfile.js 6 | index.html 7 | -------------------------------------------------------------------------------- /example-images/1_zoom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/1_zoom.jpg -------------------------------------------------------------------------------- /example-images/2_zoom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/2_zoom.jpg -------------------------------------------------------------------------------- /example-images/3_zoom_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_zoom_1.jpg -------------------------------------------------------------------------------- /example-images/3_zoom_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_zoom_2.jpg -------------------------------------------------------------------------------- /example-images/3_zoom_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_zoom_3.jpg -------------------------------------------------------------------------------- /example-images/3_zoom_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_zoom_4.jpg -------------------------------------------------------------------------------- /example-images/1_standard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/1_standard.jpg -------------------------------------------------------------------------------- /example-images/2_standard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/2_standard.jpg -------------------------------------------------------------------------------- /example-images/test_zoom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/test_zoom.jpg -------------------------------------------------------------------------------- /example-images/3_standard_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_standard_1.jpg -------------------------------------------------------------------------------- /example-images/3_standard_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_standard_2.jpg -------------------------------------------------------------------------------- /example-images/3_standard_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_standard_3.jpg -------------------------------------------------------------------------------- /example-images/3_standard_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_standard_4.jpg -------------------------------------------------------------------------------- /example-images/3_thumbnail_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_thumbnail_1.jpg -------------------------------------------------------------------------------- /example-images/3_thumbnail_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_thumbnail_2.jpg -------------------------------------------------------------------------------- /example-images/3_thumbnail_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_thumbnail_3.jpg -------------------------------------------------------------------------------- /example-images/3_thumbnail_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/3_thumbnail_4.jpg -------------------------------------------------------------------------------- /example-images/test_standard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-like-robots/EasyZoom/HEAD/example-images/test_standard.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | node_modules/ 3 | 4 | .DS_Store 5 | .idea 6 | .svn 7 | 8 | *.gz 9 | *.db 10 | *.log 11 | *.bak 12 | *.dat 13 | *.out 14 | *.pid 15 | *.seed 16 | *.sublime-project 17 | *.sublime-workspace -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [{*.js, *.json}] 10 | indent_style = space 11 | indent_size = 4 12 | 13 | [*.css] 14 | indent_style = tab 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easyzoom", 3 | "version": "2.5.2", 4 | "description": "EasyZoom is an elegant, highly optimised jQuery image zoom and panning plugin based on the original work by Alen Grakalic.", 5 | "keywords": [ 6 | "zoom", 7 | "image", 8 | "flyout", 9 | "panning" 10 | ], 11 | "authors": [ 12 | { 13 | "name": "Matt Hinchliffe", 14 | "homepage": "http://maketea.co.uk" 15 | } 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "git@github.com:i-like-robots/EasyZoom.git" 20 | }, 21 | "dependencies": { 22 | "jquery": ">=1.7" 23 | }, 24 | "license": "MIT", 25 | "main": [ 26 | "dist/easyzoom.js" 27 | ], 28 | "ignore": [ 29 | "test", 30 | "example-images", 31 | "index.html" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easyzoom", 3 | "version": "2.6.0", 4 | "description": "EasyZoom is an elegant, highly optimised jQuery image zoom and panning plugin based on the original work by Alen Grakalic.", 5 | "keywords": [ 6 | "zoom", 7 | "image", 8 | "flyout", 9 | "panning" 10 | ], 11 | "author": "Matt Hinchliffe", 12 | "repository": { 13 | "type": "git", 14 | "url": "git@github.com:i-like-robots/EasyZoom.git" 15 | }, 16 | "homepage": "https://github.com/i-like-robots/EasyZoom", 17 | "license": "MIT", 18 | "scripts": { 19 | "prepublishOnly": "grunt", 20 | "test": "grunt jshint && open test/runner.html" 21 | }, 22 | "main": "dist/easyzoom.js", 23 | "dependencies": { 24 | "jquery": ">=1.7" 25 | }, 26 | "devDependencies": { 27 | "grunt": "^1.5.2", 28 | "grunt-cli": "^1.4.2", 29 | "grunt-contrib-jshint": "^3.2.0", 30 | "grunt-contrib-uglify": "^5.2.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // strict 3 | "bitwise": false, 4 | "camelcase": true, 5 | "curly": false, 6 | "eqeqeq": false, 7 | "es3": false, 8 | "forin": false, 9 | "freeze": false, 10 | "immed": true, 11 | "indent": 4, 12 | "latedef": true, 13 | "newcap": true, 14 | "noarg": true, 15 | "noempty": true, 16 | "nonew": false, 17 | "plusplus": false, 18 | "quotmark": "single", 19 | "undef": true, 20 | "strict": true, 21 | "trailing": true, 22 | "unused": true, 23 | "expr": true, 24 | 25 | // relax 26 | "boss": true, 27 | "eqnull": true, 28 | "supernew": true, 29 | "validthis": true, 30 | 31 | // environment 32 | "browser": true, 33 | 34 | // globals 35 | "globals": { 36 | "module": true, 37 | "define": false, 38 | "require": false, 39 | "jQuery": false 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 Matt Hinchliffe 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | QUnit 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 |
20 | 21 | 22 | 23 |
24 |
25 | 26 |
27 | 28 |
29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /css/easyzoom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * EasyZoom core styles 3 | */ 4 | .easyzoom { 5 | position: relative; 6 | 7 | /* 'Shrink-wrap' the element */ 8 | display: inline-block; 9 | *display: inline; 10 | *zoom: 1; 11 | } 12 | 13 | .easyzoom img { 14 | vertical-align: bottom; 15 | } 16 | 17 | .easyzoom.is-loading img { 18 | cursor: progress; 19 | } 20 | 21 | .easyzoom.is-ready img { 22 | cursor: crosshair; 23 | } 24 | 25 | .easyzoom.is-error img { 26 | cursor: not-allowed; 27 | } 28 | 29 | .easyzoom-notice { 30 | position: absolute; 31 | top: 50%; 32 | left: 50%; 33 | z-index: 150; 34 | width: 10em; 35 | margin: -1em 0 0 -5em; 36 | line-height: 2em; 37 | text-align: center; 38 | background: #FFF; 39 | box-shadow: 0 0 10px #888; 40 | } 41 | 42 | .easyzoom-flyout { 43 | position:absolute; 44 | z-index: 100; 45 | overflow: hidden; 46 | background: #FFF; 47 | } 48 | 49 | /** 50 | * EasyZoom layout variations 51 | */ 52 | .easyzoom--overlay .easyzoom-flyout { 53 | top: 0; 54 | left: 0; 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | .easyzoom--adjacent .easyzoom-flyout { 60 | top: 0; 61 | left: 100%; 62 | width: 100%; 63 | height: 100%; 64 | margin-left: 20px; 65 | } 66 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | uglify: { 6 | options: { 7 | banner: [ 8 | '/*!', 9 | ' * @name <%= pkg.name %>', 10 | ' * @author <%= pkg.author %>', 11 | ' * @modified <%= grunt.template.today("dddd, mmmm dS, yyyy") %>', 12 | ' * @version <%= pkg.version %>', 13 | ' */' 14 | ].join('\n') 15 | }, 16 | dist: { 17 | files: [ 18 | { 19 | src: 'src/easyzoom.js', 20 | dest: 'dist/easyzoom.js' 21 | } 22 | ] 23 | } 24 | }, 25 | jshint: { 26 | all: ['src/**/*.js'], 27 | options: { 28 | jshintrc: true 29 | } 30 | } 31 | }); 32 | 33 | grunt.loadNpmTasks('grunt-contrib-jshint'); 34 | grunt.loadNpmTasks('grunt-contrib-uglify'); 35 | 36 | grunt.registerTask('default', ['jshint', 'uglify']); 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EasyZoom, jQuery image zoom plugin 2 | 3 | [EasyZoom][1] is an elegant, highly optimised [jQuery][2] image zoom and panning plugin based on the [original work][3] by [Alen Grakalic][4]. EasyZoom supports touch-enabled devices and is easily customisable with CSS. It's been trusted for years by hundreds of thousands of websites including many well known brands like Patagonia, Gillette, Sports Direct, Topshop and Topman, Amara, Mary Kay, Dremel, Little Greene, iFixit, and many more. 4 | 5 | ## Dependencies 6 | 7 | jQuery 1.7+ 8 | 9 | Compatible with jQuery 1.x, 2.x and 3.x (inc. slim). 10 | 11 | ## Issues 12 | 13 | Have a bug? Please report an issues on the [Github project page][1] 14 | 15 | https://github.com/i-like-robots/EasyZoom/issues 16 | 17 | ## Versioning 18 | 19 | Releases will be numbered in following format: 20 | 21 | `..` 22 | 23 | ## License 24 | 25 | This work is licensed under a [MIT License][5]. 26 | 27 | ## Authors 28 | 29 | This jQuery plugin was written by [Matt Hinchliffe][6]. 30 | 31 | Thanks also for contributions from: 32 | 33 | - [Steve Lindstrom](https://github.com/slindstr) 34 | 35 | [1]: http://github.com/i-like-robots/EasyZoom/ 36 | [2]: http://www.jquery.com 37 | [3]: http://cssglobe.com/lab/easyzoom/easyzoom.html 38 | [4]: http://grakalic.com 39 | [5]: http://opensource.org/licenses/MIT 40 | [6]: http://maketea.co.uk 41 | -------------------------------------------------------------------------------- /css/example.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body { 8 | font: normal 16px/1.5 Arial, sans-serif; 9 | color: #111; 10 | background: #eee; 11 | } 12 | 13 | h1, h2, h3, h4, header > p { 14 | text-align: center; 15 | color: #555; 16 | } 17 | 18 | h1 { 19 | margin: 0 0 .2em; 20 | font-size: 2.5em; 21 | letter-spacing: -.075em; 22 | } 23 | 24 | h2, h1 + p { 25 | margin: 0 0 .5em; 26 | font-size: 1.5em; 27 | } 28 | 29 | h3, h4 { 30 | margin: 0 0 .5em; 31 | font-size: 1.25em; 32 | } 33 | 34 | * + h3 { 35 | margin-top: 1em; 36 | } 37 | 38 | header > h1 { 39 | margin-bottom: 0; 40 | } 41 | 42 | header > p { 43 | margin-bottom: 1em; 44 | } 45 | 46 | p, dl, ul, ol { 47 | margin: 0 0 1.5em; 48 | } 49 | 50 | dt { 51 | font-weight: bold; 52 | } 53 | 54 | dd { 55 | margin: 0 0 1em; 56 | font-size: .8125em; 57 | color: #555; 58 | } 59 | 60 | ul, ol { 61 | padding-left: 1.5em; 62 | } 63 | 64 | button, 65 | a.button { 66 | font-size: 1.2em; 67 | line-height: 1; 68 | padding: .25em .5em; 69 | border: none; 70 | text-decoration: none; 71 | color: #fff; 72 | background: #333; 73 | border-radius: 7px; 74 | } 75 | 76 | button:hover, 77 | a.button:hover { 78 | background-color: #111; 79 | } 80 | 81 | a img { 82 | border: 0; 83 | } 84 | 85 | figure { 86 | margin: 0; 87 | } 88 | 89 | pre, code, var, tt { 90 | font-size: 15px; 91 | font-style: normal; 92 | font-family: Consolas, "Lucida Console", Monaco, monospace; 93 | } 94 | 95 | pre { 96 | overflow: auto; 97 | padding: 1em .5em; 98 | border: 1px solid #333; 99 | line-height: 1.25; 100 | text-align: left; 101 | border-radius: 5px; 102 | } 103 | 104 | table { 105 | border: 1px solid #ddd; 106 | border-collapse: collapse; 107 | } 108 | 109 | tr > * { 110 | border-right: 1px solid #ddd; 111 | } 112 | 113 | tr > :last-child { 114 | border-right: 0; 115 | } 116 | 117 | th, td { 118 | padding: 5px; 119 | text-align: left; 120 | min-width: 150px; 121 | } 122 | 123 | th { 124 | background: #fafafa; 125 | } 126 | 127 | td { 128 | border-top: 1px solid #ddd; 129 | } 130 | 131 | .container { 132 | width: 640px; 133 | margin: 0 auto; 134 | padding: 2em 2em 4em; 135 | background: #fff; 136 | box-shadow: 0 0 5em rgba(0, 0, 0, .1); 137 | } 138 | 139 | .container section + section { 140 | margin-top: 3em; 141 | border-top: 1px solid #ccc; 142 | padding-top: 1em; 143 | } 144 | 145 | .thumbnails { 146 | overflow: hidden; 147 | margin: 1em 0; 148 | padding: 0; 149 | text-align: center; 150 | } 151 | 152 | .thumbnails li { 153 | display: inline-block; 154 | width: 140px; 155 | margin: 0 5px; 156 | } 157 | 158 | .thumbnails img { 159 | display: block; 160 | min-width: 100%; 161 | max-width: 100%; 162 | } 163 | 164 | .toggle { 165 | display: block; 166 | margin: 10px auto 1.5em; 167 | } 168 | -------------------------------------------------------------------------------- /css/pygments.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night - Eighties */ 2 | .highlight .hll { background-color: #515151 } 3 | .highlight { background: #2d2d2d; color: #cccccc } 4 | .highlight .c { color: #999999 } /* Comment */ 5 | .highlight .err { color: #f2777a } /* Error */ 6 | .highlight .k { color: #cc99cc } /* Keyword */ 7 | .highlight .l { color: #f99157 } /* Literal */ 8 | .highlight .n { color: #cccccc } /* Name */ 9 | .highlight .o { color: #66cccc } /* Operator */ 10 | .highlight .p { color: #cccccc } /* Punctuation */ 11 | .highlight .cm { color: #999999 } /* Comment.Multiline */ 12 | .highlight .cp { color: #999999 } /* Comment.Preproc */ 13 | .highlight .c1 { color: #999999 } /* Comment.Single */ 14 | .highlight .cs { color: #999999 } /* Comment.Special */ 15 | .highlight .gd { color: #f2777a } /* Generic.Deleted */ 16 | .highlight .ge { font-style: italic } /* Generic.Emph */ 17 | .highlight .gh { color: #cccccc; font-weight: bold } /* Generic.Heading */ 18 | .highlight .gi { color: #99cc99 } /* Generic.Inserted */ 19 | .highlight .gp { color: #999999; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #66cccc; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .kc { color: #cc99cc } /* Keyword.Constant */ 23 | .highlight .kd { color: #cc99cc } /* Keyword.Declaration */ 24 | .highlight .kn { color: #66cccc } /* Keyword.Namespace */ 25 | .highlight .kp { color: #cc99cc } /* Keyword.Pseudo */ 26 | .highlight .kr { color: #cc99cc } /* Keyword.Reserved */ 27 | .highlight .kt { color: #ffcc66 } /* Keyword.Type */ 28 | .highlight .ld { color: #99cc99 } /* Literal.Date */ 29 | .highlight .m { color: #f99157 } /* Literal.Number */ 30 | .highlight .s { color: #99cc99 } /* Literal.String */ 31 | .highlight .na { color: #6699cc } /* Name.Attribute */ 32 | .highlight .nb { color: #cccccc } /* Name.Builtin */ 33 | .highlight .nc { color: #ffcc66 } /* Name.Class */ 34 | .highlight .no { color: #f2777a } /* Name.Constant */ 35 | .highlight .nd { color: #66cccc } /* Name.Decorator */ 36 | .highlight .ni { color: #cccccc } /* Name.Entity */ 37 | .highlight .ne { color: #f2777a } /* Name.Exception */ 38 | .highlight .nf { color: #6699cc } /* Name.Function */ 39 | .highlight .nl { color: #cccccc } /* Name.Label */ 40 | .highlight .nn { color: #ffcc66 } /* Name.Namespace */ 41 | .highlight .nx { color: #6699cc } /* Name.Other */ 42 | .highlight .py { color: #cccccc } /* Name.Property */ 43 | .highlight .nt { color: #66cccc } /* Name.Tag */ 44 | .highlight .nv { color: #f2777a } /* Name.Variable */ 45 | .highlight .ow { color: #66cccc } /* Operator.Word */ 46 | .highlight .w { color: #cccccc } /* Text.Whitespace */ 47 | .highlight .mf { color: #f99157 } /* Literal.Number.Float */ 48 | .highlight .mh { color: #f99157 } /* Literal.Number.Hex */ 49 | .highlight .mi { color: #f99157 } /* Literal.Number.Integer */ 50 | .highlight .mo { color: #f99157 } /* Literal.Number.Oct */ 51 | .highlight .sb { color: #99cc99 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #cccccc } /* Literal.String.Char */ 53 | .highlight .sd { color: #999999 } /* Literal.String.Doc */ 54 | .highlight .s2 { color: #99cc99 } /* Literal.String.Double */ 55 | .highlight .se { color: #f99157 } /* Literal.String.Escape */ 56 | .highlight .sh { color: #99cc99 } /* Literal.String.Heredoc */ 57 | .highlight .si { color: #f99157 } /* Literal.String.Interpol */ 58 | .highlight .sx { color: #99cc99 } /* Literal.String.Other */ 59 | .highlight .sr { color: #99cc99 } /* Literal.String.Regex */ 60 | .highlight .s1 { color: #99cc99 } /* Literal.String.Single */ 61 | .highlight .ss { color: #99cc99 } /* Literal.String.Symbol */ 62 | .highlight .bp { color: #cccccc } /* Name.Builtin.Pseudo */ 63 | .highlight .vc { color: #f2777a } /* Name.Variable.Class */ 64 | .highlight .vg { color: #f2777a } /* Name.Variable.Global */ 65 | .highlight .vi { color: #f2777a } /* Name.Variable.Instance */ 66 | .highlight .il { color: #f99157 } /* Literal.Number.Integer.Long */ 67 | -------------------------------------------------------------------------------- /dist/easyzoom.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name easyzoom 3 | * @author Matt Hinchliffe 4 | * @modified Friday, December 30th, 2022 5 | * @version 2.5.2 6 | */ 7 | !function(t,e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],function(t){e(t)}):"object"==typeof module&&module.exports?module.exports=t.EasyZoom=e(require("jquery")):t.EasyZoom=e(t.jQuery)}(this,function(i){"use strict";var c,d,l,p,o,s,h={loadingNotice:"Loading image",errorNotice:"The image could not be loaded",errorDuration:2500,linkAttribute:"href",preventClicks:!0,beforeShow:i.noop,beforeHide:i.noop,onShow:i.noop,onHide:i.noop,onMove:i.noop};function n(t,e){this.$target=i(t),this.opts=i.extend({},h,e,this.$target.data()),void 0===this.isOpen&&this._init()}return n.prototype._init=function(){this.$link=this.$target.find("a"),this.$image=this.$target.find("img"),this.$flyout=i('
'),this.$notice=i('
'),this.$target.on({"mousemove.easyzoom touchmove.easyzoom":i.proxy(this._onMove,this),"mouseleave.easyzoom touchend.easyzoom":i.proxy(this._onLeave,this),"mouseenter.easyzoom touchstart.easyzoom":i.proxy(this._onEnter,this)}),this.opts.preventClicks&&this.$target.on("click.easyzoom",function(t){t.preventDefault()})},n.prototype.show=function(t,e){var o=this;if(!1!==this.opts.beforeShow.call(this)){if(!this.isReady)return this._loadImage(this.$link.attr(this.opts.linkAttribute),function(){!o.isMouseOver&&e||o.show(t)});this.$target.append(this.$flyout);var i=this.$target.outerWidth(),s=this.$target.outerHeight(),h=this.$flyout.width(),n=this.$flyout.height(),a=this.$zoom.width(),r=this.$zoom.height();c=Math.ceil(a-h),d=Math.ceil(r-n),l=(c=c<0?0:c)/i,p=(d=d<0?0:d)/s,this.isOpen=!0,this.opts.onShow.call(this),t&&this._move(t)}},n.prototype._onEnter=function(t){var e=t.originalEvent.touches;this.isMouseOver=!0,e&&1!=e.length||(t.preventDefault(),this.show(t,!0))},n.prototype._onMove=function(t){this.isOpen&&(t.preventDefault(),this._move(t))},n.prototype._onLeave=function(){this.isMouseOver=!1,this.isOpen&&this.hide()},n.prototype._onLoad=function(t){t.currentTarget.width&&(this.isReady=!0,this.$notice.detach(),this.$flyout.html(this.$zoom),this.$target.removeClass("is-loading").addClass("is-ready"),t.data.call&&t.data())},n.prototype._onError=function(){var t=this;this.$notice.text(this.opts.errorNotice),this.$target.removeClass("is-loading").addClass("is-error"),this.detachNotice=setTimeout(function(){t.$notice.detach(),t.detachNotice=null},this.opts.errorDuration)},n.prototype._loadImage=function(t,e){var o=new Image;this.$target.addClass("is-loading").append(this.$notice.text(this.opts.loadingNotice)),this.$zoom=i(o).on("error",i.proxy(this._onError,this)).on("load",e,i.proxy(this._onLoad,this)),o.style.position="absolute",o.src=t},n.prototype._move=function(t){s=0===t.type.indexOf("touch")?(e=t.touches||t.originalEvent.touches,o=e[0].pageX,e[0].pageY):(o=t.pageX||o,t.pageY||s);var e=this.$target.offset(),t=o-e.left,e=s-e.top,t=Math.ceil(t*l),e=Math.ceil(e*p);t<0||e<0||c'); 79 | this.$notice = $('
'); 80 | 81 | this.$target.on({ 82 | 'mousemove.easyzoom touchmove.easyzoom': $.proxy(this._onMove, this), 83 | 'mouseleave.easyzoom touchend.easyzoom': $.proxy(this._onLeave, this), 84 | 'mouseenter.easyzoom touchstart.easyzoom': $.proxy(this._onEnter, this) 85 | }); 86 | 87 | this.opts.preventClicks && this.$target.on('click.easyzoom', function(e) { 88 | e.preventDefault(); 89 | }); 90 | }; 91 | 92 | /** 93 | * Show 94 | * @param {MouseEvent|TouchEvent} e 95 | * @param {Boolean} testMouseOver (Optional) 96 | */ 97 | EasyZoom.prototype.show = function(e, testMouseOver) { 98 | var self = this; 99 | 100 | if (this.opts.beforeShow.call(this) === false) return; 101 | 102 | if (!this.isReady) { 103 | return this._loadImage(this.$link.attr(this.opts.linkAttribute), function() { 104 | if (self.isMouseOver || !testMouseOver) { 105 | self.show(e); 106 | } 107 | }); 108 | } 109 | 110 | this.$target.append(this.$flyout); 111 | 112 | var targetWidth = this.$target.outerWidth(); 113 | var targetHeight = this.$target.outerHeight(); 114 | 115 | var flyoutInnerWidth = this.$flyout.width(); 116 | var flyoutInnerHeight = this.$flyout.height(); 117 | 118 | var zoomImgWidth = this.$zoom.width(); 119 | var zoomImgHeight = this.$zoom.height(); 120 | 121 | zoomImgOverlapX = Math.ceil(zoomImgWidth - flyoutInnerWidth); 122 | zoomImgOverlapY = Math.ceil(zoomImgHeight - flyoutInnerHeight); 123 | 124 | // For when the zoom image is smaller than the flyout element. 125 | if (zoomImgOverlapX < 0) zoomImgOverlapX = 0; 126 | if (zoomImgOverlapY < 0) zoomImgOverlapY = 0; 127 | 128 | ratioX = zoomImgOverlapX / targetWidth; 129 | ratioY = zoomImgOverlapY / targetHeight; 130 | 131 | this.isOpen = true; 132 | 133 | this.opts.onShow.call(this); 134 | 135 | e && this._move(e); 136 | }; 137 | 138 | /** 139 | * On enter 140 | * @private 141 | * @param {Event} e 142 | */ 143 | EasyZoom.prototype._onEnter = function(e) { 144 | var touches = e.originalEvent.touches; 145 | 146 | this.isMouseOver = true; 147 | 148 | if (!touches || touches.length == 1) { 149 | e.preventDefault(); 150 | this.show(e, true); 151 | } 152 | }; 153 | 154 | /** 155 | * On move 156 | * @private 157 | * @param {Event} e 158 | */ 159 | EasyZoom.prototype._onMove = function(e) { 160 | if (!this.isOpen) return; 161 | 162 | e.preventDefault(); 163 | this._move(e); 164 | }; 165 | 166 | /** 167 | * On leave 168 | * @private 169 | */ 170 | EasyZoom.prototype._onLeave = function() { 171 | this.isMouseOver = false; 172 | this.isOpen && this.hide(); 173 | }; 174 | 175 | /** 176 | * On load 177 | * @private 178 | * @param {Event} e 179 | */ 180 | EasyZoom.prototype._onLoad = function(e) { 181 | // IE may fire a load event even on error so test the image dimensions 182 | if (!e.currentTarget.width) return; 183 | 184 | this.isReady = true; 185 | 186 | this.$notice.detach(); 187 | this.$flyout.html(this.$zoom); 188 | this.$target.removeClass('is-loading').addClass('is-ready'); 189 | 190 | e.data.call && e.data(); 191 | }; 192 | 193 | /** 194 | * On error 195 | * @private 196 | */ 197 | EasyZoom.prototype._onError = function() { 198 | var self = this; 199 | 200 | this.$notice.text(this.opts.errorNotice); 201 | this.$target.removeClass('is-loading').addClass('is-error'); 202 | 203 | this.detachNotice = setTimeout(function() { 204 | self.$notice.detach(); 205 | self.detachNotice = null; 206 | }, this.opts.errorDuration); 207 | }; 208 | 209 | /** 210 | * Load image 211 | * @private 212 | * @param {String} href 213 | * @param {Function} callback 214 | */ 215 | EasyZoom.prototype._loadImage = function(href, callback) { 216 | var zoom = new Image(); 217 | 218 | this.$target 219 | .addClass('is-loading') 220 | .append(this.$notice.text(this.opts.loadingNotice)); 221 | 222 | this.$zoom = $(zoom) 223 | .on('error', $.proxy(this._onError, this)) 224 | .on('load', callback, $.proxy(this._onLoad, this)); 225 | 226 | zoom.style.position = 'absolute'; 227 | zoom.src = href; 228 | }; 229 | 230 | /** 231 | * Move 232 | * @private 233 | * @param {Event} e 234 | */ 235 | EasyZoom.prototype._move = function(e) { 236 | 237 | if (e.type.indexOf('touch') === 0) { 238 | var touchlist = e.touches || e.originalEvent.touches; 239 | pointerPositionX = touchlist[0].pageX; 240 | pointerPositionY = touchlist[0].pageY; 241 | } else { 242 | pointerPositionX = e.pageX || pointerPositionX; 243 | pointerPositionY = e.pageY || pointerPositionY; 244 | } 245 | 246 | var targetOffset = this.$target.offset(); 247 | var relativePositionX = pointerPositionX - targetOffset.left; 248 | var relativePositionY = pointerPositionY - targetOffset.top; 249 | var moveX = Math.ceil(relativePositionX * ratioX); 250 | var moveY = Math.ceil(relativePositionY * ratioY); 251 | 252 | // Close if outside 253 | if (moveX < 0 || moveY < 0 || moveX > zoomImgOverlapX || moveY > zoomImgOverlapY) { 254 | this.hide(); 255 | } else { 256 | var top = moveY * -1; 257 | var left = moveX * -1; 258 | 259 | if ('transform' in document.body.style) { 260 | this.$zoom.css({ transform: 'translate(' + left + 'px, ' + top + 'px)' }); 261 | } else { 262 | this.$zoom.css({ top: top, left: left }); 263 | } 264 | 265 | this.opts.onMove.call(this, top, left); 266 | } 267 | }; 268 | 269 | /** 270 | * Hide 271 | */ 272 | EasyZoom.prototype.hide = function() { 273 | if (!this.isOpen) return; 274 | if (this.opts.beforeHide.call(this) === false) return; 275 | 276 | this.$flyout.detach(); 277 | this.isOpen = false; 278 | 279 | this.opts.onHide.call(this); 280 | }; 281 | 282 | /** 283 | * Swap 284 | * @param {String} standardSrc 285 | * @param {String} zoomHref 286 | * @param {String|Array} srcset (Optional) 287 | */ 288 | EasyZoom.prototype.swap = function(standardSrc, zoomHref, srcset) { 289 | this.hide(); 290 | this.isReady = false; 291 | 292 | this.detachNotice && clearTimeout(this.detachNotice); 293 | 294 | this.$notice.parent().length && this.$notice.detach(); 295 | 296 | this.$target.removeClass('is-loading is-ready is-error'); 297 | 298 | this.$image.attr({ 299 | src: standardSrc, 300 | srcset: $.isArray(srcset) ? srcset.join() : srcset 301 | }); 302 | 303 | this.$link.attr(this.opts.linkAttribute, zoomHref); 304 | }; 305 | 306 | /** 307 | * Teardown 308 | */ 309 | EasyZoom.prototype.teardown = function() { 310 | this.hide(); 311 | 312 | this.$target 313 | .off('.easyzoom') 314 | .removeClass('is-loading is-ready is-error'); 315 | 316 | this.detachNotice && clearTimeout(this.detachNotice); 317 | 318 | delete this.$link; 319 | delete this.$zoom; 320 | delete this.$image; 321 | delete this.$notice; 322 | delete this.$flyout; 323 | 324 | delete this.isOpen; 325 | delete this.isReady; 326 | }; 327 | 328 | // jQuery plugin wrapper 329 | $.fn.easyZoom = function(options) { 330 | return this.each(function() { 331 | var api = $.data(this, 'easyZoom'); 332 | 333 | if (!api) { 334 | $.data(this, 'easyZoom', new EasyZoom(this, options)); 335 | } else if (api.isOpen === undefined) { 336 | api._init(); 337 | } 338 | }); 339 | }; 340 | 341 | return EasyZoom; 342 | })); 343 | -------------------------------------------------------------------------------- /test/lib/qunit-2.19.1.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 2.19.1 3 | * https://qunitjs.com/ 4 | * 5 | * Copyright OpenJS Foundation and other contributors 6 | * Released under the MIT license 7 | * https://jquery.org/license 8 | */ 9 | 10 | /** Font Family and Sizes */ 11 | 12 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult { 13 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 14 | } 15 | 16 | #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 17 | #qunit-tests { font-size: smaller; } 18 | 19 | 20 | /** Resets */ 21 | 22 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 23 | margin: 0; 24 | padding: 0; 25 | } 26 | 27 | /* Style our buttons in a simple way, uninfluenced by the styles 28 | the tested app might load. Don't affect buttons in #qunit-fixture! 29 | https://github.com/qunitjs/qunit/pull/1395 30 | https://github.com/qunitjs/qunit/issues/1437 */ 31 | #qunit-testrunner-toolbar button, 32 | #qunit-testresult button { 33 | all: unset; /* best effort, modern browsers only */ 34 | font: inherit; 35 | color: initial; 36 | border: initial; 37 | background-color: buttonface; 38 | padding: 0 4px; 39 | } 40 | 41 | 42 | /** Fixed headers with scrollable tests */ 43 | 44 | @supports (display: flex) or (display: -webkit-box) { 45 | @media (min-height: 500px) { 46 | #qunit { 47 | position: fixed; 48 | left: 0px; 49 | right: 0px; 50 | top: 0px; 51 | bottom: 0px; 52 | padding: 8px; 53 | display: -webkit-box; 54 | display: flex; 55 | flex-direction: column; 56 | } 57 | 58 | #qunit-tests { 59 | overflow: scroll; 60 | } 61 | 62 | #qunit-banner { 63 | flex: 5px 0 0; 64 | } 65 | } 66 | } 67 | 68 | 69 | /** Header (excluding toolbar) */ 70 | 71 | #qunit-header { 72 | padding: 0.5em 0 0.5em 1em; 73 | 74 | color: #C2CCD1; 75 | background-color: #0D3349; 76 | 77 | font-size: 1.5em; 78 | line-height: 1em; 79 | font-weight: 400; 80 | 81 | border-radius: 5px 5px 0 0; 82 | } 83 | 84 | #qunit-header a { 85 | text-decoration: none; 86 | color: inherit; 87 | } 88 | 89 | #qunit-header a:hover, 90 | #qunit-header a:focus { 91 | color: #FFF; 92 | } 93 | 94 | #qunit-banner { 95 | height: 5px; 96 | } 97 | 98 | #qunit-filteredTest { 99 | padding: 0.5em 1em 0.5em 1em; 100 | color: #366097; 101 | background-color: #F4FF77; 102 | } 103 | 104 | #qunit-userAgent { 105 | padding: 0.5em 1em 0.5em 1em; 106 | color: #FFF; 107 | background-color: #2B81AF; 108 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 109 | } 110 | 111 | 112 | /** Toolbar */ 113 | 114 | #qunit-testrunner-toolbar { 115 | padding: 0.5em 1em 0.5em 1em; 116 | color: #5E740B; 117 | background-color: #EEE; 118 | } 119 | 120 | #qunit-testrunner-toolbar .clearfix { 121 | height: 0; 122 | clear: both; 123 | } 124 | 125 | #qunit-testrunner-toolbar label { 126 | display: inline-block; 127 | } 128 | 129 | #qunit-testrunner-toolbar input[type=checkbox], 130 | #qunit-testrunner-toolbar input[type=radio] { 131 | margin: 3px; 132 | vertical-align: -2px; 133 | } 134 | 135 | #qunit-testrunner-toolbar input[type=text] { 136 | box-sizing: border-box; 137 | height: 1.6em; 138 | } 139 | 140 | #qunit-testrunner-toolbar button, 141 | #qunit-testresult button { 142 | border-radius: .25em; 143 | border: 1px solid #AAA; 144 | background-color: #F8F8F8; 145 | color: #222; 146 | line-height: 1.6; 147 | cursor: pointer; 148 | } 149 | #qunit-testrunner-toolbar button:hover, 150 | #qunit-testresult button:hover { 151 | border-color: #AAA; 152 | background-color: #FFF; 153 | color: #444; 154 | } 155 | #qunit-testrunner-toolbar button:active, 156 | #qunit-testresult button:active { 157 | border-color: #777; 158 | background-color: #CCC; 159 | color: #000; 160 | } 161 | #qunit-testrunner-toolbar button:focus, 162 | #qunit-testresult button:focus { 163 | border-color: #2F68DA; 164 | /* emulate 2px border without a layout shift */ 165 | box-shadow: inset 0 0 0 1px #2F68DA 166 | } 167 | #qunit-testrunner-toolbar button:disabled, 168 | #qunit-testresult button:disabled { 169 | border-color: #CCC; 170 | background-color: #CCC; 171 | color: #FFF; 172 | cursor: default; 173 | } 174 | 175 | #qunit-toolbar-filters { 176 | float: right; 177 | /* aligning right avoids overflows and inefficient use of space 178 | around the dropdown menu on narrow viewports */ 179 | text-align: right; 180 | } 181 | 182 | .qunit-url-config, 183 | .qunit-filter, 184 | #qunit-modulefilter { 185 | display: inline-block; 186 | line-height: 2.1em; 187 | text-align: left; 188 | } 189 | 190 | .qunit-filter, 191 | #qunit-modulefilter { 192 | position: relative; 193 | margin-left: 1em; 194 | } 195 | 196 | .qunit-url-config label { 197 | margin-right: 0.5em; 198 | } 199 | 200 | #qunit-modulefilter-search { 201 | box-sizing: border-box; 202 | min-width: 400px; 203 | min-width: min(400px, 80vw); 204 | } 205 | 206 | #qunit-modulefilter-search-container { 207 | position: relative; 208 | } 209 | #qunit-modulefilter-search-container:after { 210 | position: absolute; 211 | right: 0.3em; 212 | bottom: 0; 213 | line-height: 100%; 214 | content: "\25bc"; 215 | color: black; 216 | } 217 | 218 | #qunit-modulefilter-dropdown { 219 | /* align with #qunit-modulefilter-search */ 220 | box-sizing: border-box; 221 | min-width: 400px; 222 | min-width: min(400px, 80vw); 223 | max-width: 80vw; 224 | position: absolute; 225 | right: 0; 226 | top: 100%; 227 | margin-top: 2px; 228 | 229 | /* ensure that when on a narrow viewports and having only one result, 230 | that #qunit-modulefilter-actions fall outside the dropdown rectangle. */ 231 | min-height: 3em; 232 | 233 | border: 1px solid #AAA; 234 | border-top-color: transparent; 235 | border-radius: 0 0 .25em .25em; 236 | color: #0D3349; 237 | background-color: #F5F5F5; 238 | z-index: 99; 239 | } 240 | 241 | #qunit-modulefilter-actions { 242 | display: block; 243 | overflow: auto; 244 | /* align with #qunit-modulefilter-dropdown-list */ 245 | font: smaller/1.5em sans-serif; 246 | } 247 | @media (min-width: 350px) { 248 | #qunit-modulefilter-actions { 249 | position: absolute; 250 | right: 0; 251 | } 252 | } 253 | 254 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > * { 255 | box-sizing: border-box; 256 | max-height: 2.8em; 257 | display: block; 258 | padding: 0.4em; 259 | } 260 | 261 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > button { 262 | float: right; 263 | margin: 0.25em; 264 | } 265 | 266 | #qunit-modulefilter-dropdown-list { 267 | margin: 0; 268 | padding: 0; 269 | font: smaller/1.5em sans-serif; 270 | } 271 | 272 | #qunit-modulefilter-dropdown-list li { 273 | list-style: none; 274 | } 275 | #qunit-modulefilter-dropdown-list .clickable { 276 | display: block; 277 | padding: 0.25em 0.50em 0.25em 0.15em; 278 | white-space: nowrap; 279 | overflow: hidden; 280 | text-overflow: ellipsis; 281 | } 282 | #qunit-modulefilter-dropdown-list .clickable.checked { 283 | font-weight: bold; 284 | background-color: #E2F0F7; 285 | color: #0D3349; 286 | } 287 | #qunit-modulefilter-dropdown .clickable:hover { 288 | background-color: #FFF; 289 | color: #444; 290 | } 291 | 292 | 293 | /** Tests: Pass/Fail */ 294 | 295 | #qunit-tests { 296 | list-style-position: inside; 297 | } 298 | 299 | #qunit-tests li { 300 | padding: 0.4em 1em 0.4em 1em; 301 | border-bottom: 1px solid #FFF; 302 | list-style-position: inside; 303 | } 304 | 305 | #qunit-tests > li { 306 | display: none; 307 | } 308 | 309 | #qunit-tests li.running, 310 | #qunit-tests li.pass, 311 | #qunit-tests li.fail, 312 | #qunit-tests li.skipped, 313 | #qunit-tests li.aborted { 314 | display: list-item; 315 | } 316 | 317 | #qunit-tests.hidepass { 318 | position: relative; 319 | } 320 | 321 | #qunit-tests.hidepass li.running, 322 | #qunit-tests.hidepass li.pass:not(.todo) { 323 | visibility: hidden; 324 | position: absolute; 325 | width: 0; 326 | height: 0; 327 | padding: 0; 328 | border: 0; 329 | margin: 0; 330 | } 331 | 332 | #qunit-tests li strong { 333 | cursor: pointer; 334 | } 335 | 336 | #qunit-tests li.skipped strong { 337 | cursor: default; 338 | } 339 | 340 | #qunit-tests li a { 341 | padding: 0.5em; 342 | color: inherit; 343 | text-decoration: underline; 344 | } 345 | #qunit-tests li a:hover, 346 | #qunit-tests li a:focus { 347 | color: #0D3349; 348 | } 349 | 350 | #qunit-tests li .runtime { 351 | float: right; 352 | font-size: smaller; 353 | } 354 | 355 | .qunit-assert-list { 356 | margin-top: 0.5em; 357 | padding: 0.5em; 358 | 359 | background-color: #FFF; 360 | 361 | border-radius: 5px; 362 | } 363 | 364 | .qunit-source { 365 | margin: 0.6em 0 0.3em; 366 | } 367 | 368 | .qunit-collapsed { 369 | display: none; 370 | } 371 | 372 | #qunit-tests table { 373 | border-collapse: collapse; 374 | margin-top: 0.2em; 375 | } 376 | 377 | #qunit-tests th { 378 | text-align: right; 379 | vertical-align: top; 380 | padding: 0 0.5em 0 0; 381 | } 382 | 383 | #qunit-tests td { 384 | vertical-align: top; 385 | } 386 | 387 | #qunit-tests pre { 388 | margin: 0; 389 | white-space: pre-wrap; 390 | word-wrap: break-word; 391 | } 392 | 393 | #qunit-tests del { 394 | color: #374E0C; 395 | background-color: #E0F2BE; 396 | text-decoration: none; 397 | } 398 | 399 | #qunit-tests ins { 400 | color: #500; 401 | background-color: #FFCACA; 402 | text-decoration: none; 403 | } 404 | 405 | /*** Test Counts */ 406 | 407 | #qunit-tests b.counts { color: #0D3349; } 408 | #qunit-tests b.passed { color: #5E740B; } 409 | #qunit-tests b.failed { color: #710909; } 410 | 411 | #qunit-tests li li { 412 | padding: 5px; 413 | background-color: #FFF; 414 | border-bottom: none; 415 | list-style-position: inside; 416 | } 417 | 418 | /*** Passing Styles */ 419 | 420 | 421 | #qunit-tests .pass { 422 | color: #2F68DA; 423 | background-color: #E2F0F7; 424 | } 425 | 426 | #qunit-tests .pass .test-name { 427 | color: #366097; 428 | } 429 | 430 | #qunit-tests li li.pass { 431 | color: #3C510C; 432 | background-color: #FFF; 433 | border-left: 10px solid #C6E746; 434 | } 435 | 436 | #qunit-tests .pass .test-actual, 437 | #qunit-tests .pass .test-expected { color: #999; } 438 | 439 | #qunit-banner.qunit-pass { background-color: #C6E746; } 440 | 441 | /*** Failing Styles */ 442 | 443 | #qunit-tests .fail { 444 | color: #000; 445 | background-color: #EE5757; 446 | } 447 | 448 | #qunit-tests li li.fail { 449 | color: #710909; 450 | background-color: #FFF; 451 | border-left: 10px solid #EE5757; 452 | white-space: pre; 453 | } 454 | 455 | #qunit-tests > li:last-child { 456 | border-radius: 0 0 5px 5px; 457 | } 458 | 459 | #qunit-tests .fail .test-actual { color: #EE5757; } 460 | #qunit-tests .fail .test-expected { color: #008000; } 461 | 462 | #qunit-banner.qunit-fail { background-color: #EE5757; } 463 | 464 | 465 | /*** Aborted tests */ 466 | #qunit-tests .aborted { color: #000; background-color: orange; } 467 | /*** Skipped tests */ 468 | 469 | #qunit-tests .skipped { 470 | background-color: #EBECE9; 471 | } 472 | 473 | #qunit-tests .qunit-todo-label, 474 | #qunit-tests .qunit-skipped-label { 475 | background-color: #F4FF77; 476 | display: inline-block; 477 | font-style: normal; 478 | color: #366097; 479 | line-height: 1.8em; 480 | padding: 0 0.5em; 481 | margin: -0.4em 0.4em -0.4em 0; 482 | } 483 | 484 | #qunit-tests .qunit-todo-label { 485 | background-color: #EEE; 486 | } 487 | 488 | /** Result */ 489 | 490 | #qunit-testresult { 491 | color: #366097; 492 | background-color: #E2F0F7; 493 | 494 | border-bottom: 1px solid #FFF; 495 | } 496 | #qunit-testresult a { 497 | color: #2F68DA; 498 | } 499 | #qunit-testresult .clearfix { 500 | height: 0; 501 | clear: both; 502 | } 503 | #qunit-testresult .module-name { 504 | font-weight: 700; 505 | } 506 | #qunit-testresult-display { 507 | padding: 0.5em 1em 0.5em 1em; 508 | width: 85%; 509 | float:left; 510 | } 511 | #qunit-testresult-controls { 512 | padding: 0.5em 1em 0.5em 1em; 513 | width: 10%; 514 | float:left; 515 | } 516 | 517 | /** Fixture */ 518 | 519 | #qunit-fixture { 520 | position: absolute; 521 | top: -10000px; 522 | left: -10000px; 523 | width: 1000px; 524 | height: 1000px; 525 | } 526 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | EasyZoom, jQuery image zoom plugin 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 |
34 | 35 |
36 |

37 | EasyZoom 38 |

39 |

40 | jQuery image zoom plugin 41 |

42 |
43 | 44 |

45 | EasyZoom is an elegant, highly optimised jQuery image zoom and panning plugin based on the original work by Alen Grakalic. EasyZoom supports touch-enabled devices and is easily customisable with CSS. 46 |

47 | 48 |

49 | Download 50 | View project on GitHub 51 |

52 | 53 |
54 | 55 | 56 |
57 | 58 |

59 | Examples 60 |

61 | 62 |

63 | Use your mouse cursor or finger to zoom and pan the images below. 64 |

65 | 66 |

67 | Overlay 68 |

69 | 70 |
71 | 72 | 73 | 74 |
75 | 76 |

77 | Adjacent 78 |

79 | 80 | 81 |
82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 |

90 | With thumbnail images 91 |

92 | 93 |
94 | 95 | 96 | 97 |
98 | 99 | 121 | 122 |

123 | Active/Inactive toggle 124 |

125 | 126 |
127 | 128 | 129 | 130 |
131 | 132 | 133 |

134 | Photos all by Dag Endre Opedal. 135 |

136 | 137 |
138 | 139 | 140 |
141 | 142 |

143 | Setup 144 |

145 | 146 |

147 | HTML 148 |

149 | 150 |

151 | EasyZoom does not rely on a specific markup structure but it is important that the EasyZoom target element (<div class="easyzoom">) only contains a link to the large image and the smaller image. Any other elements within the EasyZoom target must not affect its layout, E.G. elements that are positioned absolutely. 152 |

153 | 154 |
155 |
<div class="easyzoom">
156 |     <a href="images/zoom.jpg">
157 |         <img src="images/standard.jpg" alt="" />
158 |     </a>
159 | </div>
160 |
161 | 162 |

163 | CSS 164 |

165 | 166 |

167 | The EasyZoom target element must 'shrink wrap' the smaller image, this can be achieved either by floating it or by displaying it as an inline block. Extra white space below the image (usually caused by the line box the image sits within) can be removed either by displaying it at block level or changing its position within the line box. 168 |

169 | 170 |

171 | Take a look at the included easyzoom.css for more information on styling EasyZoom. 172 |

173 | 174 |
175 |
/* Shrink wrap strategy 1 */
176 | .easyzoom {
177 |     float: left;
178 | }
179 | .easyzoom img {
180 |     display: block;
181 | }
182 | 
183 | 
184 | /* Shrink wrap strategy 2 */
185 | .easyzoom {
186 |     display: inline-block;
187 | }
188 | .easyzoom img {
189 |     vertical-align: bottom;
190 | }
191 |
192 | 193 |

194 | JavaScript 195 |

196 | 197 |

198 | The EasyZoom plugin is instantiated as any other jQuery plugin and an instances API can be accessed via element data. EasyZoom is also AMD and CommonJS compatible. 199 |

200 | 201 |
202 |
// Instantiate EasyZoom instances
203 | var $easyzoom = $('.easyzoom').easyZoom();
204 | 
205 | // Get an instance API
206 | var api = $easyzoom.data('easyZoom');
207 |
208 | 209 |
210 | 211 | 212 |
213 | 214 |

215 | Options 216 |

217 | 218 |

219 | Global options can be specified via the standard jQuery plugin interface or as data attributes on individual EasyZoom elements. Remember that camelCase options should be written as hyphen-separated attributes, for example the preventClicks option would be defined on the element with the data-prevent-clicks attribute. 220 |

221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 |
OptionDefault valueDescription
loadingNotice"Loading image" 235 | The text to display within the notice box while loading the zoom image. 236 |
errorNotice"The image could not be loaded"The text to display within the notice box if an error occurs when loading the zoom image.
errorDuration2500The time (in milliseconds) to display the error notice
linkAttribute"href"Attribute to retrieve the zoom image URL from.
preventClickstruePrevent clicks on the zoom image link.
onShow$.noopCallback function to execute when the flyout is displayed.
onMove$.noopCallback function to execute when the cursor is moved while over the image.
onHide$.noopCallback function to execute when the flyout is removed.
275 | 276 |
277 | 278 | 279 |
280 | 281 |

282 | API 283 |

284 | 285 |
286 |
287 | .show([MouseEvent|TouchEvent], [Boolean]) 288 |
289 |
290 | Displays the zoom image flyout. Optionally takes an instance of a 291 | mouse or 292 | touch event 293 | and can be set to only display the flyout if the mouse is over the target. 294 |
295 |
296 | .hide() 297 |
298 |
299 | Removes the zoom image flyout. 300 |
301 |
302 | .teardown() 303 |
304 |
305 | Removes all events and elements created and attached by EasyZoom. 306 |
307 |
308 | .swap(standardSrc, zoomSrc, [srcset]) 309 |
310 |
311 | Easily switch the standard and zoom image sources. To display retina images via the srcset attribute, use the optional srcset argument. 312 |
313 |
314 | 315 |
316 | 317 |
318 | 319 | 320 | Fork me on GitHub 321 | 322 | 323 | 324 | 325 | 356 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /test/lib/jquery-3.6.0.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0