1/* 2 * jQuery Custombox v1.0.2 - 2013-10-08 3 * jQuery Modal Window Effects. 4 * http://dixso.github.io/custombox/ 5 * (c) 2013 Julio De La Calle - http://dixso.net - @dixso9 6 * 7 * Under MIT License - http://www.opensource.org/licenses/mit-license.php 8 */ 9// the semi-colon before function invocation is a safety net against concatenated 10// scripts and/or other plugins which may not be closed properly. 11;(function ( $, window, document, undefined ) { 12 "use strict"; 13 // undefined is used here as the undefined global variable in ECMAScript 3 is 14 // mutable (ie. it can be changed by someone else). undefined isn't really being 15 // passed in so we can ensure the value of it is truly undefined. In ES5, undefined 16 // can no longer be modified. 17 18 // window and document are passed through as local variable rather than global 19 // as this (slightly) quickens the resolution process and can be more efficiently 20 // minified (especially when both are regularly referenced in your plugin). 21 22 // Create the defaults once. 23 var cb = 'custombox', 24 defaults = { 25 url: null, // Set the URL, ID or Class. 26 cache: false, // If set to false, it will force requested pages not to be cached by the browser only when send by AJAX. 27 escKey: true, // Allows the user to close the modal by pressing 'ESC'. 28 eClose: null, // Element ID or Class for to be close the modal. 29 zIndex: 9999, // Overlay z-index: Number or auto. 30 overlay: true, // Show the overlay. 31 overlayColor: '#000', // Overlay color. 32 overlayOpacity: 0.8, // The overlay opacity level. Range: 0 to 1. 33 overlayClose: true, // Allows the user to close the modal by clicking the overlay. 34 overlaySpeed: 200, // Sets the speed of the overlay, in milliseconds. 35 customClass: null, // Custom class to modal. 36 width: null, // Set a fixed total width. 37 height: null, // Set a fixed total height. 38 effect: 'fadein', // fadein | slide | newspaper | fall | sidefall | blur | flip | sign | superscaled | slit | rotate | letmein | makeway | slip | blur. 39 position: null, // Only with effects: slide, flip and rotate. (top, right, bottom, left and center) | (vertical or horizontal). 40 speed: 600, // Sets the speed of the transitions, in milliseconds. 41 open: null, // Callback that fires right before begins to open. 42 complete: null, // Callback that fires right after loaded content is displayed. 43 close: null, // Callback that fires once is closed. 44 error: 'Error 404!', // Text to be displayed when an error. 45 responsive: true 46 }; 47 48 // The plugin constructor. 49 function Plugin ( element, options ) { 50 51 this.element = element; 52 53 // Get the max zIndex. 54 if ( typeof this.element === 'object' && typeof options === 'object' && isNaN( options.zIndex ) && options.zIndex === 'auto' ) { 55 options.zIndex = ( this._isIE() ? defaults.zIndex : this._zIndex() ); 56 } 57 58 // Merge objects. 59 this.settings = this._extend( {}, defaults, options ); 60 61 if ( typeof this.element === 'object' ) { 62 // Private method. 63 this._box.init( this ); 64 } else { 65 // Public method. 66 this[this.element](); 67 } 68 69 } 70 71 Plugin.prototype = { 72 /* 73 ---------------------------- 74 Private methods 75 ---------------------------- 76 */ 77 _overlay: function() { 78 var rgba = this._hexToRgb(this.settings.overlayColor), 79 styles = {}; 80 // Only IE 8 81 if ( navigator.appVersion.indexOf('MSIE 8.') != -1 ) { 82 styles.backgroundColor = this.settings.overlayColor; 83 styles.zIndex = parseFloat(this.settings.zIndex) + 1; 84 styles.filter = 'alpha(opacity=' + this.settings.overlayOpacity * 100 + ')'; 85 } else { 86 styles['background-color'] = 'rgba(' + rgba.r + ',' + rgba.g + ', ' + rgba.b + ',' + this.settings.overlayOpacity + ')'; 87 styles['z-index'] = parseFloat(this.settings.zIndex) + 1; 88 styles['transition'] = 'all ' + this.settings.overlaySpeed / 1000 + 's'; 89 } 90 91 document.getElementsByTagName('body')[0].appendChild(this._create({ 92 id: 'overlay', 93 eClass: 'overlay' 94 }, styles)); 95 }, 96 _box: { 97 init: function ( obj ) { 98 // Check if callback 'open'. 99 if ( obj.settings.open && typeof obj.settings.open === 'function' ) { 100 obj.settings.open( undefined !== arguments[0] ? arguments[0] : '' ); 101 } 102 103 // Add generic class custombox. 104 obj._addClass( document.getElementsByTagName( 'html' )[0], 'html' ); 105 106 // Check if scrollbar is visible. 107 var body = document.body, 108 html = document.documentElement; 109 110 var bodyHeight = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
111 windowHeight = 'innerHeight' in window ? window.innerHeight : document.documentElement.offsetHeight; 112 113 if ( bodyHeight > windowHeight ) { 114 115 var outer = obj._create({},{ 116 visibility: 'hidden', 117 width: '100px' 118 }); 119 120 body.appendChild(outer); 121 122 var widthNoScroll = outer.offsetWidth; 123 124 // Force scrollbars 125 outer.style.overflow = "scroll"; 126 127 // Add inner div. 128 var inner = obj._create({},{ 129 width: '100%' 130 }); 131 132 outer.appendChild(inner); 133 134 var widthWithScroll = inner.offsetWidth; 135 136 // Remove divs 137 outer.parentNode.removeChild(outer); 138 139 // Hide scrollbar. 140 obj._addClass( body, 'scrollbar' ); 141 body.style.marginRight = widthNoScroll - widthWithScroll + 'px'; 142 } 143 144 // Check 'href'. 145 if ( obj.settings.url === null ) { 146 if ( obj.element !== null ) { 147 obj.settings.url = obj.element.getAttribute('href'); 148 } 149 } 150 151 if ( typeof obj.settings.url === 'string' ) { 152 if ( obj.settings.url.charAt(0) === '#' || obj.settings.url.charAt(0) === '.' ) { 153 // Inline. 154 if ( document.querySelector(obj.settings.url) ) { 155 obj._box.build( obj, document.querySelector(obj.settings.url).cloneNode(true) ); 156 } else { 157 obj._box.build( obj, null ); 158 } 159 } else { 160 // Ajax. 161 this.ajax( obj ); 162 } 163 } else { 164 obj._box.build( obj, null ); 165 } 166 }, 167 create: function ( obj ) { 168 var styles = {}; 169 170 if ( obj._isIE() ) { 171 styles.zIndex = parseFloat(obj.settings.zIndex) + 2; 172 } else { 173 styles['z-index'] = parseFloat(obj.settings.zIndex) + 2; 174 } 175 176 var modal = obj._create({ 177 id: 'modal', 178 eClass: 'modal ' + obj._box.effect( obj ) + ( obj.settings.customClass ? ' ' + obj.settings.customClass : '' ) 179 }, styles), 180 content = obj._create({ 181 id: 'modal-content', 182 eClass: 'modal-content' 183 }, { 184 'transition-duration': obj.settings.speed / 1000 + 's' 185 }); 186 187 // Insert modal to the content. 188 modal.appendChild(content); 189 190 // Insert modal just after the body. 191 document.body.insertBefore(modal, document.body.firstChild); 192 193 // Create overlay after the modal content. 194 if ( obj.settings.overlay ) { 195 obj._overlay(); 196 } 197 198 return [modal, content]; 199 }, 200 effect: function ( obj ) { 201 var position = ['slide','flip','rotate'], 202 perspective = ['letmein','makeway','slip','blur'], 203 effect = cb + '-' + obj.settings.effect; 204 205 // Position. 206 for ( var i = 0, len1 = position.length; i < len1; i++ ) { 207 if ( position[i] === obj.settings.effect ) { 208 effect = cb + '-' + obj.settings.effect + '-' + obj.settings.position; 209 } 210 } 211 212 // HTML head. 213 for ( var x = 0, len2 = perspective.length; x < len2; x++ ) { 214 if ( perspective[x] === obj.settings.effect ) { 215 216 if ( obj.settings.effect !== 'blur' ) { 217 // Add class. 218 obj._addClass( document.getElementsByTagName( 'html' )[0], 'perspective' ); 219 } 220 221 var div = document.createElement('div'); 222 div.className = cb + '-container'; 223 224 // Move the body's children into this wrapper 225 while ( document.body.firstChild ) { 226 div.appendChild(document.body.firstChild); 227 } 228 229 // Append the wrapper to the body 230 document.body.appendChild(div); 231 } 232 } 233 234 return effect; 235 236 }, 237 build: function ( obj, modal ) { 238 239 if ( obj.settings.error !== false && typeof obj.settings.error === 'string' ) { 240 // If is null, show message error. 241 if ( modal === null ) { 242 modal = document.createElement('div'); 243 obj._addClass( modal, 'error' ); 244 modal.innerHTML = obj.settings.error; 245 } 246 247 // [0] => modal 248 // [1] => content 249 var tmp = obj._box.create( obj ); 250 251 // Insert content to the modal. 252 tmp[1].appendChild(modal); 253 254 // Show the content. 255 modal.style.display = 'block'; 256 257 // Temporal sizes. 258 var tmpSize = { 259 width: parseInt(obj.settings.width, 0), 260 height: parseInt(obj.settings.height, 0) 261 }; 262 263 // Check width: If it is a number and if not null.
264 if ( !isNaN( tmpSize.width ) && tmpSize.width === obj.settings.width && tmpSize.width.toString() === obj.settings.width.toString() && tmpSize.width !== null ) { 265 modal.style.width = tmpSize.width + 'px'; 266 } 267 268 // Check height: If it is a number and if not null. 269 if ( !isNaN( tmpSize.height ) && tmpSize.height === obj.settings.height && tmpSize.height.toString() === obj.settings.height.toString() && tmpSize.height !== null ) { 270 modal.style.height = tmpSize.height + 'px'; 271 } 272 273 // Only IE 8. 274 if ( navigator.appVersion.indexOf('MSIE 8.') != -1 ) { 275 modal.style.marginLeft = - modal.offsetWidth / 2 + 'px'; 276 modal.style.marginTop = - modal.offsetHeight / 2 + 'px'; 277 } 278 279 // Show modal. 280 setTimeout( function () { 281 282 // Init listeners. 283 obj._listeners(); 284 285 // Show modal. 286 tmp[0].className += ' ' + cb + '-show'; 287 288 var script = tmp[1].getElementsByTagName('script'); 289 290 // Execute the scripts. 291 for ( var i = 0, len = script.length; i < len; i++ ) { 292 new Function( script[i].text )(); 293 } 294 295 setTimeout( function () { 296 // Check if callback 'complete'. 297 if ( obj.settings.complete && typeof obj.settings.complete === 'function' ) { 298 obj.settings.complete( undefined !== arguments[0] ? arguments[0] : '' ); 299 } 300 }, obj.settings.speed ); 301 302 }, ( obj.settings.overlay ? obj.settings.overlaySpeed : 200 ) ); 303 } 304 }, 305 ajax: function ( obj ) { 306 var xhr = new XMLHttpRequest(); 307 xhr.onreadystatechange = function () { 308 var completed = 4; 309 if( xhr.readyState === completed ) { 310 if( xhr.status === 200 ) { 311 312 var modal = document.createElement('div'); 313 modal.innerHTML = xhr.responseText; 314 315 obj._box.build( obj, modal ); 316 317 } else { 318 obj._box.build( obj, null ); 319 } 320 } 321 }; 322 xhr.open('GET', obj.settings.url + ( !obj.settings.cache ? '?_=' + new Date().getTime() : '' ), true); 323 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 324 xhr.send(null); 325 } 326 }, 327 _close: function () { 328 var obj = this, 329 d = document; 330 obj._removeClass( ( obj._isIE() ? d.querySelectorAll('.' + cb + '-modal')[0] : d.getElementsByClassName(cb + '-modal')[0] ), cb + '-show' ); 331 obj._removeClass( d.getElementsByTagName( 'html' )[0], cb + '-perspective' ); 332 333 setTimeout( function () { 334 // Remove classes. 335 obj._removeClass( d.getElementsByTagName( 'html' )[0], cb + '-html' ); 336 obj._removeClass( d.getElementsByTagName( 'body' )[0], cb + '-scrollbar' ); 337 d.getElementsByTagName( 'body' )[0].style.marginRight = null; 338 339 // Remove modal. 340 var modal = ( obj._isIE() ? d.querySelectorAll('.' + cb + '-modal')[0] : d.getElementsByClassName(cb + '-modal')[0] ); 341 obj._remove( modal ); 342 343 // Remove overlay. 344 if ( obj.settings.overlay ) { 345 obj._remove( ( obj._isIE() ? d.querySelectorAll('.' + cb + '-overlay')[0] : d.getElementsByClassName(cb + '-overlay')[0] ) ); 346 } 347 348 // Check if callback 'close'. 349 if ( obj.settings.close && typeof obj.settings.close === 'function' ) { 350 obj.settings.close( undefined !== arguments[0] ? arguments[0] : '' ); 351 } 352 353 // Check if callback 'close' when the method is public. 354 if ( modal.getAttribute('data-' + cb) !== null ) { 355 var onClose = modal.getAttribute('data-' + cb), 356 onCloseLaunch = new Function ( 'onClose', 'return ' + onClose )(onClose); 357 onCloseLaunch(); 358 } 359 360 }, obj.settings.speed ); 361 }, 362 _listeners: function () { 363 var obj = this; 364 365 // Listener overlay. 366 if ( obj._isIE() ) { 367 if ( typeof document.querySelectorAll('.' + cb + '-overlay')[0] !== 'undefined' && obj.settings.overlayClose ) { 368 document.querySelectorAll('.' + cb + '-overlay')[0].attachEvent('onclick', function () { 369 obj._close(); 370 }); 371 } 372 } else { 373 if ( typeof document.getElementsByClassName(cb + '-overlay')[0] !== 'undefined' && obj.settings.overlayClose ) { 374 document.getElementsByClassName(cb + '-overlay')[0].addEventListener('click', function () { 375 obj._close(); 376 }, false ); 377 } 378 } 379 380 // Listener on tab key esc. 381 if ( obj.settings.escKey ) { 382 document.onkeydown = function ( evt ) { 383 evt = evt || window.event; 384 if ( evt.keyCode === 27 ) { 385 obj._close(); 386 } 387 }; 388 } 389 390 // Listener on element close. 391 if ( obj.settings.eClose !== null && typeof obj.settings.eClose === 'string' && obj.settings.eClose.charAt(0) === '#' || typeof obj.settings.eClose === 'string' && obj.settings.eClose.charAt(0) === '.' && document.querySelector(obj.settings.eClose) ) { 392 document.querySelector(obj.settings.eClose).addEventListener('click', function () { 393 obj._close(); 394 }, false ); 395 } 396 397 // Check if callback 'close'. 398 if ( obj.settings.close && typeof obj.settings.close === 'function' ) { 399 400 var store = obj.settings.close; 401 var modal = ( obj._isIE() ? document.querySelectorAll('.' + cb + '-modal')[0] : document.getElementsByClassName(cb + '-modal')[0] ); 402 modal.setAttribute('data-' + cb, store); 403 404 } 405 406 }, 407 /* 408 ---------------------------- 409 Utilities 410 ---------------------------- 411 */ 412 _extend: function () { 413 for( var i = 1, arg = arguments.length; i < arg; i++ ) { 414 for( var key in arguments[i] ) { 415 if( arguments[i].hasOwnProperty(key) ) { 416 arguments[0][key] = arguments[i][key]; 417 } 418 } 419 } 420 return arguments[0]; 421 }, 422 _create: function ( attr, styles, element ) { 423 var div = ( element === undefined || element === null ? document.createElement('div') : element ); 424 425 if ( attr !== null ) { 426 // Add the id. 427 if ( attr.id !== null ) { 428 div.id = cb + '-' + attr.id + new Date().getTime(); 429 } 430 431 // Add the class. 432 if ( attr.eClass !== null ) { 433 this._addClass( div, attr.eClass ); 434 } 435 } 436 437 if ( styles !== null ) { 438 439 // Loop with styles (obj). 440 for ( var obj in styles ) { 441 if ( styles.hasOwnProperty(obj) ) { 442 // Insert browser dependent styles. 443 if ( this._isIE() ) { 444 div.style[obj] = styles[obj]; 445 } else { 446 div.style.setProperty( obj, styles[obj], null ); 447 } 448 449 if ( obj === 'transition-duration' && !this._isIE() ) { 450 var prefix = [ '-webkit-', '-moz-', '-o-', '-ms-' ]; 451 // Insert prefix. 452 for ( var x = 0, pre = prefix.length; x < pre; x++ ) { 453 div.style.setProperty( prefix[x] + obj, styles[obj], null ); 454 } 455 } 456 } 457 } 458 } 459 460 return div; 461 }, 462 _hexToRgb: function ( hex ) { 463 // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb 464 var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 465 hex = hex.replace(shorthandRegex, function(m, r, g, b) { 466 return r + r + g + g + b + b; 467 }); 468 469 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 470 return result ? { 471 r: parseInt(result[1], 16), 472 g: parseInt(result[2], 16), 473 b: parseInt(result[3], 16) 474 } : null; 475 }, 476 _addClass: function ( element, eClass ) { 477 if ( !this._hasClass( element, eClass ) ) { 478 element.className = ( element.className.length && element.className !== ' ' ? element.className + ' ' + cb + '-' + eClass : cb + '-' + eClass ); 479 } 480 }, 481 _removeClass: function ( element, eClass ) { 482 if ( this._hasClass( element, eClass ) ) { 483 var reg = new RegExp('(\\s|^)' + eClass + '(\\s|$)'); 484 element.className = element.className.replace(reg,' '); 485 } 486 }, 487 _hasClass: function ( element, eClass ) { 488 return ( element !== undefined ? element.className.match(new RegExp('(\\s|^)' + eClass + '(\\s|$)')) : false ); 489 }, 490 _remove: function ( element ) { 491 if ( element !== undefined ) { 492 element.parentNode.removeChild(element); 493 } 494 }, 495 _zIndex: function () { 496 var elems = document.getElementsByTagName('*'), 497 zIndexMax = 0; 498 for ( var i = 0, etotal = elems.length; i < etotal; i++ ) { 499 var zindex = document.defaultView.getComputedStyle(elems[i],null).getPropertyValue('z-index'); 500 if ( zindex > zIndexMax && zindex !== 'auto' ) { 501 zIndexMax = zindex; 502 } 503 } 504 return zIndexMax; 505 }, 506 _isIE: function () { 507 return navigator.appVersion.indexOf('MSIE 9.') != -1 || navigator.appVersion.indexOf('MSIE 8.') != -1; 508 }, 509 /* 510 ---------------------------- 511 Public methods 512 ---------------------------- 513 */ 514 close: function () { 515 this._close(); 516 } 517 }; 518 519 // A really lightweight plugin wrapper around the constructor,
520 // preventing against multiple instantiations with jQuery. 521 $.fn[ cb ] = function ( options ) { 522 var args = arguments, 523 isElement = typeof HTMLElement === 'object' ? options instanceof HTMLElement : options && typeof options === 'object' && options !== null && options.nodeType === 1 && typeof options.nodeName === 'string'; 524 525 if ( options === undefined || typeof options === 'object' ) { 526 if ( isElement ) { 527 528 if ( navigator.appName === 'Microsoft Internet Explorer' ) { 529 // Write a new regEx to find the version number. 530 var re = new RegExp('MSIE ([0-9]{1,}[.0-9]{0,})'); 531 532 // If the regEx through the userAgent is not null. 533 if (re.exec(navigator.userAgent) != null) { 534 //Set the IE version 535 var version = parseInt(RegExp.$1); 536 } 537 } 538 539 if ( typeof version === 'undefined' || version >= 10 ) { 540 // Check time to avoid double click. 541 if ( options.getAttribute('data-' + cb) !== null && parseInt(options.getAttribute('data-' + cb)) + 1 > Math.round( new Date().getTime() / 1000 )) { 542 return; 543 } 544 545 // Set time to avoid double click. 546 options.setAttribute('data-' + cb, Math.round( new Date().getTime() / 1000 ) ); 547 } 548 549 $(options).each( function () { 550 $.data( this, cb, new Plugin( this, args[1] ) ); 551 }); 552 553 } else { 554 new Plugin( null, args[0] ); 555 } 556 } else if ( typeof options === 'string' && options === 'close' ) { 557 $.data( this, cb, new Plugin( args[0], args[1] ) ); 558 } 559 }; 560 561})( jQuery, window, document );
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.