├── .prettierignore ├── img ├── color.jpg ├── color-sprite.jpg └── color-sprite-lg.jpg ├── .gitignore ├── .travis.yml ├── bower.json ├── package.json ├── css ├── gray.min.css ├── gray.css ├── main.css └── normalize.css ├── LICENSE ├── README.md ├── js ├── jquery.gray.min.js └── jquery.gray.js └── index.html /.prettierignore: -------------------------------------------------------------------------------- 1 | css/ 2 | js/ 3 | -------------------------------------------------------------------------------- /img/color.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlhorky/gray/HEAD/img/color.jpg -------------------------------------------------------------------------------- /img/color-sprite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlhorky/gray/HEAD/img/color-sprite.jpg -------------------------------------------------------------------------------- /img/color-sprite-lg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlhorky/gray/HEAD/img/color-sprite-lg.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | ehthumbs.db 7 | Thumbs.db -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | deploy: 3 | provider: npm 4 | email: karl.horky@gmail.com 5 | api_key: 6 | secure: Kf9l3hRuNlWd/7LUOmzu7Tky8r5eGNWl4Tlh6xE2qViOov5WVLQyrb+22MSYfuPBcOb7F++rUMeCpz8Ef6rz8rTrKFMYgNXNSVTe35Zi7BnE6jf0GvPi8gkQLgNwxywEB4jRvRV8O+lanuVROHsiK3O2taktE5YG7+nP0pbT9Cw= 7 | on: 8 | tags: true 9 | repo: karlhorky/gray 10 | branch: gh-pages 11 | notifications: 12 | email: false 13 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gray", 3 | "version": "1.7.0", 4 | "homepage": "https://github.com/karlhorky/gray", 5 | "authors": [ 6 | "Karl Horky" 7 | ], 8 | "description": "Make an image gray in all browsers.", 9 | "main": ["css/gray.css", "js/jquery.gray.min.js"], 10 | "keywords": [ 11 | "gray", 12 | "grey", 13 | "grayscale", 14 | "images", 15 | "image", 16 | "img" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "tests" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-gray", 3 | "version": "1.7.0", 4 | "description": "Make an image grayscale in all browsers.", 5 | "main": "js/jquery.gray.js", 6 | "scripts": { 7 | "test": "echo \"No test specified\"" 8 | }, 9 | "repository": "karlhorky/gray", 10 | "keywords": [ 11 | "gray", 12 | "grey", 13 | "grayscale", 14 | "images", 15 | "image", 16 | "jquery", 17 | "jquery-plugin", 18 | "ecosystem:jquery" 19 | ], 20 | "author": "Karl Horky", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/karlhorky/gray/issues" 24 | }, 25 | "homepage": "https://github.com/karlhorky/gray#readme" 26 | } 27 | -------------------------------------------------------------------------------- /css/gray.min.css: -------------------------------------------------------------------------------- 1 | /*! Gray v1.7.0 (https://github.com/karlhorky/gray) | MIT */ 2 | .grayscale{filter:url("data:image/svg+xml;utf8,#grayscale");-webkit-filter:grayscale(1);filter:grayscale(1);filter:gray}.grayscale.grayscale-fade{transition:filter .5s}@media screen and (-webkit-min-device-pixel-ratio:0){.grayscale.grayscale-fade{-webkit-transition:-webkit-filter .5s;transition:-webkit-filter .5s}}.grayscale.grayscale-fade:hover,.grayscale.grayscale-off{-webkit-filter:grayscale(0);filter:grayscale(0)}.grayscale.grayscale-replaced{-webkit-filter:none;filter:none}.grayscale.grayscale-replaced>svg{-webkit-transition:opacity .5s ease;transition:opacity .5s ease;opacity:1}.grayscale.grayscale-replaced.grayscale-fade:hover>svg,.grayscale.grayscale-replaced.grayscale-off>svg{opacity:0} 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Karl Horky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /css/gray.css: -------------------------------------------------------------------------------- 1 | /*! Gray v1.7.0 (https://github.com/karlhorky/gray) | MIT */ 2 | .grayscale { 3 | /* Firefox 10-34 */ 4 | filter: url("data:image/svg+xml;utf8,#grayscale"); 5 | 6 | /* 7 | Chrome 19+, 8 | Safari 6+, 9 | Safari 6+ iOS, 10 | Opera 15+ 11 | */ 12 | -webkit-filter: grayscale(1); 13 | 14 | /* Firefox 35+ */ 15 | filter: grayscale(1); 16 | 17 | /* IE 6-9 */ 18 | filter: gray; 19 | } 20 | 21 | .grayscale.grayscale-fade { 22 | transition: filter .5s; 23 | } 24 | 25 | /* Webkit hack until filter is unprefixed */ 26 | @media screen and (-webkit-min-device-pixel-ratio: 0) { 27 | .grayscale.grayscale-fade { 28 | -webkit-transition: -webkit-filter .5s; 29 | transition: -webkit-filter .5s; 30 | } 31 | } 32 | 33 | .grayscale.grayscale-off, 34 | .grayscale.grayscale-fade:hover { 35 | -webkit-filter: grayscale(0); 36 | filter: grayscale(0); 37 | } 38 | 39 | /* Background element */ 40 | .grayscale.grayscale-replaced { 41 | -webkit-filter: none; 42 | filter: none; 43 | } 44 | 45 | .grayscale.grayscale-replaced > svg { 46 | -webkit-transition: opacity .5s ease; 47 | transition: opacity .5s ease; 48 | opacity: 1; 49 | } 50 | 51 | .grayscale.grayscale-replaced.grayscale-off > svg, 52 | .grayscale.grayscale-replaced.grayscale-fade:hover > svg { 53 | opacity: 0; 54 | } 55 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box 3 | } 4 | 5 | body { 6 | font-family: 'Open Sans', sans-serif; 7 | text-align: center; 8 | padding: 40px 0; 9 | } 10 | 11 | h1 { 12 | color: #bbb; 13 | } 14 | 15 | h1 small { 16 | font-size: 60%; 17 | display: block; 18 | } 19 | 20 | h2 { 21 | display: none; 22 | } 23 | 24 | h3 { 25 | font-size: 14px; 26 | text-align: left; 27 | background: #aaa; 28 | margin: 20px 0 25px; 29 | padding: 8px 10px; 30 | border-radius: 4px; 31 | } 32 | 33 | h3, 34 | h3 a { 35 | color: #fff; 36 | text-decoration: none; 37 | } 38 | 39 | h3 a:hover:before { 40 | content: '#'; 41 | font-size: 20px; 42 | color: #aaa; 43 | position: absolute; 44 | margin-left: -30px; 45 | margin-top: -4px; 46 | } 47 | 48 | .container { 49 | width: 80%; 50 | max-width: 500px; 51 | margin: 0 auto; 52 | } 53 | 54 | .row:before, 55 | .row:after { 56 | content: " "; 57 | display: table; 58 | } 59 | 60 | .row:after { 61 | clear: both; 62 | } 63 | 64 | .row { 65 | *zoom: 1; 66 | } 67 | 68 | h3 + .col-half, 69 | h3 + .col-half + .col-half { 70 | position: relative; 71 | height: 120px; 72 | top: 25px; 73 | } 74 | 75 | h3 + .col-half { 76 | padding-bottom: 80px; 77 | } 78 | 79 | pre { 80 | margin-top: 20px; 81 | display: inline-block; 82 | background-color: #f3f3f3; 83 | color: #888; 84 | border: 1px solid #ddd; 85 | font-size: 12px; 86 | line-height: 20px; 87 | overflow: auto; 88 | padding: 6px 10px; 89 | border-radius: 3px; 90 | text-align: left; 91 | max-width: 90%; 92 | } 93 | 94 | code { 95 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 96 | } 97 | 98 | *[data-label]:before { 99 | content: attr(data-label); 100 | font-size: 15px; 101 | color: #999; 102 | display: block; 103 | position: absolute; 104 | text-align: center; 105 | top: -25px; 106 | width: 100%; 107 | } 108 | 109 | .github-iframe { 110 | margin-bottom: -9px; 111 | } 112 | 113 | .tweet, 114 | .tweet > div > div { 115 | display: inline-block 116 | } 117 | 118 | .tweet { 119 | text-decoration: none; 120 | color: #fff; 121 | margin-left: 1em; 122 | } 123 | 124 | .tweet > div { 125 | border-radius: 5px; 126 | transition: 25ms ease-out; 127 | padding: 4px 8px; 128 | background-color: #55acee; 129 | border-color: #55acee; 130 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 131 | } 132 | 133 | .tweet > div:hover, 134 | .tweet > div:active { 135 | background-color: #2795e9; 136 | border-color: #2795e9; 137 | } 138 | 139 | .tweet > div > div { 140 | fill: #fff; 141 | stroke: none; 142 | } 143 | 144 | .tweet svg { 145 | margin-top: -4px; 146 | width: 1em; 147 | height: 1em; 148 | vertical-align: middle; 149 | } 150 | 151 | @media (min-width: 481px) { 152 | body { 153 | padding-top: 0; 154 | } 155 | 156 | h1 small { 157 | display: inline; 158 | } 159 | 160 | h2 { 161 | display: block; 162 | } 163 | 164 | h3 + .col-half, 165 | h3 + .col-half + .col-half { 166 | height: 77px; 167 | top: 0; 168 | } 169 | 170 | h3 + .col-half { 171 | padding-bottom: 0; 172 | } 173 | 174 | .container { 175 | max-width: 740px; 176 | } 177 | 178 | *[data-label]:before { 179 | content: none; 180 | } 181 | 182 | .col-half { 183 | float: left; 184 | width: 50%; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gray 2 | 3 | CSS Styles and jQuery plugin to display images in grayscale.npm version 4 | 5 | #### [Demo](https://karlhorky.github.io/gray/) 6 | 7 | Support: 8 | 9 | - IE 6-11 (10 and 11 use the JavaScript polyfill) 10 | - Edge 12+ (12 uses the JavaScript polyfill) 11 | - Firefox 10+, Firefox on Android 12 | - Chrome 19+, Chrome for Android 25+ 13 | - Android Browser 4.4+ 14 | - Safari 6+, Safari iOS 6+ 15 | - Opera 15+, Opera Mobile 16+ 16 | - BlackBerry Browser 10+ 17 | 18 | ## Installation 19 | 20 | You can install with [npm](https://www.npmjs.com/): 21 | 22 | ```shell 23 | npm install --save jquery-gray 24 | ``` 25 | 26 | Or [Bower](http://bower.io): 27 | 28 | ```shell 29 | bower install --save gray 30 | ``` 31 | 32 | Or use the CDN links: 33 | 34 | ``` 35 | https://npmcdn.com/jquery-gray@1.7.0/css/gray.min.css 36 | https://npmcdn.com/jquery-gray@1.7.0/js/jquery.gray.min.js 37 | ``` 38 | 39 | Or you can just [download](https://github.com/karlhorky/gray/archive/gh-pages.zip) it. 40 | 41 | ## How to Use 42 | 43 | 1. Add the CSS from [gray.css](https://github.com/karlhorky/gray/blob/gh-pages/css/gray.css). 44 | 45 | If you want to use your own CSS selector instead of `.grayscale`, edit or copy the CSS. 46 | 47 | 2. Add the plugin after jQuery at the bottom of the body. 48 | 49 | ```html 50 | 51 | ``` 52 | 53 | The plugin automatically initializes for all elements with a class of `grayscale`. 54 | 55 | The plugin can also be called manually with: 56 | 57 | ```javascript 58 | $('.my-grayscale-class').gray(); 59 | ``` 60 | 61 | The effect can be toggled with the `grayscale-off` class: 62 | 63 | ```javascript 64 | $('.grayscale').toggleClass('grayscale-off'); 65 | ``` 66 | 67 | 3. Add your image with a class of `grayscale`. 68 | 69 | ```html 70 | 71 | ``` 72 | 73 | Images with CSS background-image, background-size and (numeric) background-position are also supported: 74 | 75 | ```html 76 |
87 | ``` 88 | 89 | Non-numeric background-size (cover, contain, ...) and background-position (center, ...) are not currently supported (pull requests welcome!). 90 | 91 | 4. (Optional) Add class of `grayscale-fade` if you want transitioning from grayscale back to color on hover 92 | 93 | ```html 94 | 95 | ``` 96 | 97 | 5. If you are using Modernizr already, make sure that the [required feature detects](https://github.com/karlhorky/gray#modernizr) are included in your build. 98 | 99 | 6. Revel in your absolute and utter awesomeness. 100 | 101 | ## Caveats 102 | 103 | ### Non-numeric background-size and background-position 104 | 105 | Non-numeric background-size (`cover`, `contain`, ...) and background-position (`center`, ...) are not currently supported. 106 | 107 | ### Percentage-based background-position 108 | 109 | Percentage-based background-position (ex. `50% 50%`, ...) is not currently supported. 110 | 111 | ### Non-visible elements will not be correctly initialized 112 | 113 | Calling the plugin on hidden images (or other images that cannot have their size calculated) will fail in polyfill browsers. Workarounds can be found in the discussions at [#57](https://github.com/karlhorky/gray/issues/57#issuecomment-193702953) and [#40](https://github.com/karlhorky/gray/issues/40#issuecomment-136187306). 114 | 115 | ### Child elements removed in browsers without support for CSS filters 116 | 117 | Target elements with child elements will have those child elements removed in browsers without support for CSS filters. [#61](https://github.com/karlhorky/gray/issues/61) 118 | 119 | ### Event listeners removed in browsers without support for CSS filters 120 | 121 | Target elements with event listeners removed in browsers without support for CSS filters. [#65](https://github.com/karlhorky/gray/issues/65) 122 | 123 | ### Colored borders 124 | 125 | Colored borders will be also converted to grayscale in non-polyfill browsers. To also convert to grayscale in polyfill browsers, the class `grayscale-replaced` can be used: 126 | 127 | ```css 128 | .grayscale-replaced { 129 | border-color: #494949 !important; 130 | } 131 | ``` 132 | 133 | ## How it Works 134 | 135 | In [browsers that support css filters](http://caniuse.com/#feat=css-filters), the styles in `gray.css` will use CSS filters to turn the image gray. 136 | 137 | ### Modernizr 138 | 139 | The `jquery.gray` plugin uses the [`Modernizr._prefixes`, `css-filters`, `Inline SVG` and `svg-filters` feature detects](https://modernizr.com/download/?cssfilters-inlinesvg-svgfilters-prefixes-setclasses) from Modernizr to determine browser support. If a browser supports inline SVG and SVG filters but not CSS filters, the plugin replaces the elements with SVG elements with filters. 140 | 141 | ## Changelog 142 | 143 | - v1.7.0: Upgrade Modernizr [#80](https://github.com/karlhorky/gray/issues/80) 144 | - v1.6.0: Throw error when modernizr feature detects not in build [#71](https://github.com/karlhorky/gray/issues/71) [#72](https://github.com/karlhorky/gray/issues/72) 145 | - v1.5.0: Add SVG <title> to polyfill for accessibility ([demo](https://karlhorky.github.io/gray/#img-alt)) 146 | - v1.4.5: Fix sizing of img tags with padding 147 | - v1.4.4: Fix bug with missing padding properties with background images 148 | - v1.4.3: Fix bug with padding on img tag 149 | - v1.4.2: Add Firefox 35+ support, normalize cross-browser rendering 150 | - v1.4.1: Fix bug with `display: none` on parents 151 | - v1.4.0: Add support for programmatic toggling of grayscale 152 | - v1.3.6: Fix image size with resized img tag and grayscale-fade in polyfill 153 | - v1.3.5: Declare variables to fix error in strict mode 154 | - v1.3.4: Don't override existing modernizr 155 | - v1.3.3: Update minified js to match source 156 | - v1.3.2: Remove grayscale on hover in ie6-9 (fade option), use same svg filter in polyfill as in css 157 | - v1.3.1: Bugfix for empty gray class name 158 | - v1.3.0: Rename fade class to grayscale-fade to resolve conflict with bootstrap 159 | - v1.2.0: IE shim: Copy styles from element to replacement element 160 | - v1.1.1: Improve documentation and demo 161 | - v1.1.0: Support for background images with basic background-size and background-position 162 | - v1.0.0: First basic version with support for <img> tags 163 | 164 | ## License 165 | 166 | MIT © Karl Horky 167 | -------------------------------------------------------------------------------- /js/jquery.gray.min.js: -------------------------------------------------------------------------------- 1 | /*! Gray v1.7.0 https://github.com/karlhorky/gray) | MIT */ 2 | /*! Modernizr 2.8.3 (Custom Build) | MIT & BSD */ 3 | if(function(e,t,i){if(!e.Modernizr){var r=[],n=[],s={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var i=this;setTimeout((function(){t(i[e])}),0)},addTest:function(e,t,i){n.push({name:e,fn:t,options:i})},addAsyncTest:function(e){n.push({name:null,fn:e})}},o=s._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):["",""];s._prefixes=o;var a=function(){};a.prototype=s,(a=new a).addTest("svgfilters",(function(){var t=!1;try{t="SVGFEColorMatrixElement"in e&&2==SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE}catch(e){}return t}));var l="CSS"in e&&"supports"in e.CSS,d="supportsCSS"in e;a.addTest("supports",l||d);var u=t.documentElement,f="svg"===u.nodeName.toLowerCase();a.addTest("inlinesvg",(function(){var e=w("div");return e.innerHTML="","http://www.w3.org/2000/svg"==("undefined"!=typeof SVGRect&&e.firstChild&&e.firstChild.namespaceURI)}));var h="Moz O ms Webkit",g=s._config.usePrefixes?h.split(" "):[];s._cssomPrefixes=g;var p=s._config.usePrefixes?h.toLowerCase().split(" "):[];s._domPrefixes=p;var c={elem:w("modernizr")};a._q.push((function(){delete c.elem}));var m={style:c.elem.style};a._q.unshift((function(){delete m.style})),s.testAllProps=k,s.testAllProps=M,a.addTest("cssfilters",(function(){if(a.supports)return M("filter","blur(2px)");var e=w("a");return e.style.cssText=o.join("filter:blur(2px); "),!!e.style.length&&(t.documentMode===i||t.documentMode>9)})),function(){var e,t,i,s,o,l;for(var d in n)if(n.hasOwnProperty(d)){if(e=[],(t=n[d]).name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(i=0;il;l++)if(u=e[l],f=m.style[u],x(u,"-")&&(u=b(u)),m.style[u]!==i){if(n||v(r,"undefined"))return s(),"pfx"!=t||u;try{m.style[u]=r}catch(e){}if(m.style[u]!=f)return s(),"pfx"!=t||u}return s(),!1}function k(e,t,i,r,n){var s=e.charAt(0).toUpperCase()+e.slice(1),o=(e+" "+g.join(s+" ")+s).split(" ");return v(t,"string")||v(t,"undefined")?N(o,t,r,n):function(e,t,i){var r;for(var n in e)if(e[n]in t)return!1===i?e[n]:v(r=t[e[n]],"function")?S(r,i||t):r;return!1}(o=(e+" "+p.join(s+" ")+s).split(" "),t,i)}function M(e,t,r){return k(e,i,i,t,r)}}(window,document),!window.Modernizr._prefixes)throw new Error("jquery-gray: Modernizr._prefixes not set!\n\nPlease add the necessary feature detects:\nhttps://github.com/karlhorky/gray#modernizr");!function(e,t,i,r){var n={fade:!1,classes:{fade:"grayscale-fade"}},s=0;function o(t,i){var r;r=((i=i||{}).classes||{}).fade||n.classes.fade,i.fade=i.fade||t.className.indexOf(r)>-1,this.element=t,this.elementId=s++,this.settings=e.extend({},n,i),this._defaults=n,this._name="gray",this.init()}e.extend(o.prototype,{init:function(){var t;!Modernizr.cssfilters&&Modernizr.inlinesvg&&Modernizr.svgfilters&&(t=e(this.element),(this.cssFilterDeprecated(t)||this.settings.fade)&&this.switchImage(t))},cssFilterDeprecated:function(e){return"none"===e.css("filter")},elementType:function(e){return"IMG"===e.prop("tagName")?"Img":"Bg"},pxToNumber:function(e){return parseInt(e.replace("px",""))},getComputedStyle:function(e){for(var i={},r={},n=0,s=(i=t.getComputedStyle(e,null)).length;n')},switchImage:function(t){var i,r,n,s,o,a;r=this["get"+(i=this.elementType(t))+"Params"](t),n=this.settings.fade?this.settings.classes.fade:"",s=t[0].alt?' aria-labelledby="gray-title-'+this.elementId+'"':"",o=t[0].alt?''+t[0].alt+"":"",a=e('
"+o+'
'),r.styles=this.setStyles(i,r.styles,r.svg,r.image),a.css(r.styles),this.addSVGFilterOnce(),t.replaceWith(a)}}),e.fn.gray=function(t){return this.each((function(){e.data(this,"plugin_gray")||e.data(this,"plugin_gray",new o(this,t))})),this},e(t).on("load",(function(){e(".grayscale:not(.grayscale-replaced)").gray()}))}(jQuery,window,document) 4 | -------------------------------------------------------------------------------- /css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined in IE 8/9. 28 | */ 29 | 30 | article, 31 | aside, 32 | details, 33 | figcaption, 34 | figure, 35 | footer, 36 | header, 37 | hgroup, 38 | main, 39 | nav, 40 | section, 41 | summary { 42 | display: block; 43 | } 44 | 45 | /** 46 | * 1. Correct `inline-block` display not defined in IE 8/9. 47 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 48 | */ 49 | 50 | audio, 51 | canvas, 52 | progress, 53 | video { 54 | display: inline-block; /* 1 */ 55 | vertical-align: baseline; /* 2 */ 56 | } 57 | 58 | /** 59 | * Prevent modern browsers from displaying `audio` without controls. 60 | * Remove excess height in iOS 5 devices. 61 | */ 62 | 63 | audio:not([controls]) { 64 | display: none; 65 | height: 0; 66 | } 67 | 68 | /** 69 | * Address `[hidden]` styling not present in IE 8/9. 70 | * Hide the `template` element in IE, Safari, and Firefox < 22. 71 | */ 72 | 73 | [hidden], 74 | template { 75 | display: none; 76 | } 77 | 78 | /* Links 79 | ========================================================================== */ 80 | 81 | /** 82 | * Remove the gray background color from active links in IE 10. 83 | */ 84 | 85 | a { 86 | background: transparent; 87 | } 88 | 89 | /** 90 | * Improve readability when focused and also mouse hovered in all browsers. 91 | */ 92 | 93 | a:active, 94 | a:hover { 95 | outline: 0; 96 | } 97 | 98 | /* Text-level semantics 99 | ========================================================================== */ 100 | 101 | /** 102 | * Address styling not present in IE 8/9, Safari 5, and Chrome. 103 | */ 104 | 105 | abbr[title] { 106 | border-bottom: 1px dotted; 107 | } 108 | 109 | /** 110 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 111 | */ 112 | 113 | b, 114 | strong { 115 | font-weight: bold; 116 | } 117 | 118 | /** 119 | * Address styling not present in Safari 5 and Chrome. 120 | */ 121 | 122 | dfn { 123 | font-style: italic; 124 | } 125 | 126 | /** 127 | * Address variable `h1` font-size and margin within `section` and `article` 128 | * contexts in Firefox 4+, Safari 5, and Chrome. 129 | */ 130 | 131 | h1 { 132 | font-size: 2em; 133 | margin: 0.67em 0; 134 | } 135 | 136 | /** 137 | * Address styling not present in IE 8/9. 138 | */ 139 | 140 | mark { 141 | background: #ff0; 142 | color: #000; 143 | } 144 | 145 | /** 146 | * Address inconsistent and variable font size in all browsers. 147 | */ 148 | 149 | small { 150 | font-size: 80%; 151 | } 152 | 153 | /** 154 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 155 | */ 156 | 157 | sub, 158 | sup { 159 | font-size: 75%; 160 | line-height: 0; 161 | position: relative; 162 | vertical-align: baseline; 163 | } 164 | 165 | sup { 166 | top: -0.5em; 167 | } 168 | 169 | sub { 170 | bottom: -0.25em; 171 | } 172 | 173 | /* Embedded content 174 | ========================================================================== */ 175 | 176 | /** 177 | * Remove border when inside `a` element in IE 8/9. 178 | */ 179 | 180 | img { 181 | border: 0; 182 | } 183 | 184 | /** 185 | * Correct overflow displayed oddly in IE 9. 186 | */ 187 | 188 | svg:not(:root) { 189 | overflow: hidden; 190 | } 191 | 192 | /* Grouping content 193 | ========================================================================== */ 194 | 195 | /** 196 | * Address margin not present in IE 8/9 and Safari 5. 197 | */ 198 | 199 | figure { 200 | margin: 1em 40px; 201 | } 202 | 203 | /** 204 | * Address differences between Firefox and other browsers. 205 | */ 206 | 207 | hr { 208 | -moz-box-sizing: content-box; 209 | box-sizing: content-box; 210 | height: 0; 211 | } 212 | 213 | /** 214 | * Contain overflow in all browsers. 215 | */ 216 | 217 | pre { 218 | overflow: auto; 219 | } 220 | 221 | /** 222 | * Address odd `em`-unit font size rendering in all browsers. 223 | */ 224 | 225 | code, 226 | kbd, 227 | pre, 228 | samp { 229 | font-family: monospace, monospace; 230 | font-size: 1em; 231 | } 232 | 233 | /* Forms 234 | ========================================================================== */ 235 | 236 | /** 237 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 238 | * styling of `select`, unless a `border` property is set. 239 | */ 240 | 241 | /** 242 | * 1. Correct color not being inherited. 243 | * Known issue: affects color of disabled elements. 244 | * 2. Correct font properties not being inherited. 245 | * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. 246 | */ 247 | 248 | button, 249 | input, 250 | optgroup, 251 | select, 252 | textarea { 253 | color: inherit; /* 1 */ 254 | font: inherit; /* 2 */ 255 | margin: 0; /* 3 */ 256 | } 257 | 258 | /** 259 | * Address `overflow` set to `hidden` in IE 8/9/10. 260 | */ 261 | 262 | button { 263 | overflow: visible; 264 | } 265 | 266 | /** 267 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 268 | * All other form control elements do not inherit `text-transform` values. 269 | * Correct `button` style inheritance in Firefox, IE 8+, and Opera 270 | * Correct `select` style inheritance in Firefox. 271 | */ 272 | 273 | button, 274 | select { 275 | text-transform: none; 276 | } 277 | 278 | /** 279 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 280 | * and `video` controls. 281 | * 2. Correct inability to style clickable `input` types in iOS. 282 | * 3. Improve usability and consistency of cursor style between image-type 283 | * `input` and others. 284 | */ 285 | 286 | button, 287 | html input[type="button"], /* 1 */ 288 | input[type="reset"], 289 | input[type="submit"] { 290 | -webkit-appearance: button; /* 2 */ 291 | cursor: pointer; /* 3 */ 292 | } 293 | 294 | /** 295 | * Re-set default cursor for disabled elements. 296 | */ 297 | 298 | button[disabled], 299 | html input[disabled] { 300 | cursor: default; 301 | } 302 | 303 | /** 304 | * Remove inner padding and border in Firefox 4+. 305 | */ 306 | 307 | button::-moz-focus-inner, 308 | input::-moz-focus-inner { 309 | border: 0; 310 | padding: 0; 311 | } 312 | 313 | /** 314 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 315 | * the UA stylesheet. 316 | */ 317 | 318 | input { 319 | line-height: normal; 320 | } 321 | 322 | /** 323 | * It's recommended that you don't attempt to style these elements. 324 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 325 | * 326 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 327 | * 2. Remove excess padding in IE 8/9/10. 328 | */ 329 | 330 | input[type="checkbox"], 331 | input[type="radio"] { 332 | box-sizing: border-box; /* 1 */ 333 | padding: 0; /* 2 */ 334 | } 335 | 336 | /** 337 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 338 | * `font-size` values of the `input`, it causes the cursor style of the 339 | * decrement button to change from `default` to `text`. 340 | */ 341 | 342 | input[type="number"]::-webkit-inner-spin-button, 343 | input[type="number"]::-webkit-outer-spin-button { 344 | height: auto; 345 | } 346 | 347 | /** 348 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 349 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome 350 | * (include `-moz` to future-proof). 351 | */ 352 | 353 | input[type="search"] { 354 | -webkit-appearance: textfield; /* 1 */ 355 | -moz-box-sizing: content-box; 356 | -webkit-box-sizing: content-box; /* 2 */ 357 | box-sizing: content-box; 358 | } 359 | 360 | /** 361 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 362 | * Safari (but not Chrome) clips the cancel button when the search input has 363 | * padding (and `textfield` appearance). 364 | */ 365 | 366 | input[type="search"]::-webkit-search-cancel-button, 367 | input[type="search"]::-webkit-search-decoration { 368 | -webkit-appearance: none; 369 | } 370 | 371 | /** 372 | * Define consistent border, margin, and padding. 373 | */ 374 | 375 | fieldset { 376 | border: 1px solid #c0c0c0; 377 | margin: 0 2px; 378 | padding: 0.35em 0.625em 0.75em; 379 | } 380 | 381 | /** 382 | * 1. Correct `color` not being inherited in IE 8/9. 383 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 384 | */ 385 | 386 | legend { 387 | border: 0; /* 1 */ 388 | padding: 0; /* 2 */ 389 | } 390 | 391 | /** 392 | * Remove default vertical scrollbar in IE 8/9. 393 | */ 394 | 395 | textarea { 396 | overflow: auto; 397 | } 398 | 399 | /** 400 | * Don't inherit the `font-weight` (applied by a rule above). 401 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 402 | */ 403 | 404 | optgroup { 405 | font-weight: bold; 406 | } 407 | 408 | /* Tables 409 | ========================================================================== */ 410 | 411 | /** 412 | * Remove most spacing between table cells. 413 | */ 414 | 415 | table { 416 | border-collapse: collapse; 417 | border-spacing: 0; 418 | } 419 | 420 | td, 421 | th { 422 | padding: 0; 423 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Gray 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 |
18 |

Gray by Karl Horky

19 | 20 |

Make an image gray in all browsers.

21 | 22 | 30 | 31 | 37 |
38 | 56 | Tweet 57 |
58 |
59 | 60 |
61 |
62 |

Color

63 |
64 |
65 |

Gray

66 |
67 |
68 | 69 |
70 |

71 | <img> tag 72 |

73 | 74 |
75 | 76 |
77 |
78 | 79 |
80 |
81 | 82 |
83 |
84 |
<img src="img/color.jpg" class="grayscale">
85 |
86 |
87 | 88 |
89 |

90 | <img> tag with transition 91 |

92 | 93 |
94 | 95 |
96 |
97 | 98 |
99 |
100 | 101 |
102 |
103 |
<img src="img/color.jpg" class="grayscale grayscale-fade">
104 |
105 |
106 | 107 |
108 |

109 | <img> tag with alt 110 |

111 | 112 |
113 | Decorative lights 114 |
115 |
116 | Decorative lights 117 |
118 |
119 | 120 |
121 |
122 |
<img src="img/color.jpg" class="grayscale" alt="Decorative lights">
123 |
124 |
125 | 126 |
127 |

128 | <img> tag with styles 129 |

130 | 131 |
132 | 143 |
144 |
145 | 157 |
158 |
159 | 160 |
161 |
162 |
<img src="img/color.jpg" class="grayscale" style="
163 |   position  : absolute;
164 |   top       : 0;
165 |   left      : 50%;
166 |   margin    : 0 0 0 -90px;
167 |   padding   : 5px;
168 |   border    : 1px solid #ddd;
169 | ">
170 |
171 |
172 | 173 |
174 |

175 | CSS background 176 |

177 | 178 |
179 |
187 |
188 |
189 |
198 |
199 |
200 | 201 |
202 |
203 |
<div style="
204 |   background-image: url(img/color.jpg);
205 |   display         : inline-block;
206 |   width           : 180px;
207 |   height          : 72px;
208 | " class="grayscale"></div>
209 |
210 |
211 | 212 |
213 |

214 | CSS sprite background 215 |

216 | 217 |
218 |
227 |
228 |
229 |
239 |
240 |
241 | 242 |
243 |
244 |
<div style="
245 |   background-image   : url(img/color-sprite.jpg);
246 |   background-position: -180px 0;
247 |   display            : inline-block;
248 |   width              : 180px;
249 |   height             : 72px;
250 | " class="grayscale"></div>
251 |
252 |
253 | 254 |
255 |

256 | 257 | CSS sprite background with background-size 258 | 259 |

260 | 261 |
262 |
272 |
273 |
274 |
285 |
286 |
287 | 288 |
289 |
290 |
<div style="
291 |   background-image   : url(img/color-sprite-lg.jpg);
292 |   background-size    : auto 72px;
293 |   background-position: -180px 0;
294 |   display            : inline-block;
295 |   width              : 180px;
296 |   height             : 72px;
297 | " class="grayscale"></div>
298 |
299 |
300 | 301 |
302 |

303 | Toggling Grayscale 304 |

305 | 306 | 309 |
310 | 311 |
312 |
313 |
$('.grayscale').toggleClass('grayscale-off');
314 |
315 |
316 |
317 | 318 | Fork me on GitHub 324 | 325 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | -------------------------------------------------------------------------------- /js/jquery.gray.js: -------------------------------------------------------------------------------- 1 | /*! Gray v1.7.0 https://github.com/karlhorky/gray) | MIT */ 2 | /*! modernizr 3.6.0 (Custom Build) | MIT * 3 | * https://modernizr.com/download/?-cssfilters-inlinesvg-svgfilters-prefixes-setclasses !*/ 4 | !function(e,n,t){if(e.Modernizr)return;function r(e,n){return typeof e===n}function s(){var e,n,t,s,o,i,l;for(var a in S)if(S.hasOwnProperty(a)){if(e=[],n=S[a],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;tp;p++)if(m=e[p],g=j.style[m],l(m,"-")&&(m=a(m)),j.style[m]!==t){if(o||r(s,"undefined"))return u(),"pfx"==n?m:!0;try{j.style[m]=s}catch(h){}if(j.style[m]!=g)return u(),"pfx"==n?m:!0}return u(),!1}function y(e,n,t,s,o){var i=e.charAt(0).toUpperCase()+e.slice(1),l=(e+" "+z.join(i+" ")+i).split(" ");return r(n,"string")||r(n,"undefined")?g(l,n,s,o):(l=(e+" "+A.join(i+" ")+i).split(" "),f(l,n,t))}function h(e,n,r){return y(e,t,t,n,r)}var C=[],S=[],w={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var t=this;setTimeout(function(){n(t[e])},0)},addTest:function(e,n,t){S.push({name:e,fn:n,options:t})},addAsyncTest:function(e){S.push({name:null,fn:e})}},_=w._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):["",""];w._prefixes=_;var Modernizr=function(){};Modernizr.prototype=w,Modernizr=new Modernizr,Modernizr.addTest("svgfilters",function(){var n=!1;try{n="SVGFEColorMatrixElement"in e&&2==SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE}catch(t){}return n});var x="CSS"in e&&"supports"in e.CSS,E="supportsCSS"in e;Modernizr.addTest("supports",x||E);var T=n.documentElement,b="svg"===T.nodeName.toLowerCase();Modernizr.addTest("inlinesvg",function(){var e=i("div");return e.innerHTML="","http://www.w3.org/2000/svg"==("undefined"!=typeof SVGRect&&e.firstChild&&e.firstChild.namespaceURI)});var P="Moz O ms Webkit",z=w._config.usePrefixes?P.split(" "):[];w._cssomPrefixes=z;var A=w._config.usePrefixes?P.toLowerCase().split(" "):[];w._domPrefixes=A;var N={elem:i("modernizr")};Modernizr._q.push(function(){delete N.elem});var j={style:N.elem.style};Modernizr._q.unshift(function(){delete j.style}),w.testAllProps=y,w.testAllProps=h,Modernizr.addTest("cssfilters",function(){if(Modernizr.supports)return h("filter","blur(2px)");var e=i("a");return e.style.cssText=_.join("filter:blur(2px); "),!!e.style.length&&(n.documentMode===t||n.documentMode>9)}),s(),o(C),delete w.addTest,delete w.addAsyncTest;for(var M=0;M -1; 31 | 32 | this.element = element; 33 | this.elementId = id++; 34 | this.settings = $.extend({}, defaults, options); 35 | this._defaults = defaults; 36 | this._name = pluginName; 37 | this.init(); 38 | } 39 | 40 | $.extend(Plugin.prototype, { 41 | 42 | init: function () { 43 | var element; 44 | 45 | if (!Modernizr.cssfilters && 46 | Modernizr.inlinesvg && 47 | Modernizr.svgfilters 48 | ) { 49 | element = $(this.element); 50 | 51 | if (this.cssFilterDeprecated(element) || this.settings.fade) { 52 | this.switchImage(element); 53 | } 54 | } 55 | }, 56 | 57 | // TODO: Test a freshly made element (modernizr feature test?) 58 | // instead of testing the active element (fragile) 59 | cssFilterDeprecated: function(element) { 60 | return element.css('filter') === 'none'; 61 | }, 62 | 63 | elementType: function(element) { 64 | return element.prop('tagName') === 'IMG' ? 'Img' : 'Bg'; 65 | }, 66 | 67 | pxToNumber: function(pxString) { 68 | return parseInt(pxString.replace('px', '')); 69 | }, 70 | 71 | getComputedStyle: function(element) { 72 | var computedStyle = {}, 73 | styles = {}; 74 | 75 | computedStyle = window.getComputedStyle(element, null); 76 | 77 | for(var i = 0, length = computedStyle.length; i < length; i++) { 78 | var prop = computedStyle[i]; 79 | var val = computedStyle.getPropertyValue(prop); 80 | styles[prop] = val; 81 | } 82 | 83 | return styles; 84 | }, 85 | 86 | extractUrl: function(backgroundImage) { 87 | var url, 88 | regex; 89 | 90 | startRegex = /^url\(["']?/; 91 | endRegex = /["']?\)$/; 92 | url = backgroundImage.replace(startRegex, '') 93 | .replace(endRegex, ''); 94 | 95 | return url; 96 | }, 97 | 98 | positionToNegativeMargin: function(backgroundPosition) { 99 | var x, 100 | y, 101 | margin; 102 | 103 | x = backgroundPosition.match(/^(-?\d+\S+)/)[0]; 104 | y = backgroundPosition.match(/\s(-?\d+\S+)$/)[0]; 105 | 106 | margin = 'margin:' + y + ' 0 0 ' + x; 107 | 108 | return margin; 109 | }, 110 | 111 | getBgSize: function(url, backgroundSize) { 112 | var img, 113 | ratio, 114 | defaultW, 115 | w, 116 | defaultH, 117 | h, 118 | size; 119 | 120 | img = new Image(); 121 | img.src = url; 122 | 123 | // TODO: Break this up or simplify 124 | if (backgroundSize !== 'auto' && backgroundSize !== 'cover' && backgroundSize !== 'contain' && backgroundSize !== 'inherit') { 125 | var $element = $(this.element); 126 | 127 | ratio = img.width / img.height; 128 | w = parseInt((backgroundSize.match(/^(\d+)px/) || [0,0])[1]); 129 | h = parseInt((backgroundSize.match(/\s(\d+)px$/) || [0,0])[1]); 130 | defaultW = $element.height() * ratio; 131 | defaultH = $element.width() / ratio; 132 | w = w || defaultW; 133 | h = h || defaultH; 134 | } 135 | 136 | if (w || h) { 137 | size = { 138 | width: w, 139 | height: h 140 | }; 141 | } else { 142 | size = { 143 | width : img.width, 144 | height: img.height 145 | }; 146 | } 147 | 148 | return size; 149 | }, 150 | 151 | getImgParams: function(element) { 152 | var params = {}; 153 | 154 | params.styles = this.getComputedStyle(element[0]); 155 | 156 | var padding = { 157 | top : this.pxToNumber(params.styles['padding-top']), 158 | right : this.pxToNumber(params.styles['padding-right']), 159 | bottom: this.pxToNumber(params.styles['padding-bottom']), 160 | left : this.pxToNumber(params.styles['padding-left']) 161 | }; 162 | 163 | var borderWidth = { 164 | top : this.pxToNumber(params.styles['border-top-width']), 165 | right : this.pxToNumber(params.styles['border-right-width']), 166 | bottom: this.pxToNumber(params.styles['border-bottom-width']), 167 | left : this.pxToNumber(params.styles['border-left-width']) 168 | }; 169 | 170 | params.image = { 171 | width : this.pxToNumber(params.styles.width), 172 | height: this.pxToNumber(params.styles.height) 173 | }; 174 | 175 | params.svg = { 176 | url : element[0].src, 177 | padding : padding, 178 | borderWidth: borderWidth, 179 | width: 180 | params.image.width + 181 | padding.left + 182 | padding.right + 183 | borderWidth.left + 184 | borderWidth.right, 185 | height: 186 | params.image.height + 187 | padding.top + 188 | padding.bottom + 189 | borderWidth.top + 190 | borderWidth.bottom, 191 | offset: '' 192 | }; 193 | 194 | return params; 195 | }, 196 | 197 | getBgParams: function(element) { 198 | var params = {}, 199 | url, 200 | position; 201 | 202 | url = this.extractUrl(element.css('background-image')); 203 | bgSize = this.getBgSize(url, element.css('background-size')); 204 | offset = this.positionToNegativeMargin(element.css('background-position')); 205 | 206 | params.styles = this.getComputedStyle(element[0]); 207 | 208 | params.svg = $.extend( 209 | { url : url }, 210 | bgSize, 211 | { offset: offset } 212 | ); 213 | 214 | params.image = { 215 | width : params.svg.width, 216 | height: params.svg.height 217 | }; 218 | 219 | return params; 220 | }, 221 | 222 | setStyles: function(type, styles, svg, image) { 223 | styles.display = 'inline-block'; 224 | styles.overflow = 225 | styles['overflow-x'] = 226 | styles['overflow-y'] = 'hidden'; 227 | styles['background-image'] = 'url("' + svg.url + '")'; 228 | styles['background-size'] = image.width + 'px ' + image.height + 'px'; 229 | 230 | if (type === 'Img') { 231 | styles['background-repeat'] = 'no-repeat'; 232 | styles['background-position'] = svg.padding.left + 'px ' + svg.padding.top + 'px'; 233 | styles.width = svg.width; 234 | styles.height = svg.height; 235 | } 236 | 237 | delete styles.filter; 238 | 239 | return styles; 240 | }, 241 | 242 | // TODO: Run this outside of the plugin so that it's not run 243 | // on every element 244 | addSVGFilterOnce: function() { 245 | $body = $('body'); 246 | if (!$body.data('plugin_' + pluginName + '_has_filter')) { 247 | $body.data('plugin_' + pluginName + '_has_filter', 'true') 248 | .append(''); 249 | } 250 | }, 251 | 252 | switchImage: function(element) { 253 | var type, 254 | params, 255 | classes, 256 | labelledby, 257 | title, 258 | template; 259 | 260 | type = this.elementType(element); 261 | params = this['get' + type + 'Params'](element); 262 | 263 | classes = this.settings.fade ? this.settings.classes.fade : ''; 264 | 265 | labelledby = element[0].alt ? 266 | ' aria-labelledby="gray-title-' + this.elementId + '"' : 267 | ''; 268 | 269 | title = element[0].alt ? 270 | '' + element[0].alt + '' : 271 | ''; 272 | 273 | template = $( 274 | '
' + 275 | '' + 276 | title + 277 | '' + 278 | '' + 279 | '
'); 280 | 281 | params.styles = this.setStyles(type, params.styles, params.svg, params.image); 282 | 283 | // TODO: Should this really set all params or should we set only unique ones by comparing to a control element? 284 | template.css(params.styles); 285 | 286 | this.addSVGFilterOnce(); 287 | element.replaceWith(template); 288 | } 289 | }); 290 | 291 | $.fn[pluginName] = function (options) { 292 | this.each(function() { 293 | if (!$.data(this, 'plugin_' + pluginName)) { 294 | $.data(this, 'plugin_' + pluginName, new Plugin(this, options)); 295 | } 296 | }); 297 | return this; 298 | }; 299 | 300 | $(window).on('load', function() { 301 | $('.grayscale:not(.grayscale-replaced)')[pluginName](); 302 | }); 303 | 304 | })(jQuery, window, document); 305 | --------------------------------------------------------------------------------