1(function (root, factory) { 2 //@author http://ifandelse.com/its-not-hard-making-your-library-support-amd-and-commonjs/ 3 if (typeof module === "object" && module.exports) { 4 module.exports = factory(require("jquery")); 5 } else { 6 root.ssi_modal = factory(root.jQuery); 7 } 8}(this, function ($) { 9 var animationSupport = checkAnimationSupport(); 10 var openedModals = 0; 11 var sharedBackdrop = 0; 12 var byKindShare = { 13 stackModal: 0, 14 normalModal: 0 15 }; 16 var uniqueId = 0; 17 var orphanBackdrop = false; 18 19 /** 20 * @constructor 21 * @param {object} options 22 * @return 23 */ 24 var Ssi_modal = function (options) { 25 /** 26 * @namespace 27 * @property {object} defaults - The default options. 28 * @property {string} defaults.content - The main content of the modal. 29 * @property {boolean|(boolean|'shared'|'byKindShared')} defaults.backdrop - Enables disables the back drop. The shared option defines that the modal will open a back drop only if there is not anyone already in the dom. * The byKindShared is similar to the shared but the already rendered backdrop must belong to the same kind of modals (normal modal,stack modal,imgBox modal) else will open new. 30 * @property {boolean} defaults.outSideClose - Close the modal when you click outside. 31 * @property {boolean} defaults.bodyScroll - Enables/disables the scroll bar of the document when the modal is opened. 32 * @property {boolean} defaults.closeIcon - Show/hide the close button 33 * @property {boolean} defaults.keepContent - Forces the modal to remove or not the content when it close.It not associated with stack modals 34 * @property {function} defaults.beforeShow - Callback when the modal opens. 35 * @property {function} defaults.onShow - Callback when the modal opens. 36 * @property {function} defaults.beforeClose - Callback when the modal closes. 37 * @property {function} defaults.onClose - Callback when the modal closes. 38 * @property {'right top'|'right bottom'|'left top'|'left bottom'|'center top'|'center bottom'} defaults.position - Sets the position of the modals. 39 * @property {boolean} defaults.stack - Make the modal a part of stack.For example toast/notification messages. Requires position. 40 * @property {boolean} defaults.onClickClose - Enables/Disables the ability to close the modal when you click in the main window. 41 * @property {string} defaults.className - Defines a class to the modal outer element. 42 * @property {string} defaults.backdropClassName - Defines a class to the backdrop element. 43 * @property {object} defaults.preview - Set the options and the state of a modal according to the preview 44 * @property {boolean} defaults.preview.icon - Generate an icon that allows the user to change display state 45 * @property {boolean} defaults.preview.hideIcons - Enables/disables the ability to hide the modal after a certain time when the modal is in fullScreen state. 46 * @property {'fullScreen' | 'normal'} defaults.preview.state - The state tha the modal will have when opens. 47 * @property {object | 'false'} defaults.closeAfter 48 * @property {number} defaults.closeAfter.time - After the defined time the modal will close. 49 * @property {boolean} defaults.closeAfter.displayTime - Display the in a span with class="ssi-displayTime" that you must set. In example <span class="ssi-displayTime"></span> . 50 * @property {boolean} defaults.closeAfter.resetOnHover -Reset the time that modal will close. 51 52 * @property {object} defaults.iframe - Options for iframe. 53 * @property {boolean} defaults.iframe.allowFullScreen - The default treasure. 54 * @property {string} defaults.iframe.className - Set a 55 * @property {boolean} defaults.center - Element centering.Not associated with positioned modals
56 * @property {boolean || string} defaults.animation - Enables/disables animations if you set a string all animation type will be set to that sting. 57 * @property {object || string || boolean} defaults.modalAnimation - Set the animations for the modal window. 58 * @property {string || boolean} defaults.modalAnimation.show - The animation tha start when the modal opens. 59 * @property {string || 'boolean} defaults.modalAnimation.hide - The animation tha start when the modal closes. 60 * @property {boolean} defaults.backdropAnimation - Set the animations for modal the back drop. 61 * @property {string || boolean} defaults.backdropAnimation.show - The animation tha start when the backdrop appears. 62 * @property {string || 'boolean} defaults.backdropAnimation.hide - The animation tha start when the modal closes. 63 * @property {Object[]} defaults.buttons - The buttons of modal. 64 * @property {'button' || 'link'} defaults.buttons.type - The type of button. 65 * @property {keycode} defaults.buttons.keyPres - Registers a keypress event that will trigger the button's click method. 66 * @property {boolean} defaults.buttons.className - Defines a class to the button element. 67 * @property {number||false} defaults.buttons.enableAfter - Disables the button.if set a number the button will be enable after that time in seconds. 68 * @property {string} defaults.buttons.id - Defines an id to the button element. 69 * @property {string} defaults.buttons.label - The text of the button. 70 * @property {object || string || boolean} defaults.buttons.modalAnimation - Changes the animations of the modal. 71 * @property {object} defaults.buttons.modalAnimation.show - If you set this the next modal will open with this animation. 72 * @property {object} defaults.buttons.modalAnimation.hide - It changes the current modal hide animation. 73 * @property {object || string || boolean} defaults.buttons.backdropAnimation - Changes the animations of the backdrop. 74 * @property {object} defaults.buttons.backdropAnimation.show - If you set this the next backdrop will open with this animation. 75 * @property {object} defaults.buttons.backdropAnimation.hide - It changes the current backdrop hide animation. 76 * @property {boolean} defaults.iconButtons - Register a new icon in the top of the modal( where the x button is).You can modify it only with css using content and background properties. 77 * @property {boolean} defaults.iconButtons.className - Defines a class name to the element. 78 * @property {boolean} defaults.iconButtons.method - The function that will be fired when you press the icons.This function has access to the event object and the modal's object (ie function(event,modal){}) 79 * @property {boolean} defaults.title - The title of the modal. 80 * @property {string} defaults.sizeClass - Defines the size of the modal. 81 * @property {boolean} defaults.fixedHeight - If modal height is bigger than the screen the height of modal will be fixed and will fit the screen also the content will be scrollable. 82 * @property {boolean} defaults.fitScreen - The modal min-height will be the height of screen. 83 * @property {boolean} defaults.navigation - Enables/disables the navigation of imgBox. 84 */ 85 86 /** 87 * The unique id number of modal. 88 * @type {number} 89 */ 90 91 this.numberId = uniqueId; 92 if (options.stack) { 93 this.pluginName = 'stackModal'; 94 } else { 95 this.pluginName = 'normalModal'; 96 } 97 /** 98 * The id of the backdrop. 99 * @type {string} 100 */ 101 this.backdropId = ''; 102 this.showbd = true; 103 this.setOptions(options); 104 }; 105 Ssi_modal.prototype.setOptions = function (options, value) { 106 if (typeof options === 'object') { 107 var defaults = { 108 content: '', 109 bodyScroll: false, 110 keepContent: false, 111 position: '', 112 backdrop: true, 113 stack: false, 114 onClickClose: false, 115 bodyElement: false, 116 className: '', 117 backdropClassName: '', 118 preview: { 119 icon: false, 120 hideIcons: false, 121 state: 'normal'//full 122 }, 123 closeAfter: false, // time: 4, displayTime:false, resetOnHover:true } 124 outSideClose: true, 125 onClose: '', 126 onShow: '', 127 beforeClose: '', 128 beforeShow: '', 129 iframe: {//{className,allowfullscreen} 130 allowFullScreen: true, 131 className: '' 132 }, 133 center: false, 134 closeIcon: true, 135 navigation: false, 136 sizeClass: 'medium', 137 animation: false, 138 modalAnimation: undefined,//{show:'',hide:''} 139 backdropAnimation: undefined,//{show:'',hide:''} 140 animationSpeed: 300, 141 buttons: [], //[{className: 'btn btn-danger', enableAfter:3, id: '', label: 'Open', modalReverseAnimation:true backdropReverseAnimation:true closeAfter:{ clearTimeOut:true, keepContent:true, method: function(){ } } ] 142 iconButtons: [],//[className:'',method:function(){}] 143 title: '', 144 fixedHeight: false, 145 fitScreen: false 146 }; 147 var modalObj = this; 148 this.options = $.extend(true, defaults, options); 149 this.options.iconButtons = toArray(this.options.iconButtons); 150 if (this.options.preview.icon) { 151 this.options.iconButtons.push({ 152 className: 'ssi-displayIcon', method: function () { 153 modalObj.changePreviewState(); 154 } 155 }) 156 } 157 if (this.options.closeIcon) { 158 this.options.iconButtons.push({ 159 className: 'ssi-closeIcon', method: function () { 160 modalObj.close(); 161 } 162 }) 163 } 164 setAnimations(this); 165 } else { 166 this.options[options] = value; 167 if (options === 'animation' || 'modalAnimation' || 'backdropAnimation') { 168 setAnimations(this); 169 } 170 } 171 return this; 172 }; 173 /** 174 * Initialize the modal and backdrop and expose them to the DOM 175 * @returns {Ssi_modal} 176 */ 177 Ssi_modal.prototype.init = function () { 178 if (this.options.backdrop) 179 this.backdropInit(); 180 this.modalInit(); 181 uniqueId++; 182 return this; 183 }; 184 185 /** 186 * Returns the content element of the modal. 187 * @returns {JQuery} 188 */ 189 Ssi_modal.prototype.get$content = function () { 190 return this.get$modal().find('#ssi-modalContent'); 191 }; 192 //returns the outer element of the modal (ie if we use stack modals will return the window object else will return the modalOuter) 193 /** 194 * Returns the modal element of the modal. 195 * @returns {JQuery} 196 */ 197 Ssi_modal.prototype.get$modal = function (id) { 198 id = id || this.modalId; 199 return this.$modal || $('#' + id); 200 }; 201 /** 202 * Returns the title element of the modal. 203 * @returns {JQuery} 204 */ 205 Ssi_modal.prototype.get$title = function () { 206 return this.get$modal().find('#ssi-modalTitle'); 207 }; 208 Ssi_modal.prototype.destroyTitle = function () { 209 this.get$title().remove(); 210 this.options.title = ''; 211 return this; 212 }; 213 Ssi_modal.prototype.destroyContent = function () { 214 this.get$content().remove(); 215 this.options.content = ''; 216 return this; 217 }; 218 Ssi_modal.prototype.destroyButtons = function (type) { 219 this.get$buttons(type).remove(); 220 this.options.buttons = []; 221 return this; 222 }; 223 Ssi_modal.prototype.destroyIcons = function () { 224 this.get$icons().remove(); 225 this.options.icons = []; 226 return this; 227 }; 228 229 /** 230 * Returns the title icons of the modal. 231 * @returns {JQuery} 232 */ 233 Ssi_modal.prototype.get$icons = function () { 234 return this.get$modal().find('.ssi-topIcons'); 235 }; 236 237 /** 238 * Returns the buttons element of the modal. 239 * @returns {JQuery} 240 */ 241 Ssi_modal.prototype.get$buttons = function (type) { 242 type = type || 'buttons'; 243 return this.get$modal().find('#ssi-' + type); 244 }; 245 /** 246 * Returns the window element of the modal. 247 * @returns {JQuery} 248 */ 249 Ssi_modal.prototype.get$window = function () { 250 return this.get$modal().find('#ssi-modalWindow'); 251 }; 252 253 /** 254 * Returns the wrapper element of the modal. 255 * @returns {JQuery} 256 */ 257 Ssi_modal.prototype.get$wrapper = function () { 258 if (this.options.stack) { 259 return this.get$modal().parent(); 260 } 261 return this.get$modal().find('#ssi-modalWrapper'); 262 }; 263 //returns the Outer element 264 /** 265 * Returns the outer element of the modal. 266 * @returns {JQuery} 267 */ 268 //returns the backdrop element 269 /** 270 * Returns the backdrop element of the modal. 271 * @returns {JQuery} 272 */ 273 Ssi_modal.prototype.get$backdrop = function () { 274 return this.$backdrop || $('#' + this.backdropId); 275 }; 276 277 var time = null; 278 279 //get/exit full screen state 280 /** 281 * Changes the previe state of the modal 282 * @returns {Ssi_modal} 283 */ 284 Ssi_modal.prototype.changePreviewState = function () { 285 var $modalOuter = this.get$modal(); 286 if (this.options.preview.state === 'fullScreen') {//if the current state is full 287 $modalOuter.removeClass('ssi-fullScreen');//remove class 288 this.options.preview.state = 'normal';//set state to normal 289 $modalOuter.find('#ssi-modalContent').css("height", ""); 290 if (this.options.fixedHeight || this.options.fitScreen) 291 this.setModalHeight();//set height again 292 clearTimeout(time); 293 $modalOuter.off('mousemove.ssi-modal'); 294 } else {//if current state is normal 295 if (this.options.preview.hideIcons) { 296 var $icons = $modalOuter.find('.ssi-topIcons'); 297 if (this.options.buttons) 298 var $buttons = $modalOuter.find('#ssi-buttons');//find the buttons area 299 $modalOuter.on('mousemove.ssi-modal', function () {//register mousemove event 300 clearTimeout(time); 301 $icons.fadeIn();//show the icons 302 $buttons.slideDown();//and buttons 303 time = setTimeout(function () {//after 2 seconds 304 $buttons.slideUp();//hide them 305 $icons.fadeOut() 306 }, 2000) 307 }); 308 } 309 this.setModalHeight(40, 'height'); //set the height 310 $modalOuter.addClass('ssi-fullScreen'); 311 this.options.preview.state = 'fullScreen';//change state to full 312 } 313 return this; 314 }; 315 316 Ssi_modal.prototype.setPluginName = function (name) { 317 this.pluginName = name; 318 byKindShare[name] = 0; 319 return this; 320 }; 321 322 /** 323 * Initialize the content element if it is necessary and registers tha content. 324 * @param {string} content -The content of the element. 325 * @param{'html' || 'append' || 'prepend} method -The jquery method tha will use to register the content to the modal. 326 * @returns {*} 327 */ 328 Ssi_modal.prototype.setContent = function (content, method) { 329 method = method || 'html'; 330 var $modalContent; 331 if (this.options.content !== true) {
332 $modalContent = $('<div id="ssi-modalContent" class="ssi-modalContent ' + (this.options.fixedHeight ? 'ssi-overflow ' : '') + '"></div>'); 333 if (this.options.content === '') { 334 if (this.options.title === true) { 335 this.get$title().after($modalContent) 336 } else { 337 this.get$window().prepend($modalContent); 338 } 339 this.setModalHeight(); 340 } 341 this.options.content = true; 342 } else { 343 $modalContent = this.get$content(); 344 } 345 var theContent = content; 346 if (content instanceof $ && this.options.bodyElement === true) { 347 if (this.options.extendOriginalContent === true) { 348 var beforeClose = this.options.beforeClose; 349 this.options.beforeClose = function (modal) { 350 var resume; 351 if (typeof beforeClose === 'function') 352 resume = beforeClose(modal); 353 if (resume !== false) { 354 content.eq(0).after(modal.get$content().contents().unwrap().css('display', '')).remove(); 355 } else { 356 return resume 357 } 358 359 }; 360 } 361 362 theContent = content.eq(0).clone(); 363 if (!theContent.is(":visible")) { 364 theContent.show(); 365 } 366 } 367 $modalContent[method](theContent); 368 369 return $modalContent 370 }; 371 372 /** 373 * Initialize the buttons element if it is necessary and registers tha buttons. 374 * @param {object[]} buttons -The buttons that will be added to the element. 375 * @param {string} area -The area that we'll append the buttons. 376 * @returns {*} 377 */ 378 Ssi_modal.prototype.setButtons = function (buttons, area) { 379 var $buttonsArea, fixHeight = false; 380 buttons = toArray(buttons); 381 if (area !== false) { 382 area = (typeof area !== 'undefined' ? $(area) : this.get$window()); 383 $buttonsArea = area.find('#ssi-buttons'); 384 $buttonsArea = $buttonsArea[0]; 385 } 386 387 if (!$buttonsArea) { 388 $buttonsArea = $('<div id="ssi-buttons" class="ssi-buttons"><div id="ssi-leftButtons" class="ssi-leftButtons"></div><div id="ssi-rightButtons" class="ssi-rightButtons"></div></div>'); 389 if (area) { 390 fixHeight = true; 391 area.append($buttonsArea); 392 } 393 394 this.options.buttons = true; 395 } 396 var length = buttons.length; 397 var $leftArea = $buttonsArea.find('#ssi-leftButtons'); 398 var $rightArea = $buttonsArea.find('#ssi-rightButtons'); 399 var leftAreaArray = []; 400 var rightAreaArray = []; 401 for (var i = 0, $btn; i < length; i++) { 402 $btn = this.generateButton(buttons[i]); 403 if (buttons[i].side === 'left') { 404 leftAreaArray.push($btn); 405 } else { 406 rightAreaArray.push($btn); 407 } 408 } 409 $leftArea.append(leftAreaArray); 410 $rightArea.append(rightAreaArray); 411 if (fixHeight)this.setModalHeight(); 412 return $buttonsArea; 413 }; 414 /** 415 * Helps to define the animations 416 */ 417 var changeAnimations = function (animations, type) { 418 switch (typeof animations) { 419 case 'boolean': 420 if (type === 'show') { 421 animations = (animations ? 'anim ssi-fadeIn' : 'ssi-show') 422 } else { 423 animations = (animations ? 'anim ssi-fadeOut' : 'ssi-hidden') 424 } 425 break; 426 case 'undefined': 427 if (type === 'show') { 428 animations = 'ssi-show'; 429 } else { 430 animations = 'ssi-hidden'; 431 } 432 } 433 return animations 434 }; 435 /** 436 * Helps to define the animations 437 */ 438 var setAnimations = function (modalObj) { 439 var modalAnim = (modalObj.options.modalAnimation || modalObj.options.animation || false); 440 var backdropAnim = (modalObj.options.backdropAnimation || modalObj.options.animation || false); 441 var inAnim, 442 outAnim; 443 444 inAnim = changeAnimations((typeof modalAnim.show !== 'undefined' ? modalAnim.show : modalAnim), 'show'); 445 outAnim = changeAnimations((typeof modalAnim.hide !== 'undefined' ? modalAnim.hide : modalAnim), 'hide'); 446 modalObj.options.modalAnimation = { 447 'show': inAnim, 448 'hide': outAnim 449 }; 450 451 inAnim = changeAnimations((typeof backdropAnim.show !== 'undefined' ? backdropAnim.show : backdropAnim), 'show'); 452 outAnim = changeAnimations((typeof backdropAnim.hide !== 'undefined' ? backdropAnim.hide : backdropAnim), 'hide'); 453 modalObj.options.backdropAnimation = { 454 'show': inAnim, 455 'hide': outAnim 456 }; 457 if (animationSupport === false) { 458 modalObj.options.modalAnimation = { 459 'show': (modalObj.options.modalAnimation.show !== 'ssi-show' ? 'anim ssi-fadeIn' : 'ssi-show'), 460 'hide': (modalObj.options.modalAnimation.hide !== 'ssi-hidden' ? 'anim ssi-fadeOut' : 'ssi-hidden') 461 }; 462 modalObj.options.backdropAnimation = { 463 'show': (modalObj.options.backdropAnimation.show !== 'ssi-show' ? 'anim ssi-fadeIn' : 'ssi-show'), 464 'hide': (modalObj.options.backdropAnimation.hide !== 'ssi-hidden' ? 'anim ssi-fadeOut' : 'ssi-hidden') 465 }; 466 } 467 }; 468 /** 469 * Register events and timer for closeAfter property 470 * */ 471 var setCloseAfter = function (modalObj) { 472 var $modal = modalObj.get$modal(); 473 modalObj.time = setTimeout(function () { 474 475 modalObj.close(); 476 }, (modalObj.options.closeAfter.time * 1000)); 477 if (modalObj.options.closeAfter.displayTime && modalObj.options.title) { 478 var $displayTime = $modal.find('span.ssi-displayTime').html(modalObj.options.closeAfter.time); 479 updateTime(modalObj, $displayTime, function () {
480 modalObj.$displayTime.remove() 481 }); 482 } 483 if (modalObj.options.closeAfter.resetOnHover) { 484 $modal.on('mouseenter.ssi-modal', function () { 485 clearTimeout(modalObj.time); 486 if ($displayTime) { 487 $displayTime.html(modalObj.options.closeAfter.time); 488 clearInterval(modalObj.countDown); 489 } 490 }); 491 $modal.on('mouseleave.ssi-modal', function () { 492 modalObj.time = setTimeout(function () { 493 modalObj.close(); 494 }, (modalObj.options.closeAfter.time * 1000)); 495 if (modalObj.options.closeAfter.displayTime && modalObj.options.title) { 496 updateTime(modalObj, $displayTime, function () { 497 $displayTime.parent().remove() 498 }); 499 } 500 }); 501 } 502 }; 503 /** 504 * Initialize the backdrop and append it to the DOM 505 * 506 * @return {JQuery} 507 */ 508 Ssi_modal.prototype.backdropInit = function () { 509 var $backdrop; 510 if (typeof orphanBackdrop === 'string') {//if an orphan backdrop exists 511 var $orphanBackdrop = $('#' + orphanBackdrop); 512 this.backdropId = orphanBackdrop;//change the id to the same as the new modal 513 $backdrop = $orphanBackdrop.attr('class', 'ssi-backdrop ' + this.pluginName + ' ' + this.options.backdropClassName); 514 this.showbd = false; 515 orphanBackdrop = true; 516 } else { 517 $backdrop = $('<div id="ssi-backdrop' + this.numberId + '" class="ssi-backdrop ssi-hidden ' + (this.options.backdropClassName) + ' ' + this.pluginName + '"></div>'); 518 if (this.options.backdrop === 'shared' || this.options.backdrop === 'byKindShared') { 519 var $sharedBackdrop; 520 if (this.options.backdrop === 'byKindShared') { 521 $sharedBackdrop = $('.ssi-backdrop.ssi-openedDialog.' + this.pluginName); 522 } else { 523 $sharedBackdrop = $('.ssi-backdrop.ssi-openedDialog'); 524 } 525 if (!$sharedBackdrop[0]) {//check if backdrop already exists 526 $('body').append($backdrop);//if not , append one 527 this.backdropId = 'ssi-backdrop' + this.numberId; 528 this.showbd = true; 529 } else { 530 this.backdropId = $sharedBackdrop.attr('id'); 531 this.showbd = false; 532 $backdrop = $sharedBackdrop; 533 } 534 } else if (this.options.backdrop === true) { 535 $('body').append($backdrop); 536 this.backdropId = 'ssi-backdrop' + this.numberId; 537 this.showbd = true; 538 } 539 this.$backdrop = $backdrop; 540 } 541 if (this.options.outSideClose && this.options.position) {//check for ie 542 var modal = this; 543 $backdrop.on('click.ssi-modal' + this.numberId, function (e) { 544 e.preventDefault(); 545 modal.close(); 546 }); 547 } 548 return $backdrop; 549 }; 550 /** 551 * Initialize the outer. 552 * @return {JQuery} 553 */ 554 var setOuter = function (modalObj) { 555 return $('<div class="ssi-modalOuter ' + (modalObj.options.stack ? ' ssi-stack' : '' + modalObj.options.className) + (modalObj.options.center ? ' ssi-center ' : ' ') + ' ' + (modalObj.options.position ? ' ssi-modalPositioned ' + modalObj.options.position : '') + '"></div>'); 556 557 }; 558 559 /** 560 * Initialize the wrapper. 561 * @return $backdrop 562 */ 563 var setWrapper = function (modalObj) { 564 return $('<div id="ssi-modalWrapper" class=" ssi-modalWrapper ' + modalObj.options.sizeClass + '"></div>'); 565 566 }; 567 /** 568 * Initialize the icons element if necessary and append the icons to the element. 569 * @param {object[]} icons -The icons that will append to the icons element. 570 * @returns {jQuery} 571 */ 572 Ssi_modal.prototype.setIcons = function (icons) { 573 var $icons, iconArray = []; 574 if (this.options.iconButtons !== true) { 575 $icons = $('<div class="ssi-topIcons"></div>'); 576 this.options.iconButtons = true; 577 } else { 578 $icons = this.get$icons(); 579 } 580 var modalObj = this; 581 var iconsLength = icons.length; 582 for (var i = 0, icon;
582 i < iconsLength; i++) { 583 icon = icons[i]; 584 (function (icon) { 585 iconArray.push($('<a class="' + icon.className + '"></a>') 586 .click(function (e) { 587 e.preventDefault(); 588 if (typeof icon.method === 'function') { 589 $.proxy(icon.method, this)(e, modalObj); 590 } 591 })) 592 })(icon) 593 } 594 595 $icons.append(iconArray); 596 return $icons; 597 }; 598 /** 599 * Initialize the window 600 * @return {jQuery} 601 */ 602 var setWindow = function (modalObj) { 603 var $modalWindow = $('<div id="ssi-modalWindow" class="ssi-modalWindow ' + (modalObj.options.center ? modalObj.options.sizeClass : '') + (modalObj.options.stack ? ' ' + modalObj.options.sizeClass + ' ' + modalObj.options.className + ' ' : '') + '"></div>'), 604 $modalContent = '', 605 windowContent = []; 606 if (modalObj.options.content) { 607 $modalContent = modalObj.setContent(modalObj.options.content, 'html') 608 } 609 if (modalObj.options.title) { 610 windowContent.push(modalObj.setTitle(modalObj.options.title)); 611 } 612 if (modalObj.options.onClickClose) { 613 $modalWindow.addClass('ssi-hover').click(function (e) { 614 var $eTarget = $(e.target); 615 if (!$eTarget.is('a') && !$eTarget.is('button')) { 616 modalObj.close(); 617 } 618 }) 619 } 620 if ((modalObj.options.iconButtons).length > 0) { 621 windowContent.push(modalObj.setIcons(modalObj.options.iconButtons, true)); 622 } 623 windowContent.push($modalContent); 624 if (typeof modalObj.options.buttons !== 'undefined' && !$.isEmptyObject(modalObj.options.buttons)) { 625 windowContent.push(modalObj.setButtons(modalObj.options.buttons, false)); 626 } 627 $modalWindow.append(windowContent); 628 return $modalWindow; 629 }; 630 631 /** 632 *Generates a button according to the options. 633 * @param {object} buttonOptions -The button options. 634 * @constructor 635 * @returns {jQuery} 636 */ 637 638 Ssi_modal.prototype.generateButton = function (buttonOptions) { 639 var defaults = { 640 className: '', 641 enableAfter: false, 642 method: function () { 643 }, 644 type: 'button', 645 focused: false, 646 id: '', 647 label: '', 648 modalAnimation: '', 649 backdropAnimation: '' 650 }; 651 buttonOptions = $.extend({}, defaults, buttonOptions); 652 var tag = 'button', href = '', modalObj = this, resume; 653 if (buttonOptions.type === 'link') {//set tag type (<a> or <button>) 654 tag = 'a'; 655 href = ' href="#"'; 656 } 657 var $btn = $('<' + tag + href + (buttonOptions.id ? ' id="' + buttonOptions.id + '"' : ' ') + (buttonOptions.enableAfter ? 'disabled ' : '') + ' class="ssi-modalBtn ' + (buttonOptions.className || '') + '">' 658 + buttonOptions.label + 659 '</' + tag + '>'); 660 if (typeof buttonOptions.enableAfter === 'number') { 661 var $count = $('<span class="ssi-countDown">' + buttonOptions.enableAfter + '</span>'); 662 updateTime(modalObj, $count, function () { 663 $btn.removeClass('disabled'); 664 $btn.removeAttr('disabled'); 665 $count.remove(); 666 }); 667 $btn.append($count); 668 } 669//append button to selected object and set click event 670 if (buttonOptions.keyPress) { 671 $('body').on('keydown.ssi_modal', function (e) { 672 if (e.keyCode == buttonOptions.keyPress && !$btn.is(':disabled')) { 673 $btn.trigger('click'); 674 } 675 }); 676 } 677 if (buttonOptions.focused) { 678 setTimeout(function () { 679 $btn.focus(); 680 }, 100) 681 } 682 return $btn.click(function (e) { 683 e.preventDefault(); 684 if (buttonOptions.clearTimeOut) { 685 clearTimeOut(modalObj); 686 } 687 if (typeof buttonOptions.method === 'function') { 688 resume = $.proxy(buttonOptions.method, this)(e, modalObj); 689 } 690 if (resume === false) { 691 return; 692 } 693 if (typeof buttonOptions.keepContent === 'boolean' && buttonOptions.keepContent !== modalObj.options.keepContent) { 694 modalObj.options.keepContent = buttonOptions.keepContent; // change keepContent option according to button option 695 } 696 if (buttonOptions.closeAfter) { 697 modalObj.close(); 698//finally close the modal if closeAfter option is true 699 } 700 }); 701 }; 702 /** 703 * Initialize the modal and append it to the DOM 704 */ 705 Ssi_modal.prototype.modalInit = function () { 706 var $modalWindow = setWindow(this), 707 modalObj = this; 708 if (this.options.position) { 709 if (this.options.stack) { 710 var appendAction = 'append'; 711 if (this.options.position.indexOf('bottom') >
711 -1) {//if we hava bottom position we want to prepend the window to appears in the top of stack 712 appendAction = 'prepend'; 713 } 714 var position = this.options.position.replace(" ", '.');//change the spaces with dot to make it a class selector 715 var positionedElement = $('div.ssi-modalOuter.ssi-stack' + '.' + position); 716 if (positionedElement[0]) {//check if this element with this position exists to the dom. 717 positionedElement 718 .find('#ssi-modalWrapper')//if exists append the window to the dom. 719 [appendAction]($modalWindow); 720 } 721 this.$modal = $modalWindow; 722 } 723 } 724 if (!this.options.stack || !positionedElement[0]) {//if not stack modal or the element with this position dont exist to the dom create and append one. 725 var wrapper = setWrapper(this); 726 var $modal = setOuter(this) 727 .append(wrapper 728 .append($modalWindow)) 729 .appendTo($('body')); 730 if (!this.options.stack) {//if not stack give a unique id to the outer 731 this.$modal = $modal; 732 $modal.one('onShow.ssi-modal', function () { 733 if (modalObj.options.outSideClose === true) { 734 $modal.click(function (e) { 735 if (e.target === this) { 736 e.preventDefault(); 737 modalObj.close(); 738 } 739 }); 740 wrapper.click(function (e) { 741 if (e.target === this) { 742 e.preventDefault(); 743 modalObj.close(); 744 } 745 746 }); 747 } 748 }) 749 750 } 751 } 752 this.modalId = 'ssi-' + this.pluginName + this.numberId; 753 (this.$modal).attr('id', 'ssi-' + this.pluginName + this.numberId); 754 (this.$modal).addClass(this.pluginName + ' ssi-modal'); 755 this.$modal.data('ssi-modal', this).addClass('ssi-hidden'); 756 if (typeof orphanBackdrop === 'string')this.backdropInit(); 757 return this.$modal; 758 }; 759 /** 760 * Appends title to the modal. 761 * @param {string} title 762 * @return $title 763 */ 764 Ssi_modal.prototype.setTitle = function (title) { 765 var $title, fixHeight = false; 766 if (this.options.title !== true) { 767 $title = $('<div id="ssi-modalTitle" class="ssi-modalTitle ' + (!this.options.content ? 'ssi-borderOut ' : '') + '">' + this.options.title + '</div>'); 768 if (this.options.title === '') { 769 this.get$window().prepend($title); 770 fixHeight = true; 771 } 772 this.options.title = true; 773 } else { 774 $title = this.get$title(); 775 } 776 $title.html(title); 777 if (fixHeight)this.setModalHeight(); 778 return $title; 779 }; 780 781 Ssi_modal.prototype.showModal = function () { 782 var $modal = this.get$modal(), 783 modalObj = this; 784 785 setTimeout(function () { 786 $modal.trigger("beforeShow.ssi-modal");//trigger show event 787 }, 0); 788 if (this.options.bodyScroll === false) { 789 $('body').addClass('ssi-modalOpen');//add this class to body to disable scrollbar 790 openedModals++;//calculate open modals 791 } 792 if (this.options.backdrop === 'shared') { 793 sharedBackdrop++; 794 } else if (this.options.backdrop === 'byKindShared') { 795 byKindShare[this.pluginName]++ 796 } 797 798 $modal.addClass('ssi-openedDialog'); 799 var callback = function () { 800 $(this).removeClass('ssi-hidden'); 801 if (typeof modalObj.options.onShow === 'function') { 802 modalObj.options.onShow(modalObj);//execute onShow callback 803 } 804 setTimeout(function () { 805 $modal.trigger("onShow.ssi-modal");//trigger show event); 806 }, 0); 807 }; 808 $modal.addAnimation(this.options.modalAnimation.show, function () { 809 callback(); 810 }).removeClass('ssi-hidden'); 811 if (this.options.center) { 812 $modal.css('display', ''); 813 } 814 if (modalObj.options.preview.state === 'fullScreen') {//if the default state is fullscreen 815 modalObj.options.preview.state = 'normal'; 816 modalObj.changePreviewState(); 817 } 818 819 this.setModalHeight(); 820 821 if (typeof this.options.closeAfter.time === 'number') { 822 setCloseAfter(this) 823 } 824 delete this.$modal; 825 826 }; 827 828 /** 829 * Opens the modal. 830 * @return {Ssi_modal} 831 */ 832 Ssi_modal.prototype.showBackdrop = function () { 833 var modalObj = this; 834 var $backdrop = this.get$backdrop().addClass('ssi-openedDialog'); 835 836 $backdrop.addAnimation(this.options.backdropAnimation.show).removeClass('ssi-hidden'); 837 838 delete this.$backdrop; 839 }; 840 841 Ssi_modal.prototype.show = function () { 842 843 if (typeof this.options.beforeShow === 'function') { 844 var resume = this.options.beforeShow(this); 845 if (resume === false) { 846 return this; 847 } 848 } 849 850 this.showModal(); 851 852 if (orphanBackdrop === false && this.options.backdrop && this.showbd === true) { 853 this.showBackdrop(); 854 } 855 856 return this; 857 }; 858 859 /** 860 * Closes the modal 861 * @return {Ssi_modal} 862 */ 863 Ssi_modal.prototype.destroyBackdrop = function () { 864 var $backdrop = this.get$backdrop(), modalObj = this; 865 if (this.options.keepContent !== true) { 866 $backdrop.off('click.ssi-modal' + this.numberId); 867 } 868 var thisS = this 869 var closeBack = function () { 870 if ((thisS.options.backdrop === true || ( ( ( thisS.options.backdrop === 'shared' && sharedBackdrop < 1) || ( thisS.options.backdrop === 'byKindShared' && b
870yKindShare[thisS.pluginName] < 1) ) && ( (!thisS.get$modal(thisS.modalId.replace(thisS.numberId.toString(), thisS.backdropId.replace('ssi-backdrop', '')))[0]) || thisS.backdropId.replace('ssi-backdrop', '') == thisS.numberId)) )) {//thisS maybe blow your mine 871 var closeBackdrop = function () {//thisS will execute when the hide animation end 872 $backdrop.addClass('ssi-hidden').removeClass('ssi-openedDialog'); 873 $backdrop.trigger('backdropClose.ssi-modal'); 874 if (modalObj.options.keepContent !== true) $backdrop.remove();//remove backdrop if keepContent option is false 875 }; 876 $backdrop.addAnimation(thisS.options.backdropAnimation.hide, closeBackdrop); 877 } 878 if (orphanBackdrop === thisS.backdropId) { 879 orphanBackdrop = false; 880 } 881 } 882 if (this.options.stack && this.options.outSideClose) { 883 setTimeout(closeBack, 10); 884 } else { 885 closeBack() 886 } 887 return this; 888 }; 889 890 Ssi_modal.prototype.destroyModal = function () { 891 var $modal = this.get$modal(), 892 modalObj = this; 893 $modal.off('.ssi_modal'); 894 $modal.trigger("beforeClose.ssi-modal"); //trigger close event 895 if (this.options.backdrop === 'shared') { 896 sharedBackdrop--; 897 } else if (this.options.backdrop === 'byKindShared') { 898 byKindShare[this.pluginName]--; 899 } 900 901 if ($modal.hasClass('ssi-openedDialog')) { 902 $modal.removeClass('ssi-openedDialog'); 903 if (this.options.bodyScroll === false) { 904 openedModals--;// downgrade opened modals 905 } 906 } 907 908 var closeModal = function () {//this will execute as a callback when the hide animation end 909 $modal.addClass('ssi-hidden'); 910 if (modalObj.options.stack) { 911 $modal.addClass('ssi-smoothSlide').slideUp('500', function () { 912 $modal.removeClass('ssi-smoothSlide'); 913 $modal.trigger("onClose.ssi-modal"); //trigger close event 914 if (modalObj.options.keepContent !== true) $modal.remove();//will remove modal from DOM if keepContent option is false 915 916 }); 917 } else { 918 $modal.trigger("onClose.ssi-modal"); //trigger close event 919 if (modalObj.options.keepContent !== true)$modal.remove();//will remove modal from DOM if keepContent option is false 920 } 921 if (typeof modalObj.options.onClose === 'function') 922 modalObj.options.onClose(modalObj);//execute onClose callback 923 924 if (modalObj.options.keepContent !== true) { 925 $modal.off('.ssi-modal').find('#ssi-modalWrapper').off('.ssi-modal'); 926 } 927 }; 928 929 //close the modal window 930 $modal.addAnimation(this.options.modalAnimation.hide, closeModal); 931 this.options.icons = []; 932 this.options.buttons = []; 933 this.options.content = ''; 934 this.options.title = ''; 935 orphanBackdrop = this.backdropId; 936 return this; 937 }; 938 939 Ssi_modal.prototype.close = function () { 940 if (typeof this.options.beforeClose === 'function') { 941 var resume = this.options.beforeClose(this); 942 if (resume === false) { 943 return this; 944 } 945 } 946 var $body = $('body'); 947 $body.off('.ssi_modal'); 948 949 this.destroyModal(); 950 this.destroyBackdrop(); 951 952 if (openedModals < 1) {//if no more modals left remove class from body and off events 953 $body.removeClass('ssi-modalOpen'); 954 } 955 clearTimeOut(this); 956 return this; 957 }; 958 959//calculates modals height 960 /** 961 * Sets the height of the modal 962 * @method setModalHeight 963 * @param {number} offset -Add more offset to the modal. 964 * @param {'height'||'min-height'||'max-height'} option -Force the function to excecute. 965 * @param {object} $content -The $content object of modal. 966 * @return 967 */ 968 Ssi_modal.prototype.setModalHeight = function (offset, option) { 969 if (!this.options.fitScreen && !this.options.fixedHeight && !option) { 970 return this; 971 } 972 973 if (typeof offset !== 'number') { 974 offset = 100; 975 } 976 977 var $content = this.get$content(); 978 var windowHeight = $(window).height(), 979 btnsHeight = 0, titleHeight = 0; 980 if (this.options.buttons) 981 btnsHeight = $content.next().innerHeight(); 982 if (this.options.title) 983 titleHeight = this.get$title().innerHeight(); 984 var totalHeight = btnsHeight + titleHeight + offset, 985 optionsOffset = 0; 986 if (!option) { 987 988 if (this.options.fitScreen && this.options.fixedHeight) { 989 if (typeof this.options.fitScreen === 'number') { 990 optionsOffset = Math.abs((this.options.fitScreen + this.options.fixedHeight) / 2 - offset); 991 } 992 $content.css('height', windowHeight - totalHeight - optionsOffset); //add more margin down 993 } else { 994 if (this.options.fitScreen) { 995 if (typeof this.options.fitScreen === 'number') { 996 optionsOffset = Math.abs(this.options.fitScreen - offset); 997 } 998 $content.css('min-height', windowHeight - totalHeight - optionsOffset); //add more margin down 999 } 1000 if (this.options.fixedHeight) { 1001 optionsOffset = 0; 1002 if (typeof this.options.fixedHeight === 'number') { 1003 optionsOffset = Math.abs(this.options.fixedHeight - offset); 1004 } 1005 $content.css('max-height', (windowHeight - totalHeight - optionsOffset)); //add more margin down 1006 } 1007 } 1008 1009 } else if (typeof option === 'string') { 1010 $content.css(option, (windowHeight - totalHeight)); //add more margin down 1011 } 1012 return totalHeight; 1013 }; 1014 /** 1015 * Clears the timeout 1016 */ 1017 var clearTimeOut = function (modalObj) { 1018 clearTimeout(modalObj.time); 1019 modalObj.time = null; 1020 clearInterval(modalObj.countDown); 1021 1022 }; 1023 1024 /** 1025 * Updates the text of an element 1026 * @param {Ssi_modal} modalObj 1027 * @param {JQuery} $target -the element that will be updated 1028 * @param {function} callback -The function that will execute when the time expires; 1029 */ 1030 var updateTime = function (modalObj, $target, callback) { 1031 var doUpdate = function () { 1032 var count = parseInt($target.html()); 1033 if ((count - 1) !== 0) { 1034 $target.html(count - 1); 1035 } else { 1036 if (callback) 1037 callback(); 1038 clearInterval(modalObj.countDown); 1039 } 1040 }; 1041 modalObj.countDown = setInterval(doUpdate, 1000); 1042 }; 1043 1044//-------------------------------------------------------------------------------------------------------------- 1045 1046 /** 1047 * Creates a new modal window. 1048 * @param {object} options -The options of the modal 1049 * @param {string} element -The id or class name om the element that trigger the modal. 1050 * @return {Ssi_modal} 1051 */ 1052 1053 /** 1054 * @author http://stackoverflow.com/a/8015864/4801797 1055 */ 1056 $.fn.extend({ 1057 hasClasses: function (selectors) { 1058 var self = this; 1059 for (var i in selectors) { 1060 if ($(self).hasClass(selectors[i])) 1061 return true; 1062 } 1063 return false;
1064 } 1065 }); 1066 1067 var ssi_modal = { 1068 checkElement: function (element) { 1069 var $element = $(element); 1070 if ($element[0]) { 1071 var data = $element.data('ssi-modal');//then check if object exists in data-ssi-modal 1072 if (data) { 1073 if (!$('#' + data.modalId)[0]) {// if data exists but no modal exists(probably removed by button) 1074 $element.data('ssi-modal', '');//then remove data-ssi-modal 1075 return false 1076 } 1077 } 1078 } 1079 if (data) { 1080 return data 1081 } else { 1082 return false; 1083 } 1084 }, 1085 createObject: function (options, element) { 1086 var $element, obj, data; 1087 if (typeof element !== 'undefined') { //this means that we use jquery method(see line 406) 1088 $element = $(element); 1089 data = $element.data('ssi-modal');//then check if object exists in data-ssi-modal 1090 } else { 1091 options.keepContent = false; 1092 } 1093 if (data) { 1094 obj = data 1095 } else { 1096 obj = new Ssi_modal(options); 1097 if (typeof element !== 'undefined') { 1098 $element.data('ssi-modal', obj);// save the object to the target 1099 } 1100 } 1101 return obj; 1102 }, 1103 /** 1104 * Opens the modal 1105 * @param {object} options -The options of the modal. 1106 * @param {string} element -The id or class name om the element that trigger the modal. 1107 *@returns {Ssi_modal} 1108 */ 1109 show: function (options, element) { 1110 var obj = false; 1111 if (element) { 1112 obj = this.checkElement(element); 1113 } 1114 if (obj === false) { 1115 return this.createObject(options, element).init().show(); 1116 } else if (typeof obj === 'object') { 1117 return obj.show(); 1118 } 1119 1120 }, 1121 /** 1122 * Closes the targeted modal or the very top 1123 * @param {string} $target 1124 */ 1125 close: function ($target) { 1126 if (!$target) { 1127 var modal = $('.ssi-modalOuter'); 1128 $target = modal.eq(modal.length - 1); 1129 } 1130 return $target.data('ssi-modal') 1131 .close(); 1132 }, 1133 /** 1134 * Closes all or a group of modals. 1135 * @param {'normalModal'||'pluginName'} group 1136 * @param {className} except -The modal with this class will not close 1137 */ 1138 proto: Ssi_modal.prototype, 1139 closeAll: function (group, except) {//close all opened modal with the right order and all callbacks will execute normally 1140 except = toArray(except); 1141 var $activeModals; 1142 var groupVarType = typeof group; 1143 if ((groupVarType === 'string' && group !== '') || groupVarType === 'array') { 1144 group = toArray(group); 1145 var groupLength = group.length; 1146 for (var i = 0; i < groupLength; i++) { 1147 $activeModals = $('.ssi-modal.ssi-openedDialog.' + group[i]); 1148 close($activeModals); 1149 } 1150 } else { 1151 $activeModals = $('.ssi-modal.ssi-openedDialog'); 1152 close($activeModals); 1153 } 1154 1155 function close($modals) { 1156 var modalsLength = $modals.length; 1157 for (var i = modalsLength - 1; i >= 0; i--) { 1158 var $modal = $modals.eq(i); 1159 if (!$modal.hasClasses(except)) { 1160 $modal.data('ssi-modal').close(); 1161 } 1162 1163 } 1164 } 1165 }, 1166 /** 1167 * Remove immediately all the modals from the dom. No modal callbacks will execute. 1168 * @param {function} callback -Just a callback 1169 */ 1170 removeAll: function () {//close all opened modal no callbacks and no keepContent will execute you can determine one callback 1171 $('.ssi-modalOuter').addClass('ssi-hidden').remove(); 1172 $('.ssi-backdrop').addClass('ssi-hidden').remove(); 1173 $('body').removeClass('ssi-modalOpen'); 1174 openedModals = 0; 1175 sharedBackdrop = 0; 1176 byKindShare = { 1177 stackModal: 0, 1178 normalModal: 0 1179 }; 1180 uniqueId = 0; 1181 } 1182 }; 1183 1184//-----------------------------Start of confirm plugin------------------------------------------------------------------ 1185 1186 ssi_modal.dialog = function (options, method) { 1187 var defaults = { 1188 sizeClass: 'dialog', 1189 okBtn: { 1190 className: '', 1191 label: 'Ok' 1192 }, 1193 title: '', 1194 closeIcon: false, 1195 outSideClose: false 1196 }; 1197 options.okBtn = $.extend({}, defaults.okBtn, options.okBtn); 1198 options = $.extend({}, defaults, options); 1199 options.buttons = [{ 1200 className: options.okBtn.className, 1201 label: options.okBtn.label, 1202 closeAfter: true, 1203 method: method 1204 }]; 1205 return new Ssi_modal(options).init().show(); 1206 }; 1207 1208 //-----------------------------End of dialog plugin------------------------------------------------------------------ 1209 1210//-----------------------------Start of confirm plugin------------------------------------------------------------------ 1211 1212 ssi_modal.confirm = function (options, method) { 1213 var defaults = { 1214 okBtn: { 1215 className: '', 1216 label: 'Ok' 1217 }, 1218 cancelBtn: { 1219 className: '', 1220 label: 'Cancel' 1221 }, 1222 closeIcon: false, 1223 sizeClass: 'dialog', 1224 title: '', 1225 1226 outSideClose: false 1227 }; 1228 options.okBtn = $.extend({}, defaults.okBtn, options.okBtn); 1229 options.cancelBtn = $.extend({}, defaults.cancelBtn, options.cancelBtn); 1230 options = $.extend({}, defaults, options); 1231 options.buttons = [{ 1232 className: options.okBtn.className, 1233 label: options.okBtn.label, 1234 closeAfter: true, 1235 method: function (e, modal) { 1236 if (typeof method === 'function') 1237 method(true, e, modal); 1238 } 1239 }, { 1240 className: options.cancelBtn.className, 1241 label: options.cancelBtn.label, 1242 closeAfter: true, 1243 method: function (e, modal) { 1244 if (typeof method === 'function') 1245 method(false, e, modal); 1246 } 1247 }]; 1248 return new Ssi_modal(options).init().show(); 1249 }; 1250 1251 //--------------------------------End of confirm plugin-------------------------------------------------- 1252
1253//-----------------------------Start of imgBox plugin------------------------------------------------------------------ 1254 function isDataURL(s) { 1255 return !!s.match(isDataURL.regex); 1256 } 1257 1258 isDataURL.regex = /^\s*data:([a-z]+\/[a-z0-9\-\+]+(;[a-z\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i; 1259 1260 var imgBoxOptions = {'ssi-mainOption': {}};//this will hold the imgbox options when will call ssi_modal.imgBox function 1261 ssi_modal.imgBox = function (options, group) {//set options for the image box 1262 group = group || 'ssi-mainOption'; 1263 imgBoxOptions[group] = $.extend({}, imgBoxOptions['ssi-mainOption'], options); 1264 }; 1265 1266 var currentIndex, 1267 $elementsLength, 1268 $eventTarget; 1269 1270 /** 1271 * Navigates to the next/previous image. 1272 * @param {'next' || 'prev'} direction -The navigation direction 1273 * @returns {Ssi_modal} 1274 */ 1275 ssi_modal.proto.navigate = function (direction) { 1276 var $groupElements = $('a[data-ssi_imgGroup="' + $eventTarget.attr('data-ssi_imgGroup') + '"]'); 1277 if (!currentIndex)currentIndex = $groupElements.index($eventTarget); 1278 if (!$elementsLength)$elementsLength = $groupElements.length; 1279 if ((direction === 'next' && currentIndex + 1 >= $elementsLength) || (direction === 'prev' && currentIndex < 0)) { 1280 return this; 1281 } 1282 1283 this.destroyModal(); 1284 if (direction === 'next') {//next image 1285 currentIndex++; 1286 } else if (direction === 'prev') {//previous image 1287 currentIndex--; 1288 } 1289 $groupElements.eq(currentIndex).trigger('click.ssi-imgBox'); 1290 return this; 1291 }; 1292 1293 ssi_modal.imgBox.show = function (url, options) { 1294 var defaults = {//set defaults 1295 backdrop: 'byKindShared', 1296 fixedHeight: true, 1297 navigation: true, 1298 closeIcon: true, 1299 title: false, 1300 allowIframe:true, 1301 hideImgButtons: true 1302 }; 1303 options = $.extend(true, defaults, options); 1304 $.extend(options, { 1305 img: true, 1306 content: '<div class="ssi-loader"></div>', 1307 sizeClass: '' 1308 }); 1309 var imgBox = ssi_modal.createObject(options) 1310 .setPluginName('imgBox'); 1311 imgBox.imgUrl = url; 1312 imgBox.imgTitle = options.title; 1313 imgBox.init(); 1314 if (options.title) { 1315 imgBox.get$icons().addClass('inTitle'); 1316 } 1317 1318 imgBox.show(); 1319 setImg(imgBox, url); 1320 1321 }; 1322 $('body').on('click.ssi-imgBox', 'a.ssi-imgBox', function (e) {//click event handler for all links with ssi-imgbox class 1323 e.preventDefault(); 1324 e.stopPropagation(); 1325 $eventTarget = $(e.currentTarget); 1326 var group = $eventTarget.attr('data-ssi_imgGroup') || 'ssi-mainOption';//get the options of the right group 1327 var options = imgBoxOptions[group] || imgBoxOptions['ssi-mainOption']; 1328 var url = $eventTarget.attr('href'); 1329 if (options.imgButtons !== '' && !$.isEmptyObject(options.imgButtons)) { 1330 for (var i = 0; i < options.imgButtons.length; i++) { //check if the current button is in the exclude list 1331 if (options.imgButtons[i].exclude) { 1332 var btnClass = options.imgButtons[i].exclude.split(','); 1333 for (var y = 0; y < btnClass.length; y++) { 1334 if ($eventTarget.hasClass(btnClass[y])) { 1335 options.imgButtons.splice(i, 1); 1336 break; 1337 } 1338 } 1339 } 1340 } 1341 } 1342 if (options.title) { 1343 if (options.title === true) { 1344 options.title = $eventTarget.attr('title');//get title of the target 1345 } 1346 } 1347 ssi_modal.imgBox.show(url, options, $eventTarget); 1348 }); 1349 1350 function setImg(imgBox, url) { 1351 1352 var $modalWrapper = imgBox.get$wrapper(), 1353 $content = $modalWrapper.find('#ssi-modalContent'); 1354 if (!url || url == '#') { 1355 var alt = ($eventTarget ? $eventTarget.attr('data-alt') : ''); 1356 $img = '<h3>Image not found</h3><br>' + (typeof alt !== 'undefined' ? '<h4>' + alt + '</h4>' : ''); 1357 placeImg(true); 1358 return; 1359 } 1360 var interval, 1361 startInterval,
1362 supportsNatural = ("naturalWidth" in (new Image())), 1363 windowHeight = $(window).height(), 1364 windowWidth = $(window).width(), 1365 $img = [''], 1366 i = 0; 1367 if (imgBox.options.navigation && $eventTarget) { 1368 $content.append(setImgNavigation); 1369 } 1370 var imgTypes = [ 1371 'jpg', 1372 'jpeg', 1373 'png', 1374 'gif', 1375 'bmp' 1376 ]; 1377 if (!imgBox.options.allowIframe||$.inArray(url.split('.').pop().toLowerCase(), imgTypes) !== -1||isDataURL(url)) { 1378 $img = $('<img src="' + url + '" class="ssi-modalImg"/>') 1379 .on('load', function () { 1380 if (!supportsNatural) { 1381 var ghost = new Image(); 1382 ghost.src = $img.attr('src'); 1383 var width = ghost.width; 1384 var height = ghost.height; 1385 onHasSize(width, height); 1386 } 1387 }) 1388 .error(function () { 1389 var alt = ($eventTarget ? $eventTarget.attr('data-alt') : ''); 1390 $img = '<h3>Image not found</h3><br>' + (typeof alt !== 'undefined' ? '<h4>' + alt + '</h4>' : ''); 1391 placeImg(true); 1392 }); 1393 checkSize(); 1394 if (startInterval) { 1395 interval = setInterval(function () { 1396 $modalWrapper.addClass('ssi-imgBorder'); 1397 checkSize(); 1398 i++ 1399 }, 50); 1400 } 1401 1402 } else { 1403 if (typeof imgBox.options.iframe.allowFullScreen !== 'boolean') { 1404 imgBox.options.iframe.allowFullScreen = true; 1405 } 1406 imgBox.options.iframe.className = imgBox.options.iframe.className || ''; 1407 $img = $('<iframe src="' + url + '" frameborder="0" ' + (imgBox.options.iframe.allowFullScreen ? 'allowfullscreen' : '') + '></iframe>'); 1408 1409 if (imgBox.options.center) { 1410 $modalWrapper.addClass('ssi-iframe ').find('#ssi-modalWindow' + imgBox.numberId).addClass(imgBox.options.iframe.className); 1411 } else { 1412 $modalWrapper.addClass('ssi-iframe ' + imgBox.options.iframe.className); 1413 } 1414 placeImg(); 1415 } 1416 1417 function setImgNavigation() { 1418 var $groupElements = $('a[data-ssi_imgGroup="' + $eventTarget.attr('data-ssi_imgGroup') + '"]'); 1419 if (!$groupElements.length)return; 1420 var index = $groupElements.index($eventTarget), 1421 $elementLength = $groupElements.length; 1422 if (index + 1 >= $elementLength && index < 1)return; 1423 var $nav = $('<div class="ssi-modalNavigation"></divid>').mouseover(function () { 1424 $nav.addClass('ssi-navFadeIn'); 1425 }).mouseleave(function () { 1426 $nav.removeClass('ssi-navFadeIn'); 1427 }), 1428 $next = $('<div class="ssi-modalNext ' + (index + 1 >= $elementLength ? 'ssi-hidden' : '') + '"><span></span></div>'), 1429 $prev = $('<div class="ssi-modalPrev ' + (index < 1 ? 'ssi-hidden' : '') + '"><span></span></div>'); 1430 $nav.append($next, $prev); 1431 imgBox.get$backdrop().one('backdropClose.ssi-modal', function () { 1432 1433 $elementsLength = ''; 1434 currentIndex = ''; 1435 }); 1436 imgBox.get$modal().one('beforeClose.ssi-modal', function () { 1437 $nav.remove(); 1438 }).one('onShow.ssi-modal', function () { 1439 $next.one('click', function (e) { 1440 e.preventDefault(); 1441 imgBox.navigate('next'); 1442 $(this).off('click.ssi_modal'); 1443 }); 1444 $prev.one('click', function (e) { 1445 e.preventDefault(); 1446 imgBox.navigate('prev'); 1447 $(this).off('click.ssi_modal'); 1448 }); 1449 }); 1450 1451 return $nav; 1452 } 1453 1454 function placeImg(error) { 1455 $content.find('.ssi-loader').remove(); 1456 var content = [];
1457 if (!error && imgBox.options.imgButtons !== '' && !$.isEmptyObject(imgBox.options.imgButtons)) { 1458 var imgButtons = imgBox.setButtons(imgBox.options.imgButtons, imgBox.get$content()).addClass('ssi-imgButtons'); 1459 if (imgBox.options.hideImgButtons === true) { 1460 imgButtons.addClass('ssi-navFade ssi-navFadeOut'); 1461 imgBox.get$wrapper().mouseover(function () { 1462 imgButtons.addClass('ssi-navFadeIn'); 1463 }).mouseleave(function () { 1464 imgButtons.removeClass('ssi-navFadeIn'); 1465 }) 1466 } 1467 1468 content.push(imgButtons); 1469 1470 } 1471 content.push($img); 1472 $content.append(content); 1473 } 1474 1475 function AspectRatio(srcWidth, srcHeight, maxWidth, maxHeight) {//find the aspect ration 1476 var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight); 1477 return {width: srcWidth * ratio, height: srcHeight * ratio}; 1478 } 1479 1480 function onHasSize(width, height) { 1481 clearInterval(interval); 1482 var naturalWidth = width || (supportsNatural ? $img[0].naturalWidth : $img.width()); 1483 var naturalHeight = height || (supportsNatural ? $img[0].naturalHeight : $img.height()); 1484 1485 var imgHeight = imgBox.setModalHeight(120, true); 1486 if ((naturalHeight > windowHeight - imgHeight || naturalWidth > windowWidth) && imgBox.options.fixedHeight === true) { 1487 var dimensions = AspectRatio(naturalWidth, naturalHeight, windowWidth - 100, windowHeight - imgHeight); 1488 naturalWidth = dimensions.width; 1489 naturalHeight = dimensions.height; 1490 if (i > 2) { 1491 $modalWrapper.addClass('ssi-overHeight') 1492 } 1493 } 1494 $content.css('height', naturalHeight); 1495 if (imgBox.options.center) { 1496 $content.parent().css({'width': naturalWidth, 'height': naturalHeight}); 1497 } 1498 $modalWrapper.css('width', naturalWidth); 1499 placeImg(); 1500 1501 $modalWrapper.addClass('ssi-imgBorder') 1502 1503 } 1504 1505 /** 1506 * Initialize the arrows of navigation. 1507 * @param {Ssi_modal}modalObj 1508 * @returns {*|HTMLElement} 1509 */ 1510 1511 /** 1512 * checks when the image's size is available 1513 */ 1514 function checkSize() { 1515 if (supportsNatural) { 1516 if ($img[0].naturalWidth > 0) { 1517 onHasSize(); 1518 return; 1519 } 1520 } else { 1521 clearInterval(interval); 1522 if ($img.width() > 50) { 1523 onHasSize(); 1524 return; 1525 } 1526 } 1527 startInterval = true; 1528 } 1529 1530 } 1531 1532//-----------------------------End of imgBox plugin------------------------------------------------------------------ 1533 1534//--------------------------------Start of notify plugin-------------------------------------------------- 1535 ssi_modal.notify = function (type, options, callback) { 1536 var defaults = { 1537 closeIcon: false, 1538 overrideOther: false, 1539 sizeClass: 'dialog', 1540 onClickClose: true, 1541 bodyScroll: true, 1542 animation: true, 1543 className: '', 1544 backdrop: false, 1545 outSideClose: false, 1546 position: 'right top', 1547 topZIndex: true, 1548 okBtn: { 1549 className: '', 1550 label: 'Ok' 1551 }, 1552 cancelBtn: { 1553 className: '', 1554 label: 'Cancel' 1555 }, 1556 stack: true, 1557 closeAfter: { 1558 time: 4, 1559 resetOnHover: true 1560 } 1561 }; 1562 if (type === 'confirm' || 'dialog') { 1563 options.okBtn = $.extend({}, defaults.okBtn, options.okBtn); 1564 options.cancelBtn = $.extend({}, defaults.cancelBtn, options.cancelBtn); 1565 } 1566 1567 var generateIcon = function (className) { 1568 if (className === '')return ''; 1569 return '<span class="ssi-icon ' + className + '"></span>' 1570 }; 1571 1572 var icon = '', title = ''; 1573 switch (type) { 1574 case 'success': 1575 defaults.className = ' ssi-success'; 1576 break; 1577 case 'error': 1578 defaults.className = ' ssi-error'; 1579 break; 1580 case 'info': 1581 defaults.className = ' ssi-info'; 1582 break; 1583 case 'warning': 1584 defaults.className = ' ssi-warning'; 1585 break; 1586 case 'confirm': 1587 defaults.closeAfter = false;
1588 defaults.onClickClose = false; 1589 defaults.outSideClose = false; 1590 defaults.icon = false; 1591 defaults.title = false; 1592 1593 defaults.buttons = [{ 1594 className: options.okBtn.className, 1595 label: options.okBtn.label, 1596 closeAfter: true, 1597 method: function () { 1598 if (typeof callback === 'function') { 1599 callback(true); 1600 } 1601 } 1602 }, { 1603 className: options.cancelBtn.className, 1604 label: options.cancelBtn.label, 1605 closeAfter: true, 1606 method: function () { 1607 if (typeof callback === 'function') { 1608 callback(false); 1609 } 1610 } 1611 }]; 1612 break; 1613 case 'dialog': 1614 defaults.onClickClose = false; 1615 defaults.closeAfter = false; 1616 defaults.outSideClose = false; 1617 defaults.title = false; 1618 defaults.icon = false; 1619 defaults.buttons = [{ 1620 className: options.okBtn.className, 1621 label: options.okBtn.label, 1622 closeAfter: true, 1623 method: callback 1624 }]; 1625 break; 1626 default: 1627 defaults.className = type; 1628 } 1629 if (options.className) { 1630 options.className += defaults.className || ''; 1631 } 1632 options = $.extend(true, defaults, options); 1633 1634 if (options.icon != false) { 1635 icon = options.icon || type || ''; 1636 } 1637 if (options.title != false) { 1638 title = options.title || type; 1639 } 1640 if ((options.icon != false && options.title != false) && icon != '') { 1641 options.title = generateIcon(icon) + ' ' + title; 1642 } 1643 if (options.backdrop === true) { 1644 options.backdrop = 'byKndShared' 1645 } 1646 options.keepContent = false; 1647 if (options.overrideOther) { 1648 var classes = options.position.split(' '); 1649 $('body').find('div.' + classes[0] + '.' + classes[1]).children().empty() 1650 } 1651 1652 return ssi_modal.createObject(options) 1653 .setPluginName('notify').init().show(); 1654 }; 1655//--------------------------------End of notify plugin-------------------------------------------------- 1656 1657//--------------------------------Start of jquery selector plugin-------------------------------------------------- 1658 1659 $.fn.ssi_modal = function () { 1660 var opts; 1661 if (typeof arguments[1] === 'object') { 1662 var action = arguments[0]; 1663 opts = arguments[1] || {}; 1664 var callback = arguments[2]; 1665 } else { 1666 opts = arguments[0] || {}; 1667 } 1668 return this.each(function () { 1669 var element = $(this), options; 1670 if (opts.content) {//that means that we will not use any div element for content 1671 element.click(function () { 1672 switch (action) {//action could be show,dialog or confirm 1673 case 'show': 1674 ssi_modal['show'](opts, element); 1675 break; 1676 default: 1677 ssi_modal[action](opts, callback); 1678 } 1679 }) 1680 } else { 1681 var content, def, dataAttr = element.attr('data-ssi_modal'); 1682 if (dataAttr) {// that means the content is an element. data-ssi_modal shows the elements selector 1683 element.click(function () {//set click event 1684 content = $(dataAttr); 1685 def = { 1686 content: content 1687 }; 1688 options = $.extend({}, opts, def); 1689 ssi_modal.createObject(options).init().show(); 1690 }); 1691 } else {//that means the target is the element that contains the content 1692 def = { 1693 content: element 1694 }; 1695 options = $.extend({}, opts, def); 1696 ssi_modal.createObject(options).init().show(); 1697 } 1698 } 1699 }); 1700 }; 1701//--------------------------------End of jquery selector plugin-------------------------------------------------- 1702 1703 /** 1704 * Adds animation to an element 1705 * @method addAnimation 1706 * @param {string} animationName 1707 * @param {function} callback 1708 * @return CallExpression 1709 */ 1710 1711//@author https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Detecting_CSS_animation_support 1712 function checkAnimationSupport() { 1713 var animation = false, 1714 animationstring = 'animation', 1715 keyframeprefix = '', 1716 domPrefixes = 'Webkit Moz O ms Khtml'.split(' '), 1717 pfx = '', 1718 elm = document.createElement('div'); 1719 1720 if (elm.style.animationName !== undefined) { 1721 animation = true; 1722 } 1723 1724 if (animation === false) { 1725 for (var i = 0; i < domPrefixes.length; i++) { 1726 if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { 1727 pfx = domPrefixes[i]; 1728 animationstring = pfx + 'Animation'; 1729 keyframeprefix = '-' + pfx.toLowerCase() + '-'; 1730 animation = true; 1731 break; 1732 } 1733 } 1734 } 1735 return animation; 1736 } 1737 1738 $.fn.addAnimation = function (animationName, callback) { 1739 var animationEnd = 'mozAnimationEnd webkitAnimationEnd MSAnimationEnd oanimationend animationend'; 1740 if (animationName.indexOf('ssi-fade') !== -1 && animationSupport === false) { 1741 return $(this)[animationName.replace('anim ssi-', '')](300, function () { 1742 if (typeof callback === 'function') { 1743 callback(); 1744 } 1745 }); 1746 } else { 1747 $(this).addClass(animationName).one(animationEnd, function () { 1748 $(this).removeClass(animationName); 1749 if (typeof callback === 'function') { 1750 callback(); 1751 } 1752 }); 1753 1754 if (animationName === 'ssi-show' || animationName === 'ssi-hidden' || animationName === '') { 1755 $(this).trigger('animationend'); 1756 } 1757 return this.each(function () { 1758 $(this) 1759 }) 1760 } 1761 }; 1762 1763 function toArray(value) {//if the value is not array returns an array with the value 1764 if (!(value instanceof Array)) { 1765 value = [value]; 1766 } 1767 return value; 1768 } 1769 1770 return ssi_modal; 1771 1772}));
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.