1$(function() { 2 3 "use strict"; 4 5 $.fn.sparkle = function(options) { 6 7 return this.each(function(k, v) { 8 9 var $this = $(v); 10 11 var settings = $.extend({ 12 13 color: "#FFFFFF", 14 count: 30, 15 overlap: 0, 16 speed: 1, 17 minSize: 4, 18 maxSize: 7, 19 direction: "both" 20 21 }, options); 22 23 // initiate a new Sparkle method and bind it to "sparkle" so we 24 // can set up events to it. 25 var sparkle = new Sparkle($this, settings); 26 27 // bind mouseover/focus/mouseout/blur events to the element 28 // with a namespace for easy unbinding. 29 $this.on({ 30 "mouseover.sparkle focus.sparkle": function() { 31 sparkle.over($this); 32 }, 33 "mouseout.sparkle blur.sparkle": function() { 34 sparkle.out(); 35 } 36 }); 37 38 }); 39 40 }; 41 42 // Constructor method for sparkles, 43 // we call init on the class and all other 44 // methods on the the Sparkle class are prototyped 45 function Sparkle($parent, options) { 46 47 this.options = options; 48 this.init($parent); 49 50 } 51 52 Sparkle.prototype = { 53 54 "init": function($parent) { 55 56 var cssOpts = { 57 58 position: "absolute", 59 top: "-" + this.options.overlap + "px", 60 left: "-" + this.options.overlap + "px", 61 "pointer-events": "none" 62 63 }; 64 65 // we need to give the element position if it doesn't 66 // already have it, so that we can put the canvas right 67 // over the top. 68 if ($parent.css("position") === "static") { 69 $parent.css("position", "relative"); 70 } 71 72 // set up the canvas element as a document fragment 73 // and give it a class and some css amd append it 74 // to our parent element. 75 this.$canvas = 76 $("<canvas>") 77 .addClass("sparkle-canvas") 78 .css( cssOpts ) 79 .hide(); 80 81 // check if the parent has a z-index, if it does 82 // then make the canvas 1 place higher than it! 83 if ($parent.css("z-index") !== "auto") { 84 var zdex = parseInt($parent.css("z-index"),10); 85 this.$canvas.css("z-index", zdex+1); 86 } 87 88 // check if the DOM element is a singleton, ie it 89 // doesnt have a closing tag... we can't put the canvas 90 // inside an <img> for example. 91 var singletons = "IMG|BR|HR|INPUT"; 92 var regexp = "\\b"+ $parent[0].nodeName +"\\b"; 93 this.isSingleton = new RegExp(regexp).test(singletons); 94 95 if( this.isSingleton ) { 96 this.$canvas.insertAfter( $parent ); 97 } else { 98 this.$canvas.appendTo( $parent ); 99 } 100 101 // create our canvas context and save it for 102 // future use with this.canvas 103 this.canvas = this.$canvas[0]; 104 this.context = this.canvas.getContext("2d"); 105 106 // create our sparkle sprite using the datauri 107 // supplied at end of prototype 108 this.sprite = new Image(); 109 this.sprite.src = this.datauri; 110 this.spriteCoords = [0, 6, 13, 20]; 111 112 // set the canvas with and height using the parent 113 // with and height set in the options 114 this.canvas.width = $parent.outerWidth()*1.2; 115 this.canvas.height = $parent.outerHeight()*1.2; 116 117 // store our particles into an object for future use 118 this.particles = this.createSparkles(this.canvas.width, this.canvas.height); 119 120 this.anim = null; 121 this.fade = false;
122 123 }, 124 125 "randomParticleSize": function() { 126 127 return Math.floor(Math.random()*(this.options.maxSize-this.options.minSize+1)+this.options.minSize); 128 129 }, 130 131 "randomHexColor": function() { 132 133 return '#' + ('000000' + Math.floor(Math.random() * 16777215).toString(16)).slice(-6); 134 135 }, 136 137 "createSparkles": function(w, h) { 138 139 // temporarily store our created particles 140 var tempicles = []; 141 142 // loop through and add a new particles 143 // on each loop for the count provided 144 for (var i = 0; i < this.options.count; i++) { 145 146 var color; 147 148 if (this.options.color === "rainbow") { 149 150 // if we chose rainbow, give us much random so color very blergh 151 // http://www.paulirish.com/2009/random-hex-color-code-snippets/ 152 color = this.randomHexColor(); 153 154 } else if ($.type(this.options.color) === "array") { 155 156 // if we supplied an array, choose a random color from array. 157 color = this.options.color[Math.floor(Math.random() * this.options.color.length)]; 158 159 } else { 160 161 color = this.options.color; 162 163 } 164 165 var yDelta = Math.floor(Math.random() * 1000) - 500; 166 167 if( this.options.direction === "down" ) { 168 yDelta = Math.floor(Math.random() * 500) - 550; 169 } else if ( this.options.direction === "up" ) { 170 yDelta = Math.floor(Math.random() * 500) + 50; 171 } 172 173 // create a particle with random position, 174 // random sprite start point, delta, size and a defined color. 175 tempicles[i] = { 176 position: { 177 x: Math.floor(Math.random() * w), 178 y: Math.floor(Math.random() * h) 179 }, 180 style: this.spriteCoords[Math.floor(Math.random() * this.spriteCoords.length)], 181 delta: { 182 x: Math.floor(Math.random() * 1000) - 500, 183 y: yDelta 184 }, 185 size: this.randomParticleSize(), 186 color: color 187 }; 188 189 } 190 191 return tempicles; 192 193 }, 194 195 "draw": function() { 196 197 // draw is where we draw our particles to the stage. 198 // first we clear the entire context for updating. 199 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 200 201 // for every particle 202 for (var i = 0; i < this.particles.length; i++) { 203 204 // save the context so we can restore teh default settings. 205 this.context.save(); 206 this.context.globalAlpha = this.particles[i].opacity; 207 this.context.drawImage(this.sprite, this.particles[i].style, 0, 7, 7, this.particles[i].position.x, this.particles[i].position.y, this.particles[i].size, this.particles[i].size); 208 209 // if we set a color we want to tint the sprite with it 210 if (this.options.color) { 211 212 this.context.globalCompositeOperation = "source-atop"; 213 this.context.globalAlpha = 0.6; 214 this.context.fillStyle = this.particles[i].color; 215 this.context.fillRect(this.particles[i].position.x, this.particles[i].position.y, 7, 7); 216 217 } 218 219 this.context.restore(); 220 221 } 222 223 }, 224 225 "update": function() { 226 227 // update is our particle alteration and animation frame 228 // render loop, calling draw on each update. 229 var _this = this; 230 231 this.anim = window.requestAnimationFrame(function(time) { 232 233 // store a floored version of the time passed 234 var flatTime = Math.floor(time); 235 236 for (var i = 0; i < _this.particles.length; i++) { 237 238 var p = _this.particles[i]; 239 var resizeParticle = false;
240 241 // randomly move particles in the x/y direction 242 // we weight x heavier than y allowing some random 243 // decelleration giving an ethereal floating feeling 244 var randX = (Math.random() > Math.random() * 2); 245 var randY = (Math.random() < Math.random() * 5); 246 247 // arbitrary position change/speed based on what felt good. 248 if (randX) { 249 p.position.x += ((p.delta.x * _this.options.speed) / 1500); 250 } 251 252 // arbitrary position change/speed based on what felt good. 253 if (randY) { 254 p.position.y -= ((p.delta.y * _this.options.speed) / 800); 255 } 256 257 // if particle fell off of canvas, then position it 258 // back at the opposite side... minus 7 pixels which is the 259 // largest size a particle can be. 260 if (p.position.x > _this.canvas.width) { 261 p.position.x = -(_this.options.maxSize); 262 resizeParticle = true; 263 } else if (p.position.x < -(_this.options.maxSize)) { 264 p.position.x = _this.canvas.width; 265 resizeParticle = true; 266 } 267 268 // if it fell off top or bottom, give it a random x position 269 if (p.position.y > _this.canvas.height) { 270 p.position.y = -(_this.options.maxSize); 271 p.position.x = Math.floor(Math.random() * _this.canvas.width); 272 resizeParticle = true; 273 } else if (p.position.y < -(_this.options.maxSize)) { 274 p.position.y = _this.canvas.height; 275 p.position.x = Math.floor(Math.random() * _this.canvas.width); 276 resizeParticle = true; 277 } 278 279 // if the particle left the canvas, let's resize it 280 if ( resizeParticle ) { 281 p.size = _this.randomParticleSize(); 282 p.opacity = 0.4; 283 } 284 285 // if we're trying to fade out fast because 286 // of a _out_ event, increase opacity delta 287 if (_this.fade) { 288 p.opacity -= 0.035; 289 } else { 290 p.opacity -= 0.005; 291 } 292 293 // if the opacity went below 0, then 294 // set it back to 1.2 (this gives slightly longer brightness) 295 if (p.opacity <= 0.15) { 296 p.opacity = (_this.fade) ? 0 : 1.2; 297 } 298 299 // basically we want to randomly change the sparkles 300 // sprite position, this arbitrary number _felt_ right. 301 if (flatTime % Math.floor((Math.random() * 7)+1) === 0) { 302 p.style = _this.spriteCoords[Math.floor(Math.random() * _this.spriteCoords.length)]; 303 } 304 305 } 306 307 // draw all the particles. 308 _this.draw(time); 309 310 // only _stop_ the animation after we've finished 311 // fading out and we also hide the canvas. 312 if (_this.fade) { 313 _this.fadeCount -= 1; 314 if (_this.fadeCount < 0) { 315 window.cancelAnimationFrame(_this.anim); 316 _this.$canvas.hide(); 317 } else { 318 _this.update(); 319 } 320 } else { 321 _this.update(); 322 } 323 324 }); 325 326 }, 327 328 "over": function($parent) { 329 330 // We set the width/height of the canvas upon mouseover 331 // because of document-load issues with fonts and images and 332 // other things changing dimentions of elements. 333 this.canvas.width = $parent.outerWidth() + (this.options.overlap * 2); 334 this.canvas.height = $parent.outerHeight() + (this.options.overlap * 2); 335 336 // also if the base element is a singleton then we re-position the 337 // canvas. we don't want the canvas to be in the wrong position if 338 // something has moved. 339 if( this.isSingleton ) { 340 this.$canvas.css({ 341 top: $parent.position().top - this.options.overlap , 342 left: $parent.position().left - this.options.overlap 343 }); 344 } 345 346 // we hide/show the canvas element on hover 347 // just to make sure it has it's garbage collected 348 this.$canvas.show(); 349 350 // make sure the animation frame was cancelled, or we 351 // get multiple update/draw loops happening (BAD) .. this 352 // can happen because we let the animation loop continue 353 // while it fades out. 354 window.cancelAnimationFrame(this.anim); 355 356 // randomize the opacity every time we over the animation 357 // this stops our particles all being at same opacity 358 // after the fadeout happens. 359 for (var i = 0; i < this.options.count; i++) { 360 this.particles[i].opacity = Math.random(); 361 } 362 363 // run our update loop. 364 this.fade = false;
365 this.update(); 366 367 }, 368 369 "out": function() { 370 371 // here we just tell the update loop that 372 // we want to fade out, and that we want to 373 // take 100 frames to fade out 374 this.fade = true; 375 this.fadeCount = 100; 376 377 }, 378 379 // datauri is our sparkle sprite. Don't touch this. 380 "datauri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAHCAYAAAD5wDa1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozNDNFMzM5REEyMkUxMUUzOEE3NEI3Q0U1QUIzMTc4NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozNDNFMzM5RUEyMkUxMUUzOEE3NEI3Q0U1QUIzMTc4NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjM0M0UzMzlCQTIyRTExRTM4QTc0QjdDRTVBQjMxNzg2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjM0M0UzMzlDQTIyRTExRTM4QTc0QjdDRTVBQjMxNzg2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+jzOsUQAAANhJREFUeNqsks0KhCAUhW/Sz6pFSc1AD9HL+OBFbdsVOKWLajH9EE7GFBEjOMxcUNHD8dxPBCEE/DKyLGMqraoqcd4j0ChpUmlBEGCFRBzH2dbj5JycJAn90CEpy1J2SK4apVSM4yiKonhePYwxMU2TaJrm8BpykpWmKQ3D8FbX9SOO4/tOhDEG0zRhGAZo2xaiKDLyPGeSyPM8sCxr868+WC/mvu9j13XBtm1ACME8z7AsC/R9r0fGOf+arOu6jUwS7l6tT/B+xo+aDFRo5BykHfav3/gSYAAtIdQ1IT0puAAAAABJRU5ErkJggg==" 381 382 }; 383 384});
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.