1/** 2 * 3 * Version: 0.2.6 4 * Author: Gianluca Guarini 5 * Contact: [email protected] 6 * Website: http://www.gianlucaguarini.com/ 7 * Twitter: @gianlucaguarini 8 * 9 * Copyright (c) 2013 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(function($) { 34 $.fn.extend({ 35 BlackAndWhite: function(options) { 36 'use strict'; 37 var $container = this, 38 defaults = { 39 hoverEffect: true, 40 webworkerPath: false, 41 responsive: true, 42 invertHoverEffect: false, 43 speed: 500, 44 onImageReady: null 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 fadeSpeedIn = $.isPlainObject(options.speed) ? options.speed.fadeIn : options.speed, 58 fadeSpeedOut = $.isPlainObject(options.speed) ? options.speed.fadeOut : options.speed; 59 60 var isIE7 = (document.all && !window.opera && window.XMLHttpRequest) ? true : false; 61 62 /* 63 * 64 * features detection 65 * 66 */ 67 68 var browserPrefixes = ' -webkit- -moz- -o- -ms- '.split(' '); 69 70 var cssPrefixString = {}; 71 var cssPrefix = function(property) { 72 if (cssPrefixString[property] || cssPrefixString[property] === '') 73 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 * Private methods 109 * 110 */ 111 var _onMouseLeave = function(e) { 112 $(e.currentTarget).find('.BWfade').stop(true, true)[!invertHoverEffect ? 'fadeIn' : 'fadeOut'](fadeSpeedIn); 113 }; 114 115 var _onMouseEnter = function(e) { 116 $(e.currentTarget).find('.BWfade').stop(true, true)[invertHoverEffect ? 'fadeIn' : 'fadeOut'](fadeSpeedIn); 117 }; 118 119 var _onImageReady = function(img) { 120 if (typeof options.onImageReady === 'function') 121 options.onImageReady(img); 122 };
123 // Loop all the images converting them by the webworker (this process is unobstrusive and it does not block the page loading) 124 var _webWorkerLoop = function() { 125 if (!imagesArray.length) 126 return; 127 128 BnWWorker.postMessage(imagesArray[0].imageData); 129 130 BnWWorker.onmessage = function(event) { 131 imagesArray[0].ctx.putImageData(event.data, 0, 0); 132 _onImageReady(imagesArray[0].img); 133 imagesArray.splice(0, 1); 134 _webWorkerLoop(); 135 }; 136 }; 137 //convert any image into B&W using HTML5 canvas 138 var _manipulateImage = function(img, canvas, width, height) { 139 var ctx = canvas.getContext('2d'), 140 currImg = img, 141 i = 0, 142 grey; 143 144 ctx.drawImage(img, 0, 0, width, height); 145 146 var imageData = ctx.getImageData(0, 0, width, height), 147 px = imageData.data, 148 length = px.length; 149 150 // web worker superfast implementation 151 if (BnWWorker) { 152 153 imagesArray.push({ 154 imageData: imageData, 155 ctx: ctx, 156 img: img 157 }); 158 159 } else { 160 161 // no webworker slow implementation 162 for (; i < length; i += 4) { 163 grey = px[i] * 0.3 + px[i + 1] * 0.59 + px[i + 2] * 0.11; 164 px[i] = px[i + 1] = px[i + 2] = grey; 165 } 166 167 ctx.putImageData(imageData, 0, 0); 168 169 _onImageReady(img); 170 } 171 }; 172 173 var _injectTags = function($img, $imageWrapper) { 174 175 var pic = $img[0], 176 src = pic.src, 177 width = $($img).width(), 178 height = $($img).height(); 179 180 if (supportsCanvas && !cssfilters) { 181 182 var css = { 183 'position': 'absolute', 184 'z-index' : 2, 185 top: 0, 186 left: 0, 187 display: invertHoverEffect ? 'none' : 'block', 188 width: width, 189 height: height 190 }; 191 192 var realWidth = pic.width, 193 realHeight = pic.height; 194 195 //adding the canvas 196 $('<canvas class="BWfade" width="' + realWidth + '" height="' + realHeight + '"></canvas>').prependTo($imageWrapper); 197 //getting the canvas 198 var $canvas = $imageWrapper.find('canvas'); 199 200 //setting the canvas position on the Pics 201 $canvas.css(css); 202 203 _manipulateImage(pic, $canvas[0], realWidth, realHeight); 204 205 } else { 206 207 var cs = { 208 'position': 'absolute', 209 'z-index' : 2, 210 top: 0, 211 left: 0, 212 display: invertHoverEffect ? 'none' : 'block' 213 }; 214 215 cs[cssPrefix('Filter')] = 'grayscale(O)'; 216 217 if (Modernizr.touch) { 218 cs[cssPrefix('Filter')] = 'grayscale(0)'; 219 } 220 221 //adding the canvas 222 $('<img src=' + src + ' width="' + width + '" height="' + height + '" class="BWFilter BWfade" /> ').prependTo($imageWrapper); 223 $('.BWFilter').css($.extend(cs, { 224 'filter': 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)' 225 })); 226 227 _onImageReady(pic); 228 229 } 230 231 window.setTimeout(function () { 232 $img.addClass('fadein'); 233 }, 10); 234 235 }; 236 237 var _injectTagsFlickr = function($img, $imageWrapper) { 238 239 if (!cssfilters) { 240 241 var pic = $img[0], 242 src = pic.src, 243 width = $($img).width(), 244 height = $($img).height(), 245 mozCss = { 246 'position': 'absolute', 247 'z-index' : 2, 248 top: 0, 249 left: 0, 250 display: invertHoverEffect ? 'none' : 'block', 251 width: width, 252 height: height 253 }; 254 255 mozCss['filter'] = 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\' filterRes=\'400\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale")'; 256 257 //adding the canvas 258 $('<img src=' + src + ' width="' + width + '" height="' + height + '" class="BWFilter BWfade" /> ').prependTo($imageWrapper); 259 $('.BWFilter').css(mozCss); 260 261 _onImageReady(pic); 262 263 window.setTimeout(function () { 264 $img.addClass('fadein'); 265 }, 10); 266 267 } 268 269 }; 270 this.init = function(options) { 271 // convert all the images 272 273 if (!cssfilters) { 274 275 $container.filter('.badge').each(function(index, tmpImageWrapper) { 276 var $imageWrapper = $(tmpImageWrapper), 277 $pic = $imageWrapper.find('img'); 278 _injectTagsFlickr($pic, $imageWrapper); 279 }); 280 281 if (hoverEffect) { 282 283 $('.flickr-badge') 284 .on('mouseenter', 'a', _onMouseEnter) 285 .on('mouseleave', 'a', _onMouseLeave); 286 287 } 288 289 } 290 291 $container.each(function(index, tmpImageWrapper) { 292 var $imageWrapper = $(tmpImageWrapper), 293 $pic = $imageWrapper.find('img'); 294 295 if (!$pic.width()) { 296 $pic.on("load", function() { 297 _injectTags($pic, $imageWrapper); 298 }); 299 } 300 else { 301 _injectTags($pic, $imageWrapper); 302 } 303 304 }); 305 306 // start the webworker 307 if (BnWWorker) { 308 // web worker implementation 309 _webWorkerLoop(); 310 } 311 // binding the hover effect
312 if (hoverEffect) { 313 314 $container 315 .on('mouseenter', _onMouseEnter) 316 .on('mouseleave', _onMouseLeave); 317 318 } 319 320 // make it responsive 321 if (responsive) { 322 $window.on('resize orientationchange', $container.resizeImages); 323 } 324 325 }; 326 327 this.resizeImages = function() { 328 329 $container.each(function(index, currImageWrapper) { 330 var pic = $(currImageWrapper).find('img:not(.BWFilter)'); 331 var currWidth, currHeight; 332 if (isIE7) { 333 currWidth = $(pic).prop('width'); 334 currHeight = $(pic).prop('height'); 335 } else { 336 currWidth = $(pic).width(); 337 currHeight = $(pic).height(); 338 } 339 340 $(this).find('.BWFilter, canvas').css({ 341 width: currWidth, 342 height: currHeight 343 }); 344 345 }); 346 }; 347 348 return this.init(options); 349 350 } 351 352 }); 353 354}(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.