1/*! flip - v1.1.2 - 2016-10-20 2* https://github.com/nnattawat/flip 3* Copyright (c) 2016 Nattawat Nonsung; Licensed MIT */ 4(function( $ ) { 5 /* 6 * Private attributes and method 7 */ 8 9 // Function from David Walsh: http://davidwalsh.name/css-animation-callback licensed with http://opensource.org/licenses/MIT 10 var whichTransitionEvent = function() { 11 var t, el = document.createElement("fakeelement"), 12 transitions = { 13 "transition" : "transitionend", 14 "OTransition" : "oTransitionEnd", 15 "MozTransition" : "transitionend", 16 "WebkitTransition": "webkitTransitionEnd" 17 }; 18 19 for (t in transitions) { 20 if (el.style[t] !== undefined) { 21 return transitions[t]; 22 } 23 } 24 }; 25 26 /* 27 * Model declaration 28 */ 29 var Flip = function($el, options, callback) { 30 // Define default setting 31 this.setting = { 32 axis: "y", 33 reverse: false, 34 trigger: "hover", 35 speed: 500, 36 forceHeight: false, 37 forceWidth: false, 38 autoSize: true, 39 front: '.front', 40 back: '.back' 41 }; 42 43 this.setting = $.extend(this.setting, options); 44 45 if (typeof options.axis === 'string' && (options.axis.toLowerCase() === 'x' || options.axis.toLowerCase() === 'y')) { 46 this.setting.axis = options.axis.toLowerCase(); 47 } 48 49 if (typeof options.reverse === "boolean") { 50 this.setting.reverse = options.reverse; 51 } 52 53 if (typeof options.trigger === 'string') { 54 this.setting.trigger = options.trigger.toLowerCase(); 55 } 56 57 var speed = parseInt(options.speed); 58 if (!isNaN(speed)) { 59 this.setting.speed = speed; 60 } 61 62 if (typeof options.forceHeight === "boolean") { 63 this.setting.forceHeight = options.forceHeight; 64 } 65 66 if (typeof options.forceWidth === "boolean") { 67 this.setting.forceWidth = options.forceWidth; 68 } 69 70 if (typeof options.autoSize === "boolean") { 71 this.setting.autoSize = options.autoSize; 72 } 73 74 if (typeof options.front === 'string' || options.front instanceof $) { 75 this.setting.front = options.front; 76 } 77 78 if (typeof options.back === 'string' || options.back instanceof $) { 79 this.setting.back = options.back; 80 } 81 82 // Other attributes 83 this.element = $el; 84 this.frontElement = this.getFrontElement(); 85 this.backElement = this.getBackElement(); 86 this.isFlipped = false; 87 88 this.init(callback); 89 }; 90 91 /* 92 * Public methods 93 */ 94 $.extend(Flip.prototype, { 95 96 flipDone: function(callback) { 97 var self = this; 98 // Providing a nicely wrapped up callback because transform is essentially async 99 self.element.one(whichTransitionEvent(), function() { 100 self.element.trigger('flip:done'); 101 if (typeof callback === 'function') { 102 callback.call(self.element); 103 } 104 }); 105 }, 106 107 flip: function(callback) { 108 if (this.isFlipped) { 109 return; 110 } 111 112 this.isFlipped = true; 113 114 var rotateAxis = "rotate" + this.setting.axis; 115 this.frontElement.css({ 116 transform: rotateAxis + (this.setting.reverse ? "(-180deg)" : "(180deg)"), 117 "z-index": "0" 118 }); 119 120 this.backElement.css({ 121 transform: rotateAxis + "(0deg)", 122 "z-index": "1" 123 }); 124 this.flipDone(callback); 125 }, 126 127 unflip: function(callback) { 128 if (!this.isFlipped) { 129 return; 130 } 131 132 this.isFlipped = false; 133 134 var rotateAxis = "rotate" + this.setting.axis; 135 this.frontElement.css({ 136 transform: rotateAxis + "(0deg)", 137 "z-index": "1" 138 }); 139 140 this.backElement.css({ 141 transform: rotateAxis + (this.setting.reverse ? "(180deg)" : "(-180deg)"), 142 "z-index": "0" 143 }); 144 this.flipDone(callback); 145 }, 146 147 getFrontElement: function() { 148 if (this.setting.front instanceof $) { 149 return this.setting.front; 150 } else { 151 return this.element.find(this.setting.front); 152 } 153 }, 154 155 getBackElement: function() { 156 if (this.setting.back instanceof $) { 157 return this.setting.back; 158 } else { 159 return this.element.find(this.setting.back); 160 } 161 }, 162 163 init: function(callback) { 164 var self = this; 165 166 var faces = self.frontElement.add(self.backElement); 167 var rotateAxis = "rotate" + self.setting.axis; 168 var perspective = self.element["outer" + (rotateAxis === "rotatex" ? "Height" : "Width")]() * 2; 169 var elementCss = { 170 'perspective': perspective, 171 'position': 'relative' 172 }; 173 var backElementCss = { 174 "transform": rotateAxis + "(" + (self.setting.reverse ? "180deg" : "-180deg") + ")", 175 "z-index": "0", 176 "position": "relative" 177 }; 178 var faceElementCss = { 179 "backface-visibility": "hidden", 180 "transform-style": "preserve-3d", 181 "position": "absolute", 182 "z-index": "1" 183 }; 184 185 if (self.setting.forceHeight) { 186 faces.outerHeight(self.element.height()); 187 } else if (self.setting.autoSize) { 188 faceElementCss.height = '100%'; 189 } 190 191 if (self.setting.forceWidth) { 192 faces.outerWidth(self.element.width()); 193 } else if (self.setting.autoSize) { 194 faceElementCss.width = '100%'; 195 } 196 197 // Back face always visible on Chrome #39 198 if ((window.chrome || (window.Intl && Intl.v8BreakIterator)) && 'CSS' in window) { 199 //Blink Engine, add preserve-3d to self.element 200 elementCss["-webkit-transform-style"] = "preserve-3d"; 201 } 202 203 204 faces.css(faceElementCss).find('*').css({ 205 "backface-visibility": "hidden" 206 }); 207 208 self.element.css(elementCss); 209 self.backElement.css(backElementCss); 210 211 // #39 212 // not forcing width/height may cause an initial flip to show up on 213 // page load when we apply the style to reverse the backface... 214 // To prevent self we first apply the basic styles and then give the 215 // browser a moment to apply them. Only afterwards do we add the transition. 216 setTimeout(function() { 217 // By now the browser should have applied the styles, so the transition 218 // will only affect subsequent flips. 219 var speedInSec = self.setting.speed / 1000 || 0.5; 220 faces.css({ 221 "transition": "all " + speedInSec + "s ease-out" 222 }); 223 224 // This allows flip to be called for setup with only a callback (default settings) 225 if (typeof callback === 'function') { 226 callback.call(self.element); 227 } 228 229 // While this used to work with a setTimeout of zero, at some point that became 230 // unstable and the initial flip returned. The reason for this is unknown but we 231 // will temporarily use a short delay of 20 to mitigate this issue. 232 }, 20); 233 234 self.attachEvents(); 235 }, 236 237 clickHandler: function(event) { 238 if (!event) { event = window.event; } 239 if (this.element.find($(event.target).closest('button, a, input[type="submit"]')).length) { 240 return; 241 } 242 243 if (this.isFlipped) { 244 this.unflip(); 245 } else { 246 this.flip(); 247 } 248 }, 249 250 hoverHandler: function() { 251 var self = this; 252 self.element.off('mouseleave.flip'); 253 254 self.flip(); 255 256 setTimeout(function() { 257 self.element.on('mouseleave.flip', $.proxy(self.unflip, self)); 258 if (!self.element.is(":hover")) { 259 self.unflip(); 260 } 261 }, (self.setting.speed + 150)); 262 }, 263 264 attachEvents: function() { 265 var self = this; 266 if (self.setting.trigger === "click") { 267 self.element.on($.fn.tap ? "tap.flip" : "click.flip", $.proxy(self.clickHandler, self)); 268 } else if (self.setting.trigger === "hover") { 269 self.element.on('mouseenter.flip', $.proxy(self.hoverHandler, self)); 270 self.element.on('mouseleave.flip', $.proxy(self.unflip, self)); 271 } 272 }, 273 274 flipChanged: function(callback) { 275 this.element.trigger('flip:change'); 276 if (typeof callback === 'function') { 277 callback.call(this.element); 278 } 279 }, 280 281 changeSettings: function(options, callback) { 282 var self = this; 283 var changeNeeded = false;
284 285 if (options.axis !== undefined && self.setting.axis !== options.axis.toLowerCase()) { 286 self.setting.axis = options.axis.toLowerCase(); 287 changeNeeded = true; 288 } 289 290 if (options.reverse !== undefined && self.setting.reverse !== options.reverse) { 291 self.setting.reverse = options.reverse; 292 changeNeeded = true; 293 } 294 295 if (changeNeeded) { 296 var faces = self.frontElement.add(self.backElement); 297 var savedTrans = faces.css(["transition-property", "transition-timing-function", "transition-duration", "transition-delay"]); 298 299 faces.css({ 300 transition: "none" 301 }); 302 303 // This sets up the first flip in the new direction automatically 304 var rotateAxis = "rotate" + self.setting.axis; 305 306 if (self.isFlipped) { 307 self.frontElement.css({ 308 transform: rotateAxis + (self.setting.reverse ? "(-180deg)" : "(180deg)"), 309 "z-index": "0" 310 }); 311 } else { 312 self.backElement.css({ 313 transform: rotateAxis + (self.setting.reverse ? "(180deg)" : "(-180deg)"), 314 "z-index": "0" 315 }); 316 } 317 // Providing a nicely wrapped up callback because transform is essentially async 318 setTimeout(function() { 319 faces.css(savedTrans); 320 self.flipChanged(callback); 321 }, 0); 322 } else { 323 // If we didnt have to set the axis we can just call back. 324 self.flipChanged(callback); 325 } 326 } 327 328 }); 329 330 /* 331 * jQuery collection methods 332 */ 333 $.fn.flip = function (options, callback) { 334 if (typeof options === 'function') { 335 callback = options; 336 } 337 338 if (typeof options === "string" || typeof options === "boolean") { 339 this.each(function() { 340 var flip = $(this).data('flip-model'); 341 342 if (options === "toggle") { 343 options = !flip.isFlipped; 344 } 345 346 if (options) { 347 flip.flip(callback); 348 } else { 349 flip.unflip(callback); 350 } 351 }); 352 } else { 353 this.each(function() { 354 if ($(this).data('flip-model')) { // The element has been initiated, all we have to do is change applicable settings 355 var flip = $(this).data('flip-model'); 356 357 if (options && (options.axis !== undefined || options.reverse !== undefined)) { 358 flip.changeSettings(options, callback); 359 } 360 } else { // Init 361 $(this).data('flip-model', new Flip($(this), (options || {}), callback)); 362 } 363 }); 364 } 365 366 return this; 367 }; 368 369}( 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.