HoverFX.js (20449B)
1 (function($) { 2 3 window.initHoverFX = function(options, isUI, resizeEvent) { 4 var defaults, item, opts, params, instanceName, className, classElements, doesCSS3, supportRGBA; 5 item = $('.contentswap-effect'); 6 supportRGBA = true; 7 doesCSS3 = true; 8 9 opts = options; 10 11 function setParams(elem) { 12 13 className = $(elem).attr('class'); 14 classElements = className.split(" "); 15 for (var i = 0; i <= item.length; i++) { 16 for (var prop in opts) { 17 if (classElements[i] === prop) { 18 instanceName = prop; 19 } 20 } 21 } 22 23 return opts ? params = opts[instanceName] : params = defaults[instanceName]; 24 } 25 26 function getInner(elem, type) { 27 28 var inner; 29 switch (type) { 30 case "overlay": 31 inner = $(elem).find('.swap-inner'); 32 break; 33 case "imageSwap": 34 inner = $(elem).find('.second-image'); 35 break; 36 case "caption": 37 inner = $(elem).find('.swap-inner'); 38 break; 39 } 40 return inner; 41 } 42 43 function getDimms(elem) { 44 var dims = { 45 width: '100%', 46 height: Math.abs(parseFloat($(elem).outerHeight(false))) 47 }; 48 return dims 49 } 50 51 function moveCSSProps(source, target) { 52 var ml = source.css('margin-left'); 53 var mr = source.css('margin-right'); 54 var mt = source.css('margin-top'); 55 var mb = source.css('margin-bottom'); 56 var floatVal = source.css('float'); 57 source.css({ 58 'float': 'none', 59 'margin-left': '0px', 60 'margin-right': '0px', 61 'margin-top': '0px', 62 'margin-bottom': '0px' 63 }) 64 target.css({ 65 'float': floatVal, 66 'margin-left': ml, 67 'margin-right': mr, 68 'margin-top': mt, 69 'margin-bottom': mb 70 }) 71 72 } 73 74 function setCaptionHeight(height, elem) { 75 if (height != 'auto' || height != 'undefined') elem.css('height', parseInt(height) + 'px'); 76 } 77 78 function genRGBA(hex, alpha, elem) { 79 // with both longhand and shorthand support (accepts both #fff or #fffff) 80 if (hex.indexOf('#') == -1 || hex.indexOf('rgb(') > -1 || hex.indexOf('rgba') > -1) { 81 return { 82 rgba: hex 83 }; 84 } 85 var opacity; 86 alpha ? opacity = (alpha / 100).toFixed(2) : opacity = 1; 87 88 function convertRGBDecimalToHex(rgb) { 89 90 // check for RGB 91 var regexRGB = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/; 92 var values = regexRGB.exec(rgb); 93 94 // check for RGBA 95 if (!values) { 96 var regexRGBA = /rgba *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *, *(0.+[0-9]) *\)/; 97 values = regexRGBA.exec(rgb); 98 } 99 100 if (!values) return rgb; 101 if (values.length != 5) { 102 return rgb; // fall back to what was given. 103 } 104 var r = Math.round(parseFloat(values[1])); 105 var g = Math.round(parseFloat(values[2])); 106 var b = Math.round(parseFloat(values[3])); 107 if (values[4]) { 108 opacity = values[4]; 109 } 110 return "#" + (r + 0x10000).toString(16).substring(3).toUpperCase() + (g + 0x10000).toString(16).substring(3).toUpperCase() + (b + 0x10000).toString(16).substring(3).toUpperCase(); 111 } 112 113 hex = convertRGBDecimalToHex(hex); 114 115 var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 116 hex = hex.replace(shorthandRegex, function(m, r, g, b) { 117 return r + r + g + g + b + b; 118 }); 119 120 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 121 122 function alhpaToHex(val) { 123 var num = val * 255; 124 return Math.floor(num).toString(16); 125 } 126 127 if (typeof(elem) !== 'undefined' && result) { 128 switch (supportRGBA) { 129 case true: 130 elem.css('background-color', 'rgba(' + [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)].join(",") + ',' + opacity + ')'); 131 break; 132 case false: 133 elem.css({ 134 'background': 'transparent', 135 'filter': 'progid:DXImageTransform.Microsoft.gradient(startColorstr=#' + alhpaToHex(opacity) + result[0].replace('#', '') + ',endColorstr=#' + alhpaToHex(opacity) + result[0].replace('#', '') + ');', 136 'zoom': 1 137 }); 138 break; 139 } 140 } 141 142 return result ? { 143 rgba: 'rgba(' + [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)].join(",") + ',' + opacity + ')', 144 fallback: alhpaToHex(opacity) + result[0].replace('#', '') 145 } : null; 146 } 147 148 function getEaseType(ease) { 149 // Add more ease types - work in progress 150 var easeCSS = ""; 151 var easeType; 152 var oldWebkit = false; 153 154 switch (ease.toLowerCase()) { 155 case 'easeinoutback': 156 easeType = 'cubic-bezier(0.680, -0.550, 0.265, 1.550)'; 157 oldWebkit = 'cubic-bezier(0.680, 0, 0.265, 1)'; 158 break; 159 case 'quick-in': 160 easeType = "cubic-bezier(0.315, -0.185, 0.000, 1.270)"; 161 oldWebkit = "cubic-bezier(0.315, 0, 0.000, 1)"; 162 break; 163 case 'accelerate': 164 easeType = "cubic-bezier(0.885, 0.420, 0.000, 1.270)"; 165 oldWebkit = "cubic-bezier(0.885, 0.420, 0.000, 1)"; 166 break; 167 case 'super-fast': 168 easeType = "cubic-bezier(0.000, 0.870, 0.000, 0.890)"; 169 break; 170 case 'ease-in-out-back': 171 easeType = "cubic-bezier(0.680, -0.550, 0.265, 1.550)"; 172 oldWebkit = "cubic-bezier(0.680, 0, 0.265, 1)"; 173 break; 174 case 'ease-in-out-expo': 175 easeType = "cubic-bezier(1.000, 0.000, 0.000, 1.000)"; 176 break; 177 case 'ease-out-back': 178 easeType = "cubic-bezier(0.175, 0.885, 0.320, 1.275)"; 179 oldWebkit = "cubic-bezier(0.175, 0.885, 0.320, 1)"; 180 break; 181 case 'ease-out-circ': 182 easeType = "cubic-bezier(0.075, 0.820, 0.165, 1.000)"; 183 break; 184 case 'ease-in-back': 185 easeType = "cubic-bezier(0.600, -0.280, 0.735, 0.045)"; 186 oldWebkit = "cubic-bezier(0.600, 0, 0.735, 0.045)"; 187 break; 188 case 'ease-in-circ': 189 easeType = "cubic-bezier(0.600, 0.040, 0.980, 0.335)"; 190 oldWebkit = "cubic-bezier(0.600, 0.040, 0.980, 0.335)"; 191 break; 192 case 'ease': 193 easeType = "ease"; 194 break; 195 case "ease-in": 196 easeType = "ease-in"; 197 break; 198 case "ease-in-out": 199 easeType = "ease-in-out"; 200 break; 201 case "ease-out": 202 easeType = "ease-out"; 203 break; 204 } 205 206 if (oldWebkit) { 207 easeType = oldWebkit; 208 // easeCSS += "-webkit-transition-timing-function:" + oldWebkit + ";"; 209 } 210 var prefixes = ["-webkit-", "-moz-", "-o-", ""]; 211 for (var i = 0; i < prefixes.length; i++) { 212 easeCSS += prefixes[i] + "transition-timing-function:" + easeType + ";" 213 } 214 215 return easeCSS; 216 217 218 }; 219 220 221 function centerIcon(icon) { 222 var elem = $(icon); 223 elem 224 .parent() 225 .css({ 226 'width': elem.width(), 227 'height': elem.height() 228 }) 229 } 230 options.resizeEvent = resizeEvent ? true : false; 231 232 233 start(options); 234 235 function start(options) { 236 var addEffects = $(); 237 238 item.each(function() { 239 240 var self, params, inner, overlay, initial, dims, type, transitionProp, easeType, icon; 241 self = $(this); 242 self.unbind('.hoverfx'); 243 self.css({ 244 "width": "", 245 "height": "" 246 }); 247 248 249 params = setParams(self); 250 inner = getInner(self, params.contentType); 251 initial = self.find('.initial-image'); 252 overlay = self.find('.overlay'); 253 params.overlayColor = inner.css('background-color'); 254 params.innerColor = inner.css('background-color'); 255 inner.removeAttr('style'); 256 overlay.removeAttr('style'); 257 initial.removeAttr('style'); 258 259 moveCSSProps(initial, self); 260 261 dims = getDimms(self); 262 //console.log(dims); 263 easeType = getEaseType(params.effectEasing); 264 type = params.contentType; 265 266 icon = inner.find('.swap-icons img'); 267 centerIcon(icon); 268 if (type == 'overlay') { 269 transitionProp = 'all'; 270 } else { 271 transitionProp = 'margin'; 272 } 273 initial.css('float', 'none'); 274 275 if (type == "caption") { 276 if (self.find('.caption-wrap').length == 0) { 277 var captionWrap = $('<div />').addClass('caption-wrap overlay'); 278 inner.wrap(captionWrap); 279 } 280 overlay = self.find('.caption-wrap'); 281 } else { 282 overlay = self.find('.overlay'); 283 } 284 overlay.add(inner).css('display', 'block'); 285 286 287 288 function applyTransition(elem, prop, easeCSS, duration, includeTiming) { 289 var property = prop ? prop : "all"; 290 var customEase = ""; 291 var dur = params.effectDelay + "ms"; 292 var delay = ""; 293 294 295 296 var transitionValue = property + " " + dur; 297 elem.css({ 298 '-webkit-transition': transitionValue, 299 '-moz-transition': transitionValue, 300 '-o-transition': transitionValue, 301 'transition': transitionValue 302 }) 303 if (includeTiming) { 304 applyTiming(elem, easeCSS); 305 } 306 } 307 308 function applyTiming(elem, easeCSS) { 309 elem.attr('style', elem.attr('style') + easeCSS); 310 } 311 312 self.addClass(params.effectType); 313 314 var loaded = false; 315 316 if (initial.height() > 0) { 317 318 loaded = true; 319 var initialDims = getDimms(initial); 320 self.css({ 321 'width': initialDims.width/*, 322 'height': initialDims.height*/ 323 }); 324 325 if (type == "overlay") { 326 applyTransition(inner, transitionProp, easeType, params.effectDelay, true); 327 } 328 } 329 330 initial.on('load', function() { 331 var imageDims = getDimms($(this)); 332 333 self.css({ 334 'width': imageDims.width/*, 335 'height': imageDims.height*/ 336 }); 337 if (type == 'overlay') { 338 inner.css({ 339 'margin-top': 0 / 2, 340 'margin-left': Math.abs(imageDims.width - inner.outerWidth()) / 2 341 }); 342 } 343 if (type == "overlay") { 344 applyTransition(inner, transitionProp, easeType, params.effectDelay); 345 } 346 347 }); 348 349 inner.css({ 350 'background-color': genRGBA(params.overlayColor, params.overlayAlpha).rgba 351 }); 352 353 if (type == "overlay") { 354 applyTransition(overlay, 'opacity', easeType, params.effectDelay, true); 355 } 356 357 358 359 var showCaption, hideCaption; 360 361 var isMobile = { 362 Android: function() { 363 return navigator.userAgent.match(/Android/i); 364 }, 365 BlackBerry: function() { 366 return navigator.userAgent.match(/BlackBerry/i); 367 }, 368 iOS: function() { 369 return navigator.userAgent.match(/iPhone|iPad|iPod/i); 370 }, 371 Opera: function() { 372 return navigator.userAgent.match(/Opera Mini/i); 373 }, 374 Windows: function() { 375 return navigator.userAgent.match(/IEMobile/i); 376 }, 377 any: function() { 378 return !!(isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows() || ("ontouchstart" in document)); 379 } 380 }; 381 382 var _isMobile = isMobile.any(); 383 384 385 if (params.link) { 386 if (_isMobile == true) { 387 388 } else { 389 self.bind('click.hoverfx', function() { 390 if (params.openPage === 'same') { 391 window.location.assign(params['link']); 392 } else { 393 window.open(params['link'], '_blank'); 394 } 395 }); 396 } 397 } 398 399 400 if (type == 'overlay') { 401 self.unbind('.caption'); 402 self.addClass('contentswap-overlay'); 403 var initialDims = getDimms(initial); 404 //console.log(dims.width + " .. " + inner.outerWidth()); 405 if (initial.height() > 0) { 406 inner.css({ 407 // 'margin-top': Math.abs(initialDims.height - inner.outerHeight()) / 2, 408 'margin-top': 0 / 2, 409 'margin-left': Math.abs(initialDims.width - inner.outerWidth()) / 2 410 }); 411 } 412 413 } 414 415 if (type == 'caption') { 416 self.addClass('caption'); 417 418 if (params.direction == 'top') { 419 if (!loaded) { 420 setTimeout(function() { 421 overlay.css({ 422 'margin-top': (-inner.outerHeight() - 1) + 'px', 423 'opacity': 1 424 }); 425 }, 10); 426 427 } else { 428 overlay.css({ 429 'margin-top': (-inner.outerHeight() - 1) + 'px', 430 'opacity': 1 431 }); 432 } 433 434 setTimeout(function() { 435 overlay.insertBefore(initial); 436 437 }, 10); 438 } else { 439 440 setTimeout(function() { 441 overlay.css({ 442 'opacity': 1 443 }); 444 }, 10); 445 } 446 //else applyTransition(initial,transitionProp); 447 var showCaption, hideCaption; 448 449 450 //work in progress 451 if (params.captionType == "over") { 452 453 if (params.direction == 'top') { 454 overlay.css({ 455 'position': 'absolute', 456 'z-index': 9991 457 458 }); 459 } else { 460 overlay.css({ 461 'margin-top': '1px' 462 }); 463 } 464 applyTransition(overlay, 'margin', easeType, params.effectDelay, true); 465 466 showCaption = function() { 467 468 overlay.css({ 469 'margin-top': (-inner.outerHeight()) + 'px' 470 }); 471 if (params.direction == 'top') overlay.css('margin-top', 0); 472 }; 473 hideCaption = function() { 474 overlay.css({ 475 'margin-top': "0px" 476 }); 477 if (params.direction == 'top') overlay.css('margin-top', (-inner.outerHeight()) + 'px'); 478 } 479 } else { 480 applyTransition(overlay, "margin", easeType, params.effectDelay, true); 481 applyTransition(initial, "margin", easeType, params.effectDelay, true); 482 483 484 showCaption = function() { 485 486 if (params.captionHeight <= inner.outerHeight()) { 487 setCaptionHeight(params.captionHeight, inner); 488 } 489 490 if (params.direction == 'top' && params.captionType != 'over') { 491 492 overlay.css({ 493 'margin-top': '0px' 494 }); 495 } else { 496 overlay.css({ 497 'margin-top': -inner.outerHeight() 498 }) 499 initial.css({ 500 'margin-top': -inner.outerHeight(), 501 'margin-bottom': inner.outerHeight() 502 }) 503 504 } 505 } 506 507 hideCaption = function() { 508 if (params.direction == 'top') { 509 overlay.css({ 510 'margin-top': (-inner.outerHeight() - 1) + 'px' 511 }) 512 } else { 513 overlay.css({ 514 'margin-top': '1px' 515 }) 516 initial.css({ 517 'margin-top': '0px', 518 'margin-bottom': '0px' 519 }) 520 } 521 } 522 } 523 524 525 } 526 527 if (_isMobile == true) { 528 self.addClass('hover'); 529 if (type == "caption") { 530 showCaption(); 531 } else { 532 533 } 534 535 } else { 536 if (type == "caption") { 537 self.bind('mouseenter.hoverfx', showCaption) 538 .bind('mouseleave.hoverfx', hideCaption); 539 } 540 541 } 542 543 544 545 546 }); 547 } 548 549 } 550 })(jQuery);