1/** 2 * 3 * Version: 0.0.6 4 * Author: Gianluca Guarini 5 * Contact: [email protected] 6 * Website: http://www.gianlucaguarini.com/ 7 * Twitter: @gianlucaguarini 8 * 9 * Copyright (c) Gianluca Guarini 10 * 11 * Permission is hereby granted, free of charge, to any person 12 * obtaining a copy of this software and associated documentation 13 * files (the "Software"), to deal in the Software without 14 * restriction, including without limitation the rights to use, 15 * copy, modify, merge, publish, distribute, sublicense, and/or sell 16 * copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following 18 * conditions: 19 * 20 * The above copyright notice and this permission notice shall be 21 * included in all copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 25 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 27 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 * OTHER DEALINGS IN THE SOFTWARE. 31 **/ 32 33 34(function(window, document, $) { 35 'use strict'; 36 37 // Plugin private cache 38 // static vars 39 var cache = { 40 filterId: 0 41 }, 42 $body = $('body'); 43 44 var Vague = function(elm, customOptions) { 45 // Default options 46 var defaultOptions = { 47 intensity: 5, 48 forceSVGUrl: false, 49 animationOptions: { 50 duration: 1000, 51 easing: 'linear' 52 } 53 }, 54 // extend the default options with the ones passed to the plugin 55 options = $.extend(defaultOptions, customOptions), 56 57 /* 58 * 59 * Helpers 60 * 61 */ 62 63 _browserPrefixes = ' -webkit- -moz- -o- -ms- '.split(' '), 64 _cssPrefixString = {}, 65 _cssPrefix = function(property) { 66 if (_cssPrefixString[property] || _cssPrefixString[property] === '') return _cssPrefixString[property] + property; 67 var e = document.createElement('div'); 68 var prefixes = ['', 'Moz', 'Webkit', 'O', 'ms', 'Khtml']; // Various supports... 69 for (var i in prefixes) { 70 if (typeof e.style[prefixes[i] + property] !== 'undefined') { 71 _cssPrefixString[property] = prefixes[i]; 72 return prefixes[i] + property; 73 } 74 } 75 return property.toLowerCase(); 76 }, 77 // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css-filters.js 78 _support = { 79 cssfilters: function() { 80 var el = document.createElement('div'); 81 el.style.cssText = _browserPrefixes.join('filter' + ':blur(2px); '); 82 return !!el.style.length && ((document.documentMode === undefined || document.documentMode > 9)); 83 }(), 84 85 // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/svg-filters.js 86 svgfilters: function() { 87 var result = false;
88 try { 89 result = typeof SVGFEColorMatrixElement !== undefined && 90 SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE == 2; 91 } catch (e) {} 92 return result; 93 }() 94 }, 95 96 /* 97 * 98 * PRIVATE VARS 99 * 100 */ 101 102 _blurred = false, 103 // cache the right prefixed css filter property 104 _cssFilterProp = _cssPrefix('Filter'), 105 _svgGaussianFilter, 106 _filterId, 107 // to cache the jquery animation instance 108 _animation, 109 110 /* 111 * 112 * PRIVATE METHODS 113 * 114 */ 115 116 /** 117 * Create any svg element 118 * @param { String } tagName: svg tag name 119 * @return { SVG Node } 120 */ 121 122 _createSvgElement = function(tagName) { 123 return document.createElementNS('http://www.w3.org/2000/svg', tagName); 124 }, 125 126 /** 127 * 128 * Inject the svg tag into the DOM 129 * we will use it only if the css filters are not supported 130 * 131 */ 132 133 _appendSVGFilter = function() { 134 // create the svg and the filter tags 135 var svg = _createSvgElement('svg'), 136 filter = _createSvgElement('filter'); 137 138 // cache the feGaussianBlur tag and make it available 139 // outside of this function to easily update the blur intensity 140 _svgGaussianFilter = _createSvgElement('feGaussianBlur'); 141 142 // hide the svg tag 143 // we don't want to see it into the DOM! 144 svg.setAttribute('style', 'position:absolute'); 145 svg.setAttribute('width', '0'); 146 svg.setAttribute('height', '0'); 147 // set the id that will be used as link between the DOM element to blur and the svg just created
148 filter.setAttribute('id', 'blur-effect-id-' + cache.filterId); 149 150 filter.appendChild(_svgGaussianFilter); 151 svg.appendChild(filter); 152 // append the svg into the body 153 $body.append(svg); 154 155 }; 156 157 /* 158 * 159 * PUBLIC VARS 160 * 161 */ 162 163 // cache the DOM element to blur 164 this.$elm = elm instanceof $ ? elm : $(elm); 165 166 167 /* 168 * 169 * PUBLIC METHODS 170 * 171 */ 172 173 /** 174 * 175 * Initialize the plugin creating a new svg if necessary 176 * 177 */ 178 179 this.init = function() { 180 // checking the css filter feature 181 if (_support.svgfilters) { 182 _appendSVGFilter(); 183 } 184 // cache the filter id 185 _filterId = cache.filterId; 186 // increment the filter id static var 187 cache.filterId++; 188 189 return this; 190 191 }; 192 193 /** 194 * 195 * Blur the DOM element selected 196 * 197 */ 198 199 this.blur = function() { 200 201 var cssFilterValue, 202 // variables needed to force the svg filter URL 203 loc = window.location, 204 svgUrl = options.forceSVGUrl ? loc.protocol + '//' + loc.host + loc.pathname + loc.search : ''; 205 206 // use the css filters if supported 207 if (_support.cssfilters) { 208 cssFilterValue = 'blur(' + options.intensity + 'px)'; 209 // .. or use the svg filters 210 } else if (_support.svgfilters) { 211 // update the svg stdDeviation tag to set up the blur intensity 212 _svgGaussianFilter.setAttribute('stdDeviation', options.intensity); 213 cssFilterValue = 'url(' + svgUrl + '#blur-effect-id-' + _filterId + ')'; 214 } else { 215 // .. use the IE css filters 216 cssFilterValue = 'progid:DXImageTransform.Microsoft.Blur(pixelradius=' + options.intensity + ')'; 217 } 218 219 // update the DOM element css 220 this.$elm[0].style[_cssFilterProp] = cssFilterValue; 221 // set the _blurred internal var to true to cache the element current status 222 _blurred = true; 223 224 return this; 225 }; 226 227 228 /** 229 * Animate the blur intensity 230 * @param { Int } newIntensity: new blur intensity value 231 * @param { Object } customAnimationOptions: default jQuery animate options 232 */ 233 234 this.animate = function(newIntensity, customAnimationOptions) { 235 // control the new blur intensity checking if it's a valid value 236 if (typeof newIntensity !== 'number') { 237 throw (typeof newIntensity + ' is not a valid number to animate the blur'); 238 } else if (newIntensity < 0) { 239 throw ('I can animate only positive numbers'); 240 } 241 // create a new jQuery deferred instance 242 var dfr = new $.Deferred(); 243 244 // kill the previous animation 245 if (_animation) { 246 _animation.stop(true, true); 247 } 248 249 // trigger the animation using the jQuery Animation class 250 _animation = new $.Animation(options, { 251 intensity: newIntensity 252 }, $.extend(options.animationOptions, customAnimationOptions)) 253 .progress($.proxy(this.blur, this)) 254 .done(dfr.resolve); 255 256 // return the animation deferred promise 257 return dfr.promise(); 258 }; 259 260 /** 261 * 262 * Unblur the DOM element 263 * 264 */ 265 this.unblur = function() { 266 // set the DOM filter property to none 267 this.$elm.css(_cssFilterProp, 'none'); 268 _blurred = false; 269 return this; 270 }; 271 272 /** 273 * 274 * Trigger alternatively the @blur and @unblur methods 275 * 276 */ 277 278 this.toggleblur = function() { 279 if (_blurred) { 280 this.unblur(); 281 } else { 282 this.blur(); 283 } 284 return this; 285 }; 286 /** 287 * Destroy the Vague.js instance removing also the svg filter injected into the DOM 288 */ 289 this.destroy = function() { 290 // do we need to remove the svg filter? 291 if (_support.svgfilters) { 292 $('filter#blur-effect-id-' + _filterId).parent().remove(); 293 } 294 295 this.unblur(); 296 297 // clear all the property stored into this Vague.js instance 298 for (var prop in this) { 299 delete this[prop]; 300 } 301 302 return this; 303 }; 304 // init the plugin 305 return this.init(); 306 }; 307 308 // export the plugin as a jQuery function 309 $.fn.Vague = function(options) { 310 return new Vague(this, options); 311 }; 312 313}(window, document, jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.