1/** 2 * 3 * Version: 0.2.9 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(function($) { 33 $.fn.extend({ 34 BlackAndWhite: function(options) { 35 'use strict'; 36 var $container = this, 37 defaults = { 38 hoverEffect: true, 39 webworkerPath: false, 40 responsive: true, 41 invertHoverEffect: false, 42 speed: 500, 43 onImageReady: null, 44 intensity: 1 45 }; 46 options = $.extend(defaults, options); 47 48 /** 49 * 50 * Public vars 51 * 52 */ 53 var hoverEffect = options.hoverEffect, 54 webworkerPath = options.webworkerPath, 55 invertHoverEffect = options.invertHoverEffect, 56 responsive = options.responsive, 57 intensity = (typeof options.intensity === 'number' && options.intensity < 1 && options.intensity > 0) ? options.intensity : 1, 58 fadeSpeedIn = $.isPlainObject(options.speed) ? options.speed.fadeIn : options.speed, 59 fadeSpeedOut = $.isPlainObject(options.speed) ? options.speed.fadeOut : options.speed; 60 61 var isIE7 = (document.all && !window.opera && window.XMLHttpRequest) ? true : false; 62 63 /* 64 * 65 * features detection 66 * 67 */ 68 69 var browserPrefixes = ' -webkit- -moz- -o- -ms- '.split(' '); 70 71 var cssPrefixString = {}; 72 var cssPrefix = function(property) { 73 if (cssPrefixString[property] || cssPrefixString[property] === '') return cssPrefixString[property] + property; 74 var e = document.createElement('div'); 75 var prefixes = ['', 'Moz', 'Webkit', 'O', 'ms', 'Khtml']; // Various supports... 76 for (var i in prefixes) { 77 if (typeof e.style[prefixes[i] + property] !== 'undefined') { 78 cssPrefixString[property] = prefixes[i]; 79 return prefixes[i] + property; 80 } 81 } 82 return property.toLowerCase(); 83 }; 84 85 86 // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css-filters.js 87 var cssfilters = function() { 88 var el = document.createElement('div'); 89 el.style.cssText = browserPrefixes.join('filter' + ':blur(2px); '); 90 return !!el.style.length && ((document.documentMode === undefined || document.documentMode > 9)); 91 }(); 92 /** 93 * 94 * Private vars 95 * 96 */ 97 var supportsCanvas = !! document.createElement('canvas').getContext, 98 $window = $(window), 99 /* Check if Web Workers are supported */ 100 supportWebworker = (function() { 101 return (typeof(Worker) !== "undefined") ? true : false; 102 }()), 103 cssFilter = cssPrefix('Filter'), 104 imagesArray = [], 105 BnWWorker = supportWebworker && webworkerPath ? new Worker(webworkerPath + "BnWWorker.js") : false; 106 107 /** 108 * 109 * Private methods 110 * 111 */ 112 var _onMouseLeave = function(e) { 113 $(e.currentTarget).find('.BWfade').stop(true, true)[!invertHoverEffect ? 'fadeIn' : 'fadeOut'](fadeSpeedOut); 114 }; 115 var _onMouseEnter = function(e) { 116 $(e.currentTarget).find('.BWfade').stop(true, true)[invertHoverEffect ? 'fadeIn' : 'fadeOut'](fadeSpeedIn); 117 }; 118 var _onImageReady = function(img) { 119 if (typeof options.onImageReady === 'function') 120 options.onImageReady(img); 121 };
122 // Loop all the images converting them by the webworker (this process is unobstrusive and it does not block the page loading) 123 var _webWorkerLoop = function() { 124 if (!imagesArray.length) { 125 // terminate the worker 126 // the standard way - http://www.w3.org/TR/workers/#dedicated-workers-and-the-worker-interface 127 if (BnWWorker.terminate) 128 BnWWorker.terminate(); 129 // IE 10 specific - http://msdn.microsoft.com/en-us/library/ie/hh673568(v=vs.85).aspx 130 if (BnWWorker.close) 131 BnWWorker.close(); 132 return; 133 } 134 135 BnWWorker.postMessage({ 136 imgData: imagesArray[0].imageData, 137 intensity: intensity 138 }); 139 140 BnWWorker.onmessage = function(event) { 141 imagesArray[0].ctx.putImageData(event.data, 0, 0); 142 _onImageReady(imagesArray[0].img); 143 imagesArray.splice(0, 1); 144 _webWorkerLoop(); 145 }; 146 }; 147 //convert any image into B&W using HTML5 canvas 148 var _manipulateImage = function(img, canvas, width, height) { 149 var ctx = canvas.getContext('2d'), 150 currImg = img, 151 i = 0, 152 grey; 153 154 ctx.drawImage(img, 0, 0, width, height); 155 156 var imageData = ctx.getImageData(0, 0, width, height), 157 px = imageData.data, 158 length = px.length; 159 160 // web worker superfast implementation 161 if (BnWWorker) { 162 163 imagesArray.push({ 164 imageData: imageData, 165 ctx: ctx, 166 img: img 167 }); 168 169 } else { 170 171 // no webworker slow implementation 172 for (; i < length; i += 4) { 173 var k = px[i] * 0.3 + px[i + 1] * 0.59 + px[i + 2] * 0.11; 174 px[i] = ~~ (k * intensity + px[i] * (1 - intensity)); 175 px[i + 1] = ~~ (k * intensity + px[i + 1] * (1 - intensity)); 176 px[i + 2] = ~~ (k * intensity + px[i + 2] * (1 - intensity)); 177 } 178 179 ctx.putImageData(imageData, 0, 0); 180 181 _onImageReady(img); 182 } 183 }; 184 185 var _injectTags = function($img, $imageWrapper) { 186 187 var pic = $img[0], 188 src = pic.src, 189 width = $img.width(), 190 height = $img.height(), 191 position = $img.position(), 192 css = { 193 'position': 'absolute', 194 top: position.top, 195 left: position.left, 196 display: invertHoverEffect ? 'none' : 'block' 197 }, 198 $overlay; 199 200 if (supportsCanvas && !cssfilters) { 201 202 var realWidth = pic.width, 203 realHeight = pic.height; 204 205 //adding the canvas 206 $overlay = $('<canvas class="BWfade" width="' + realWidth + '" height="' + realHeight + '"></canvas>'); 207 //setting the canvas position on the Pics 208 $overlay.css(css); 209 $overlay.prependTo($imageWrapper); 210 211 _manipulateImage(pic, $overlay.get(0), realWidth, realHeight); 212 213 } else { 214 215 css[cssPrefix('Filter')] = 'grayscale(' + intensity * 100 + '%)'; 216 //adding the canvas 217 $overlay = $('<img src=' + src + ' width="' + width + '" height="' + height + '" class="BWFilter BWfade" /> '); 218 $overlay.css($.extend(css, { 219 'filter': 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)' 220 })); 221 $overlay.prependTo($imageWrapper); 222 223 _onImageReady(pic); 224 } 225 }; 226 this.init = function(options) { 227 // convert all the images 228 $container.each(function(index, tmpImageWrapper) { 229 var $imageWrapper = $(tmpImageWrapper), 230 $pic = $imageWrapper.find('img'); 231 232 if (!$pic.width()) 233 $pic.on("load", function() { 234 _injectTags($pic, $imageWrapper); 235 }); 236 else 237 _injectTags($pic, $imageWrapper); 238 }); 239 // start the webworker 240 if (BnWWorker) { 241 // web worker implementation 242 _webWorkerLoop(); 243 } 244 // binding the hover effect 245 if (hoverEffect) { 246 $container.on('mouseleave', _onMouseLeave); 247 $container.on('mouseenter', _onMouseEnter); 248 } 249 // make it responsive 250 if (responsive) { 251 $window.on('resize orientationchange', $container.resizeImages); 252 } 253 }; 254 255 this.resizeImages = function() { 256 257 $container.each(function(index, currImageWrapper) { 258 var pic = $(currImageWrapper).find('img:not(.BWFilter)'), 259 currWidth = isIE7 ? $(pic).prop('width') : $(pic).width(), 260 currHeight = isIE7 ? $(pic).prop('height') : $(pic).height(); 261 262 $(this).find('.BWFilter, canvas').css({ 263 width: currWidth, 264 height: currHeight 265 }); 266 267 }); 268 }; 269 270 return this.init(options); 271 272 } 273 274 }); 275}(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.